Files
mesa/src/glut/fbdev/cursor.c
T
Sean D'Epagnier bd3e6ec066 VT switching now uses correct keys.
exiting when virtual screen size is larger than regular size doesn't corrupt screen.
colormap is reset when using stdin input on exit.
return is not reported as ctrl-m but '\r' as it should be
backspace keycode was incorrect and not working, fixed
2006-08-23 07:55:48 +00:00

265 lines
6.4 KiB
C

/*
* Mesa 3-D graphics library
* Version: 6.5
* Copyright (C) 1995-2006 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Library for glut using mesa fbdev driver
*
* Written by Sean D'Epagnier (c) 2006
*/
/* these routines are written to access graphics memory directly, not using mesa
to render the cursor, this is faster, it would be good to use a hardware
cursor if it exists instead */
#include <stdlib.h>
#include <inttypes.h>
#include <linux/fb.h>
#include <GL/glut.h>
#include "internal.h"
#include "cursors.h"
int CurrentCursor = GLUT_CURSOR_LEFT_ARROW;
static int LastMouseX, LastMouseY;
static unsigned char *MouseBuffer;
void InitializeCursor(void)
{
if(!MouseBuffer && (MouseBuffer = malloc(CURSOR_WIDTH * CURSOR_HEIGHT
* VarInfo.bits_per_pixel / 8)) == NULL) {
sprintf(exiterror, "malloc failure\n");
exit(0);
}
MouseX = VarInfo.xres / 2;
MouseY = VarInfo.yres / 2;
}
void EraseCursor(void)
{
int off = LastMouseY * FixedInfo.line_length
+ LastMouseX * VarInfo.bits_per_pixel / 8;
int stride = CURSOR_WIDTH * VarInfo.bits_per_pixel / 8;
int i;
unsigned char *src = MouseBuffer;
for(i = 0; i<CURSOR_HEIGHT; i++) {
memcpy(BackBuffer + off, src, stride);
src += stride;
off += FixedInfo.line_length;
}
}
static void SaveCursor(int x, int y)
{
int bypp, off, stride, i;
unsigned char *src = MouseBuffer;
if(x < 0)
LastMouseX = 0;
else
if(x > (int)VarInfo.xres - CURSOR_WIDTH)
LastMouseX = VarInfo.xres - CURSOR_WIDTH;
else
LastMouseX = x;
if(y < 0)
LastMouseY = 0;
else
if(y > (int)VarInfo.yres - CURSOR_HEIGHT)
LastMouseY = VarInfo.yres - CURSOR_HEIGHT;
else
LastMouseY = y;
bypp = VarInfo.bits_per_pixel / 8;
off = LastMouseY * FixedInfo.line_length + LastMouseX * bypp;
stride = CURSOR_WIDTH * bypp;
for(i = 0; i<CURSOR_HEIGHT; i++) {
memcpy(src, BackBuffer + off, stride);
src += stride;
off += FixedInfo.line_length;
}
}
void DrawCursor(void)
{
int i, j, px, py, xoff, xlen, yoff, ylen, bypp, cstride, dstride;
unsigned char *c;
const unsigned char *d;
if(CurrentCursor < 0 || CurrentCursor >= NUM_CURSORS)
return;
px = MouseX - CursorsXOffset[CurrentCursor];
py = MouseY - CursorsYOffset[CurrentCursor];
SaveCursor(px, py);
xoff = 0;
if(px < 0)
xoff = -px;
xlen = CURSOR_WIDTH;
if(px + CURSOR_WIDTH > VarInfo.xres)
xlen = VarInfo.xres - px;
yoff = 0;
if(py < 0)
yoff = -py;
ylen = CURSOR_HEIGHT;
if(py + CURSOR_HEIGHT > VarInfo.yres)
ylen = VarInfo.yres - py;
bypp = VarInfo.bits_per_pixel / 8;
c = BackBuffer + FixedInfo.line_length * (py + yoff) + (px + xoff) * bypp;
cstride = FixedInfo.line_length - bypp * (xlen - xoff);
d = Cursors[CurrentCursor] + (CURSOR_WIDTH * yoff + xoff)*4;
dstride = (CURSOR_WIDTH - xlen + xoff) * 4;
switch(bypp) {
case 1:
{
const int shift = 8 - REVERSECMAPSIZELOG;
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
if(d[3] < 220)
*c = ReverseColorMap
[(d[0]+(((int)(RedColorMap[c[0]]>>8)*d[3])>>8))>>shift]
[(d[1]+(((int)(GreenColorMap[c[0]]>>8)*d[3])>>8))>>shift]
[(d[2]+(((int)(BlueColorMap[c[0]]>>8)*d[3])>>8))>>shift];
c++;
d+=4;
}
d += dstride;
c += cstride;
}
} break;
case 2:
{
uint16_t *e = (void*)c;
cstride /= 2;
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
if(d[3] < 220)
e[0] = ((((d[0] + (((int)(((e[0] >> 8) & 0xf8)
| ((c[0] >> 11) & 0x7)) * d[3]) >> 8)) & 0xf8) << 8)
| (((d[1] + (((int)(((e[0] >> 3) & 0xfc)
| ((e[0] >> 5) & 0x3)) * d[3]) >> 8)) & 0xfc) << 3)
| ((d[2] + (((int)(((e[0] << 3) & 0xf8)
| (e[0] & 0x7)) * d[3]) >> 8)) >> 3));
e++;
d+=4;
}
d += dstride;
e += cstride;
}
} break;
case 3:
case 4:
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
if(d[3] < 220) {
c[0] = d[0] + (((int)c[0] * d[3]) >> 8);
c[1] = d[1] + (((int)c[1] * d[3]) >> 8);
c[2] = d[2] + (((int)c[2] * d[3]) >> 8);
}
c+=bypp;
d+=4;
}
d += dstride;
c += cstride;
} break;
}
}
#define MIN(x, y) x < y ? x : y
void SwapCursor(void)
{
int px = MouseX - CursorsXOffset[CurrentCursor];
int py = MouseY - CursorsYOffset[CurrentCursor];
int minx = MIN(px, LastMouseX);
int sizex = abs(px - LastMouseX);
int miny = MIN(py, LastMouseY);
int sizey = abs(py - LastMouseY);
DrawCursor();
/* now update the portion of the screen that has changed */
if(DisplayMode & GLUT_DOUBLE && (sizex || sizey)) {
int off, stride, i;
if(minx < 0)
minx = 0;
if(miny < 0)
miny = 0;
if(minx + sizex > VarInfo.xres - CURSOR_WIDTH)
sizex = VarInfo.xres - CURSOR_WIDTH - minx;
if(miny + sizey > VarInfo.yres - CURSOR_HEIGHT)
sizey = VarInfo.yres - CURSOR_HEIGHT - miny;
off = FixedInfo.line_length * miny
+ minx * VarInfo.bits_per_pixel / 8;
stride = (sizex + CURSOR_WIDTH) * VarInfo.bits_per_pixel / 8;
for(i = 0; i< sizey + CURSOR_HEIGHT; i++) {
memcpy(FrameBuffer+off, BackBuffer+off, stride);
off += FixedInfo.line_length;
}
}
}
void glutWarpPointer(int x, int y)
{
if(x < 0)
x = 0;
if(x >= VarInfo.xres)
x = VarInfo.xres - 1;
MouseX = x;
if(y < 0)
y = 0;
if(y >= VarInfo.yres)
y = VarInfo.yres - 1;
MouseY = y;
EraseCursor();
SwapCursor();
}
void glutSetCursor(int cursor)
{
if(cursor == GLUT_CURSOR_FULL_CROSSHAIR)
cursor = GLUT_CURSOR_CROSSHAIR;
CurrentCursor = cursor;
MouseEnabled = 1;
EraseCursor();
SwapCursor();
}