diff options
Diffstat (limited to 'distrib/sdl-1.2.15/src/video/fbcon')
21 files changed, 6038 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h new file mode 100644 index 0000000..b641454 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_mmio.h @@ -0,0 +1,56 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx register definitions */ + +#include "3dfx_regs.h" + +/* 3Dfx control macros */ + +#define tdfx_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define tdfx_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define tdfx_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define tdfx_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define tdfx_wait(space) \ +{ \ + while ( (tdfx_in8(TDFX_STATUS) & 0x1F) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define tdfx_waitidle() \ +{ \ + int i = 0; \ + \ + tdfx_wait(1); \ + tdfx_out32(COMMAND_3D, COMMAND_3D_NOP); \ + do { \ + i = (tdfx_in32(TDFX_STATUS) & STATUS_BUSY) ? 0 : i + 1; \ + } while ( i != 3 ); \ +} + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h new file mode 100644 index 0000000..e86f727 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/3dfx_regs.h @@ -0,0 +1,83 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _3DFX_REGS_H +#define _3DFX_REGS_H + +/* This information comes from the public 3Dfx specs for the Voodoo 3000 */ + +/* mapped_io register offsets */ +#define TDFX_STATUS 0x00 + +#define INTCTRL (0x00100000 + 0x04) +#define CLIP0MIN (0x00100000 + 0x08) +#define CLIP0MAX (0x00100000 + 0x0c) +#define DSTBASE (0x00100000 + 0x10) +#define DSTFORMAT (0x00100000 + 0x14) +#define SRCCOLORKEYMIN (0x00100000 + 0x18) +#define SRCCOLORKEYMAX (0x00100000 + 0x1c) +#define DSTCOLORKEYMIN (0x00100000 + 0x20) +#define DSTCOLORKEYMAX (0x00100000 + 0x24) +#define BRESERROR0 (0x00100000 + 0x28) +#define BRESERROR1 (0x00100000 + 0x2c) +#define ROP_2D (0x00100000 + 0x30) +#define SRCBASE (0x00100000 + 0x34) +#define COMMANDEXTRA_2D (0x00100000 + 0x38) +#define PATTERN0 (0x00100000 + 0x44) +#define PATTERN1 (0x00100000 + 0x48) +#define CLIP1MIN (0x00100000 + 0x4c) +#define CLIP1MAX (0x00100000 + 0x50) +#define SRCFORMAT (0x00100000 + 0x54) +#define SRCSIZE (0x00100000 + 0x58) +#define SRCXY (0x00100000 + 0x5c) +#define COLORBACK (0x00100000 + 0x60) +#define COLORFORE (0x00100000 + 0x64) +#define DSTSIZE (0x00100000 + 0x68) +#define DSTXY (0x00100000 + 0x6c) +#define COMMAND_2D (0x00100000 + 0x70) +#define LAUNCH_2D (0x00100000 + 0x80) +#define PATTERNBASE (0x00100000 + 0x100) + +#define COMMAND_3D (0x00200000 + 0x120) + +/* register bitfields (not all, only as needed) */ + +#define BIT(x) (1UL << (x)) + +#define COMMAND_2D_BITBLT 0x01 +#define COMMAND_2D_FILLRECT 0x05 +#define COMMAND_2D_LINE 0x06 +#define COMMAND_2D_POLYGON_FILL 0x08 +#define COMMAND_2D_INITIATE BIT(8) +#define COMMAND_2D_REVERSELINE BIT(9) +#define COMMAND_2D_STIPPLELINE BIT(12) +#define COMMAND_2D_MONOCHROME_PATT BIT(13) +#define COMMAND_2D_MONOCHROME_TRANSP BIT(16) + +#define COMMAND_3D_NOP 0x00 + +#define STATUS_RETRACE BIT(6) +#define STATUS_BUSY BIT(9) + +#endif /* _3DFX_REGS_H */ + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c new file mode 100644 index 0000000..eb083b8 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.c @@ -0,0 +1,215 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fb3dfx.h" +#include "3dfx_mmio.h" + + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + /* find start of retrace */ + tdfx_waitidle(); + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == STATUS_RETRACE ) + ; + /* wait until we're past the start */ + while( (tdfx_in32(TDFX_STATUS) & STATUS_RETRACE) == 0 ) + ; +} +static void WaitIdle(_THIS) +{ + tdfx_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int bpp; + Uint32 dst_base; + Uint32 format; + int dstX, dstY; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the destination pixel format */ + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + format = dst->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + + /* Calculate source and destination base coordinates */ + dstX = rect->x; + dstY = rect->y; + + /* Execute the fill command */ + tdfx_wait(6); + tdfx_out32(DSTBASE, dst_base); + tdfx_out32(DSTFORMAT, format); + tdfx_out32(COLORFORE, color); + tdfx_out32(COMMAND_2D, COMMAND_2D_FILLRECT); + tdfx_out32(DSTSIZE, rect->w | (rect->h << 16)); + tdfx_out32(LAUNCH_2D, dstX | (dstY << 16)); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int bpp; + Uint32 src_format; + Uint32 src_base; + Uint32 dst_base; + int srcX, srcY; + int dstX, dstY; + Uint32 blitop; + Uint32 use_colorkey; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set the source and destination pixel format */ + src_base = ((char *)src->pixels - mapped_mem); + bpp = src->format->BitsPerPixel; + src_format = src->pitch | ((bpp+((bpp==8) ? 0 : 8)) << 13); + dst_base = ((char *)dst->pixels - mapped_mem); + bpp = dst->format->BitsPerPixel; + + srcX = srcrect->x; + srcY = srcrect->y; + dstX = dstrect->x; + dstY = dstrect->y; + + /* Assemble the blit operation */ + blitop = COMMAND_2D_BITBLT | (0xCC << 24); + if ( srcX <= dstX ) { + blitop |= BIT(14); + srcX += (dstrect->w - 1); + dstX += (dstrect->w - 1); + } + if ( srcY <= dstY ) { + blitop |= BIT(15); + srcY += (dstrect->h - 1); + dstY += (dstrect->h - 1); + } + + /* Perform the blit! */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + tdfx_wait(3); + tdfx_out32(SRCCOLORKEYMIN, src->format->colorkey); + tdfx_out32(SRCCOLORKEYMAX, src->format->colorkey); + tdfx_out32(ROP_2D, 0xAA00); + use_colorkey = 1; + } else { + use_colorkey = 0; + } + tdfx_wait(9); + tdfx_out32(SRCBASE, (Uint32)src_base); + tdfx_out32(SRCFORMAT, src_format); + tdfx_out32(DSTBASE, (Uint32)dst_base); + tdfx_out32(DSTFORMAT, src_format); + tdfx_out32(COMMAND_2D, blitop); + tdfx_out32(COMMANDEXTRA_2D, use_colorkey); + tdfx_out32(DSTSIZE, dstrect->w | (dstrect->h << 16)); + tdfx_out32(DSTXY, dstX | (dstY << 16)); + tdfx_out32(LAUNCH_2D, srcX | (srcY << 16)); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_3DfxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* Reset the 3Dfx controller */ + tdfx_out32(BRESERROR0, 0); + tdfx_out32(BRESERROR1, 0); + + /* The 3Dfx has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The 3Dfx has accelerated normal and colorkey blits */ + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h new file mode 100644 index 0000000..4a59de9 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fb3dfx.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* 3Dfx hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for 3Dfx acceleration */ +extern void FB_3DfxAccel(_THIS, __u32 card); diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c new file mode 100644 index 0000000..63dff87 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.c @@ -0,0 +1,442 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include <unistd.h> +#include <sys/time.h> +#include <ctype.h> + +#include "SDL_stdinc.h" +#include "SDL_fbvideo.h" +#include "SDL_fbelo.h" + +/* + calibration default values + values are read from the following environment variables: + + SDL_ELO_MIN_X + SDL_ELO_MAX_X + SDL_ELO_MIN_Y + SDL_ELO_MAX_Y +*/ + +static int ELO_MIN_X = 400; +static int ELO_MAX_X = 3670; +static int ELO_MIN_Y = 500; +static int ELO_MAX_Y = 3540; + +#define ELO_SNAP_SIZE 6 +#define ELO_TOUCH_BYTE 'T' +#define ELO_ID 'I' +#define ELO_MODE 'M' +#define ELO_PARAMETER 'P' +#define ELO_REPORT 'B' +#define ELO_ACK 'A' + +#define ELO_INIT_CHECKSUM 0xAA + +#define ELO_BTN_PRESS 0x01 +#define ELO_STREAM 0x02 +#define ELO_BTN_RELEASE 0x04 + +#define ELO_TOUCH_MODE 0x01 +#define ELO_STREAM_MODE 0x02 +#define ELO_UNTOUCH_MODE 0x04 +#define ELO_RANGE_CHECK_MODE 0x40 +#define ELO_TRIM_MODE 0x02 +#define ELO_CALIB_MODE 0x04 +#define ELO_SCALING_MODE 0x08 +#define ELO_TRACKING_MODE 0x40 + +#define ELO_SERIAL_MASK 0xF8 + +#define ELO_SERIAL_IO '0' + +#define ELO_MAX_TRIALS 3 +#define ELO_MAX_WAIT 100000 +#define ELO_UNTOUCH_DELAY 5 +#define ELO_REPORT_DELAY 1 + +/* eloParsePacket +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) { + static int elo_button = 0; + static int last_x = 0; + static int last_y = 0; + int x,y; + + /* Check if we have a touch packet */ + if (mousebuf[1] != ELO_TOUCH_BYTE) { + return 0; + } + + x = ((mousebuf[4] << 8) | mousebuf[3]); + y = ((mousebuf[6] << 8) | mousebuf[5]); + + if((SDL_abs(x - last_x) > ELO_SNAP_SIZE) || (SDL_abs(y - last_y) > ELO_SNAP_SIZE)) { + *dx = ((mousebuf[4] << 8) | mousebuf[3]); + *dy = ((mousebuf[6] << 8) | mousebuf[5]); + } + else { + *dx = last_x; + *dy = last_y; + } + + last_x = *dx; + last_y = *dy; + + if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) { + elo_button = 1; + } + if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) { + elo_button = 0; + } + + *button_state = elo_button; + return 1; +} + +/* Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy) { + int input_x = *dx; + int input_y = *dy; + int width = ELO_MAX_X - ELO_MIN_X; + int height = ELO_MAX_Y - ELO_MIN_Y; + + *dx = ((int)cache_vinfo.xres - ((int)cache_vinfo.xres * (input_x - ELO_MIN_X)) / width); + *dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height; +} + + +/* eloGetPacket +*/ +int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) { + int num_bytes; + int ok; + + if(fd == 0) { + num_bytes = ELO_PACKET_SIZE; + } + else { + num_bytes = read(fd, + (char *) (buffer + *buffer_p), + ELO_PACKET_SIZE - *buffer_p); + } + + if (num_bytes < 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "System error while reading from Elographics touchscreen.\n"); +#endif + return 0; + } + + while (num_bytes) { + if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) { + SDL_memcpy(&buffer[0], &buffer[1], num_bytes-1); + } + else { + if (*buffer_p < ELO_PACKET_SIZE-1) { + *checksum = *checksum + buffer[*buffer_p]; + *checksum = *checksum % 256; + } + (*buffer_p)++; + } + num_bytes--; + } + + if (*buffer_p == ELO_PACKET_SIZE) { + ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); + *checksum = ELO_INIT_CHECKSUM; + *buffer_p = 0; + + if (!ok) { + return 0; + } + + return 1; + } + else { + return 0; + } +} + +/* eloSendPacket +*/ + +int eloSendPacket(unsigned char* packet, int fd) +{ + int i, result; + int sum = ELO_INIT_CHECKSUM; + + packet[0] = ELO_START_BYTE; + for (i = 0; i < ELO_PACKET_SIZE-1; i++) { + sum += packet[i]; + sum &= 0xFF; + } + packet[ELO_PACKET_SIZE-1] = sum; + + result = write(fd, packet, ELO_PACKET_SIZE); + + if (result != ELO_PACKET_SIZE) { +#ifdef DEBUG_MOUSE + printf("System error while sending to Elographics touchscreen.\n"); +#endif + return 0; + } + else { + return 1; + } +} + + +/* eloWaitForInput + */ +int eloWaitForInput(int fd, int timeout) +{ + fd_set readfds; + struct timeval to; + int r; + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + to.tv_sec = 0; + to.tv_usec = timeout; + + r = select(FD_SETSIZE, &readfds, NULL, NULL, &to); + return r; +} + +/* eloWaitReply + */ +int eloWaitReply(unsigned char type, unsigned char *reply, int fd) { + int ok; + int i, result; + int reply_p = 0; + int sum = ELO_INIT_CHECKSUM; + + i = ELO_MAX_TRIALS; + do { + ok = 0; + + result = eloWaitForInput(fd, ELO_MAX_WAIT); + + if (result > 0) { + ok = eloGetPacket(reply, &reply_p, &sum, fd); + + if (ok && reply[1] != type && type != ELO_PARAMETER) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Wrong reply received\n"); +#endif + ok = 0; + } + } + else { +#ifdef DEBUG_MOUSE + fprintf(stderr, "No input!\n"); +#endif + } + + if (result == 0) { + i--; + } + } while(!ok && (i>0)); + + return ok; +} + + +/* eloWaitAck + */ + +int eloWaitAck(int fd) { + unsigned char packet[ELO_PACKET_SIZE]; + int i, nb_errors; + + if (eloWaitReply(ELO_ACK, packet, fd)) { + for (i = 0, nb_errors = 0; i < 4; i++) { + if (packet[2 + i] != '0') { + nb_errors++; + } + } + + if (nb_errors != 0) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors); +#endif + } + return 1; + } + else { + return 0; + } +} + + +/* eloSendQuery -- +*/ +int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) { + int ok; + + if (eloSendPacket(request, fd)) { + ok = eloWaitReply(toupper(request[1]), reply, fd); + if (ok) { + ok = eloWaitAck(fd); + } + return ok; + } + else { + return 0; + } +} + + +/* eloSendControl +*/ +int eloSendControl(unsigned char* control, int fd) { + if (eloSendPacket(control, fd)) { + return eloWaitAck(fd); + } + else { + return 0; + } +} + +/* eloInitController +*/ +int eloInitController(int fd) { + unsigned char req[ELO_PACKET_SIZE]; + unsigned char reply[ELO_PACKET_SIZE]; + const char *buffer = NULL; + int result = 0; + + struct termios mouse_termios; + + /* try to read the calibration values */ + buffer = SDL_getenv("SDL_ELO_MIN_X"); + if(buffer) { + ELO_MIN_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_X"); + if(buffer) { + ELO_MAX_X = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MIN_Y"); + if(buffer) { + ELO_MIN_Y = SDL_atoi(buffer); + } + buffer = SDL_getenv("SDL_ELO_MAX_Y"); + if(buffer) { + ELO_MAX_Y = SDL_atoi(buffer); + } + +#ifdef DEBUG_MOUSE + fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n", + ELO_MIN_X, + ELO_MAX_X, + ELO_MIN_Y, + ELO_MAX_Y); +#endif + + /* set comm params */ + SDL_memset(&mouse_termios, 0, sizeof(mouse_termios)); + mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; + mouse_termios.c_cc[VMIN] = 1; + result = tcsetattr(fd, TCSANOW, &mouse_termios); + + if (result < 0) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to configure Elographics touchscreen port\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_PARAMETER); + if (!eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Not at the specified rate or model 2310, will continue\n"); +#endif + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = tolower(ELO_ID); + if (eloSendQuery(req, reply, fd)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Ok, controller configured!\n"); +#endif + } + else { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to ask Elographics touchscreen identification\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_MODE; + req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; + req[4] = ELO_TRACKING_MODE; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n"); +#endif + return 0; + } + + SDL_memset(req, 0, ELO_PACKET_SIZE); + req[1] = ELO_REPORT; + req[2] = ELO_UNTOUCH_DELAY; + req[3] = ELO_REPORT_DELAY; + if (!eloSendControl(req, fd)) { +#ifdef DEBUG_MOUSE + fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n"); +#endif + return 0; + } + + return 1; +} + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy) { + unsigned char buffer[ELO_PACKET_SIZE]; + int pointer = 0; + int checksum = ELO_INIT_CHECKSUM; + + while(pointer < ELO_PACKET_SIZE) { + if(eloGetPacket(buffer, &pointer, &checksum, fd)) { + break; + } + } + + if(!eloParsePacket(buffer, realx, realy, button_state)) { + return 0; + } + + *x = *realx; + *y = *realy; + + eloConvertXY(this, x, y); + + return 1; +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h new file mode 100644 index 0000000..e7fde4f --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbelo.h @@ -0,0 +1,55 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef SDL_fbelo_h +#define SDL_fbelo_h + +#include "SDL_fbvideo.h" + +/* ELO */ +#define ELO_PACKET_SIZE 10 +#define ELO_START_BYTE 'U' + +/* eloConvertXY + Convert the raw coordinates from the ELO controller + to a screen position. +*/ +void eloConvertXY(_THIS, int *dx, int *dy); + +/* eloInitController(int fd) + Initialize the ELO serial touchscreen controller +*/ +int eloInitController(int fd); + +/* eloParsePacket + extract position and button state from a packet +*/ +int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state); + +/* eloReadPosition + read a packet and get the cursor position +*/ + +int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy); + +#endif /* SDL_fbelo_h */ diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c new file mode 100644 index 0000000..5e369a4 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents.c @@ -0,0 +1,1254 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Handle the event stream, converting console events into SDL events */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> + +/* For parsing /proc */ +#include <dirent.h> +#include <ctype.h> + +#include <linux/vt.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "SDL_timer.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbevents_c.h" +#include "SDL_fbkeys.h" + +#include "SDL_fbelo.h" + +#ifndef GPM_NODE_FIFO +#define GPM_NODE_FIFO "/dev/gpmdata" +#endif + +/*#define DEBUG_KEYBOARD*/ +/*#define DEBUG_MOUSE*/ + +/* The translation tables from a console scancode to a SDL keysym */ +#define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) +static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; +static SDLKey keymap[128]; +static Uint16 keymap_temp[128]; /* only used at startup */ +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); + +/* Ugh, we have to duplicate the kernel's keysym mapping code... + Oh, it's not so bad. :-) + + FIXME: Add keyboard LED handling code + */ +static void FB_vgainitkeymaps(int fd) +{ + struct kbentry entry; + int map, i; + + /* Don't do anything if we are passed a closed keyboard */ + if ( fd < 0 ) { + return; + } + + /* Load all the keysym mappings */ + for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { + SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); + for ( i=0; i<NR_KEYS; ++i ) { + entry.kb_table = map; + entry.kb_index = i; + if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { + /* fill keytemp. This replaces SDL_fbkeys.h */ + if ( (map == 0) && (i<128) ) { + keymap_temp[i] = entry.kb_value; + } + /* The "Enter" key is a special case */ + if ( entry.kb_value == K_ENTER ) { + entry.kb_value = K(KT_ASCII,13); + } + /* Handle numpad specially as well */ + if ( KTYP(entry.kb_value) == KT_PAD ) { + switch ( entry.kb_value ) { + case K_P0: + case K_P1: + case K_P2: + case K_P3: + case K_P4: + case K_P5: + case K_P6: + case K_P7: + case K_P8: + case K_P9: + vga_keymap[map][i]=entry.kb_value; + vga_keymap[map][i]+= '0'; + break; + case K_PPLUS: + vga_keymap[map][i]=K(KT_ASCII,'+'); + break; + case K_PMINUS: + vga_keymap[map][i]=K(KT_ASCII,'-'); + break; + case K_PSTAR: + vga_keymap[map][i]=K(KT_ASCII,'*'); + break; + case K_PSLASH: + vga_keymap[map][i]=K(KT_ASCII,'/'); + break; + case K_PENTER: + vga_keymap[map][i]=K(KT_ASCII,'\r'); + break; + case K_PCOMMA: + vga_keymap[map][i]=K(KT_ASCII,','); + break; + case K_PDOT: + vga_keymap[map][i]=K(KT_ASCII,'.'); + break; + default: + break; + } + } + /* Do the normal key translation */ + if ( (KTYP(entry.kb_value) == KT_LATIN) || + (KTYP(entry.kb_value) == KT_ASCII) || + (KTYP(entry.kb_value) == KT_LETTER) ) { + vga_keymap[map][i] = entry.kb_value; + } + } + } + } +} + +int FB_InGraphicsMode(_THIS) +{ + return((keyboard_fd >= 0) && (saved_kbd_mode >= 0)); +} + +int FB_EnterGraphicsMode(_THIS) +{ + struct termios keyboard_termios; + + /* Set medium-raw keyboard mode */ + if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) { + + /* Switch to the correct virtual terminal */ + if ( current_vt > 0 ) { + struct vt_stat vtstate; + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + saved_vt = vtstate.v_active; + } + if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, current_vt); + } + } + + /* Set the terminal input mode */ + if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) { + SDL_SetError("Unable to get terminal attributes"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) { + SDL_SetError("Unable to get current keyboard mode"); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + keyboard_fd = -1; + return(-1); + } + keyboard_termios = saved_kbd_termios; + keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG); + keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + keyboard_termios.c_cc[VMIN] = 0; + keyboard_termios.c_cc[VTIME] = 0; + if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set terminal attributes"); + return(-1); + } + /* This will fail if we aren't root or this isn't our tty */ + if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in raw mode"); + return(-1); + } + if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) { + FB_CloseKeyboard(this); + SDL_SetError("Unable to set keyboard in graphics mode"); + return(-1); + } + /* Prevent switching the virtual terminal */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + } + return(keyboard_fd); +} + +void FB_LeaveGraphicsMode(_THIS) +{ + if ( FB_InGraphicsMode(this) ) { + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode); + tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios); + saved_kbd_mode = -1; + + /* Head back over to the original virtual terminal */ + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); + if ( saved_vt > 0 ) { + ioctl(keyboard_fd, VT_ACTIVATE, saved_vt); + } + } +} + +void FB_CloseKeyboard(_THIS) +{ + if ( keyboard_fd >= 0 ) { + FB_LeaveGraphicsMode(this); + if ( keyboard_fd > 0 ) { + close(keyboard_fd); + } + } + keyboard_fd = -1; +} + +int FB_OpenKeyboard(_THIS) +{ + /* Open only if not already opened */ + if ( keyboard_fd < 0 ) { + static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + int i, tty0_fd; + + /* Try to query for a free virtual terminal */ + tty0_fd = -1; + for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) { + tty0_fd = open(tty0[i], O_WRONLY, 0); + } + if ( tty0_fd < 0 ) { + tty0_fd = dup(0); /* Maybe stdin is a VT? */ + } + ioctl(tty0_fd, VT_OPENQRY, ¤t_vt); + close(tty0_fd); + if ( (geteuid() == 0) && (current_vt > 0) ) { + for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) { + char vtpath[12]; + + SDL_snprintf(vtpath, SDL_arraysize(vtpath), vcs[i], current_vt); + keyboard_fd = open(vtpath, O_RDWR, 0); +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "vtpath = %s, fd = %d\n", + vtpath, keyboard_fd); +#endif /* DEBUG_KEYBOARD */ + + /* This needs to be our controlling tty + so that the kernel ioctl() calls work + */ + if ( keyboard_fd >= 0 ) { + tty0_fd = open("/dev/tty", O_RDWR, 0); + if ( tty0_fd >= 0 ) { + ioctl(tty0_fd, TIOCNOTTY, 0); + close(tty0_fd); + } + } + } + } + if ( keyboard_fd < 0 ) { + /* Last resort, maybe our tty is a usable VT */ + struct vt_stat vtstate; + + keyboard_fd = open("/dev/tty", O_RDWR); + + if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) { + current_vt = vtstate.v_active; + } else { + current_vt = 0; + } + } +#ifdef DEBUG_KEYBOARD + fprintf(stderr, "Current VT: %d\n", current_vt); +#endif + saved_kbd_mode = -1; + + /* Make sure that our input is a console terminal */ + { int dummy; + if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) { + close(keyboard_fd); + keyboard_fd = -1; + SDL_SetError("Unable to open a console terminal"); + } + } + + /* Set up keymap */ + FB_vgainitkeymaps(keyboard_fd); + } + return(keyboard_fd); +} + +static enum { + MOUSE_NONE = -1, + MOUSE_MSC, /* Note: GPM uses the MSC protocol */ + MOUSE_PS2, + MOUSE_IMPS2, + MOUSE_MS, + MOUSE_BM, + MOUSE_ELO, + MOUSE_TSLIB, + NUM_MOUSE_DRVS +} mouse_drv = MOUSE_NONE; + +void FB_CloseMouse(_THIS) +{ +#if SDL_INPUT_TSLIB + if (ts_dev != NULL) { + ts_close(ts_dev); + ts_dev = NULL; + mouse_fd = -1; + } +#endif /* SDL_INPUT_TSLIB */ + if ( mouse_fd > 0 ) { + close(mouse_fd); + } + mouse_fd = -1; +} + +/* Returns processes listed in /proc with the desired name */ +static int find_pid(DIR *proc, const char *wanted_name) +{ + struct dirent *entry; + int pid; + + /* First scan proc for the gpm process */ + pid = 0; + while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) { + if ( isdigit(entry->d_name[0]) ) { + FILE *status; + char path[PATH_MAX]; + char name[PATH_MAX]; + + SDL_snprintf(path, SDL_arraysize(path), "/proc/%s/status", entry->d_name); + status=fopen(path, "r"); + if ( status ) { + int matches = 0; + name[0] = '\0'; + matches = fscanf(status, "Name: %s", name); + if ( (matches == 1) && (SDL_strcmp(name, wanted_name) == 0) ) { + pid = SDL_atoi(entry->d_name); + } + fclose(status); + } + } + } + return pid; +} + +/* Returns true if /dev/gpmdata is being written to by gpm */ +static int gpm_available(char *proto, size_t protolen) +{ + int available; + DIR *proc; + int pid; + int cmdline, len, arglen; + char path[PATH_MAX]; + char args[PATH_MAX], *arg; + + /* Don't bother looking if the fifo isn't there */ +#ifdef DEBUG_MOUSE + fprintf(stderr,"testing gpm\n"); +#endif + if ( access(GPM_NODE_FIFO, F_OK) < 0 ) { + return(0); + } + + available = 0; + proc = opendir("/proc"); + if ( proc ) { + char raw_proto[10] = { '\0' }; + char repeat_proto[10] = { '\0' }; + while ( !available && (pid=find_pid(proc, "gpm")) > 0 ) { + SDL_snprintf(path, SDL_arraysize(path), "/proc/%d/cmdline", pid); + cmdline = open(path, O_RDONLY, 0); + if ( cmdline >= 0 ) { + len = read(cmdline, args, sizeof(args)); + arg = args; + while ( len > 0 ) { + arglen = SDL_strlen(arg)+1; +#ifdef DEBUG_MOUSE + fprintf(stderr,"gpm arg %s len %d\n",arg,arglen); +#endif + if ( SDL_strcmp(arg, "-t") == 0) { + /* protocol string, keep it for later */ + char *t, *s; + t = arg + arglen; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(raw_proto, t, SDL_arraysize(raw_proto)); + if (s) *s = ' '; + } + if ( SDL_strncmp(arg, "-R", 2) == 0 ) { + char *t, *s; + available = 1; + t = arg + 2; + s = SDL_strchr(t, ' '); + if (s) *s = 0; + SDL_strlcpy(repeat_proto, t, SDL_arraysize(repeat_proto)); + if (s) *s = ' '; + } + len -= arglen; + arg += arglen; + } + close(cmdline); + } + } + closedir(proc); + + if ( available ) { + if ( SDL_strcmp(repeat_proto, "raw") == 0 ) { + SDL_strlcpy(proto, raw_proto, protolen); + } else if ( *repeat_proto ) { + SDL_strlcpy(proto, repeat_proto, protolen); + } else { + SDL_strlcpy(proto, "msc", protolen); + } + } + } + return available; +} + + +/* rcg06112001 Set up IMPS/2 mode, if possible. This gives + * us access to the mousewheel, etc. Returns zero if + * writes to device failed, but you still need to query the + * device to see which mode it's actually in. + */ +static int set_imps2_mode(int fd) +{ + /* If you wanted to control the mouse mode (and we do :) ) ... + Set IMPS/2 protocol: + {0xf3,200,0xf3,100,0xf3,80} + Reset mouse device: + {0xFF} + */ + Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80}; + /*Uint8 reset = 0xff;*/ + fd_set fdset; + struct timeval tv; + int retval = 0; + + if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) { + /* Don't reset it, that'll clear IMPS/2 mode on some mice + if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) { + retval = 1; + } + */ + } + + /* Get rid of any chatter from the above */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + return retval; +} + + +/* Returns true if the mouse uses the IMPS/2 protocol */ +static int detect_imps2(int fd) +{ + int imps2; + + imps2 = 0; + + if ( SDL_getenv("SDL_MOUSEDEV_IMPS2") ) { + imps2 = 1; + } + if ( ! imps2 ) { + Uint8 query_ps2 = 0xF2; + fd_set fdset; + struct timeval tv; + + /* Get rid of any mouse motion noise */ + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 0; + tv.tv_usec = 0; + while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) { + char temp[32]; + if (read(fd, temp, sizeof(temp)) <= 0) { + break; + } + } + + /* Query for the type of mouse protocol */ + if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) { + Uint8 ch = 0; + + /* Get the mouse protocol response */ + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = 1; + tv.tv_usec = 0; + if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) { + break; + } + } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) && + ((ch == 0xFA) || (ch == 0xAA)) ); + + /* Experimental values (Logitech wheelmouse) */ +#ifdef DEBUG_MOUSE +fprintf(stderr, "Last mouse mode: 0x%x\n", ch); +#endif + if ( (ch == 3) || (ch == 4) ) { + imps2 = 1; + } + } + } + return imps2; +} + +int FB_OpenMouse(_THIS) +{ + int i; + const char *mousedev; + const char *mousedrv; + + mousedrv = SDL_getenv("SDL_MOUSEDRV"); + mousedev = SDL_getenv("SDL_MOUSEDEV"); + mouse_fd = -1; + +#if SDL_INPUT_TSLIB + if ( mousedrv && (SDL_strcmp(mousedrv, "TSLIB") == 0) ) { + if (mousedev == NULL) mousedev = SDL_getenv("TSLIB_TSDEVICE"); + if (mousedev != NULL) { + ts_dev = ts_open(mousedev, 1); + if ((ts_dev != NULL) && (ts_config(ts_dev) >= 0)) { +#ifdef DEBUG_MOUSE + fprintf(stderr, "Using tslib touchscreen\n"); +#endif + mouse_drv = MOUSE_TSLIB; + mouse_fd = ts_fd(ts_dev); + return mouse_fd; + } + } + mouse_drv = MOUSE_NONE; + return mouse_fd; + } +#endif /* SDL_INPUT_TSLIB */ + + /* ELO TOUCHSCREEN SUPPORT */ + + if ( mousedrv && (SDL_strcmp(mousedrv, "ELO") == 0) ) { + mouse_fd = open(mousedev, O_RDWR); + if ( mouse_fd >= 0 ) { + if(eloInitController(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ELO touchscreen\n"); +#endif + mouse_drv = MOUSE_ELO; + } + + } + else if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + + return(mouse_fd); + } + + /* STD MICE */ + + if ( mousedev == NULL ) { + /* FIXME someday... allow multiple mice in this driver */ + static const char *ps2mice[] = { + "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL + }; + /* First try to use GPM in repeater mode */ + if ( mouse_fd < 0 ) { + char proto[10]; + if ( gpm_available(proto, SDL_arraysize(proto)) ) { + mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + if ( SDL_strcmp(proto, "msc") == 0 ) { + mouse_drv = MOUSE_MSC; + } else if ( SDL_strcmp(proto, "ps2") == 0 ) { + mouse_drv = MOUSE_PS2; + } else if ( SDL_strcmp(proto, "imps2") == 0 ) { + mouse_drv = MOUSE_IMPS2; + } else if ( SDL_strcmp(proto, "ms") == 0 || + SDL_strcmp(proto, "bare") == 0 ) { + mouse_drv = MOUSE_MS; + } else if ( SDL_strcmp(proto, "bm") == 0 ) { + mouse_drv = MOUSE_BM; + } else { + /* Unknown protocol... */ +#ifdef DEBUG_MOUSE + fprintf(stderr, "GPM mouse using unknown protocol = %s\n", proto); +#endif + close(mouse_fd); + mouse_fd = -1; + } + } +#ifdef DEBUG_MOUSE + if ( mouse_fd >= 0 ) { + fprintf(stderr, "Using GPM mouse, protocol = %s\n", proto); + } +#endif /* DEBUG_MOUSE */ + } + } + /* Now try to use a modern PS/2 mouse */ + for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) { + mouse_fd = open(ps2mice[i], O_RDWR, 0); + if (mouse_fd < 0) { + mouse_fd = open(ps2mice[i], O_RDONLY, 0); + } + if (mouse_fd >= 0) { + /* rcg06112001 Attempt to set IMPS/2 mode */ + set_imps2_mode(mouse_fd); + if (detect_imps2(mouse_fd)) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using IMPS2 mouse\n"); +#endif + mouse_drv = MOUSE_IMPS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using PS2 mouse\n"); +#endif + mouse_drv = MOUSE_PS2; + } + } + } + /* Next try to use a PPC ADB port mouse */ + if ( mouse_fd < 0 ) { + mouse_fd = open("/dev/adbmouse", O_RDONLY, 0); + if ( mouse_fd >= 0 ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using ADB mouse\n"); +#endif + mouse_drv = MOUSE_BM; + } + } + } + /* Default to a serial Microsoft mouse */ + if ( mouse_fd < 0 ) { + if ( mousedev == NULL ) { + mousedev = "/dev/mouse"; + } + mouse_fd = open(mousedev, O_RDONLY, 0); + if ( mouse_fd >= 0 ) { + struct termios mouse_termios; + + /* Set the sampling speed to 1200 baud */ + tcgetattr(mouse_fd, &mouse_termios); + mouse_termios.c_iflag = IGNBRK | IGNPAR; + mouse_termios.c_oflag = 0; + mouse_termios.c_lflag = 0; + mouse_termios.c_line = 0; + mouse_termios.c_cc[VTIME] = 0; + mouse_termios.c_cc[VMIN] = 1; + mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL; + mouse_termios.c_cflag |= CS8; + mouse_termios.c_cflag |= B1200; + tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios); + if ( mousedrv && (SDL_strcmp(mousedrv, "PS2") == 0) ) { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (user specified) PS2 mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_PS2; + } else { +#ifdef DEBUG_MOUSE +fprintf(stderr, "Using (default) MS mouse on %s\n", mousedev); +#endif + mouse_drv = MOUSE_MS; + } + } + } + if ( mouse_fd < 0 ) { + mouse_drv = MOUSE_NONE; + } + return(mouse_fd); +} + +static int posted = 0; + +void FB_vgamousecallback(int button, int relative, int dx, int dy) +{ + int button_1, button_3; + int button_state; + int state_changed; + int i; + Uint8 state; + + if ( dx || dy ) { + posted += SDL_PrivateMouseMotion(0, relative, dx, dy); + } + + /* Swap button 1 and 3 */ + button_1 = (button & 0x04) >> 2; + button_3 = (button & 0x01) << 2; + button &= ~0x05; + button |= (button_1|button_3); + + /* See what changed */ + button_state = SDL_GetMouseState(NULL, NULL); + state_changed = button_state ^ button; + for ( i=0; i<8; ++i ) { + if ( state_changed & (1<<i) ) { + if ( button & (1<<i) ) { + state = SDL_PRESSED; + } else { + state = SDL_RELEASED; + } + posted += SDL_PrivateMouseButton(state, i+1, 0, 0); + } + } +} + +/* Handle input from tslib */ +#if SDL_INPUT_TSLIB +static void handle_tslib(_THIS) +{ + struct ts_sample sample; + int button; + + while (ts_read(ts_dev, &sample, 1) > 0) { + button = (sample.pressure > 0) ? 1 : 0; + button <<= 2; /* must report it as button 3 */ + FB_vgamousecallback(button, 0, sample.x, sample.y); + } + return; +} +#endif /* SDL_INPUT_TSLIB */ + +/* For now, use MSC, PS/2, and MS protocols + Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.) + */ +static void handle_mouse(_THIS) +{ + static int start = 0; + static unsigned char mousebuf[BUFSIZ]; + static int relative = 1; + + int i, nread; + int button = 0; + int dx = 0, dy = 0; + int packetsize = 0; + int realx, realy; + + /* Figure out the mouse packet size */ + switch (mouse_drv) { + case MOUSE_NONE: + break; /* carry on to read from device and discard it. */ + case MOUSE_MSC: + packetsize = 5; + break; + case MOUSE_IMPS2: + packetsize = 4; + break; + case MOUSE_PS2: + case MOUSE_MS: + case MOUSE_BM: + packetsize = 3; + break; + case MOUSE_ELO: + /* try to read the next packet */ + if(eloReadPosition(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) { + button = (button & 0x01) << 2; + FB_vgamousecallback(button, 0, dx, dy); + } + return; /* nothing left to do */ + case MOUSE_TSLIB: +#if SDL_INPUT_TSLIB + handle_tslib(this); +#endif + return; /* nothing left to do */ + default: + /* Uh oh.. */ + packetsize = 0; + break; + } + + /* Special handling for the quite sensitive ELO controller */ + if (mouse_drv == MOUSE_ELO) { + + } + + /* Read as many packets as possible */ + nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start); + if ( nread < 0 ) { + return; + } + + if (mouse_drv == MOUSE_NONE) { + return; /* we're done; just draining the input queue. */ + } + + nread += start; +#ifdef DEBUG_MOUSE + fprintf(stderr, "Read %d bytes from mouse, start = %d\n", nread, start); +#endif + + for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) { + switch (mouse_drv) { + case MOUSE_NONE: /* shouldn't actually hit this. */ + break; /* just throw everything away. */ + case MOUSE_MSC: + /* MSC protocol has 0x80 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)(mousebuf[i+1]) + + (signed char)(mousebuf[i+3]); + dy = -((signed char)(mousebuf[i+2]) + + (signed char)(mousebuf[i+4])); + break; + case MOUSE_PS2: + /* PS/2 protocol has nothing in high byte */ + if ( (mousebuf[i] & 0xC0) != 0 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2; /*Left*/ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + break; + case MOUSE_IMPS2: + /* Get current mouse state */ + button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/ + (mousebuf[i] & 0x02) >> 1 | /*Right*/ + (mousebuf[i] & 0x01) << 2 | /*Left*/ + (mousebuf[i] & 0x40) >> 3 | /* 4 */ + (mousebuf[i] & 0x80) >> 3; /* 5 */ + dx = (mousebuf[i] & 0x10) ? + mousebuf[i+1] - 256 : mousebuf[i+1]; + dy = (mousebuf[i] & 0x20) ? + -(mousebuf[i+2] - 256) : -mousebuf[i+2]; + switch (mousebuf[i+3]&0x0F) { + case 0x0E: /* DX = +1 */ + case 0x02: /* DX = -1 */ + break; + case 0x0F: /* DY = +1 (map button 4) */ + FB_vgamousecallback(button | (1<<3), + 1, 0, 0); + break; + case 0x01: /* DY = -1 (map button 5) */ + FB_vgamousecallback(button | (1<<4), + 1, 0, 0); + break; + } + break; + case MOUSE_MS: + /* Microsoft protocol has 0x40 in high byte */ + if ( (mousebuf[i] & 0x40) != 0x40 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = ((mousebuf[i] & 0x20) >> 3) | + ((mousebuf[i] & 0x10) >> 4); + dx = (signed char)(((mousebuf[i] & 0x03) << 6) | + (mousebuf[i + 1] & 0x3F)); + dy = (signed char)(((mousebuf[i] & 0x0C) << 4) | + (mousebuf[i + 2] & 0x3F)); + break; + case MOUSE_BM: + /* BusMouse protocol has 0xF8 in high byte */ + if ( (mousebuf[i] & 0xF8) != 0x80 ) { + /* Go to next byte */ + i -= (packetsize-1); + continue; + } + /* Get current mouse state */ + button = (~mousebuf[i]) & 0x07; + dx = (signed char)mousebuf[i+1]; + dy = -(signed char)mousebuf[i+2]; + break; + default: + /* Uh oh.. */ + dx = 0; + dy = 0; + break; + } + FB_vgamousecallback(button, relative, dx, dy); + } + if ( i < nread ) { + SDL_memcpy(mousebuf, &mousebuf[i], (nread-i)); + start = (nread-i); + } else { + start = 0; + } + return; +} + +/* Handle switching to another VC, returns when our VC is back */ +static void switch_vt_prep(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + SDL_PrivateAppActive(0, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); + + /* Save the contents of the screen, and go to text mode */ + wait_idle(this); + screen_arealen = ((screen->h + (2*this->offset_y)) * screen->pitch); + screen_contents = (Uint8 *)SDL_malloc(screen_arealen); + if ( screen_contents ) { + SDL_memcpy(screen_contents, screen->pixels, screen_arealen); + } + FB_SavePaletteTo(this, 256, screen_palette); + ioctl(console_fd, FBIOGET_VSCREENINFO, &screen_vinfo); + ioctl(keyboard_fd, KDSETMODE, KD_TEXT); + ioctl(keyboard_fd, VT_UNLOCKSWITCH, 1); +} +static void switch_vt_done(_THIS) +{ + SDL_Surface *screen = SDL_VideoSurface; + + /* Restore graphics mode and the contents of the screen */ + ioctl(keyboard_fd, VT_LOCKSWITCH, 1); + ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &screen_vinfo); + FB_RestorePaletteFrom(this, 256, screen_palette); + if ( screen_contents ) { + SDL_memcpy(screen->pixels, screen_contents, screen_arealen); + SDL_free(screen_contents); + screen_contents = NULL; + } + + /* Get updates to the shadow surface while switched away */ + if ( SDL_ShadowSurface ) { + SDL_UpdateRect(SDL_ShadowSurface, 0, 0, 0, 0); + } + + SDL_PrivateAppActive(1, (SDL_APPACTIVE|SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS)); +} +static void switch_vt(_THIS, unsigned short which) +{ + struct vt_stat vtstate; + + /* Figure out whether or not we're switching to a new console */ + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) || + (which == vtstate.v_active) ) { + return; + } + + /* New console, switch to it */ + SDL_mutexP(hw_lock); + switch_vt_prep(this); + if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) { + ioctl(keyboard_fd, VT_WAITACTIVE, which); + switched_away = 1; + } else { + switch_vt_done(this); + } + SDL_mutexV(hw_lock); +} + +static void handle_keyboard(_THIS) +{ + unsigned char keybuf[BUFSIZ]; + int i, nread; + int pressed; + int scancode; + SDL_keysym keysym; + + nread = read(keyboard_fd, keybuf, BUFSIZ); + for ( i=0; i<nread; ++i ) { + scancode = keybuf[i] & 0x7F; + if ( keybuf[i] & 0x80 ) { + pressed = SDL_RELEASED; + } else { + pressed = SDL_PRESSED; + } + TranslateKey(scancode, &keysym); + /* Handle Ctrl-Alt-FN for vt switch */ + switch (keysym.sym) { + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + case SDLK_F9: + case SDLK_F10: + case SDLK_F11: + case SDLK_F12: + if ( (SDL_GetModState() & KMOD_CTRL) && + (SDL_GetModState() & KMOD_ALT) ) { + if ( pressed ) { + switch_vt(this, (keysym.sym-SDLK_F1)+1); + } + break; + } + /* Fall through to normal processing */ + default: + posted += SDL_PrivateKeyboard(pressed, &keysym); + break; + } + } +} + +void FB_PumpEvents(_THIS) +{ + fd_set fdset; + int max_fd; + static struct timeval zero; + + do { + if ( switched_away ) { + struct vt_stat vtstate; + + SDL_mutexP(hw_lock); + if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0) && + vtstate.v_active == current_vt ) { + switched_away = 0; + switch_vt_done(this); + } + SDL_mutexV(hw_lock); + } + + posted = 0; + + FD_ZERO(&fdset); + max_fd = 0; + if ( keyboard_fd >= 0 ) { + FD_SET(keyboard_fd, &fdset); + if ( max_fd < keyboard_fd ) { + max_fd = keyboard_fd; + } + } + if ( mouse_fd >= 0 ) { + FD_SET(mouse_fd, &fdset); + if ( max_fd < mouse_fd ) { + max_fd = mouse_fd; + } + } + if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) { + if ( keyboard_fd >= 0 ) { + if ( FD_ISSET(keyboard_fd, &fdset) ) { + handle_keyboard(this); + } + } + if ( mouse_fd >= 0 ) { + if ( FD_ISSET(mouse_fd, &fdset) ) { + handle_mouse(this); + } + } + } + } while ( posted ); +} + +void FB_InitOSKeymap(_THIS) +{ + int i; + + /* Initialize the Linux key translation table */ + + /* First get the ascii keys and others not well handled */ + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(i) { + /* These aren't handled by the x86 kernel keymapping (?) */ + case SCANCODE_PRINTSCREEN: + keymap[i] = SDLK_PRINT; + break; + case SCANCODE_BREAK: + keymap[i] = SDLK_BREAK; + break; + case SCANCODE_BREAK_ALTERNATIVE: + keymap[i] = SDLK_PAUSE; + break; + case SCANCODE_LEFTSHIFT: + keymap[i] = SDLK_LSHIFT; + break; + case SCANCODE_RIGHTSHIFT: + keymap[i] = SDLK_RSHIFT; + break; + case SCANCODE_LEFTCONTROL: + keymap[i] = SDLK_LCTRL; + break; + case SCANCODE_RIGHTCONTROL: + keymap[i] = SDLK_RCTRL; + break; + case SCANCODE_RIGHTWIN: + keymap[i] = SDLK_RSUPER; + break; + case SCANCODE_LEFTWIN: + keymap[i] = SDLK_LSUPER; + break; + case SCANCODE_LEFTALT: + keymap[i] = SDLK_LALT; + break; + case SCANCODE_RIGHTALT: + keymap[i] = SDLK_RALT; + break; + case 127: + keymap[i] = SDLK_MENU; + break; + /* this should take care of all standard ascii keys */ + default: + keymap[i] = KVAL(vga_keymap[0][i]); + break; + } + } + for (i=0; i<SDL_arraysize(keymap); ++i) { + switch(keymap_temp[i]) { + case K_F1: keymap[i] = SDLK_F1; break; + case K_F2: keymap[i] = SDLK_F2; break; + case K_F3: keymap[i] = SDLK_F3; break; + case K_F4: keymap[i] = SDLK_F4; break; + case K_F5: keymap[i] = SDLK_F5; break; + case K_F6: keymap[i] = SDLK_F6; break; + case K_F7: keymap[i] = SDLK_F7; break; + case K_F8: keymap[i] = SDLK_F8; break; + case K_F9: keymap[i] = SDLK_F9; break; + case K_F10: keymap[i] = SDLK_F10; break; + case K_F11: keymap[i] = SDLK_F11; break; + case K_F12: keymap[i] = SDLK_F12; break; + + case K_DOWN: keymap[i] = SDLK_DOWN; break; + case K_LEFT: keymap[i] = SDLK_LEFT; break; + case K_RIGHT: keymap[i] = SDLK_RIGHT; break; + case K_UP: keymap[i] = SDLK_UP; break; + + case K_P0: keymap[i] = SDLK_KP0; break; + case K_P1: keymap[i] = SDLK_KP1; break; + case K_P2: keymap[i] = SDLK_KP2; break; + case K_P3: keymap[i] = SDLK_KP3; break; + case K_P4: keymap[i] = SDLK_KP4; break; + case K_P5: keymap[i] = SDLK_KP5; break; + case K_P6: keymap[i] = SDLK_KP6; break; + case K_P7: keymap[i] = SDLK_KP7; break; + case K_P8: keymap[i] = SDLK_KP8; break; + case K_P9: keymap[i] = SDLK_KP9; break; + case K_PPLUS: keymap[i] = SDLK_KP_PLUS; break; + case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break; + case K_PSTAR: keymap[i] = SDLK_KP_MULTIPLY; break; + case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break; + case K_PENTER: keymap[i] = SDLK_KP_ENTER; break; + case K_PDOT: keymap[i] = SDLK_KP_PERIOD; break; + + case K_SHIFT: if ( keymap[i] != SDLK_RSHIFT ) + keymap[i] = SDLK_LSHIFT; + break; + case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break; + case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break; + case K_CTRL: if ( keymap[i] != SDLK_RCTRL ) + keymap[i] = SDLK_LCTRL; + break; + case K_CTRLL: keymap[i] = SDLK_LCTRL; break; + case K_CTRLR: keymap[i] = SDLK_RCTRL; break; + case K_ALT: keymap[i] = SDLK_LALT; break; + case K_ALTGR: keymap[i] = SDLK_RALT; break; + + case K_INSERT: keymap[i] = SDLK_INSERT; break; + case K_REMOVE: keymap[i] = SDLK_DELETE; break; + case K_PGUP: keymap[i] = SDLK_PAGEUP; break; + case K_PGDN: keymap[i] = SDLK_PAGEDOWN; break; + case K_FIND: keymap[i] = SDLK_HOME; break; + case K_SELECT: keymap[i] = SDLK_END; break; + + case K_NUM: keymap[i] = SDLK_NUMLOCK; break; + case K_CAPS: keymap[i] = SDLK_CAPSLOCK; break; + + case K_F13: keymap[i] = SDLK_PRINT; break; + case K_HOLD: keymap[i] = SDLK_SCROLLOCK; break; + case K_PAUSE: keymap[i] = SDLK_PAUSE; break; + + case 127: keymap[i] = SDLK_BACKSPACE; break; + + default: break; + } + } +} + +static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) +{ + /* Set the keysym information */ + keysym->scancode = scancode; + keysym->sym = keymap[scancode]; + keysym->mod = KMOD_NONE; + + /* If UNICODE is on, get the UNICODE value for the key */ + keysym->unicode = 0; + if ( SDL_TranslateUNICODE ) { + int map; + SDLMod modstate; + + modstate = SDL_GetModState(); + map = 0; + if ( modstate & KMOD_SHIFT ) { + map |= (1<<KG_SHIFT); + } + if ( modstate & KMOD_CTRL ) { + map |= (1<<KG_CTRL); + } + if ( modstate & KMOD_LALT ) { + map |= (1<<KG_ALT); + } + if ( modstate & KMOD_RALT ) { + map |= (1<<KG_ALTGR); + } + if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { + if ( modstate & KMOD_CAPS ) { + map ^= (1<<KG_SHIFT); + } + } + if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { + if ( modstate & KMOD_NUM ) { + keysym->unicode=KVAL(vga_keymap[map][scancode]); + } + } else { + keysym->unicode = KVAL(vga_keymap[map][scancode]); + } + } + return(keysym); +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h new file mode 100644 index 0000000..fe8b09c --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbevents_c.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Variables and functions exported by SDL_sysevents.c to other parts + of the native video subsystem (SDL_sysvideo.c) +*/ +extern int FB_OpenKeyboard(_THIS); +extern void FB_CloseKeyboard(_THIS); +extern int FB_OpenMouse(_THIS); +extern void FB_CloseMouse(_THIS); +extern int FB_EnterGraphicsMode(_THIS); +extern int FB_InGraphicsMode(_THIS); +extern void FB_LeaveGraphicsMode(_THIS); + +extern void FB_InitOSKeymap(_THIS); +extern void FB_PumpEvents(_THIS); diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h new file mode 100644 index 0000000..2b01b6b --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbkeys.h @@ -0,0 +1,139 @@ + +/* Scancodes for the Linux framebuffer console + - Taken with thanks from SVGAlib 1.4.0 +*/ + +#define SCANCODE_ESCAPE 1 + +#define SCANCODE_1 2 +#define SCANCODE_2 3 +#define SCANCODE_3 4 +#define SCANCODE_4 5 +#define SCANCODE_5 6 +#define SCANCODE_6 7 +#define SCANCODE_7 8 +#define SCANCODE_8 9 +#define SCANCODE_9 10 +#define SCANCODE_0 11 + +#define SCANCODE_MINUS 12 +#define SCANCODE_EQUAL 13 + +#define SCANCODE_BACKSPACE 14 +#define SCANCODE_TAB 15 + +#define SCANCODE_Q 16 +#define SCANCODE_W 17 +#define SCANCODE_E 18 +#define SCANCODE_R 19 +#define SCANCODE_T 20 +#define SCANCODE_Y 21 +#define SCANCODE_U 22 +#define SCANCODE_I 23 +#define SCANCODE_O 24 +#define SCANCODE_P 25 +#define SCANCODE_BRACKET_LEFT 26 +#define SCANCODE_BRACKET_RIGHT 27 + +#define SCANCODE_ENTER 28 + +#define SCANCODE_LEFTCONTROL 29 + +#define SCANCODE_A 30 +#define SCANCODE_S 31 +#define SCANCODE_D 32 +#define SCANCODE_F 33 +#define SCANCODE_G 34 +#define SCANCODE_H 35 +#define SCANCODE_J 36 +#define SCANCODE_K 37 +#define SCANCODE_L 38 +#define SCANCODE_SEMICOLON 39 +#define SCANCODE_APOSTROPHE 40 +#define SCANCODE_GRAVE 41 + +#define SCANCODE_LEFTSHIFT 42 +#define SCANCODE_BACKSLASH 43 + +#define SCANCODE_Z 44 +#define SCANCODE_X 45 +#define SCANCODE_C 46 +#define SCANCODE_V 47 +#define SCANCODE_B 48 +#define SCANCODE_N 49 +#define SCANCODE_M 50 +#define SCANCODE_COMMA 51 +#define SCANCODE_PERIOD 52 +#define SCANCODE_SLASH 53 + +#define SCANCODE_RIGHTSHIFT 54 +#define SCANCODE_KEYPADMULTIPLY 55 + +#define SCANCODE_LEFTALT 56 +#define SCANCODE_SPACE 57 +#define SCANCODE_CAPSLOCK 58 + +#define SCANCODE_F1 59 +#define SCANCODE_F2 60 +#define SCANCODE_F3 61 +#define SCANCODE_F4 62 +#define SCANCODE_F5 63 +#define SCANCODE_F6 64 +#define SCANCODE_F7 65 +#define SCANCODE_F8 66 +#define SCANCODE_F9 67 +#define SCANCODE_F10 68 + +#define SCANCODE_NUMLOCK 69 +#define SCANCODE_SCROLLLOCK 70 + +#define SCANCODE_KEYPAD7 71 +#define SCANCODE_CURSORUPLEFT 71 +#define SCANCODE_KEYPAD8 72 +#define SCANCODE_CURSORUP 72 +#define SCANCODE_KEYPAD9 73 +#define SCANCODE_CURSORUPRIGHT 73 +#define SCANCODE_KEYPADMINUS 74 +#define SCANCODE_KEYPAD4 75 +#define SCANCODE_CURSORLEFT 75 +#define SCANCODE_KEYPAD5 76 +#define SCANCODE_KEYPAD6 77 +#define SCANCODE_CURSORRIGHT 77 +#define SCANCODE_KEYPADPLUS 78 +#define SCANCODE_KEYPAD1 79 +#define SCANCODE_CURSORDOWNLEFT 79 +#define SCANCODE_KEYPAD2 80 +#define SCANCODE_CURSORDOWN 80 +#define SCANCODE_KEYPAD3 81 +#define SCANCODE_CURSORDOWNRIGHT 81 +#define SCANCODE_KEYPAD0 82 +#define SCANCODE_KEYPADPERIOD 83 + +#define SCANCODE_LESS 86 + +#define SCANCODE_F11 87 +#define SCANCODE_F12 88 + +#define SCANCODE_KEYPADENTER 96 +#define SCANCODE_RIGHTCONTROL 97 +#define SCANCODE_CONTROL 97 +#define SCANCODE_KEYPADDIVIDE 98 +#define SCANCODE_PRINTSCREEN 99 +#define SCANCODE_RIGHTALT 100 +#define SCANCODE_BREAK 101 /* Beware: is 119 */ +#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */ + +#define SCANCODE_HOME 102 +#define SCANCODE_CURSORBLOCKUP 103 /* Cursor key block */ +#define SCANCODE_PAGEUP 104 +#define SCANCODE_CURSORBLOCKLEFT 105 /* Cursor key block */ +#define SCANCODE_CURSORBLOCKRIGHT 106 /* Cursor key block */ +#define SCANCODE_END 107 +#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */ +#define SCANCODE_PAGEDOWN 109 +#define SCANCODE_INSERT 110 +#define SCANCODE_REMOVE 111 + +#define SCANCODE_RIGHTWIN 126 +#define SCANCODE_LEFTWIN 125 + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c new file mode 100644 index 0000000..04b90b0 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.c @@ -0,0 +1,280 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbmatrox.h" +#include "matrox_mmio.h" + + +/* Wait for vertical retrace - taken from the XFree86 Matrox driver */ +static void WaitVBL(_THIS) +{ + int count; + + /* find start of retrace */ + mga_waitidle(); + while ( (mga_in8(0x1FDA) & 0x08) ) + ; + while ( !(mga_in8(0x1FDA) & 0x08) ) + ; + /* wait until we're past the start */ + count = mga_in32(0x1E20) + 2; + while ( mga_in32(0x1E20) < count ) + ; +} +static void WaitIdle(_THIS) +{ + mga_waitidle(); +} + +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +#if 0 +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + Uint32 fxbndry; + Uint32 ydstlen; + Uint32 fillop; + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + switch (dst->format->BytesPerPixel) { + case 1: + color |= (color<<8); + case 2: + color |= (color<<16); + break; + } + + /* Set up the X/Y base coordinates */ + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + /* Set up the X boundaries */ + fxbndry = (dstX | ((dstX+rect->w) << 16)); + + /* Set up the Y boundaries */ + ydstlen = (rect->h | (dstY << 16)); + + /* Set up for color fill operation */ + fillop = MGADWG_TRAP | MGADWG_SOLID | + MGADWG_ARZERO | MGADWG_SGNZERO | MGADWG_SHIFTZERO; + + /* Execute the operations! */ + mga_wait(5); + mga_out32(MGAREG_DWGCTL, fillop | MGADWG_REPLACE); + mga_out32(MGAREG_FCOL, color); + mga_out32(MGAREG_FXBNDRY, fxbndry); + mga_out32(MGAREG_YDSTLEN + MGAREG_EXEC, ydstlen); + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int pitch, w, h; + int srcX, srcY; + int dstX, dstY; + Uint32 sign; + Uint32 start, stop; + int skip; + Uint32 blitop; + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + w = dstrect->w; + h = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + pitch = dst->pitch/dst->format->BytesPerPixel; + + /* Set up the blit direction (sign) flags */ + sign = 0; + if ( srcX < dstX ) { + sign |= 1; + } + if ( srcY < dstY ) { + sign |= 4; + srcY += (h - 1); + dstY += (h - 1); + } + + /* Set up the blit source row start, end, and skip (in pixels) */ + stop = start = (srcY * pitch) + srcX; + if ( srcX < dstX ) { + start += (w - 1); + } else { + stop += (w - 1); + } + if ( srcY < dstY ) { + skip = -pitch; + } else { + skip = pitch; + } + + /* Set up the blit operation */ + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + Uint32 colorkey; + + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16) | + MGADWG_TRANSC; + + colorkey = src->format->colorkey; + switch (dst->format->BytesPerPixel) { + case 1: + colorkey |= (colorkey<<8); + case 2: + colorkey |= (colorkey<<16); + break; + } + mga_wait(2); + mga_out32(MGAREG_FCOL, colorkey); + mga_out32(MGAREG_BCOL, 0xFFFFFFFF); + } else { + blitop = MGADWG_BFCOL | MGADWG_BITBLT | + MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16); + } + mga_wait(7); + mga_out32(MGAREG_SGN, sign); + mga_out32(MGAREG_AR3, start); + mga_out32(MGAREG_AR0, stop); + mga_out32(MGAREG_AR5, skip); + mga_out32(MGAREG_FXBNDRY, (dstX | ((dstX + w-1) << 16))); + mga_out32(MGAREG_YDSTLEN, (dstY << 16) | h); + mga_out32(MGAREG_DWGCTL + MGAREG_EXEC, blitop); + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_MatroxAccel(_THIS, __u32 card) +{ + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + wait_idle = WaitIdle; + + /* The Matrox has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Matrox has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; + /* The Millenium I appears to do the colorkey test a word + at a time, and the transparency is intverted. (?) + */ + if ( card != FB_ACCEL_MATROX_MGA2064W ) { + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; + } + +#if 0 /* Not yet implemented? */ + /* The Matrox G200/G400 has an accelerated alpha blit */ + if ( (card == FB_ACCEL_MATROX_MGAG200) + || (card == FB_ACCEL_MATROX_MGAG400) + ) { + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; + } +#endif +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h new file mode 100644 index 0000000..f7d41b0 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmatrox.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Matrox hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +/* Set up the driver for Matrox acceleration */ +extern void FB_MatroxAccel(_THIS, __u32 card); diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c new file mode 100644 index 0000000..d65f27e --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse.c @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_mouse.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" + + +/* The implementation dependent data for the window manager cursor */ +struct WMcursor { + int unused; +}; diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h new file mode 100644 index 0000000..fbb031d --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbmouse_c.h @@ -0,0 +1,26 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_fbvideo.h" + +/* Functions to be exported */ diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c new file mode 100644 index 0000000..eb4b71f --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.c @@ -0,0 +1,222 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_video.h" +#include "../SDL_blit.h" +#include "SDL_fbriva.h" +#include "riva_mmio.h" +#include "riva_regs.h" + + +static int FifoEmptyCount = 0; +static int FifoFreeCount = 0; + +/* Wait for vertical retrace */ +static void WaitVBL(_THIS) +{ + volatile Uint8 *port = (Uint8 *)(mapped_io + PCIO_OFFSET + 0x3DA); + + while ( (*port & 0x08) ) + ; + while ( !(*port & 0x08) ) + ; +} +static void NV3WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x000006B0) & 0x01) ) + ; +} +static void NV4WaitIdle(_THIS) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + while ( (Rop->FifoFree < FifoEmptyCount) || + (*(mapped_io + PGRAPH_OFFSET + 0x00000700) & 0x01) ) + ; +} + +#if 0 /* Not yet implemented? */ +/* Sets video mem colorkey and accelerated blit function */ +static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) +{ + return(0); +} + +/* Sets per surface hardware alpha value */ +static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value) +{ + return(0); +} +#endif /* Not yet implemented */ + +static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) +{ + int dstX, dstY; + int dstW, dstH; + RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET); + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Set up the X/Y base coordinates */ + dstW = rect->w; + dstH = rect->h; + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current rectangle */ + dstX += rect->x; + dstY += rect->y; + + RIVA_FIFO_FREE(Bitmap, 1); + Bitmap->Color1A = color; + + RIVA_FIFO_FREE(Bitmap, 2); + Bitmap->UnclippedRectangle[0].TopLeft = (dstX << 16) | dstY; + Bitmap->UnclippedRectangle[0].WidthHeight = (dstW << 16) | dstH; + + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + SDL_VideoDevice *this = current_video; + int srcX, srcY; + int dstX, dstY; + int dstW, dstH; + RivaScreenBlt *Blt = (RivaScreenBlt *)(mapped_io + BLT_OFFSET); + + /* FIXME: For now, only blit to display surface */ + if ( dst->pitch != SDL_VideoSurface->pitch ) { + return(src->map->sw_blit(src, srcrect, dst, dstrect)); + } + + /* Don't blit to the display surface when switched away */ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( dst == this->screen ) { + SDL_mutexP(hw_lock); + } + + /* Calculate source and destination base coordinates (in pixels) */ + dstW = dstrect->w; + dstH = dstrect->h; + FB_dst_to_xy(this, src, &srcX, &srcY); + FB_dst_to_xy(this, dst, &dstX, &dstY); + + /* Adjust for the current blit rectangles */ + srcX += srcrect->x; + srcY += srcrect->y; + dstX += dstrect->x; + dstY += dstrect->y; + + RIVA_FIFO_FREE(Blt, 3); + Blt->TopLeftSrc = (srcY << 16) | srcX; + Blt->TopLeftDst = (dstY << 16) | dstX; + Blt->WidthHeight = (dstH << 16) | dstW; + + FB_AddBusySurface(src); + FB_AddBusySurface(dst); + + if ( dst == this->screen ) { + SDL_mutexV(hw_lock); + } + return(0); +} + +static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + int accelerated; + + /* Set initial acceleration on */ + src->flags |= SDL_HWACCEL; + + /* Set the surface attributes */ + if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + if ( ! this->info.blit_hw_A ) { + src->flags &= ~SDL_HWACCEL; + } + } + if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) { + if ( ! this->info.blit_hw_CC ) { + src->flags &= ~SDL_HWACCEL; + } + } + + /* Check to see if final surface blit is accelerated */ + accelerated = !!(src->flags & SDL_HWACCEL); + if ( accelerated ) { + src->map->hw_blit = HWAccelBlit; + } + return(accelerated); +} + +void FB_RivaAccel(_THIS, __u32 card) +{ + RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET); + + /* We have hardware accelerated surface functions */ + this->CheckHWBlit = CheckHWBlit; + wait_vbl = WaitVBL; + switch (card) { + case FB_ACCEL_NV3: + wait_idle = NV3WaitIdle; + break; + case FB_ACCEL_NV4: + wait_idle = NV4WaitIdle; + break; + default: + /* Hmm... FIXME */ + break; + } + FifoEmptyCount = Rop->FifoFree; + + /* The Riva has an accelerated color fill */ + this->info.blit_fill = 1; + this->FillHWRect = FillHWRect; + + /* The Riva has accelerated normal and colorkey blits. */ + this->info.blit_hw = 1; +#if 0 /* Not yet implemented? */ + this->info.blit_hw_CC = 1; + this->SetHWColorKey = SetHWColorKey; +#endif + +#if 0 /* Not yet implemented? */ + /* The Riva has an accelerated alpha blit */ + this->info.blit_hw_A = 1; + this->SetHWAlpha = SetHWAlpha; +#endif +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h new file mode 100644 index 0000000..c78682e --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbriva.h @@ -0,0 +1,36 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Riva hardware acceleration for the SDL framebuffer console driver */ + +#include "SDL_fbvideo.h" + +#ifndef FB_ACCEL_NV3 +#define FB_ACCEL_NV3 27 +#endif +#ifndef FB_ACCEL_NV4 +#define FB_ACCEL_NV4 28 +#endif + +/* Set up the driver for Riva acceleration */ +extern void FB_RivaAccel(_THIS, __u32 card); diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c new file mode 100644 index 0000000..5e58809 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.c @@ -0,0 +1,1982 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* Framebuffer console based SDL video driver implementation. +*/ + +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#ifndef HAVE_GETPAGESIZE +#include <asm/page.h> /* For definition of PAGE_SIZE */ +#endif + +#include <linux/vt.h> + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_fbvideo.h" +#include "SDL_fbmouse_c.h" +#include "SDL_fbevents_c.h" +#include "SDL_fb3dfx.h" +#include "SDL_fbmatrox.h" +#include "SDL_fbriva.h" + +/*#define FBCON_DEBUG*/ + +#if defined(i386) && defined(FB_TYPE_VGA_PLANES) +#define VGA16_FBCON_SUPPORT +#include <sys/io.h> /* For ioperm() */ +#ifndef FB_AUX_VGA_PLANES_VGA4 +#define FB_AUX_VGA_PLANES_VGA4 0 +#endif +/* +static inline void outb (unsigned char value, unsigned short port) +{ + __asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port)); +} +*/ +#endif /* FB_TYPE_VGA_PLANES */ + +/* A list of video resolutions that we query for (sorted largest to smallest) */ +static const SDL_Rect checkres[] = { + { 0, 0, 1600, 1200 }, /* 16 bpp: 0x11E, or 286 */ + { 0, 0, 1408, 1056 }, /* 16 bpp: 0x19A, or 410 */ + { 0, 0, 1280, 1024 }, /* 16 bpp: 0x11A, or 282 */ + { 0, 0, 1152, 864 }, /* 16 bpp: 0x192, or 402 */ + { 0, 0, 1024, 768 }, /* 16 bpp: 0x117, or 279 */ + { 0, 0, 960, 720 }, /* 16 bpp: 0x18A, or 394 */ + { 0, 0, 800, 600 }, /* 16 bpp: 0x114, or 276 */ + { 0, 0, 768, 576 }, /* 16 bpp: 0x182, or 386 */ + { 0, 0, 720, 576 }, /* PAL */ + { 0, 0, 720, 480 }, /* NTSC */ + { 0, 0, 640, 480 }, /* 16 bpp: 0x111, or 273 */ + { 0, 0, 640, 400 }, /* 8 bpp: 0x100, or 256 */ + { 0, 0, 512, 384 }, + { 0, 0, 320, 240 }, + { 0, 0, 320, 200 } +}; +static const struct { + int xres; + int yres; + int pixclock; + int left; + int right; + int upper; + int lower; + int hslen; + int vslen; + int sync; + int vmode; +} vesa_timings[] = { +#ifdef USE_VESA_TIMINGS /* Only tested on Matrox Millenium I */ + { 640, 400, 39771, 48, 16, 39, 8, 96, 2, 2, 0 }, /* 70 Hz */ + { 640, 480, 39683, 48, 16, 33, 10, 96, 2, 0, 0 }, /* 60 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 24038, 144, 24, 28, 8, 112, 6, 0, 0 }, /* 60 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 15386, 160, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#else + /* You can generate these timings from your XF86Config file using + the 'modeline2fb' perl script included with the fbset package. + These timings were generated for Matrox Millenium I, 15" monitor. + */ + { 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, 2 }, /* 70 Hz */ + { 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, 2 }, /* 72 Hz */ + { 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, 0 }, /* 78 Hz */ + { 640, 400, 31746, 96, 32, 41, 1, 64, 3, 2, 0 }, /* 85 Hz */ + { 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0 }, /* 75 Hz */ + { 768, 576, 26101, 144, 16, 28, 6, 112, 4, 0, 0 }, /* 60 Hz */ + { 800, 600, 20000, 64, 56, 23, 37, 120, 6, 3, 0 }, /* 72 Hz */ + { 960, 720, 17686, 144, 24, 28, 8, 112, 4, 0, 0 }, /* 60 Hz */ + { 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, 0 }, /* 70 Hz */ + { 1152, 864, 12286, 192, 32, 30, 4, 128, 4, 0, 0 }, /* 60 Hz */ + { 1280, 1024, 9369, 224, 32, 32, 4, 136, 4, 0, 0 }, /* 60 Hz */ + { 1408, 1056, 8214, 256, 40, 32, 5, 144, 5, 0, 0 }, /* 60 Hz */ + { 1600, 1200,/*?*/0, 272, 48, 32, 5, 152, 5, 0, 0 }, /* 60 Hz */ +#endif +}; +enum { + FBCON_ROTATE_NONE = 0, + FBCON_ROTATE_CCW = 90, + FBCON_ROTATE_UD = 180, + FBCON_ROTATE_CW = 270 +}; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* Initialization/Query functions */ +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat); +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); +#endif +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void FB_VideoQuit(_THIS); + +/* Hardware surface functions */ +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size); +static void FB_FreeHWSurfaces(_THIS); +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface); +static int FB_LockHWSurface(_THIS, SDL_Surface *surface); +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface); +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface); +static void FB_WaitVBL(_THIS); +static void FB_WaitIdle(_THIS); +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface); + +/* Internal palette functions */ +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo); +static void FB_RestorePalette(_THIS); + +/* Shadow buffer functions */ +static FB_bitBlit FB_blit16; +static FB_bitBlit FB_blit16blocked; + +static int SDL_getpagesize(void) +{ +#ifdef HAVE_GETPAGESIZE + return getpagesize(); +#elif defined(PAGE_SIZE) + return PAGE_SIZE; +#else +#error Can not determine system page size. + return 4096; /* this is what it USED to be in Linux... */ +#endif +} + + +/* Small wrapper for mmap() so we can play nicely with no-mmu hosts + * (non-mmu hosts disallow the MAP_SHARED flag) */ + +static void *do_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + void *ret; + ret = mmap(start, length, prot, flags, fd, offset); + if ( ret == (char *)-1 && (flags & MAP_SHARED) ) { + ret = mmap(start, length, prot, + (flags & ~MAP_SHARED) | MAP_PRIVATE, fd, offset); + } + return ret; +} + +/* FB driver bootstrap functions */ + +static int FB_Available(void) +{ + int console = -1; + /* Added check for /fb/0 (devfs) */ + /* but - use environment variable first... if it fails, still check defaults */ + int idx = 0; + const char *SDL_fbdevs[4] = { NULL, "/dev/fb0", "/dev/fb/0", NULL }; + + SDL_fbdevs[0] = SDL_getenv("SDL_FBDEV"); + if( !SDL_fbdevs[0] ) + idx++; + for( ; SDL_fbdevs[idx]; idx++ ) + { + console = open(SDL_fbdevs[idx], O_RDWR, 0); + if ( console >= 0 ) { + close(console); + break; + } + } + return(console >= 0); +} + +static void FB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *FB_CreateDevice(int devindex) +{ + SDL_VideoDevice *this; + + /* Initialize all variables that we clean on shutdown */ + this = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if ( this ) { + SDL_memset(this, 0, (sizeof *this)); + this->hidden = (struct SDL_PrivateVideoData *) + SDL_malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + SDL_free(this); + } + return(0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + wait_vbl = FB_WaitVBL; + wait_idle = FB_WaitIdle; + mouse_fd = -1; + keyboard_fd = -1; + + /* Set the function pointers */ + this->VideoInit = FB_VideoInit; + this->ListModes = FB_ListModes; + this->SetVideoMode = FB_SetVideoMode; + this->SetColors = FB_SetColors; + this->UpdateRects = NULL; + this->VideoQuit = FB_VideoQuit; + this->AllocHWSurface = FB_AllocHWSurface; + this->CheckHWBlit = NULL; + this->FillHWRect = NULL; + this->SetHWColorKey = NULL; + this->SetHWAlpha = NULL; + this->LockHWSurface = FB_LockHWSurface; + this->UnlockHWSurface = FB_UnlockHWSurface; + this->FlipHWSurface = FB_FlipHWSurface; + this->FreeHWSurface = FB_FreeHWSurface; + this->SetCaption = NULL; + this->SetIcon = NULL; + this->IconifyWindow = NULL; + this->GrabInput = NULL; + this->GetWMInfo = NULL; + this->InitOSKeymap = FB_InitOSKeymap; + this->PumpEvents = FB_PumpEvents; + + this->free = FB_DeleteDevice; + + return this; +} + +VideoBootStrap FBCON_bootstrap = { + "fbcon", "Linux Framebuffer Console", + FB_Available, FB_CreateDevice +}; + +#define FB_MODES_DB "/etc/fb.modes" + +static int read_fbmodes_line(FILE*f, char* line, int length) +{ + int blank; + char* c; + int i; + + blank=0; + /* find a relevant line */ + do + { + if (!fgets(line,length,f)) + return 0; + c=line; + while(((*c=='\t')||(*c==' '))&&(*c!=0)) + c++; + + if ((*c=='\n')||(*c=='#')||(*c==0)) + blank=1; + else + blank=0; + } + while(blank); + /* remove whitespace at the begining of the string */ + i=0; + do + { + line[i]=c[i]; + i++; + } + while(c[i]!=0); + return 1; +} + +static int read_fbmodes_mode(FILE *f, struct fb_var_screeninfo *vinfo) +{ + char line[1024]; + char option[256]; + + /* Find a "geometry" */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + if (SDL_strncmp(line,"geometry",8)==0) + break; + } + while(1); + + SDL_sscanf(line, "geometry %d %d %d %d %d", &vinfo->xres, &vinfo->yres, + &vinfo->xres_virtual, &vinfo->yres_virtual, &vinfo->bits_per_pixel); + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + SDL_sscanf(line, "timings %d %d %d %d %d %d %d", &vinfo->pixclock, + &vinfo->left_margin, &vinfo->right_margin, &vinfo->upper_margin, + &vinfo->lower_margin, &vinfo->hsync_len, &vinfo->vsync_len); + + vinfo->sync=0; + vinfo->vmode=FB_VMODE_NONINTERLACED; + + /* Parse misc options */ + do { + if (read_fbmodes_line(f, line, sizeof(line))==0) + return 0; + + if (SDL_strncmp(line,"hsync",5)==0) { + SDL_sscanf(line,"hsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_HOR_HIGH_ACT; + } + else if (SDL_strncmp(line,"vsync",5)==0) { + SDL_sscanf(line,"vsync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_VERT_HIGH_ACT; + } + else if (SDL_strncmp(line,"csync",5)==0) { + SDL_sscanf(line,"csync %s",option); + if (SDL_strncmp(option,"high",4)==0) + vinfo->sync |= FB_SYNC_COMP_HIGH_ACT; + } + else if (SDL_strncmp(line,"extsync",5)==0) { + SDL_sscanf(line,"extsync %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->sync |= FB_SYNC_EXT; + } + else if (SDL_strncmp(line,"laced",5)==0) { + SDL_sscanf(line,"laced %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_INTERLACED; + } + else if (SDL_strncmp(line,"double",6)==0) { + SDL_sscanf(line,"double %s",option); + if (SDL_strncmp(option,"true",4)==0) + vinfo->vmode |= FB_VMODE_DOUBLE; + } + } + while(SDL_strncmp(line,"endmode",7)!=0); + + return 1; +} + +static int FB_CheckMode(_THIS, struct fb_var_screeninfo *vinfo, + int index, unsigned int *w, unsigned int *h) +{ + int mode_okay; + + mode_okay = 0; + vinfo->bits_per_pixel = (index+1)*8; + vinfo->xres = *w; + vinfo->xres_virtual = *w; + vinfo->yres = *h; + vinfo->yres_virtual = *h; + vinfo->activate = FB_ACTIVATE_TEST; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, vinfo) == 0 ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Checked mode %dx%d at %d bpp, got mode %dx%d at %d bpp\n", *w, *h, (index+1)*8, vinfo->xres, vinfo->yres, vinfo->bits_per_pixel); +#endif + if ( (((vinfo->bits_per_pixel+7)/8)-1) == index ) { + *w = vinfo->xres; + *h = vinfo->yres; + mode_okay = 1; + } + } + return mode_okay; +} + +static int FB_AddMode(_THIS, int index, unsigned int w, unsigned int h, int check_timings) +{ + SDL_Rect *mode; + int i; + int next_mode; + + /* Check to see if we already have this mode */ + if ( SDL_nummodes[index] > 0 ) { + mode = SDL_modelist[index][SDL_nummodes[index]-1]; + if ( (mode->w == w) && (mode->h == h) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + return(0); + } + } + + /* Only allow a mode if we have a valid timing for it */ + if ( check_timings ) { + int found_timing = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (w == vesa_timings[i].xres) && + (h == vesa_timings[i].yres) && vesa_timings[i].pixclock ) { + found_timing = 1; + break; + } + } + if ( !found_timing ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "No valid timing line for mode %dx%d\n", w, h); +#endif + return(0); + } + } + + /* Set up the new video mode rectangle */ + mode = (SDL_Rect *)SDL_malloc(sizeof *mode); + if ( mode == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + mode->x = 0; + mode->y = 0; + mode->w = w; + mode->h = h; +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); +#endif + + /* Allocate the new list of modes, and fill in the new mode */ + next_mode = SDL_nummodes[index]; + SDL_modelist[index] = (SDL_Rect **) + SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); + if ( SDL_modelist[index] == NULL ) { + SDL_OutOfMemory(); + SDL_nummodes[index] = 0; + SDL_free(mode); + return(-1); + } + SDL_modelist[index][next_mode] = mode; + SDL_modelist[index][next_mode+1] = NULL; + SDL_nummodes[index]++; + + return(0); +} + +static int cmpmodes(const void *va, const void *vb) +{ + const SDL_Rect *a = *(const SDL_Rect**)va; + const SDL_Rect *b = *(const SDL_Rect**)vb; + if ( a->h == b->h ) + return b->w - a->w; + else + return b->h - a->h; +} + +static void FB_SortModes(_THIS) +{ + int i; + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_nummodes[i] > 0 ) { + SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes); + } + } +} + +static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + const int pagesize = SDL_getpagesize(); + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i, j; + int current_index; + unsigned int current_w; + unsigned int current_h; + const char *SDL_fbdev; + const char *rotation; + FILE *modesdb; + + /* Initialize the library */ + SDL_fbdev = SDL_getenv("SDL_FBDEV"); + if ( SDL_fbdev == NULL ) { + SDL_fbdev = "/dev/fb0"; + } + console_fd = open(SDL_fbdev, O_RDWR, 0); + if ( console_fd < 0 ) { + SDL_SetError("Unable to open %s", SDL_fbdev); + return(-1); + } + +#if !SDL_THREADS_DISABLED + /* Create the hardware surface lock mutex */ + hw_lock = SDL_CreateMutex(); + if ( hw_lock == NULL ) { + SDL_SetError("Unable to create lock mutex"); + FB_VideoQuit(this); + return(-1); + } +#endif + + /* Get the type of video hardware */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.type) { + case FB_TYPE_PACKED_PIXELS: + /* Supported, no worries.. */ + break; +#ifdef VGA16_FBCON_SUPPORT + case FB_TYPE_VGA_PLANES: + /* VGA16 is supported, but that's it */ + if ( finfo.type_aux == FB_AUX_VGA_PLANES_VGA4 ) { + if ( ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1) < 0 ) { + SDL_SetError("No I/O port permissions"); + FB_VideoQuit(this); + return(-1); + } + this->SetVideoMode = FB_SetVGA16Mode; + break; + } + /* Fall through to unsupported case */ +#endif /* VGA16_FBCON_SUPPORT */ + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + switch (finfo.visual) { + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + case FB_VISUAL_STATIC_PSEUDOCOLOR: + case FB_VISUAL_DIRECTCOLOR: + break; + default: + SDL_SetError("Unsupported console hardware"); + FB_VideoQuit(this); + return(-1); + } + + /* Check if the user wants to disable hardware acceleration */ + { const char *fb_accel; + fb_accel = SDL_getenv("SDL_FBACCEL"); + if ( fb_accel ) { + finfo.accel = SDL_atoi(fb_accel); + } + } + + /* Memory map the device, compensating for buggy PPC mmap() */ + mapped_offset = (((long)finfo.smem_start) - + (((long)finfo.smem_start)&~(pagesize-1))); + mapped_memlen = finfo.smem_len+mapped_offset; + mapped_mem = do_mmap(NULL, mapped_memlen, + PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0); + if ( mapped_mem == (char *)-1 ) { + SDL_SetError("Unable to memory map the video hardware"); + mapped_mem = NULL; + FB_VideoQuit(this); + return(-1); + } + + /* Determine the current screen depth */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console pixel format"); + FB_VideoQuit(this); + return(-1); + } + vformat->BitsPerPixel = vinfo.bits_per_pixel; + if ( vformat->BitsPerPixel < 8 ) { + /* Assuming VGA16, we handle this via a shadow framebuffer */ + vformat->BitsPerPixel = 8; + } + for ( i=0; i<vinfo.red.length; ++i ) { + vformat->Rmask <<= 1; + vformat->Rmask |= (0x00000001<<vinfo.red.offset); + } + for ( i=0; i<vinfo.green.length; ++i ) { + vformat->Gmask <<= 1; + vformat->Gmask |= (0x00000001<<vinfo.green.offset); + } + for ( i=0; i<vinfo.blue.length; ++i ) { + vformat->Bmask <<= 1; + vformat->Bmask |= (0x00000001<<vinfo.blue.offset); + } + saved_vinfo = vinfo; + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* If the I/O registers are available, memory map them so we + can take advantage of any supported hardware acceleration. + */ + vinfo.accel_flags = 0; /* Temporarily reserve registers */ + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo); + if ( finfo.accel && finfo.mmio_len ) { + mapped_iolen = finfo.mmio_len; + mapped_io = do_mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE, + MAP_SHARED, console_fd, mapped_memlen); + if ( mapped_io == (char *)-1 ) { + /* Hmm, failed to memory map I/O registers */ + mapped_io = NULL; + } + } + + rotate = FBCON_ROTATE_NONE; + rotation = SDL_getenv("SDL_VIDEO_FBCON_ROTATION"); + if (rotation != NULL) { + if (SDL_strlen(rotation) == 0) { + shadow_fb = 0; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, no shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "NONE")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_NONE; +#ifdef FBCON_DEBUG + printf("Not rotating, but still using shadow\n"); +#endif + } else if (!SDL_strcmp(rotation, "CW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CW; +#ifdef FBCON_DEBUG + printf("Rotating screen clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "CCW")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_CCW; +#ifdef FBCON_DEBUG + printf("Rotating screen counter clockwise\n"); +#endif + } else if (!SDL_strcmp(rotation, "UD")) { + shadow_fb = 1; + rotate = FBCON_ROTATE_UD; +#ifdef FBCON_DEBUG + printf("Rotating screen upside down\n"); +#endif + } else { + SDL_SetError("\"%s\" is not a valid value for " + "SDL_VIDEO_FBCON_ROTATION", rotation); + return(-1); + } + } + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + current_w = vinfo.yres; + current_h = vinfo.xres; + } else { + current_w = vinfo.xres; + current_h = vinfo.yres; + } + + /* Query for the list of available video modes */ + current_index = ((vinfo.bits_per_pixel+7)/8)-1; + modesdb = fopen(FB_MODES_DB, "r"); + for ( i=0; i<NUM_MODELISTS; ++i ) { + SDL_nummodes[i] = 0; + SDL_modelist[i] = NULL; + } + if ( SDL_getenv("SDL_FB_BROKEN_MODES") != NULL ) { + FB_AddMode(this, current_index, current_w, current_h, 0); + } else if(modesdb) { + while ( read_fbmodes_mode(modesdb, &vinfo) ) { + for ( i=0; i<NUM_MODELISTS; ++i ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = vinfo.yres; + h = vinfo.xres; + } else { + w = vinfo.xres; + h = vinfo.yres; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 0); + } + } + } + fclose(modesdb); + FB_SortModes(this); + } else { + for ( i=0; i<NUM_MODELISTS; ++i ) { + for ( j=0; j<(sizeof(checkres)/sizeof(checkres[0])); ++j ) { + unsigned int w, h; + + if (rotate == FBCON_ROTATE_CW || rotate == FBCON_ROTATE_CCW) { + w = checkres[j].h; + h = checkres[j].w; + } else { + w = checkres[j].w; + h = checkres[j].h; + } + /* See if we are querying for the current mode */ + if ( i == current_index ) { + if ( (current_w > w) || (current_h > h) ) { + /* Only check once */ + FB_AddMode(this, i, current_w, current_h, 0); + current_index = -1; + } + } + if ( FB_CheckMode(this, &vinfo, i, &w, &h) ) { + FB_AddMode(this, i, w, h, 1); + } + } + } + } + + this->info.current_w = current_w; + this->info.current_h = current_h; + this->info.wm_available = 0; + this->info.hw_available = !shadow_fb; + this->info.video_mem = shadow_fb ? 0 : finfo.smem_len/1024; + /* Fill in our hardware acceleration capabilities */ + if ( mapped_io ) { + switch (finfo.accel) { + case FB_ACCEL_MATROX_MGA2064W: + case FB_ACCEL_MATROX_MGA1064SG: + case FB_ACCEL_MATROX_MGA2164W: + case FB_ACCEL_MATROX_MGA2164W_AGP: + case FB_ACCEL_MATROX_MGAG100: + /*case FB_ACCEL_MATROX_MGAG200: G200 acceleration broken! */ + case FB_ACCEL_MATROX_MGAG400: +#ifdef FBACCEL_DEBUG + printf("Matrox hardware accelerator!\n"); +#endif + FB_MatroxAccel(this, finfo.accel); + break; + case FB_ACCEL_3DFX_BANSHEE: +#ifdef FBACCEL_DEBUG + printf("3DFX hardware accelerator!\n"); +#endif + FB_3DfxAccel(this, finfo.accel); + break; + case FB_ACCEL_NV3: + case FB_ACCEL_NV4: +#ifdef FBACCEL_DEBUG + printf("NVidia hardware accelerator!\n"); +#endif + FB_RivaAccel(this, finfo.accel); + break; + default: +#ifdef FBACCEL_DEBUG + printf("Unknown hardware accelerator.\n"); +#endif + break; + } + } + + if (shadow_fb) { + shadow_mem = (char *)SDL_malloc(mapped_memlen); + if (shadow_mem == NULL) { + SDL_SetError("No memory for shadow"); + return (-1); + } + } + + /* Enable mouse and keyboard support */ + if ( FB_OpenKeyboard(this) < 0 ) { + FB_VideoQuit(this); + return(-1); + } + if ( FB_OpenMouse(this) < 0 ) { + const char *sdl_nomouse; + + sdl_nomouse = SDL_getenv("SDL_NOMOUSE"); + if ( ! sdl_nomouse ) { + SDL_SetError("Unable to open mouse"); + FB_VideoQuit(this); + return(-1); + } + } + + /* We're done! */ + return(0); +} + +static SDL_Rect **FB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]); +} + +/* Various screen update functions available */ +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); +#ifdef VGA16_FBCON_SUPPORT +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects); +#endif + +#ifdef FBCON_DEBUG +static void print_vinfo(struct fb_var_screeninfo *vinfo) +{ + fprintf(stderr, "Printing vinfo:\n"); + fprintf(stderr, "\txres: %d\n", vinfo->xres); + fprintf(stderr, "\tyres: %d\n", vinfo->yres); + fprintf(stderr, "\txres_virtual: %d\n", vinfo->xres_virtual); + fprintf(stderr, "\tyres_virtual: %d\n", vinfo->yres_virtual); + fprintf(stderr, "\txoffset: %d\n", vinfo->xoffset); + fprintf(stderr, "\tyoffset: %d\n", vinfo->yoffset); + fprintf(stderr, "\tbits_per_pixel: %d\n", vinfo->bits_per_pixel); + fprintf(stderr, "\tgrayscale: %d\n", vinfo->grayscale); + fprintf(stderr, "\tnonstd: %d\n", vinfo->nonstd); + fprintf(stderr, "\tactivate: %d\n", vinfo->activate); + fprintf(stderr, "\theight: %d\n", vinfo->height); + fprintf(stderr, "\twidth: %d\n", vinfo->width); + fprintf(stderr, "\taccel_flags: %d\n", vinfo->accel_flags); + fprintf(stderr, "\tpixclock: %d\n", vinfo->pixclock); + fprintf(stderr, "\tleft_margin: %d\n", vinfo->left_margin); + fprintf(stderr, "\tright_margin: %d\n", vinfo->right_margin); + fprintf(stderr, "\tupper_margin: %d\n", vinfo->upper_margin); + fprintf(stderr, "\tlower_margin: %d\n", vinfo->lower_margin); + fprintf(stderr, "\thsync_len: %d\n", vinfo->hsync_len); + fprintf(stderr, "\tvsync_len: %d\n", vinfo->vsync_len); + fprintf(stderr, "\tsync: %d\n", vinfo->sync); + fprintf(stderr, "\tvmode: %d\n", vinfo->vmode); + fprintf(stderr, "\tred: %d/%d\n", vinfo->red.length, vinfo->red.offset); + fprintf(stderr, "\tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset); + fprintf(stderr, "\tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset); + fprintf(stderr, "\talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset); +} +static void print_finfo(struct fb_fix_screeninfo *finfo) +{ + fprintf(stderr, "Printing finfo:\n"); + fprintf(stderr, "\tsmem_start = %p\n", (char *)finfo->smem_start); + fprintf(stderr, "\tsmem_len = %d\n", finfo->smem_len); + fprintf(stderr, "\ttype = %d\n", finfo->type); + fprintf(stderr, "\ttype_aux = %d\n", finfo->type_aux); + fprintf(stderr, "\tvisual = %d\n", finfo->visual); + fprintf(stderr, "\txpanstep = %d\n", finfo->xpanstep); + fprintf(stderr, "\typanstep = %d\n", finfo->ypanstep); + fprintf(stderr, "\tywrapstep = %d\n", finfo->ywrapstep); + fprintf(stderr, "\tline_length = %d\n", finfo->line_length); + fprintf(stderr, "\tmmio_start = %p\n", (char *)finfo->mmio_start); + fprintf(stderr, "\tmmio_len = %d\n", finfo->mmio_len); + fprintf(stderr, "\taccel = %d\n", finfo->accel); +} +#endif + +static int choose_fbmodes_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + FILE *modesdb; + struct fb_var_screeninfo cinfo; + + matched = 0; + modesdb = fopen(FB_MODES_DB, "r"); + if ( modesdb ) { + /* Parse the mode definition file */ + while ( read_fbmodes_mode(modesdb, &cinfo) ) { + if ( (vinfo->xres == cinfo.xres && vinfo->yres == cinfo.yres) && + (!matched || (vinfo->bits_per_pixel == cinfo.bits_per_pixel)) ) { + vinfo->pixclock = cinfo.pixclock; + vinfo->left_margin = cinfo.left_margin; + vinfo->right_margin = cinfo.right_margin; + vinfo->upper_margin = cinfo.upper_margin; + vinfo->lower_margin = cinfo.lower_margin; + vinfo->hsync_len = cinfo.hsync_len; + vinfo->vsync_len = cinfo.vsync_len; + if ( matched ) { + break; + } + matched = 1; + } + } + fclose(modesdb); + } + return(matched); +} + +static int choose_vesa_mode(struct fb_var_screeninfo *vinfo) +{ + int matched; + int i; + + /* Check for VESA timings */ + matched = 0; + for ( i=0; i<(sizeof(vesa_timings)/sizeof(vesa_timings[0])); ++i ) { + if ( (vinfo->xres == vesa_timings[i].xres) && + (vinfo->yres == vesa_timings[i].yres) ) { +#ifdef FBCON_DEBUG + fprintf(stderr, "Using VESA timings for %dx%d\n", + vinfo->xres, vinfo->yres); +#endif + if ( vesa_timings[i].pixclock ) { + vinfo->pixclock = vesa_timings[i].pixclock; + } + vinfo->left_margin = vesa_timings[i].left; + vinfo->right_margin = vesa_timings[i].right; + vinfo->upper_margin = vesa_timings[i].upper; + vinfo->lower_margin = vesa_timings[i].lower; + vinfo->hsync_len = vesa_timings[i].hslen; + vinfo->vsync_len = vesa_timings[i].vslen; + vinfo->sync = vesa_timings[i].sync; + vinfo->vmode = vesa_timings[i].vmode; + matched = 1; + break; + } + } + return(matched); +} + +#ifdef VGA16_FBCON_SUPPORT +static SDL_Surface *FB_SetVGA16Mode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { + return(NULL); + } + current->format->palette->ncolors = 16; + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual finfo:\n"); + print_finfo(&finfo); +#endif + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + /* Set up the new mode framebuffer */ + current->flags = SDL_FULLSCREEN; + current->w = vinfo.xres; + current->h = vinfo.yres; + current->pitch = current->w; + current->pixels = SDL_malloc(current->h*current->pitch); + + /* Set the update rectangle function */ + this->UpdateRects = FB_VGA16Update; + + /* We're done */ + return(current); +} +#endif /* VGA16_FBCON_SUPPORT */ + +static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + struct fb_fix_screeninfo finfo; + struct fb_var_screeninfo vinfo; + int i; + Uint32 Rmask; + Uint32 Gmask; + Uint32 Bmask; + char *surfaces_mem; + int surfaces_len; + + /* Set the terminal into graphics mode */ + if ( FB_EnterGraphicsMode(this) < 0 ) { + return(NULL); + } + + /* Restore the original palette */ + FB_RestorePalette(this); + + /* Set the video mode and get the final screen format */ + if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't get console screen info"); + return(NULL); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing original vinfo:\n"); + print_vinfo(&vinfo); +#endif + /* Do not use double buffering with shadow buffer */ + if (shadow_fb) { + flags &= ~SDL_DOUBLEBUF; + } + + if ( (vinfo.xres != width) || (vinfo.yres != height) || + (vinfo.bits_per_pixel != bpp) || (flags & SDL_DOUBLEBUF) ) { + vinfo.activate = FB_ACTIVATE_NOW; + vinfo.accel_flags = 0; + vinfo.bits_per_pixel = bpp; + vinfo.xres = width; + vinfo.xres_virtual = width; + vinfo.yres = height; + if ( flags & SDL_DOUBLEBUF ) { + vinfo.yres_virtual = height*2; + } else { + vinfo.yres_virtual = height; + } + vinfo.xoffset = 0; + vinfo.yoffset = 0; + vinfo.red.length = vinfo.red.offset = 0; + vinfo.green.length = vinfo.green.offset = 0; + vinfo.blue.length = vinfo.blue.offset = 0; + vinfo.transp.length = vinfo.transp.offset = 0; + if ( ! choose_fbmodes_mode(&vinfo) ) { + choose_vesa_mode(&vinfo); + } +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing wanted vinfo:\n"); + print_vinfo(&vinfo); +#endif + if ( !shadow_fb && + ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + vinfo.yres_virtual = height; + if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { + SDL_SetError("Couldn't set console screen info"); + return(NULL); + } + } + } else { + int maxheight; + + /* Figure out how much video memory is available */ + if ( flags & SDL_DOUBLEBUF ) { + maxheight = height*2; + } else { + maxheight = height; + } + if ( vinfo.yres_virtual > maxheight ) { + vinfo.yres_virtual = maxheight; + } + } + cache_vinfo = vinfo; +#ifdef FBCON_DEBUG + fprintf(stderr, "Printing actual vinfo:\n"); + print_vinfo(&vinfo); +#endif + Rmask = 0; + for ( i=0; i<vinfo.red.length; ++i ) { + Rmask <<= 1; + Rmask |= (0x00000001<<vinfo.red.offset); + } + Gmask = 0; + for ( i=0; i<vinfo.green.length; ++i ) { + Gmask <<= 1; + Gmask |= (0x00000001<<vinfo.green.offset); + } + Bmask = 0; + for ( i=0; i<vinfo.blue.length; ++i ) { + Bmask <<= 1; + Bmask |= (0x00000001<<vinfo.blue.offset); + } + if ( ! SDL_ReallocFormat(current, vinfo.bits_per_pixel, + Rmask, Gmask, Bmask, 0) ) { + return(NULL); + } + + /* Get the fixed information about the console hardware. + This is necessary since finfo.line_length changes. + */ + if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { + SDL_SetError("Couldn't get console hardware info"); + return(NULL); + } + + /* Save hardware palette, if needed */ + FB_SavePalette(this, &finfo, &vinfo); + + if (shadow_fb) { + if (vinfo.bits_per_pixel == 16) { + blitFunc = (rotate == FBCON_ROTATE_NONE || + rotate == FBCON_ROTATE_UD) ? + FB_blit16 : FB_blit16blocked; + } else { +#ifdef FBCON_DEBUG + fprintf(stderr, "Init vinfo:\n"); + print_vinfo(&vinfo); +#endif + SDL_SetError("Using software buffer, but no blitter " + "function is available for %d bpp.", + vinfo.bits_per_pixel); + return(NULL); + } + } + + /* Set up the new mode framebuffer */ + current->flags &= SDL_FULLSCREEN; + if (shadow_fb) { + current->flags |= SDL_SWSURFACE; + } else { + current->flags |= SDL_HWSURFACE; + } + current->w = vinfo.xres; + current->h = vinfo.yres; + if (shadow_fb) { + current->pitch = current->w * ((vinfo.bits_per_pixel + 7) / 8); + current->pixels = shadow_mem; + physlinebytes = finfo.line_length; + } else { + current->pitch = finfo.line_length; + current->pixels = mapped_mem+mapped_offset; + } + + /* Set up the information for hardware surfaces */ + surfaces_mem = (char *)current->pixels + + vinfo.yres_virtual*current->pitch; + surfaces_len = (shadow_fb) ? + 0 : (mapped_memlen-(surfaces_mem-mapped_mem)); + + FB_FreeHWSurfaces(this); + FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); + + /* Let the application know we have a hardware palette */ + switch (finfo.visual) { + case FB_VISUAL_PSEUDOCOLOR: + current->flags |= SDL_HWPALETTE; + break; + default: + break; + } + + /* Update for double-buffering, if we can */ + if ( flags & SDL_DOUBLEBUF ) { + if ( vinfo.yres_virtual == (height*2) ) { + current->flags |= SDL_DOUBLEBUF; + flip_page = 0; + flip_address[0] = (char *)current->pixels; + flip_address[1] = (char *)current->pixels+ + current->h*current->pitch; + this->screen = current; + FB_FlipHWSurface(this, current); + this->screen = NULL; + } + } + + /* Set the update rectangle function */ + this->UpdateRects = FB_DirectUpdate; + + /* We're done */ + return(current); +} + +#ifdef FBCON_DEBUG +void FB_DumpHWSurfaces(_THIS) +{ + vidmem_bucket *bucket; + + printf("Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); + printf("\n"); + printf(" Base Size\n"); + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + printf("Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); + if ( bucket->prev ) { + if ( bucket->base != bucket->prev->base+bucket->prev->size ) { + printf("Warning, corrupt bucket list! (prev)\n"); + } + } else { + if ( bucket != &surfaces ) { + printf("Warning, corrupt bucket list! (!prev)\n"); + } + } + if ( bucket->next ) { + if ( bucket->next->base != bucket->base+bucket->size ) { + printf("Warning, corrupt bucket list! (next)\n"); + } + } + } + printf("\n"); +} +#endif + +static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size) +{ + vidmem_bucket *bucket; + + surfaces_memtotal = size; + surfaces_memleft = size; + + if ( surfaces_memleft > 0 ) { + bucket = (vidmem_bucket *)SDL_malloc(sizeof(*bucket)); + if ( bucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + bucket->prev = &surfaces; + bucket->used = 0; + bucket->dirty = 0; + bucket->base = base; + bucket->size = size; + bucket->next = NULL; + } else { + bucket = NULL; + } + + surfaces.prev = NULL; + surfaces.used = 1; + surfaces.dirty = 0; + surfaces.base = screen->pixels; + surfaces.size = (unsigned int)((long)base - (long)surfaces.base); + surfaces.next = bucket; + screen->hwdata = (struct private_hwdata *)&surfaces; + return(0); +} +static void FB_FreeHWSurfaces(_THIS) +{ + vidmem_bucket *bucket, *freeable; + + bucket = surfaces.next; + while ( bucket ) { + freeable = bucket; + bucket = bucket->next; + SDL_free(freeable); + } + surfaces.next = NULL; +} + +static int FB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket; + int size; + int extra; + +/* Temporarily, we only allow surfaces the same width as display. + Some blitters require the pitch between two hardware surfaces + to be the same. Others have interesting alignment restrictions. + Until someone who knows these details looks at the code... +*/ +if ( surface->pitch > SDL_VideoSurface->pitch ) { + SDL_SetError("Surface requested wider than screen"); + return(-1); +} +surface->pitch = SDL_VideoSurface->pitch; + size = surface->h * surface->pitch; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocating bucket of %d bytes\n", size); +#endif + + /* Quick check for available mem */ + if ( size > surfaces_memleft ) { + SDL_SetError("Not enough video memory"); + return(-1); + } + + /* Search for an empty bucket big enough */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( ! bucket->used && (size <= bucket->size) ) { + break; + } + } + if ( bucket == NULL ) { + SDL_SetError("Video memory too fragmented"); + return(-1); + } + + /* Create a new bucket for left-over memory */ + extra = (bucket->size - size); + if ( extra ) { + vidmem_bucket *newbucket; + +#ifdef FBCON_DEBUG + fprintf(stderr, "Adding new free bucket of %d bytes\n", extra); +#endif + newbucket = (vidmem_bucket *)SDL_malloc(sizeof(*newbucket)); + if ( newbucket == NULL ) { + SDL_OutOfMemory(); + return(-1); + } + newbucket->prev = bucket; + newbucket->used = 0; + newbucket->base = bucket->base+size; + newbucket->size = extra; + newbucket->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = newbucket; + } + bucket->next = newbucket; + } + + /* Set the current bucket values and return it! */ + bucket->used = 1; + bucket->size = size; + bucket->dirty = 0; +#ifdef FBCON_DEBUG + fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); +#endif + surfaces_memleft -= size; + surface->flags |= SDL_HWSURFACE; + surface->pixels = bucket->base; + surface->hwdata = (struct private_hwdata *)bucket; + return(0); +} +static void FB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + vidmem_bucket *bucket, *freeable; + + /* Look for the bucket in the current list */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + if ( bucket == (vidmem_bucket *)surface->hwdata ) { + break; + } + } + if ( bucket && bucket->used ) { + /* Add the memory back to the total */ +#ifdef DGA_DEBUG + printf("Freeing bucket of %d bytes\n", bucket->size); +#endif + surfaces_memleft += bucket->size; + + /* Can we merge the space with surrounding buckets? */ + bucket->used = 0; + if ( bucket->next && ! bucket->next->used ) { +#ifdef DGA_DEBUG + printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); +#endif + freeable = bucket->next; + bucket->size += bucket->next->size; + bucket->next = bucket->next->next; + if ( bucket->next ) { + bucket->next->prev = bucket; + } + SDL_free(freeable); + } + if ( bucket->prev && ! bucket->prev->used ) { +#ifdef DGA_DEBUG + printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); +#endif + freeable = bucket; + bucket->prev->size += bucket->size; + bucket->prev->next = bucket->next; + if ( bucket->next ) { + bucket->next->prev = bucket->prev; + } + SDL_free(freeable); + } + } + surface->pixels = NULL; + surface->hwdata = NULL; +} + +static int FB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + if ( surface == this->screen ) { + SDL_mutexP(hw_lock); + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } else { + if ( FB_IsSurfaceBusy(surface) ) { + FB_WaitBusySurfaces(this); + } + } + return(0); +} +static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + if ( surface == this->screen ) { + SDL_mutexV(hw_lock); + } +} + +static void FB_WaitVBL(_THIS) +{ +#ifdef FBIOWAITRETRACE /* Heheh, this didn't make it into the main kernel */ + ioctl(console_fd, FBIOWAITRETRACE, 0); +#endif + return; +} + +static void FB_WaitIdle(_THIS) +{ + return; +} + +static int FB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if ( switched_away ) { + return -2; /* no hardware access */ + } + + /* Wait for vertical retrace and then flip display */ + cache_vinfo.yoffset = flip_page*surface->h; + if ( FB_IsSurfaceBusy(this->screen) ) { + FB_WaitBusySurfaces(this); + } + wait_vbl(this); + if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) { + SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed"); + return(-1); + } + flip_page = !flip_page; + + surface->pixels = flip_address[flip_page]; + return(0); +} + +static void FB_blit16(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w != 0; w--) { + *dst = *src; + src += src_right_delta; + dst++; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes); + src_pos += src_down_delta; + height--; + } +} + +#define BLOCKSIZE_W 32 +#define BLOCKSIZE_H 32 + +static void FB_blit16blocked(Uint8 *byte_src_pos, int src_right_delta, int src_down_delta, + Uint8 *byte_dst_pos, int dst_linebytes, int width, int height) +{ + int w; + Uint16 *src_pos = (Uint16 *)byte_src_pos; + Uint16 *dst_pos = (Uint16 *)byte_dst_pos; + + while (height > 0) { + Uint16 *src = src_pos; + Uint16 *dst = dst_pos; + for (w = width; w > 0; w -= BLOCKSIZE_W) { + FB_blit16((Uint8 *)src, + src_right_delta, + src_down_delta, + (Uint8 *)dst, + dst_linebytes, + min(w, BLOCKSIZE_W), + min(height, BLOCKSIZE_H)); + src += src_right_delta * BLOCKSIZE_W; + dst += BLOCKSIZE_W; + } + dst_pos = (Uint16 *)((Uint8 *)dst_pos + dst_linebytes * BLOCKSIZE_H); + src_pos += src_down_delta * BLOCKSIZE_H; + height -= BLOCKSIZE_H; + } +} + +static void FB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + int width = cache_vinfo.xres; + int height = cache_vinfo.yres; + int bytes_per_pixel = (cache_vinfo.bits_per_pixel + 7) / 8; + int i; + + if (!shadow_fb) { + /* The application is already updating the visible video memory */ + return; + } + + if (cache_vinfo.bits_per_pixel != 16) { + SDL_SetError("Shadow copy only implemented for 16 bpp"); + return; + } + + for (i = 0; i < numrects; i++) { + int x1, y1, x2, y2; + int scr_x1, scr_y1, scr_x2, scr_y2; + int sha_x1, sha_y1; + int shadow_right_delta; /* Address change when moving right in dest */ + int shadow_down_delta; /* Address change when moving down in dest */ + char *src_start; + char *dst_start; + + x1 = rects[i].x; + y1 = rects[i].y; + x2 = x1 + rects[i].w; + y2 = y1 + rects[i].h; + + if (x1 < 0) { + x1 = 0; + } else if (x1 > width) { + x1 = width; + } + if (x2 < 0) { + x2 = 0; + } else if (x2 > width) { + x2 = width; + } + if (y1 < 0) { + y1 = 0; + } else if (y1 > height) { + y1 = height; + } + if (y2 < 0) { + y2 = 0; + } else if (y2 > height) { + y2 = height; + } + if (x2 <= x1 || y2 <= y1) { + continue; + } + + switch (rotate) { + case FBCON_ROTATE_NONE: + sha_x1 = scr_x1 = x1; + sha_y1 = scr_y1 = y1; + scr_x2 = x2; + scr_y2 = y2; + shadow_right_delta = 1; + shadow_down_delta = width; + break; + case FBCON_ROTATE_CCW: + scr_x1 = y1; + scr_y1 = width - x2; + scr_x2 = y2; + scr_y2 = width - x1; + sha_x1 = x2 - 1; + sha_y1 = y1; + shadow_right_delta = width; + shadow_down_delta = -1; + break; + case FBCON_ROTATE_UD: + scr_x1 = width - x2; + scr_y1 = height - y2; + scr_x2 = width - x1; + scr_y2 = height - y1; + sha_x1 = x2 - 1; + sha_y1 = y2 - 1; + shadow_right_delta = -1; + shadow_down_delta = -width; + break; + case FBCON_ROTATE_CW: + scr_x1 = height - y2; + scr_y1 = x1; + scr_x2 = height - y1; + scr_y2 = x2; + sha_x1 = x1; + sha_y1 = y2 - 1; + shadow_right_delta = -width; + shadow_down_delta = 1; + break; + default: + SDL_SetError("Unknown rotation"); + return; + } + + src_start = shadow_mem + + (sha_y1 * width + sha_x1) * bytes_per_pixel; + dst_start = mapped_mem + mapped_offset + scr_y1 * physlinebytes + + scr_x1 * bytes_per_pixel; + + blitFunc((Uint8 *) src_start, + shadow_right_delta, + shadow_down_delta, + (Uint8 *) dst_start, + physlinebytes, + scr_x2 - scr_x1, + scr_y2 - scr_y1); + } +} + +#ifdef VGA16_FBCON_SUPPORT +/* Code adapted with thanks from the XFree86 VGA16 driver! :) */ +#define writeGr(index, value) \ +outb(index, 0x3CE); \ +outb(value, 0x3CF); +#define writeSeq(index, value) \ +outb(index, 0x3C4); \ +outb(value, 0x3C5); + +static void FB_VGA16Update(_THIS, int numrects, SDL_Rect *rects) +{ + SDL_Surface *screen; + int width, height, FBPitch, left, i, j, SRCPitch, phase; + register Uint32 m; + Uint8 s1, s2, s3, s4; + Uint32 *src, *srcPtr; + Uint8 *dst, *dstPtr; + + if ( switched_away ) { + return; /* no hardware access */ + } + + screen = this->screen; + FBPitch = screen->w >> 3; + SRCPitch = screen->pitch >> 2; + + writeGr(0x03, 0x00); + writeGr(0x05, 0x00); + writeGr(0x01, 0x00); + writeGr(0x08, 0xFF); + + while(numrects--) { + left = rects->x & ~7; + width = (rects->w + 7) >> 3; + height = rects->h; + src = (Uint32*)screen->pixels + (rects->y * SRCPitch) + (left >> 2); + dst = (Uint8*)mapped_mem + (rects->y * FBPitch) + (left >> 3); + + if((phase = (long)dst & 3L)) { + phase = 4 - phase; + if(phase > width) phase = width; + width -= phase; + } + + while(height--) { + writeSeq(0x02, 1 << 0); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101) << 4); + s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101) << 4); + s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101) << 4); + s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4); + *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 1); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202) << 4); + s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202) << 4); + s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202) << 4); + s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4); + *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 2); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404) << 4); + s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404) << 4); + s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404) << 4); + s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4); + *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1); + srcPtr += 2; + } + + writeSeq(0x02, 1 << 3); + dstPtr = dst; + srcPtr = src; + i = width; + j = phase; + while(j--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + while(i >= 4) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + s1 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808) << 4); + s2 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808) << 4); + s3 = (m >> 27) | (m >> 18) | (m >> 9) | m; + m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808) << 4); + s4 = (m >> 27) | (m >> 18) | (m >> 9) | m; + *((Uint32*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + srcPtr += 8; + dstPtr += 4; + i -= 4; + } + while(i--) { + m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4); + *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m; + srcPtr += 2; + } + + dst += FBPitch; + src += SRCPitch; + } + rects++; + } +} +#endif /* VGA16_FBCON_SUPPORT */ + +void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOGETCMAP, &cmap); +} + +void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area) +{ + struct fb_cmap cmap; + + cmap.start = 0; + cmap.len = palette_len; + cmap.red = &area[0*palette_len]; + cmap.green = &area[1*palette_len]; + cmap.blue = &area[2*palette_len]; + cmap.transp = NULL; + ioctl(console_fd, FBIOPUTCMAP, &cmap); +} + +static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, + struct fb_var_screeninfo *vinfo) +{ + int i; + + /* Save hardware palette, if needed */ + if ( finfo->visual == FB_VISUAL_PSEUDOCOLOR ) { + saved_cmaplen = 1<<vinfo->bits_per_pixel; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + } + + /* Added support for FB_VISUAL_DIRECTCOLOR. + With this mode pixel information is passed through the palette... + Neat fading and gamma correction effects can be had by simply + fooling around with the palette instead of changing the pixel + values themselves... Very neat! + + Adam Meyerowitz 1/19/2000 + ameyerow@optonline.com + */ + if ( finfo->visual == FB_VISUAL_DIRECTCOLOR ) { + __u16 new_entries[3*256]; + + /* Save the colormap */ + saved_cmaplen = 256; + saved_cmap=(__u16 *)SDL_malloc(3*saved_cmaplen*sizeof(*saved_cmap)); + if ( saved_cmap != NULL ) { + FB_SavePaletteTo(this, saved_cmaplen, saved_cmap); + } + + /* Allocate new identity colormap */ + for ( i=0; i<256; ++i ) { + new_entries[(0*256)+i] = + new_entries[(1*256)+i] = + new_entries[(2*256)+i] = (i<<8)|i; + } + FB_RestorePaletteFrom(this, 256, new_entries); + } +} + +static void FB_RestorePalette(_THIS) +{ + /* Restore the original palette */ + if ( saved_cmap ) { + FB_RestorePaletteFrom(this, saved_cmaplen, saved_cmap); + SDL_free(saved_cmap); + saved_cmap = NULL; + } +} + +static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + int i; + __u16 r[256]; + __u16 g[256]; + __u16 b[256]; + struct fb_cmap cmap; + + /* Set up the colormap */ + for (i = 0; i < ncolors; i++) { + r[i] = colors[i].r << 8; + g[i] = colors[i].g << 8; + b[i] = colors[i].b << 8; + } + cmap.start = firstcolor; + cmap.len = ncolors; + cmap.red = r; + cmap.green = g; + cmap.blue = b; + cmap.transp = NULL; + + if( (ioctl(console_fd, FBIOPUTCMAP, &cmap) < 0) || + !(this->screen->flags & SDL_HWPALETTE) ) { + colors = this->screen->format->palette->colors; + ncolors = this->screen->format->palette->ncolors; + cmap.start = 0; + cmap.len = ncolors; + SDL_memset(r, 0, sizeof(r)); + SDL_memset(g, 0, sizeof(g)); + SDL_memset(b, 0, sizeof(b)); + if ( ioctl(console_fd, FBIOGETCMAP, &cmap) == 0 ) { + for ( i=ncolors-1; i>=0; --i ) { + colors[i].r = (r[i]>>8); + colors[i].g = (g[i]>>8); + colors[i].b = (b[i]>>8); + } + } + return(0); + } + return(1); +} + +/* Note: If we are terminated, this could be called in the middle of + another SDL video routine -- notably UpdateRects. +*/ +static void FB_VideoQuit(_THIS) +{ + int i, j; + + if ( this->screen ) { + /* Clear screen and tell SDL not to free the pixels */ + + const char *dontClearPixels = SDL_getenv("SDL_FBCON_DONT_CLEAR"); + + /* If the framebuffer is not to be cleared, make sure that we won't + * display the previous frame when disabling double buffering. */ + if ( dontClearPixels && flip_page == 0 ) { + SDL_memcpy(flip_address[0], flip_address[1], this->screen->pitch * this->screen->h); + } + + if ( !dontClearPixels && this->screen->pixels && FB_InGraphicsMode(this) ) { +#if defined(__powerpc__) || defined(__ia64__) /* SIGBUS when using SDL_memset() ?? */ + Uint8 *rowp = (Uint8 *)this->screen->pixels; + int left = this->screen->pitch*this->screen->h; + while ( left-- ) { *rowp++ = 0; } +#else + SDL_memset(this->screen->pixels,0,this->screen->h*this->screen->pitch); +#endif + } + /* This test fails when using the VGA16 shadow memory */ + if ( ((char *)this->screen->pixels >= mapped_mem) && + ((char *)this->screen->pixels < (mapped_mem+mapped_memlen)) ) { + this->screen->pixels = NULL; + } + } + + /* Clear the lock mutex */ + if ( hw_lock ) { + SDL_DestroyMutex(hw_lock); + hw_lock = NULL; + } + + /* Clean up defined video modes */ + for ( i=0; i<NUM_MODELISTS; ++i ) { + if ( SDL_modelist[i] != NULL ) { + for ( j=0; SDL_modelist[i][j]; ++j ) { + SDL_free(SDL_modelist[i][j]); + } + SDL_free(SDL_modelist[i]); + SDL_modelist[i] = NULL; + } + } + + /* Clean up the memory bucket list */ + FB_FreeHWSurfaces(this); + + /* Close console and input file descriptors */ + if ( console_fd > 0 ) { + /* Unmap the video framebuffer and I/O registers */ + if ( mapped_mem ) { + munmap(mapped_mem, mapped_memlen); + mapped_mem = NULL; + } + if ( mapped_io ) { + munmap(mapped_io, mapped_iolen); + mapped_io = NULL; + } + + /* Restore the original video mode and palette */ + if ( FB_InGraphicsMode(this) ) { + FB_RestorePalette(this); + ioctl(console_fd, FBIOPUT_VSCREENINFO, &saved_vinfo); + } + + /* We're all done with the framebuffer */ + close(console_fd); + console_fd = -1; + } + FB_CloseMouse(this); + FB_CloseKeyboard(this); +} diff --git a/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h new file mode 100644 index 0000000..1443d2b --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/SDL_fbvideo.h @@ -0,0 +1,200 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_fbvideo_h +#define _SDL_fbvideo_h + +#include <sys/types.h> +#include <termios.h> +#include <linux/fb.h> + +#include "SDL_mouse.h" +#include "SDL_mutex.h" +#include "../SDL_sysvideo.h" +#if SDL_INPUT_TSLIB +#include "tslib.h" +#endif + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_VideoDevice *this + +typedef void FB_bitBlit( + Uint8 *src_pos, + int src_right_delta, /* pixels, not bytes */ + int src_down_delta, /* pixels, not bytes */ + Uint8 *dst_pos, + int dst_linebytes, + int width, + int height); + +/* This is the structure we use to keep track of video memory */ +typedef struct vidmem_bucket { + struct vidmem_bucket *prev; + int used; + int dirty; + char *base; + unsigned int size; + struct vidmem_bucket *next; +} vidmem_bucket; + +/* Private display data */ +struct SDL_PrivateVideoData { + int console_fd; + struct fb_var_screeninfo cache_vinfo; + struct fb_var_screeninfo saved_vinfo; + int saved_cmaplen; + __u16 *saved_cmap; + + int current_vt; + int saved_vt; + int keyboard_fd; + int saved_kbd_mode; + struct termios saved_kbd_termios; + + int mouse_fd; +#if SDL_INPUT_TSLIB + struct tsdev *ts_dev; +#endif + + char *mapped_mem; + char *shadow_mem; + int mapped_memlen; + int mapped_offset; + char *mapped_io; + long mapped_iolen; + int flip_page; + char *flip_address[2]; + int rotate; + int shadow_fb; /* Tells whether a shadow is being used. */ + FB_bitBlit *blitFunc; + int physlinebytes; /* Length of a line in bytes in physical fb */ + +#define NUM_MODELISTS 4 /* 8, 16, 24, and 32 bits-per-pixel */ + int SDL_nummodes[NUM_MODELISTS]; + SDL_Rect **SDL_modelist[NUM_MODELISTS]; + + vidmem_bucket surfaces; + int surfaces_memtotal; + int surfaces_memleft; + + SDL_mutex *hw_lock; + int switched_away; + struct fb_var_screeninfo screen_vinfo; + Uint32 screen_arealen; + Uint8 *screen_contents; + __u16 screen_palette[3*256]; + + void (*wait_vbl)(_THIS); + void (*wait_idle)(_THIS); +}; +/* Old variable names */ +#define console_fd (this->hidden->console_fd) +#define current_vt (this->hidden->current_vt) +#define saved_vt (this->hidden->saved_vt) +#define keyboard_fd (this->hidden->keyboard_fd) +#define saved_kbd_mode (this->hidden->saved_kbd_mode) +#define saved_kbd_termios (this->hidden->saved_kbd_termios) +#define mouse_fd (this->hidden->mouse_fd) +#if SDL_INPUT_TSLIB +#define ts_dev (this->hidden->ts_dev) +#endif +#define cache_vinfo (this->hidden->cache_vinfo) +#define saved_vinfo (this->hidden->saved_vinfo) +#define saved_cmaplen (this->hidden->saved_cmaplen) +#define saved_cmap (this->hidden->saved_cmap) +#define mapped_mem (this->hidden->mapped_mem) +#define shadow_mem (this->hidden->shadow_mem) +#define mapped_memlen (this->hidden->mapped_memlen) +#define mapped_offset (this->hidden->mapped_offset) +#define mapped_io (this->hidden->mapped_io) +#define mapped_iolen (this->hidden->mapped_iolen) +#define flip_page (this->hidden->flip_page) +#define flip_address (this->hidden->flip_address) +#define rotate (this->hidden->rotate) +#define shadow_fb (this->hidden->shadow_fb) +#define blitFunc (this->hidden->blitFunc) +#define physlinebytes (this->hidden->physlinebytes) +#define SDL_nummodes (this->hidden->SDL_nummodes) +#define SDL_modelist (this->hidden->SDL_modelist) +#define surfaces (this->hidden->surfaces) +#define surfaces_memtotal (this->hidden->surfaces_memtotal) +#define surfaces_memleft (this->hidden->surfaces_memleft) +#define hw_lock (this->hidden->hw_lock) +#define switched_away (this->hidden->switched_away) +#define screen_vinfo (this->hidden->screen_vinfo) +#define screen_arealen (this->hidden->screen_arealen) +#define screen_contents (this->hidden->screen_contents) +#define screen_palette (this->hidden->screen_palette) +#define wait_vbl (this->hidden->wait_vbl) +#define wait_idle (this->hidden->wait_idle) + +/* Accelerator types that are supported by the driver, but are not + necessarily in the kernel headers on the system we compile on. +*/ +#ifndef FB_ACCEL_MATROX_MGAG400 +#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ +#endif +#ifndef FB_ACCEL_3DFX_BANSHEE +#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ +#endif + +/* These functions are defined in SDL_fbvideo.c */ +extern void FB_SavePaletteTo(_THIS, int palette_len, __u16 *area); +extern void FB_RestorePaletteFrom(_THIS, int palette_len, __u16 *area); + +/* These are utility functions for working with video surfaces */ + +static __inline__ void FB_AddBusySurface(SDL_Surface *surface) +{ + ((vidmem_bucket *)surface->hwdata)->dirty = 1; +} + +static __inline__ int FB_IsSurfaceBusy(SDL_Surface *surface) +{ + return ((vidmem_bucket *)surface->hwdata)->dirty; +} + +static __inline__ void FB_WaitBusySurfaces(_THIS) +{ + vidmem_bucket *bucket; + + /* Wait for graphic operations to complete */ + wait_idle(this); + + /* Clear all surface dirty bits */ + for ( bucket=&surfaces; bucket; bucket=bucket->next ) { + bucket->dirty = 0; + } +} + +static __inline__ void FB_dst_to_xy(_THIS, SDL_Surface *dst, int *x, int *y) +{ + *x = (long)((char *)dst->pixels - mapped_mem)%this->screen->pitch; + *y = (long)((char *)dst->pixels - mapped_mem)/this->screen->pitch; + if ( dst == this->screen ) { + *x += this->offset_x; + *y += this->offset_y; + } +} + +#endif /* _SDL_fbvideo_h */ diff --git a/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h new file mode 100644 index 0000000..a1cf203 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/matrox_mmio.h @@ -0,0 +1,51 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +/* MGA register definitions */ + +#include "matrox_regs.h" + +/* MGA control macros */ + +#define mga_in8(reg) *(volatile Uint8 *)(mapped_io + (reg)) +#define mga_in32(reg) *(volatile Uint32 *)(mapped_io + (reg)) + +#define mga_out8(reg,v) *(volatile Uint8 *)(mapped_io + (reg)) = v; +#define mga_out32(reg,v) *(volatile Uint32 *)(mapped_io + (reg)) = v; + + +/* Wait for fifo space */ +#define mga_wait(space) \ +{ \ + while ( mga_in8(MGAREG_FIFOSTATUS) < space ) \ + ; \ +} + + +/* Wait for idle accelerator */ +#define mga_waitidle() \ +{ \ + while ( mga_in32(MGAREG_STATUS) & 0x10000 ) \ + ; \ +} + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h new file mode 100644 index 0000000..d570b0c --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/matrox_regs.h @@ -0,0 +1,376 @@ + +/* + * MGA Millennium (MGA2064W) functions + * MGA Mystique (MGA1064SG) functions + * + * Copyright 1996 The XFree86 Project, Inc. + * + * Authors + * Dirk Hohndel + * hohndel@XFree86.Org + * David Dawes + * dawes@XFree86.Org + * Contributors: + * Guy DESBIEF, Aix-en-provence, France + * g.desbief@aix.pacwan.net + * MGA1064SG Mystique register file + */ + + +#ifndef _MGA_REG_H_ +#define _MGA_REG_H_ + +#define MGAREG_DWGCTL 0x1c00 +#define MGAREG_MACCESS 0x1c04 +/* the following is a mystique only register */ +#define MGAREG_MCTLWTST 0x1c08 +#define MGAREG_ZORG 0x1c0c + +#define MGAREG_PAT0 0x1c10 +#define MGAREG_PAT1 0x1c14 +#define MGAREG_PLNWT 0x1c1c + +#define MGAREG_BCOL 0x1c20 +#define MGAREG_FCOL 0x1c24 + +#define MGAREG_SRC0 0x1c30 +#define MGAREG_SRC1 0x1c34 +#define MGAREG_SRC2 0x1c38 +#define MGAREG_SRC3 0x1c3c + +#define MGAREG_XYSTRT 0x1c40 +#define MGAREG_XYEND 0x1c44 + +#define MGAREG_SHIFT 0x1c50 +/* the following is a mystique only register */ +#define MGAREG_DMAPAD 0x1c54 +#define MGAREG_SGN 0x1c58 +#define MGAREG_LEN 0x1c5c + +#define MGAREG_AR0 0x1c60 +#define MGAREG_AR1 0x1c64 +#define MGAREG_AR2 0x1c68 +#define MGAREG_AR3 0x1c6c +#define MGAREG_AR4 0x1c70 +#define MGAREG_AR5 0x1c74 +#define MGAREG_AR6 0x1c78 + +#define MGAREG_CXBNDRY 0x1c80 +#define MGAREG_FXBNDRY 0x1c84 +#define MGAREG_YDSTLEN 0x1c88 +#define MGAREG_PITCH 0x1c8c + +#define MGAREG_YDST 0x1c90 +#define MGAREG_YDSTORG 0x1c94 +#define MGAREG_YTOP 0x1c98 +#define MGAREG_YBOT 0x1c9c + +#define MGAREG_CXLEFT 0x1ca0 +#define MGAREG_CXRIGHT 0x1ca4 +#define MGAREG_FXLEFT 0x1ca8 +#define MGAREG_FXRIGHT 0x1cac + +#define MGAREG_XDST 0x1cb0 + +#define MGAREG_DR0 0x1cc0 +#define MGAREG_DR1 0x1cc4 +#define MGAREG_DR2 0x1cc8 +#define MGAREG_DR3 0x1ccc + +#define MGAREG_DR4 0x1cd0 +#define MGAREG_DR5 0x1cd4 +#define MGAREG_DR6 0x1cd8 +#define MGAREG_DR7 0x1cdc + +#define MGAREG_DR8 0x1ce0 +#define MGAREG_DR9 0x1ce4 +#define MGAREG_DR10 0x1ce8 +#define MGAREG_DR11 0x1cec + +#define MGAREG_DR12 0x1cf0 +#define MGAREG_DR13 0x1cf4 +#define MGAREG_DR14 0x1cf8 +#define MGAREG_DR15 0x1cfc + +#define MGAREG_SRCORG 0x2cb4 +#define MGAREG_DSTORG 0x2cb8 + +/* add or or this to one of the previous "power registers" to start + the drawing engine */ + +#define MGAREG_EXEC 0x0100 + +#define MGAREG_FIFOSTATUS 0x1e10 +#define MGAREG_STATUS 0x1e14 +#define MGAREG_ICLEAR 0x1e18 +#define MGAREG_IEN 0x1e1c + +#define MGAREG_VCOUNT 0x1e20 + +#define MGAREG_Reset 0x1e40 + +#define MGAREG_OPMODE 0x1e54 + +/* OPMODE register additives */ + +#define MGAOPM_DMA_GENERAL (0x00 << 2) +#define MGAOPM_DMA_BLIT (0x01 << 2) +#define MGAOPM_DMA_VECTOR (0x10 << 2) + +/* DWGCTL register additives */ + +/* Lines */ + +#define MGADWG_LINE_OPEN 0x00 +#define MGADWG_AUTOLINE_OPEN 0x01 +#define MGADWG_LINE_CLOSE 0x02 +#define MGADWG_AUTOLINE_CLOSE 0x03 + +/* Trapezoids */ +#define MGADWG_TRAP 0x04 +#define MGADWG_TEXTURE_TRAP 0x05 + +/* BitBlts */ + +#define MGADWG_BITBLT 0x08 +#define MGADWG_FBITBLT 0x0c +#define MGADWG_ILOAD 0x09 +#define MGADWG_ILOAD_SCALE 0x0d +#define MGADWG_ILOAD_FILTER 0x0f +#define MGADWG_IDUMP 0x0a + +/* atype access to WRAM */ + +#define MGADWG_RPL ( 0x00 << 4 ) +#define MGADWG_RSTR ( 0x01 << 4 ) +#define MGADWG_ZI ( 0x03 << 4 ) +#define MGADWG_BLK ( 0x04 << 4 ) +#define MGADWG_I ( 0x07 << 4 ) + +/* specifies whether bit blits are linear or xy */ +#define MGADWG_LINEAR ( 0x01 << 7 ) + +/* z drawing mode. use MGADWG_NOZCMP for always */ + +#define MGADWG_NOZCMP ( 0x00 << 8 ) +#define MGADWG_ZE ( 0x02 << 8 ) +#define MGADWG_ZNE ( 0x03 << 8 ) +#define MGADWG_ZLT ( 0x04 << 8 ) +#define MGADWG_ZLTE ( 0x05 << 8 ) +#define MGADWG_GT ( 0x06 << 8 ) +#define MGADWG_GTE ( 0x07 << 8 ) + +/* use this to force colour expansion circuitry to do its stuff */ + +#define MGADWG_SOLID ( 0x01 << 11 ) + +/* ar register at zero */ + +#define MGADWG_ARZERO ( 0x01 << 12 ) + +#define MGADWG_SGNZERO ( 0x01 << 13 ) + +#define MGADWG_SHIFTZERO ( 0x01 << 14 ) + +/* See table on 4-43 for bop ALU operations */ + +/* See table on 4-44 for translucidity masks */ + +#define MGADWG_BMONOLEF ( 0x00 << 25 ) +#define MGADWG_BMONOWF ( 0x04 << 25 ) +#define MGADWG_BPLAN ( 0x01 << 25 ) + +/* note that if bfcol is specified and you're doing a bitblt, it causes + a fbitblt to be performed, so check that you obey the fbitblt rules */ + +#define MGADWG_BFCOL ( 0x02 << 25 ) +#define MGADWG_BUYUV ( 0x0e << 25 ) +#define MGADWG_BU32BGR ( 0x03 << 25 ) +#define MGADWG_BU32RGB ( 0x07 << 25 ) +#define MGADWG_BU24BGR ( 0x0b << 25 ) +#define MGADWG_BU24RGB ( 0x0f << 25 ) + +#define MGADWG_REPLACE 0x000C0000 /* From Linux kernel sources */ +#define MGADWG_PATTERN ( 0x01 << 29 ) +#define MGADWG_TRANSC ( 0x01 << 30 ) +#define MGADWG_NOCLIP ( 0x01 << 31 ) +#define MGAREG_MISC_WRITE 0x3c2 +#define MGAREG_MISC_READ 0x3cc +#define MGAREG_MISC_IOADSEL (0x1 << 0) +#define MGAREG_MISC_RAMMAPEN (0x1 << 1) +#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2) +#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2) +#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2) +#define MGAREG_MISC_VIDEO_DIS (0x1 << 4) +#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5) + +/* MMIO VGA registers */ +#define MGAREG_CRTC_INDEX 0x1fd4 +#define MGAREG_CRTC_DATA 0x1fd5 +#define MGAREG_CRTCEXT_INDEX 0x1fde +#define MGAREG_CRTCEXT_DATA 0x1fdf + + +/* MGA bits for registers PCI_OPTION_REG */ +#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 ) +#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 ) +#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 ) +#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 ) + +#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 ) +#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 ) + +#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 ) +#define MGA1064_OPT_VGA_ION ( 0x01 << 8 ) + +/* MGA registers in PCI config space */ +#define PCI_MGA_INDEX 0x44 +#define PCI_MGA_DATA 0x48 +#define PCI_MGA_OPTION2 0x50 +#define PCI_MGA_OPTION3 0x54 + +#define RAMDAC_OFFSET 0x3c00 + +/* TVP3026 direct registers */ + +#define TVP3026_INDEX 0x00 +#define TVP3026_WADR_PAL 0x00 +#define TVP3026_COL_PAL 0x01 +#define TVP3026_PIX_RD_MSK 0x02 +#define TVP3026_RADR_PAL 0x03 +#define TVP3026_CUR_COL_ADDR 0x04 +#define TVP3026_CUR_COL_DATA 0x05 +#define TVP3026_DATA 0x0a +#define TVP3026_CUR_RAM 0x0b +#define TVP3026_CUR_XLOW 0x0c +#define TVP3026_CUR_XHI 0x0d +#define TVP3026_CUR_YLOW 0x0e +#define TVP3026_CUR_YHI 0x0f + +/* TVP3026 indirect registers */ + +#define TVP3026_SILICON_REV 0x01 +#define TVP3026_CURSOR_CTL 0x06 +#define TVP3026_LATCH_CTL 0x0f +#define TVP3026_TRUE_COLOR_CTL 0x18 +#define TVP3026_MUX_CTL 0x19 +#define TVP3026_CLK_SEL 0x1a +#define TVP3026_PAL_PAGE 0x1c +#define TVP3026_GEN_CTL 0x1d +#define TVP3026_MISC_CTL 0x1e +#define TVP3026_GEN_IO_CTL 0x2a +#define TVP3026_GEN_IO_DATA 0x2b +#define TVP3026_PLL_ADDR 0x2c +#define TVP3026_PIX_CLK_DATA 0x2d +#define TVP3026_MEM_CLK_DATA 0x2e +#define TVP3026_LOAD_CLK_DATA 0x2f +#define TVP3026_KEY_RED_LOW 0x32 +#define TVP3026_KEY_RED_HI 0x33 +#define TVP3026_KEY_GREEN_LOW 0x34 +#define TVP3026_KEY_GREEN_HI 0x35 +#define TVP3026_KEY_BLUE_LOW 0x36 +#define TVP3026_KEY_BLUE_HI 0x37 +#define TVP3026_KEY_CTL 0x38 +#define TVP3026_MCLK_CTL 0x39 +#define TVP3026_SENSE_TEST 0x3a +#define TVP3026_TEST_DATA 0x3b +#define TVP3026_CRC_LSB 0x3c +#define TVP3026_CRC_MSB 0x3d +#define TVP3026_CRC_CTL 0x3e +#define TVP3026_ID 0x3f +#define TVP3026_RESET 0xff + + +/* MGA1064 DAC Register file */ +/* MGA1064 direct registers */ + +#define MGA1064_INDEX 0x00 +#define MGA1064_WADR_PAL 0x00 +#define MGA1064_COL_PAL 0x01 +#define MGA1064_PIX_RD_MSK 0x02 +#define MGA1064_RADR_PAL 0x03 +#define MGA1064_DATA 0x0a + +#define MGA1064_CUR_XLOW 0x0c +#define MGA1064_CUR_XHI 0x0d +#define MGA1064_CUR_YLOW 0x0e +#define MGA1064_CUR_YHI 0x0f + +/* MGA1064 indirect registers */ +#define MGA1064_CURSOR_BASE_ADR_LOW 0x04 +#define MGA1064_CURSOR_BASE_ADR_HI 0x05 +#define MGA1064_CURSOR_CTL 0x06 +#define MGA1064_CURSOR_COL0_RED 0x08 +#define MGA1064_CURSOR_COL0_GREEN 0x09 +#define MGA1064_CURSOR_COL0_BLUE 0x0a + +#define MGA1064_CURSOR_COL1_RED 0x0c +#define MGA1064_CURSOR_COL1_GREEN 0x0d +#define MGA1064_CURSOR_COL1_BLUE 0x0e + +#define MGA1064_CURSOR_COL2_RED 0x010 +#define MGA1064_CURSOR_COL2_GREEN 0x011 +#define MGA1064_CURSOR_COL2_BLUE 0x012 + +#define MGA1064_VREF_CTL 0x018 + +#define MGA1064_MUL_CTL 0x19 +#define MGA1064_MUL_CTL_8bits 0x0 +#define MGA1064_MUL_CTL_15bits 0x01 +#define MGA1064_MUL_CTL_16bits 0x02 +#define MGA1064_MUL_CTL_24bits 0x03 +#define MGA1064_MUL_CTL_32bits 0x04 +#define MGA1064_MUL_CTL_2G8V16bits 0x05 +#define MGA1064_MUL_CTL_G16V16bits 0x06 +#define MGA1064_MUL_CTL_32_24bits 0x07 + +#define MGAGDAC_XVREFCTRL 0x18 +#define MGA1064_PIX_CLK_CTL 0x1a +#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 ) +#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 ) +#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 ) +#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 ) + +#define MGA1064_GEN_CTL 0x1d +#define MGA1064_MISC_CTL 0x1e +#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 ) +#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 ) +#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 ) +#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 ) +#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 ) +#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 ) + +#define MGA1064_GEN_IO_CTL 0x2a +#define MGA1064_GEN_IO_DATA 0x2b +#define MGA1064_SYS_PLL_M 0x2c +#define MGA1064_SYS_PLL_N 0x2d +#define MGA1064_SYS_PLL_P 0x2e +#define MGA1064_SYS_PLL_STAT 0x2f +#define MGA1064_ZOOM_CTL 0x38 +#define MGA1064_SENSE_TST 0x3a + +#define MGA1064_CRC_LSB 0x3c +#define MGA1064_CRC_MSB 0x3d +#define MGA1064_CRC_CTL 0x3e +#define MGA1064_COL_KEY_MSK_LSB 0x40 +#define MGA1064_COL_KEY_MSK_MSB 0x41 +#define MGA1064_COL_KEY_LSB 0x42 +#define MGA1064_COL_KEY_MSB 0x43 +#define MGA1064_PIX_PLLA_M 0x44 +#define MGA1064_PIX_PLLA_N 0x45 +#define MGA1064_PIX_PLLA_P 0x46 +#define MGA1064_PIX_PLLB_M 0x48 +#define MGA1064_PIX_PLLB_N 0x49 +#define MGA1064_PIX_PLLB_P 0x4a +#define MGA1064_PIX_PLLC_M 0x4c +#define MGA1064_PIX_PLLC_N 0x4d +#define MGA1064_PIX_PLLC_P 0x4e + +#define MGA1064_PIX_PLL_STAT 0x4f + +#endif + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h b/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h new file mode 100644 index 0000000..e926167 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/riva_mmio.h @@ -0,0 +1,449 @@ +/***************************************************************************\ +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| +\***************************************************************************/ + +#ifndef __RIVA_HW_H__ +#define __RIVA_HW_H__ +#define RIVA_SW_VERSION 0x00010003 + +/* + * Typedefs to force certain sized values. + */ +typedef Uint8 U008; +typedef Uint16 U016; +typedef Uint32 U032; + +/* + * HW access macros. + */ +#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d)) +#define NV_RD08(p,i) (((U008 *)(p))[i]) +#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d)) +#define NV_RD16(p,i) (((U016 *)(p))[(i)/2]) +#define NV_WR32(p,i,d) (((U032 *)(p))[(i)/4]=(d)) +#define NV_RD32(p,i) (((U032 *)(p))[(i)/4]) +#define VGA_WR08(p,i,d) NV_WR08(p,i,d) +#define VGA_RD08(p,i) NV_RD08(p,i) + +/* + * Define supported architectures. + */ +#define NV_ARCH_03 0x03 +#define NV_ARCH_04 0x04 +#define NV_ARCH_10 0x10 +/***************************************************************************\ +* * +* FIFO registers. * +* * +\***************************************************************************/ + +/* + * Raster OPeration. Windows style ROP3. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 Rop3; +} RivaRop; +/* + * 8X8 Monochrome pattern. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Shape; + U032 reserved03[0x001]; + U032 Color0; + U032 Color1; + U032 Monochrome[2]; +} RivaPattern; +/* + * Scissor clip rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeft; + U032 WidthHeight; +} RivaClip; +/* + * 2D filled rectangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; + U032 reserved03[0x03E]; + U032 TopLeft; + U032 WidthHeight; +} RivaRectangle; +/* + * 2D screen-screen BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 TopLeftSrc; + U032 TopLeftDst; + U032 WidthHeight; +} RivaScreenBlt; +/* + * 2D pixel BLT. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 TopLeft; + U032 WidthHeight; + U032 WidthHeightIn; + U032 reserved02[0x03C]; + U032 Pixels; +} RivaPixmap; +/* + * Filled rectangle combined with monochrome expand. Useful for glyphs. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 reserved03[(0x040)-1]; + U032 Color1A; + struct + { + U032 TopLeft; + U032 WidthHeight; + } UnclippedRectangle[64]; + U032 reserved04[(0x080)-3]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipB; + U032 Color1B; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClippedRectangle[64]; + U032 reserved05[(0x080)-5]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipC; + U032 Color1C; + U032 WidthHeightC; + U032 PointC; + U032 MonochromeData1C; + U032 reserved06[(0x080)+121]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipD; + U032 Color1D; + U032 WidthHeightInD; + U032 WidthHeightOutD; + U032 PointD; + U032 MonochromeData1D; + U032 reserved07[(0x080)+120]; + struct + { + U032 TopLeft; + U032 BottomRight; + } ClipE; + U032 Color0E; + U032 Color1E; + U032 WidthHeightInE; + U032 WidthHeightOutE; + U032 PointE; + U032 MonochromeData01E; +} RivaBitmap; +/* + * 3D textured, Z buffered triangle. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BC]; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 FogColor; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 AlphaTest; + U032 reserved02[0x339]; + U032 FogAndIndex; + U032 Color; + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + float TextureS; + float TextureT; +} RivaTexturedTriangle03; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BB]; + U032 ColorKey; + U032 TextureOffset; + U032 TextureFormat; + U032 TextureFilter; + U032 Blend; +/* This is a problem on LynxOS */ +#ifdef Control +#undef Control +#endif + U032 Control; + U032 FogColor; + U032 reserved02[0x39]; + struct + { + float ScreenX; + float ScreenY; + float ScreenZ; + float EyeM; + U032 Color; + U032 Specular; + float TextureS; + float TextureT; + } Vertex[16]; + U032 DrawTriangle3D; +} RivaTexturedTriangle05; +/* + * 2D line. + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop[1]; + U032 reserved01[0x0BC]; + U032 Color; /* source color 0304-0307*/ + U032 Reserved02[0x03e]; + struct { /* start aliased methods in array 0400- */ + U032 point0; /* y_x S16_S16 in pixels 0- 3*/ + U032 point1; /* y_x S16_S16 in pixels 4- 7*/ + } Lin[16]; /* end of aliased methods in array -047f*/ + struct { /* start aliased methods in array 0480- */ + U032 point0X; /* in pixels, 0 at left 0- 3*/ + U032 point0Y; /* in pixels, 0 at top 4- 7*/ + U032 point1X; /* in pixels, 0 at left 8- b*/ + U032 point1Y; /* in pixels, 0 at top c- f*/ + } Lin32[8]; /* end of aliased methods in array -04ff*/ + U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/ + struct { /* start aliased methods in array 0580- */ + U032 x; /* in pixels, 0 at left 0- 3*/ + U032 y; /* in pixels, 0 at top 4- 7*/ + } PolyLin32[16]; /* end of aliased methods in array -05ff*/ + struct { /* start aliased methods in array 0600- */ + U032 color; /* source color 0- 3*/ + U032 point; /* y_x S16_S16 in pixels 4- 7*/ + } ColorPolyLin[16]; /* end of aliased methods in array -067f*/ +} RivaLine; +/* + * 2D/3D surfaces + */ +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BE]; + U032 Offset; +} RivaSurface; +typedef volatile struct +{ + U032 reserved00[4]; + U016 FifoFree; + U016 Nop; + U032 reserved01[0x0BD]; + U032 Pitch; + U032 RenderBufferOffset; + U032 ZBufferOffset; +} RivaSurface3D; + +/***************************************************************************\ +* * +* Virtualized RIVA H/W interface. * +* * +\***************************************************************************/ + +struct _riva_hw_inst; +struct _riva_hw_state; +/* + * Virtialized chip interface. Makes RIVA 128 and TNT look alike. + */ +typedef struct _riva_hw_inst +{ + /* + * Chip specific settings. + */ + U032 Architecture; + U032 Version; + U032 CrystalFreqKHz; + U032 RamAmountKBytes; + U032 MaxVClockFreqKHz; + U032 RamBandwidthKBytesPerSec; + U032 EnableIRQ; + U032 IO; + U032 VBlankBit; + U032 FifoFreeCount; + U032 FifoEmptyCount; + /* + * Non-FIFO registers. + */ + volatile U032 *PCRTC; + volatile U032 *PRAMDAC; + volatile U032 *PFB; + volatile U032 *PFIFO; + volatile U032 *PGRAPH; + volatile U032 *PEXTDEV; + volatile U032 *PTIMER; + volatile U032 *PMC; + volatile U032 *PRAMIN; + volatile U032 *FIFO; + volatile U032 *CURSOR; + volatile U032 *CURSORPOS; + volatile U032 *VBLANKENABLE; + volatile U032 *VBLANK; + volatile U008 *PCIO; + volatile U008 *PVIO; + volatile U008 *PDIO; + /* + * Common chip functions. + */ + int (*Busy)(struct _riva_hw_inst *); + void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int); + void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); + void (*SetStartAddress)(struct _riva_hw_inst *,U032); + void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032); + void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032); + int (*ShowHideCursor)(struct _riva_hw_inst *,int); + void (*LockUnlock)(struct _riva_hw_inst *, int); + /* + * Current extended mode settings. + */ + struct _riva_hw_state *CurrentState; + /* + * FIFO registers. + */ + RivaRop *Rop; + RivaPattern *Patt; + RivaClip *Clip; + RivaPixmap *Pixmap; + RivaScreenBlt *Blt; + RivaBitmap *Bitmap; + RivaLine *Line; + RivaTexturedTriangle03 *Tri03; + RivaTexturedTriangle05 *Tri05; +} RIVA_HW_INST; +/* + * Extended mode state information. + */ +typedef struct _riva_hw_state +{ + U032 bpp; + U032 width; + U032 height; + U032 repaint0; + U032 repaint1; + U032 screen; + U032 pixel; + U032 horiz; + U032 arbitration0; + U032 arbitration1; + U032 vpll; + U032 pllsel; + U032 general; + U032 config; + U032 cursor0; + U032 cursor1; + U032 cursor2; + U032 offset0; + U032 offset1; + U032 offset2; + U032 offset3; + U032 pitch0; + U032 pitch1; + U032 pitch2; + U032 pitch3; +} RIVA_HW_STATE; + +/* + * FIFO Free Count. Should attempt to yield processor if RIVA is busy. + */ + +#define RIVA_FIFO_FREE(hwptr,cnt) \ +{ \ + while (FifoFreeCount < (cnt)) \ + FifoFreeCount = hwptr->FifoFree >> 2; \ + FifoFreeCount -= (cnt); \ +} +#endif /* __RIVA_HW_H__ */ + diff --git a/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h b/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h new file mode 100644 index 0000000..5324562 --- /dev/null +++ b/distrib/sdl-1.2.15/src/video/fbcon/riva_regs.h @@ -0,0 +1,43 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _RIVA_REGS_H +#define _RIVA_REGS_H + +/* This information comes from the XFree86 NVidia hardware driver */ + +/* mapped_io register offsets */ +#define PGRAPH_OFFSET 0x00400000 +#define FIFO_OFFSET 0x00800000 +#define ROP_OFFSET FIFO_OFFSET+0x00000000 +#define CLIP_OFFSET FIFO_OFFSET+0x00002000 +#define PATT_OFFSET FIFO_OFFSET+0x00004000 +#define PIXMAP_OFFSET FIFO_OFFSET+0x00006000 +#define BLT_OFFSET FIFO_OFFSET+0x00008000 +#define BITMAP_OFFSET FIFO_OFFSET+0x0000A000 +#define LINE_OFFSET FIFO_OFFSET+0x0000C000 +#define TRI03_OFFSET FIFO_OFFSET+0x0000E000 +#define PCIO_OFFSET 0x00601000 + +#endif /* _RIVA_REGS_H */ + |