summaryrefslogtreecommitdiffstats
path: root/src/glut/fbdev/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glut/fbdev/cursor.c')
-rw-r--r--src/glut/fbdev/cursor.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/glut/fbdev/cursor.c b/src/glut/fbdev/cursor.c
new file mode 100644
index 00000000000..9254e125593
--- /dev/null
+++ b/src/glut/fbdev/cursor.c
@@ -0,0 +1,264 @@
+/*
+ * 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();
+}