glFBDev driver from embedded-2 branch.
Probably won't be actively used/maintained, but bring it to the trunk so it doesn't get lost.
This commit is contained in:
parent
fde2b9750e
commit
a763123b35
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 5.1
|
||||
*
|
||||
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GLFBDEV_H
|
||||
#define GLFBDEV_H
|
||||
|
||||
|
||||
/* avoid including linux/fb.h */
|
||||
struct fb_fix_screeninfo;
|
||||
struct fb_var_screeninfo;
|
||||
|
||||
|
||||
/* public types */
|
||||
typedef struct GLFBDevVisualRec *GLFBDevVisualPtr;
|
||||
typedef struct GLFBDevBufferRec *GLFBDevBufferPtr;
|
||||
typedef struct GLFBDevContextRec *GLFBDevContextPtr;
|
||||
|
||||
|
||||
/* API version */
|
||||
#define GLFBDEV_VERSION_1_0 1
|
||||
|
||||
|
||||
/* For glFBDevCreateVisual */
|
||||
#define GLFBDEV_DOUBLE_BUFFER 100
|
||||
#define GLFBDEV_COLOR_INDEX 101
|
||||
#define GLFBDEV_DEPTH_SIZE 102
|
||||
#define GLFBDEV_STENCIL_SIZE 103
|
||||
#define GLFBDEV_ACCUM_SIZE 104
|
||||
#define GLFBDEV_LEVEL 105
|
||||
#define GLFBDEV_NONE 0
|
||||
|
||||
/* For glFBDevGetString */
|
||||
#define GLFBDEV_VERSION 200
|
||||
#define GLFBDEV_VENDOR 201
|
||||
|
||||
|
||||
/* Misc functions */
|
||||
|
||||
extern const char *
|
||||
glFBDevGetString( int str );
|
||||
|
||||
|
||||
extern const void *
|
||||
glFBDevGetProcAddress( const char *procName );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a GLFBDevVisual.
|
||||
* \param fixInfo - needed to get the visual types, etc.
|
||||
* \param varInfo - needed to get the bits_per_pixel, etc.
|
||||
* \param attribs - for requesting depth, stencil, accum buffers, etc.
|
||||
*/
|
||||
extern GLFBDevVisualPtr
|
||||
glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
|
||||
const struct fb_var_screeninfo *varInfo,
|
||||
const int *attribs );
|
||||
|
||||
extern void
|
||||
glFBDevDestroyVisual( GLFBDevVisualPtr visual );
|
||||
|
||||
extern int
|
||||
glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a GLFBDevBuffer.
|
||||
* \param fixInfo, varInfo - needed in order to get the screen size
|
||||
* (resolution), etc.
|
||||
* \param visual - as returned by glFBDevCreateVisual()
|
||||
* \param frontBuffer - address of front color buffer
|
||||
* \param backBuffer - address of back color buffer (may be NULL)
|
||||
* \param size - size of the color buffer(s) in bytes.
|
||||
*/
|
||||
extern GLFBDevBufferPtr
|
||||
glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
|
||||
const struct fb_var_screeninfo *varInfo,
|
||||
const GLFBDevVisualPtr visual,
|
||||
void *frontBuffer, void *backBuffer, size_t size );
|
||||
|
||||
extern void
|
||||
glFBDevDestroyBuffer( GLFBDevBufferPtr buffer );
|
||||
|
||||
extern int
|
||||
glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib);
|
||||
|
||||
extern GLFBDevBufferPtr
|
||||
glFBDevGetCurrentDrawBuffer( void );
|
||||
|
||||
extern GLFBDevBufferPtr
|
||||
glFBDevGetCurrentReadBuffer( void );
|
||||
|
||||
extern void
|
||||
glFBDevSwapBuffers( GLFBDevBufferPtr buffer );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a GLFBDevContext.
|
||||
* \param visual - as created by glFBDevCreateVisual.
|
||||
* \param share - specifies another context with which to share textures,
|
||||
* display lists, etc. (may be NULL).
|
||||
*/
|
||||
extern GLFBDevContextPtr
|
||||
glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share );
|
||||
|
||||
extern void
|
||||
glFBDevDestroyContext( GLFBDevContextPtr context );
|
||||
|
||||
extern int
|
||||
glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib);
|
||||
|
||||
extern GLFBDevContextPtr
|
||||
glFBDevGetCurrentContext( void );
|
||||
|
||||
extern int
|
||||
glFBDevMakeCurrent( GLFBDevContextPtr context,
|
||||
GLFBDevBufferPtr drawBuffer,
|
||||
GLFBDevBufferPtr readBuffer );
|
||||
|
||||
|
||||
#endif /* GLFBDEV_H */
|
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
* Test the GLFBDev interface. Only tested with radeonfb driver!!!!
|
||||
*
|
||||
* Written by Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/vt.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glfbdev.h>
|
||||
#include <math.h>
|
||||
|
||||
#define DEFAULT_DEPTH 8
|
||||
|
||||
static struct fb_fix_screeninfo FixedInfo;
|
||||
static struct fb_var_screeninfo VarInfo, OrigVarInfo;
|
||||
static int DesiredDepth = 0;
|
||||
static int OriginalVT = -1;
|
||||
static int ConsoleFD = -1;
|
||||
static int FrameBufferFD = -1;
|
||||
static caddr_t FrameBuffer = (caddr_t) -1;
|
||||
static caddr_t MMIOAddress = (caddr_t) -1;
|
||||
|
||||
|
||||
static void
|
||||
print_fixed_info(const struct fb_fix_screeninfo *fixed, const char *s)
|
||||
{
|
||||
static const char *visuals[] = {
|
||||
"MONO01", "MONO10", "TRUECOLOR", "PSEUDOCOLOR",
|
||||
"DIRECTCOLOR", "STATIC_PSEUDOCOLOR"
|
||||
};
|
||||
|
||||
printf("%s info -----------------------\n", s);
|
||||
printf("id = %16s\n", fixed->id);
|
||||
printf("smem_start = 0x%lx\n", fixed->smem_start);
|
||||
printf("smem_len = %d (0x%x)\n", fixed->smem_len, fixed->smem_len);
|
||||
printf("type = 0x%x\n", fixed->type);
|
||||
printf("type_aux = 0x%x\n", fixed->type_aux);
|
||||
printf("visual = 0x%x (%s)\n", fixed->visual, visuals[fixed->visual]);
|
||||
printf("xpanstep = %d\n", fixed->xpanstep);
|
||||
printf("ypanstep = %d\n", fixed->ypanstep);
|
||||
printf("ywrapstep = %d\n", fixed->ywrapstep);
|
||||
printf("line_length = %d\n", fixed->line_length);
|
||||
printf("mmio_start = 0x%lx\n", fixed->mmio_start);
|
||||
printf("mmio_len = %d (0x%x)\n", fixed->mmio_len, fixed->mmio_len);
|
||||
printf("accel = 0x%x\n", fixed->accel);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_var_info(const struct fb_var_screeninfo *var, const char *s)
|
||||
{
|
||||
printf("%s info -----------------------\n", s);
|
||||
printf("xres = %d\n", var->xres);
|
||||
printf("yres = %d\n", var->yres);
|
||||
printf("xres_virtual = %d\n", var->xres_virtual);
|
||||
printf("yres_virtual = %d\n", var->yres_virtual);
|
||||
printf("xoffset = %d\n", var->xoffset);
|
||||
printf("yoffset = %d\n", var->yoffset);
|
||||
printf("bits_per_pixel = %d\n", var->bits_per_pixel);
|
||||
printf("grayscale = %d\n", var->grayscale);
|
||||
|
||||
printf("red.offset = %d length = %d msb_right = %d\n",
|
||||
var->red.offset, var->red.length, var->red.msb_right);
|
||||
printf("green.offset = %d length = %d msb_right = %d\n",
|
||||
var->green.offset, var->green.length, var->green.msb_right);
|
||||
printf("blue.offset = %d length = %d msb_right = %d\n",
|
||||
var->blue.offset, var->blue.length, var->blue.msb_right);
|
||||
printf("transp.offset = %d length = %d msb_right = %d\n",
|
||||
var->transp.offset, var->transp.length, var->transp.msb_right);
|
||||
|
||||
printf("nonstd = %d\n", var->nonstd);
|
||||
printf("activate = %d\n", var->activate);
|
||||
printf("height = %d mm\n", var->height);
|
||||
printf("width = %d mm\n", var->width);
|
||||
printf("accel_flags = 0x%x\n", var->accel_flags);
|
||||
printf("pixclock = %d\n", var->pixclock);
|
||||
printf("left_margin = %d\n", var->left_margin);
|
||||
printf("right_margin = %d\n", var->right_margin);
|
||||
printf("upper_margin = %d\n", var->upper_margin);
|
||||
printf("lower_margin = %d\n", var->lower_margin);
|
||||
printf("hsync_len = %d\n", var->hsync_len);
|
||||
printf("vsync_len = %d\n", var->vsync_len);
|
||||
printf("sync = %d\n", var->sync);
|
||||
printf("vmode = %d\n", var->vmode);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
signal_handler(int signumber)
|
||||
{
|
||||
signal(signumber, SIG_IGN); /* prevent recursion! */
|
||||
fprintf(stderr, "error: got signal %d (exiting)\n", signumber);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
initialize_fbdev( void )
|
||||
{
|
||||
char ttystr[1000];
|
||||
int fd, vtnumber, ttyfd;
|
||||
int sz;
|
||||
|
||||
(void) sz;
|
||||
|
||||
if (geteuid()) {
|
||||
fprintf(stderr, "error: you need to be root\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* open the framebuffer device */
|
||||
FrameBufferFD = open("/dev/fb0", O_RDWR);
|
||||
if (FrameBufferFD < 0) {
|
||||
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* open /dev/tty0 and get the vt number */
|
||||
if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
|
||||
fprintf(stderr, "error opening /dev/tty0\n");
|
||||
exit(1);
|
||||
}
|
||||
if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
|
||||
fprintf(stderr, "error: couldn't get a free vt\n");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* open the console tty */
|
||||
sprintf(ttystr, "/dev/tty%d", vtnumber); /* /dev/tty1-64 */
|
||||
ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
|
||||
if (ConsoleFD < 0) {
|
||||
fprintf(stderr, "error couldn't open console fd\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* save current vt number */
|
||||
{
|
||||
struct vt_stat vts;
|
||||
if (ioctl(ConsoleFD, VT_GETSTATE, &vts) == 0)
|
||||
OriginalVT = vts.v_active;
|
||||
}
|
||||
|
||||
/* disconnect from controlling tty */
|
||||
ttyfd = open("/dev/tty", O_RDWR);
|
||||
if (ttyfd >= 0) {
|
||||
ioctl(ttyfd, TIOCNOTTY, 0);
|
||||
close(ttyfd);
|
||||
}
|
||||
|
||||
/* some magic to restore the vt when we exit */
|
||||
{
|
||||
struct vt_mode vt;
|
||||
if (ioctl(ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
|
||||
printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
|
||||
if (ioctl(ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
|
||||
printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
|
||||
|
||||
if (ioctl(ConsoleFD, VT_GETMODE, &vt) < 0) {
|
||||
fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vt.mode = VT_PROCESS;
|
||||
vt.relsig = SIGUSR1;
|
||||
vt.acqsig = SIGUSR1;
|
||||
if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
|
||||
fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* go into graphics mode */
|
||||
if (ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* open the framebuffer device */
|
||||
FrameBufferFD = open("/dev/fb0", O_RDWR);
|
||||
if (FrameBufferFD < 0) {
|
||||
fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the fixed screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
|
||||
fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_fixed_info(&FixedInfo, "Fixed");
|
||||
|
||||
|
||||
/* get the variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
|
||||
fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_var_info(&OrigVarInfo, "Orig Var");
|
||||
|
||||
/* operate on a copy */
|
||||
VarInfo = OrigVarInfo;
|
||||
|
||||
/* set the depth, resolution, etc */
|
||||
DesiredDepth = 32;
|
||||
if (DesiredDepth)
|
||||
VarInfo.bits_per_pixel = DesiredDepth;
|
||||
|
||||
if (VarInfo.bits_per_pixel == 16) {
|
||||
VarInfo.red.offset = 11;
|
||||
VarInfo.green.offset = 5;
|
||||
VarInfo.blue.offset = 0;
|
||||
VarInfo.red.length = 5;
|
||||
VarInfo.green.length = 6;
|
||||
VarInfo.blue.length = 5;
|
||||
VarInfo.transp.offset = 0;
|
||||
VarInfo.transp.length = 0;
|
||||
}
|
||||
else if (VarInfo.bits_per_pixel == 32) {
|
||||
VarInfo.red.offset = 16;
|
||||
VarInfo.green.offset = 8;
|
||||
VarInfo.blue.offset = 0;
|
||||
VarInfo.transp.offset = 24;
|
||||
VarInfo.red.length = 8;
|
||||
VarInfo.green.length = 8;
|
||||
VarInfo.blue.length = 8;
|
||||
VarInfo.transp.length = 8;
|
||||
}
|
||||
/* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
|
||||
VarInfo.xres_virtual = VarInfo.xres = 1280;
|
||||
VarInfo.yres_virtual = VarInfo.yres = 1024;
|
||||
VarInfo.pixclock = 7408;
|
||||
VarInfo.left_margin = 248;
|
||||
VarInfo.right_margin = 16;
|
||||
VarInfo.upper_margin = 38;
|
||||
VarInfo.lower_margin = 1;
|
||||
VarInfo.hsync_len = 144;
|
||||
VarInfo.vsync_len = 3;
|
||||
|
||||
VarInfo.xoffset = 0;
|
||||
VarInfo.yoffset = 0;
|
||||
VarInfo.nonstd = 0;
|
||||
VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
|
||||
|
||||
/* set new variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
|
||||
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
print_var_info(&VarInfo, "New Var");
|
||||
|
||||
if (FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
|
||||
FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
|
||||
fprintf(stderr, "non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n", FixedInfo.visual);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize colormap */
|
||||
if (FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
|
||||
struct fb_cmap cmap;
|
||||
unsigned short red[256], green[256], blue[256];
|
||||
int i;
|
||||
|
||||
/* we're assuming 256 entries here */
|
||||
printf("initializing directcolor colormap\n");
|
||||
cmap.start = 0;
|
||||
cmap.len = 256;
|
||||
cmap.red = red;
|
||||
cmap.green = green;
|
||||
cmap.blue = blue;
|
||||
cmap.transp = NULL;
|
||||
for (i = 0; i < cmap.len; i++) {
|
||||
red[i] = green[i] = blue[i] = (i << 8) | i;
|
||||
}
|
||||
if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
|
||||
fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fbdev says the frame buffer is at offset zero, and the mmio region
|
||||
* is immediately after.
|
||||
*/
|
||||
|
||||
/* mmap the framebuffer into our address space */
|
||||
FrameBuffer = (caddr_t) mmap(0, /* start */
|
||||
FixedInfo.smem_len, /* bytes */
|
||||
PROT_READ | PROT_WRITE, /* prot */
|
||||
MAP_SHARED, /* flags */
|
||||
FrameBufferFD, /* fd */
|
||||
0 /* offset */);
|
||||
if (FrameBuffer == (caddr_t) - 1) {
|
||||
fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
printf("FrameBuffer = %p\n", FrameBuffer);
|
||||
|
||||
#if 1
|
||||
/* mmap the MMIO region into our address space */
|
||||
MMIOAddress = (caddr_t) mmap(0, /* start */
|
||||
FixedInfo.mmio_len, /* bytes */
|
||||
PROT_READ | PROT_WRITE, /* prot */
|
||||
MAP_SHARED, /* flags */
|
||||
FrameBufferFD, /* fd */
|
||||
FixedInfo.smem_len /* offset */);
|
||||
if (MMIOAddress == (caddr_t) - 1) {
|
||||
fprintf(stderr, "error: unable to mmap mmio region: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
printf("MMIOAddress = %p\n", MMIOAddress);
|
||||
|
||||
/* try out some simple MMIO register reads */
|
||||
if (1)
|
||||
{
|
||||
typedef unsigned int CARD32;
|
||||
typedef unsigned char CARD8;
|
||||
#define RADEON_CONFIG_MEMSIZE 0x00f8
|
||||
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
|
||||
#define MMIO_IN32(base, offset) \
|
||||
*(volatile CARD32 *)(void *)(((CARD8*)(base)) + (offset))
|
||||
#define INREG(addr) MMIO_IN32(MMIOAddress, addr)
|
||||
int sz, type;
|
||||
const char *typeStr[] = {"SDR", "DDR", "64-bit SDR"};
|
||||
sz = INREG(RADEON_CONFIG_MEMSIZE);
|
||||
type = INREG(RADEON_MEM_SDRAM_MODE_REG);
|
||||
printf("RADEON_CONFIG_MEMSIZE = %d (%d MB)\n", sz, sz / 1024 / 1024);
|
||||
printf("RADEON_MEM_SDRAM_MODE_REG >> 30 = %d (%s)\n",
|
||||
type >> 30, typeStr[type>>30]);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
shutdown_fbdev( void )
|
||||
{
|
||||
struct vt_mode VT;
|
||||
|
||||
printf("cleaning up...\n");
|
||||
/* restore original variable screen info */
|
||||
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo)) {
|
||||
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
munmap(MMIOAddress, FixedInfo.mmio_len);
|
||||
munmap(FrameBuffer, FixedInfo.smem_len);
|
||||
close(FrameBufferFD);
|
||||
|
||||
/* restore text mode */
|
||||
ioctl(ConsoleFD, KDSETMODE, KD_TEXT);
|
||||
|
||||
/* set vt */
|
||||
if (ioctl(ConsoleFD, VT_GETMODE, &VT) != -1) {
|
||||
VT.mode = VT_AUTO;
|
||||
ioctl(ConsoleFD, VT_SETMODE, &VT);
|
||||
}
|
||||
|
||||
/* restore original vt */
|
||||
if (OriginalVT >= 0) {
|
||||
ioctl(ConsoleFD, VT_ACTIVATE, OriginalVT);
|
||||
OriginalVT = -1;
|
||||
}
|
||||
|
||||
close(ConsoleFD);
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from GLUT */
|
||||
static void
|
||||
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
}
|
||||
glEnd();
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gltest( void )
|
||||
{
|
||||
static const int attribs[] = {
|
||||
GLFBDEV_DOUBLE_BUFFER,
|
||||
GLFBDEV_DEPTH_SIZE, 16,
|
||||
GLFBDEV_NONE
|
||||
};
|
||||
GLFBDevContextPtr ctx;
|
||||
GLFBDevBufferPtr buf;
|
||||
GLFBDevVisualPtr vis;
|
||||
int bytes, r, g, b, a;
|
||||
float ang;
|
||||
|
||||
printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR));
|
||||
printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION));
|
||||
|
||||
/* framebuffer size */
|
||||
bytes = VarInfo.xres_virtual * VarInfo.yres_virtual * VarInfo.bits_per_pixel / 8;
|
||||
|
||||
vis = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs );
|
||||
assert(vis);
|
||||
|
||||
buf = glFBDevCreateBuffer( &FixedInfo, &VarInfo, vis, FrameBuffer, NULL, bytes );
|
||||
assert(buf);
|
||||
|
||||
ctx = glFBDevCreateContext( vis, NULL );
|
||||
assert(buf);
|
||||
|
||||
b = glFBDevMakeCurrent( ctx, buf, buf );
|
||||
assert(b);
|
||||
|
||||
/*printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));*/
|
||||
glGetIntegerv(GL_RED_BITS, &r);
|
||||
glGetIntegerv(GL_GREEN_BITS, &g);
|
||||
glGetIntegerv(GL_BLUE_BITS, &b);
|
||||
glGetIntegerv(GL_ALPHA_BITS, &a);
|
||||
printf("RED_BITS=%d GREEN_BITS=%d BLUE_BITS=%d ALPHA_BITS=%d\n",
|
||||
r, g, b, a);
|
||||
|
||||
glClearColor(0.5, 0.5, 1.0, 0);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-1, 1, -1, 1, 2, 30);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0, 0, -15);
|
||||
glViewport(0, 0, VarInfo.xres_virtual, VarInfo.yres_virtual);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for (ang = 0; ang <= 180; ang += 15) {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glPushMatrix();
|
||||
glRotatef(ang, 1, 0, 0);
|
||||
doughnut(1, 3, 40, 20);
|
||||
glPopMatrix();
|
||||
glFBDevSwapBuffers(buf);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
b = glFBDevMakeCurrent( NULL, NULL, NULL);
|
||||
assert(b);
|
||||
|
||||
glFBDevDestroyContext(ctx);
|
||||
glFBDevDestroyBuffer(buf);
|
||||
glFBDevDestroyVisual(vis);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */
|
||||
signal(SIGSEGV, signal_handler); /* catch segfaults */
|
||||
|
||||
initialize_fbdev();
|
||||
gltest();
|
||||
shutdown_fbdev();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,828 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 5.1
|
||||
*
|
||||
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* OpenGL (Mesa) interface for fbdev.
|
||||
* For info about fbdev:
|
||||
* http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html
|
||||
*
|
||||
* known VGA modes
|
||||
* Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
|
||||
* --------+--------------------------------------------------------------
|
||||
* 4 bits | ? ? 0x302 ? ? ? ?
|
||||
* 8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C
|
||||
* 15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D
|
||||
* 16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E
|
||||
* 24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F
|
||||
* 32 bits | ? ? ? ? 0x164 ?
|
||||
*/
|
||||
|
||||
|
||||
#ifdef USE_GLFBDEV_DRIVER
|
||||
|
||||
#include "glheader.h"
|
||||
#include <linux/fb.h>
|
||||
#include "GL/glfbdev.h"
|
||||
#include "context.h"
|
||||
#include "extensions.h"
|
||||
#include "imports.h"
|
||||
#include "texformat.h"
|
||||
#include "teximage.h"
|
||||
#include "texstore.h"
|
||||
#include "array_cache/acache.h"
|
||||
#include "swrast/swrast.h"
|
||||
#include "swrast_setup/swrast_setup.h"
|
||||
#include "tnl/tnl.h"
|
||||
#include "tnl/t_context.h"
|
||||
#include "tnl/t_pipeline.h"
|
||||
|
||||
|
||||
#define PF_B8G8R8 1
|
||||
#define PF_B8G8R8A8 2
|
||||
#define PF_B5G6R5 3
|
||||
#define PF_B5G5R5 4
|
||||
#define PF_CI8 5
|
||||
|
||||
|
||||
/*
|
||||
* Derived from Mesa's GLvisual class.
|
||||
*/
|
||||
struct GLFBDevVisualRec {
|
||||
GLvisual glvisual; /* base class */
|
||||
struct fb_fix_screeninfo fix;
|
||||
struct fb_var_screeninfo var;
|
||||
int pixelFormat;
|
||||
};
|
||||
|
||||
/*
|
||||
* Derived from Mesa's GLframebuffer class.
|
||||
*/
|
||||
struct GLFBDevBufferRec {
|
||||
GLframebuffer glframebuffer; /* base class */
|
||||
GLFBDevVisualPtr visual;
|
||||
struct fb_fix_screeninfo fix;
|
||||
struct fb_var_screeninfo var;
|
||||
void *frontStart;
|
||||
void *backStart;
|
||||
size_t size;
|
||||
GLuint bytesPerPixel;
|
||||
GLuint rowStride; /* in bytes */
|
||||
GLubyte *frontBottom; /* pointer to last row */
|
||||
GLubyte *backBottom; /* pointer to last row */
|
||||
GLubyte *curBottom; /* = frontBottom or backBottom */
|
||||
GLboolean mallocBackBuffer;
|
||||
};
|
||||
|
||||
/*
|
||||
* Derived from Mesa's GLcontext class.
|
||||
*/
|
||||
struct GLFBDevContextRec {
|
||||
GLcontext glcontext; /* base class */
|
||||
GLFBDevVisualPtr visual;
|
||||
GLFBDevBufferPtr drawBuffer;
|
||||
GLFBDevBufferPtr readBuffer;
|
||||
GLFBDevBufferPtr curBuffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define GLFBDEV_CONTEXT(CTX) ((GLFBDevContextPtr) (CTX))
|
||||
#define GLFBDEV_BUFFER(BUF) ((GLFBDevBufferPtr) (BUF))
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Internal device driver functions */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
static const GLubyte *
|
||||
get_string(GLcontext *ctx, GLenum pname)
|
||||
{
|
||||
(void) ctx;
|
||||
switch (pname) {
|
||||
case GL_RENDERER:
|
||||
return (const GLubyte *) "Mesa glfbdev";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_state( GLcontext *ctx, GLuint new_state )
|
||||
{
|
||||
/* not much to do here - pass it on */
|
||||
_swrast_InvalidateState( ctx, new_state );
|
||||
_swsetup_InvalidateState( ctx, new_state );
|
||||
_ac_InvalidateState( ctx, new_state );
|
||||
_tnl_InvalidateState( ctx, new_state );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
|
||||
{
|
||||
const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer;
|
||||
*width = fbdevbuffer->var.xres_virtual;
|
||||
*height = fbdevbuffer->var.yres_virtual;
|
||||
}
|
||||
|
||||
|
||||
/* specifies the buffer for swrast span rendering/reading */
|
||||
static void
|
||||
set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
|
||||
{
|
||||
GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx);
|
||||
GLFBDevBufferPtr fbdevbuf = GLFBDEV_BUFFER(buffer);
|
||||
fbdevctx->curBuffer = fbdevbuf;
|
||||
switch (bufferBit) {
|
||||
case FRONT_LEFT_BIT:
|
||||
fbdevbuf->curBottom = fbdevbuf->frontBottom;
|
||||
break;
|
||||
case BACK_LEFT_BIT:
|
||||
fbdevbuf->curBottom = fbdevbuf->backBottom;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad bufferBit in set_buffer()");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_core_functions( GLcontext *ctx )
|
||||
{
|
||||
ctx->Driver.GetString = get_string;
|
||||
ctx->Driver.UpdateState = update_state;
|
||||
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
|
||||
ctx->Driver.GetBufferSize = get_buffer_size;
|
||||
|
||||
ctx->Driver.Accum = _swrast_Accum;
|
||||
ctx->Driver.Bitmap = _swrast_Bitmap;
|
||||
ctx->Driver.Clear = _swrast_Clear; /* would be good to optimize */
|
||||
ctx->Driver.CopyPixels = _swrast_CopyPixels;
|
||||
ctx->Driver.DrawPixels = _swrast_DrawPixels;
|
||||
ctx->Driver.ReadPixels = _swrast_ReadPixels;
|
||||
ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
|
||||
|
||||
ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
|
||||
ctx->Driver.TexImage1D = _mesa_store_teximage1d;
|
||||
ctx->Driver.TexImage2D = _mesa_store_teximage2d;
|
||||
ctx->Driver.TexImage3D = _mesa_store_teximage3d;
|
||||
ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
|
||||
ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
|
||||
ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
|
||||
ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
|
||||
|
||||
ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
|
||||
ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
|
||||
ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
|
||||
ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
|
||||
ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
|
||||
ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
|
||||
|
||||
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
|
||||
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
|
||||
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
|
||||
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
|
||||
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
|
||||
ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
|
||||
ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
|
||||
ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
|
||||
ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Generate code for span functions.
|
||||
*/
|
||||
|
||||
/* 24-bit BGR */
|
||||
#define NAME(PREFIX) PREFIX##_B8G8R8
|
||||
#define SPAN_VARS \
|
||||
const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
|
||||
const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
|
||||
#define INIT_PIXEL_PTR(P, X, Y) \
|
||||
GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 3
|
||||
#define INC_PIXEL_PTR(P) P += 3
|
||||
#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
|
||||
P[0] = B; P[1] = G; P[2] = R
|
||||
#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
|
||||
P[0] = B; P[1] = G; P[2] = R
|
||||
#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
|
||||
R = P[2]; G = P[1]; B = P[0]; A = CHAN_MAX
|
||||
|
||||
#include "swrast/s_spantemp.h"
|
||||
|
||||
|
||||
/* 32-bit BGRA */
|
||||
#define NAME(PREFIX) PREFIX##_B8G8R8A8
|
||||
#define SPAN_VARS \
|
||||
const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
|
||||
const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
|
||||
#define INIT_PIXEL_PTR(P, X, Y) \
|
||||
GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 4
|
||||
#define INC_PIXEL_PTR(P) P += 4
|
||||
#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
|
||||
P[0] = B; P[1] = G; P[2] = R; P[3] = 255
|
||||
#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
|
||||
P[0] = B; P[1] = G; P[2] = R; P[3] = A
|
||||
#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
|
||||
R = P[2]; G = P[1]; B = P[0]; A = P[3]
|
||||
|
||||
#include "swrast/s_spantemp.h"
|
||||
|
||||
|
||||
/* 16-bit BGR (XXX implement dithering someday) */
|
||||
#define NAME(PREFIX) PREFIX##_B5G6R5
|
||||
#define SPAN_VARS \
|
||||
const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
|
||||
const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
|
||||
#define INIT_PIXEL_PTR(P, X, Y) \
|
||||
GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
|
||||
#define INC_PIXEL_PTR(P) P += 1
|
||||
#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
|
||||
*P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
|
||||
#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
|
||||
*P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
|
||||
#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
|
||||
R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
|
||||
G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
|
||||
B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
|
||||
A = CHAN_MAX
|
||||
|
||||
#include "swrast/s_spantemp.h"
|
||||
|
||||
|
||||
/* 15-bit BGR (XXX implement dithering someday) */
|
||||
#define NAME(PREFIX) PREFIX##_B5G5R5
|
||||
#define SPAN_VARS \
|
||||
const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
|
||||
const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
|
||||
#define INIT_PIXEL_PTR(P, X, Y) \
|
||||
GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
|
||||
#define INC_PIXEL_PTR(P) P += 1
|
||||
#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
|
||||
*P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
|
||||
#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
|
||||
*P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
|
||||
#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
|
||||
R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
|
||||
G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
|
||||
B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
|
||||
A = CHAN_MAX
|
||||
|
||||
#include "swrast/s_spantemp.h"
|
||||
|
||||
|
||||
/* 8-bit color index */
|
||||
#define NAME(PREFIX) PREFIX##_CI8
|
||||
#define SPAN_VARS \
|
||||
const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
|
||||
const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
|
||||
#define INIT_PIXEL_PTR(P, X, Y) \
|
||||
GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X)
|
||||
#define INC_PIXEL_PTR(P) P += 1
|
||||
#define STORE_CI_PIXEL(P, CI) \
|
||||
P[0] = CI
|
||||
#define FETCH_CI_PIXEL(CI, P) \
|
||||
CI = P[0]
|
||||
|
||||
#include "swrast/s_spantemp.h"
|
||||
|
||||
/**********************************************************************/
|
||||
/* Public API functions */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
const char *
|
||||
glFBDevGetString( int str )
|
||||
{
|
||||
switch (str) {
|
||||
case GLFBDEV_VENDOR:
|
||||
return "Mesa Project";
|
||||
case GLFBDEV_VERSION:
|
||||
return "1.0.0";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const void *
|
||||
glFBDevGetProcAddress( const char *procName )
|
||||
{
|
||||
struct name_address {
|
||||
const char *name;
|
||||
const void *func;
|
||||
};
|
||||
static const struct name_address functions[] = {
|
||||
{ "glFBDevGetString", (void *) glFBDevGetString },
|
||||
{ "glFBDevGetProcAddress", (void *) glFBDevGetProcAddress },
|
||||
{ "glFBDevCreateVisual", (void *) glFBDevCreateVisual },
|
||||
{ "glFBDevDestroyVisual", (void *) glFBDevDestroyVisual },
|
||||
{ "glFBDevGetVisualAttrib", (void *) glFBDevGetVisualAttrib },
|
||||
{ "glFBDevCreateBuffer", (void *) glFBDevCreateBuffer },
|
||||
{ "glFBDevDestroyBuffer", (void *) glFBDevDestroyBuffer },
|
||||
{ "glFBDevGetBufferAttrib", (void *) glFBDevGetBufferAttrib },
|
||||
{ "glFBDevGetCurrentDrawBuffer", (void *) glFBDevGetCurrentDrawBuffer },
|
||||
{ "glFBDevGetCurrentReadBuffer", (void *) glFBDevGetCurrentReadBuffer },
|
||||
{ "glFBDevSwapBuffers", (void *) glFBDevSwapBuffers },
|
||||
{ "glFBDevCreateContext", (void *) glFBDevCreateContext },
|
||||
{ "glFBDevDestroyContext", (void *) glFBDevDestroyContext },
|
||||
{ "glFBDevGetContextAttrib", (void *) glFBDevGetContextAttrib },
|
||||
{ "glFBDevGetCurrentContext", (void *) glFBDevGetCurrentContext },
|
||||
{ "glFBDevMakeCurrent", (void *) glFBDevMakeCurrent },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
const struct name_address *entry;
|
||||
for (entry = functions; entry->name; entry++) {
|
||||
if (_mesa_strcmp(entry->name, procName) == 0) {
|
||||
return entry->func;
|
||||
}
|
||||
}
|
||||
return _glapi_get_proc_address(procName);
|
||||
}
|
||||
|
||||
|
||||
GLFBDevVisualPtr
|
||||
glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
|
||||
const struct fb_var_screeninfo *varInfo,
|
||||
const int *attribs )
|
||||
{
|
||||
GLFBDevVisualPtr vis;
|
||||
const int *attrib;
|
||||
GLboolean rgbFlag = GL_TRUE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
|
||||
GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
|
||||
GLint indexBits = 0, depthBits = 0, stencilBits = 0;
|
||||
GLint accumRedBits = 0, accumGreenBits = 0;
|
||||
GLint accumBlueBits = 0, accumAlphaBits = 0;
|
||||
GLint numSamples = 0;
|
||||
|
||||
ASSERT(fixInfo);
|
||||
ASSERT(varInfo);
|
||||
|
||||
vis = CALLOC_STRUCT(GLFBDevVisualRec);
|
||||
if (!vis)
|
||||
return NULL;
|
||||
|
||||
vis->fix = *fixInfo; /* struct assignment */
|
||||
vis->var = *varInfo; /* struct assignment */
|
||||
|
||||
for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) {
|
||||
switch (*attrib) {
|
||||
case GLFBDEV_DOUBLE_BUFFER:
|
||||
dbFlag = GL_TRUE;
|
||||
break;
|
||||
case GLFBDEV_COLOR_INDEX:
|
||||
rgbFlag = GL_FALSE;
|
||||
break;
|
||||
case GLFBDEV_DEPTH_SIZE:
|
||||
depthBits = attrib[1];
|
||||
attrib++;
|
||||
break;
|
||||
case GLFBDEV_STENCIL_SIZE:
|
||||
stencilBits = attrib[1];
|
||||
attrib++;
|
||||
break;
|
||||
case GLFBDEV_ACCUM_SIZE:
|
||||
accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits
|
||||
= attrib[1];
|
||||
attrib++;
|
||||
break;
|
||||
case GLFBDEV_LEVEL:
|
||||
/* ignored for now */
|
||||
break;
|
||||
default:
|
||||
/* unexpected token */
|
||||
_mesa_free(vis);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (rgbFlag) {
|
||||
redBits = varInfo->red.length;
|
||||
greenBits = varInfo->green.length;
|
||||
blueBits = varInfo->blue.length;
|
||||
alphaBits = varInfo->transp.length;
|
||||
|
||||
if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
|
||||
fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& varInfo->bits_per_pixel == 24
|
||||
&& varInfo->red.offset == 16
|
||||
&& varInfo->green.offset == 8
|
||||
&& varInfo->blue.offset == 0) {
|
||||
vis->pixelFormat = PF_B8G8R8;
|
||||
}
|
||||
else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
|
||||
fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& varInfo->bits_per_pixel == 32
|
||||
&& varInfo->red.offset == 16
|
||||
&& varInfo->green.offset == 8
|
||||
&& varInfo->blue.offset == 0
|
||||
&& varInfo->transp.offset == 24) {
|
||||
vis->pixelFormat = PF_B8G8R8A8;
|
||||
}
|
||||
else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
|
||||
fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& varInfo->bits_per_pixel == 16
|
||||
&& varInfo->red.offset == 11
|
||||
&& varInfo->green.offset == 5
|
||||
&& varInfo->blue.offset == 0) {
|
||||
vis->pixelFormat = PF_B5G6R5;
|
||||
}
|
||||
else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
|
||||
fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& varInfo->bits_per_pixel == 16
|
||||
&& varInfo->red.offset == 10
|
||||
&& varInfo->green.offset == 5
|
||||
&& varInfo->blue.offset == 0) {
|
||||
vis->pixelFormat = PF_B5G5R5;
|
||||
}
|
||||
else {
|
||||
_mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
|
||||
/*
|
||||
printf("fixInfo->visual = 0x%x\n", fixInfo->visual);
|
||||
printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel);
|
||||
printf("varInfo->red.offset = %d\n", varInfo->red.offset);
|
||||
printf("varInfo->green.offset = %d\n", varInfo->green.offset);
|
||||
printf("varInfo->blue.offset = %d\n", varInfo->blue.offset);
|
||||
*/
|
||||
_mesa_free(vis);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexBits = varInfo->bits_per_pixel;
|
||||
if ((fixInfo->visual == FB_VISUAL_PSEUDOCOLOR ||
|
||||
fixInfo->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
|
||||
&& varInfo->bits_per_pixel == 8) {
|
||||
vis->pixelFormat = PF_CI8;
|
||||
}
|
||||
else {
|
||||
_mesa_problem(NULL, "Unsupported fbdev CI visual/bitdepth!\n");
|
||||
_mesa_free(vis);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_mesa_initialize_visual(&vis->glvisual, rgbFlag, dbFlag, stereoFlag,
|
||||
redBits, greenBits, blueBits, alphaBits,
|
||||
indexBits, depthBits, stencilBits,
|
||||
accumRedBits, accumGreenBits,
|
||||
accumBlueBits, accumAlphaBits,
|
||||
numSamples)) {
|
||||
/* something was invalid */
|
||||
_mesa_free(vis);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vis;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glFBDevDestroyVisual( GLFBDevVisualPtr visual )
|
||||
{
|
||||
if (visual)
|
||||
_mesa_free(visual);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib)
|
||||
{
|
||||
(void) visual;
|
||||
(void) attrib;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLFBDevBufferPtr
|
||||
glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
|
||||
const struct fb_var_screeninfo *varInfo,
|
||||
const GLFBDevVisualPtr visual,
|
||||
void *frontBuffer, void *backBuffer, size_t size )
|
||||
{
|
||||
GLFBDevBufferPtr buf;
|
||||
|
||||
ASSERT(visual);
|
||||
ASSERT(frontBuffer);
|
||||
ASSERT(size > 0);
|
||||
|
||||
if (visual->fix.visual != fixInfo->visual ||
|
||||
visual->fix.type != fixInfo->type ||
|
||||
visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
|
||||
visual->var.grayscale != varInfo->grayscale ||
|
||||
visual->var.red.offset != varInfo->red.offset ||
|
||||
visual->var.green.offset != varInfo->green.offset ||
|
||||
visual->var.blue.offset != varInfo->blue.offset ||
|
||||
visual->var.transp.offset != varInfo->transp.offset) {
|
||||
/* visual mismatch! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = CALLOC_STRUCT(GLFBDevBufferRec);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
_mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual,
|
||||
visual->glvisual.haveDepthBuffer,
|
||||
visual->glvisual.haveStencilBuffer,
|
||||
visual->glvisual.haveAccumBuffer,
|
||||
GL_FALSE);
|
||||
|
||||
buf->fix = *fixInfo; /* struct assignment */
|
||||
buf->var = *varInfo; /* struct assignment */
|
||||
buf->visual = visual; /* ptr assignment */
|
||||
buf->frontStart = frontBuffer;
|
||||
buf->size = size;
|
||||
buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
|
||||
buf->rowStride = visual->var.xres_virtual * buf->bytesPerPixel;
|
||||
buf->frontBottom = (GLubyte *) buf->frontStart
|
||||
+ (visual->var.yres_virtual - 1) * buf->rowStride;
|
||||
|
||||
if (visual->glvisual.doubleBufferMode) {
|
||||
if (backBuffer) {
|
||||
buf->backStart = backBuffer;
|
||||
buf->mallocBackBuffer = GL_FALSE;
|
||||
}
|
||||
else {
|
||||
buf->backStart = _mesa_malloc(size);
|
||||
if (!buf->backStart) {
|
||||
_mesa_free_framebuffer_data(&buf->glframebuffer);
|
||||
_mesa_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
buf->mallocBackBuffer = GL_TRUE;
|
||||
}
|
||||
buf->backBottom = (GLubyte *) buf->backStart
|
||||
+ (visual->var.yres_virtual - 1) * buf->rowStride;
|
||||
buf->curBottom = buf->backBottom;
|
||||
}
|
||||
else {
|
||||
buf->backStart = NULL;
|
||||
buf->mallocBackBuffer = GL_FALSE;
|
||||
buf->backBottom = NULL;
|
||||
buf->curBottom = buf->frontBottom;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
|
||||
{
|
||||
if (buffer) {
|
||||
/* check if destroying the current buffer */
|
||||
GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
|
||||
GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
|
||||
if (buffer == curDraw || buffer == curRead) {
|
||||
glFBDevMakeCurrent( NULL, NULL, NULL);
|
||||
}
|
||||
if (buffer->mallocBackBuffer) {
|
||||
_mesa_free(buffer->backStart);
|
||||
}
|
||||
/* free the software depth, stencil, accum buffers */
|
||||
_mesa_free_framebuffer_data(&buffer->glframebuffer);
|
||||
_mesa_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib)
|
||||
{
|
||||
(void) buffer;
|
||||
(void) attrib;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
GLFBDevBufferPtr
|
||||
glFBDevGetCurrentDrawBuffer( void )
|
||||
{
|
||||
GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
|
||||
if (fbdevctx)
|
||||
return fbdevctx->drawBuffer;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GLFBDevBufferPtr
|
||||
glFBDevGetCurrentReadBuffer( void )
|
||||
{
|
||||
GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
|
||||
if (fbdevctx)
|
||||
return fbdevctx->readBuffer;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glFBDevSwapBuffers( GLFBDevBufferPtr buffer )
|
||||
{
|
||||
GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
|
||||
|
||||
if (!buffer || !buffer->visual->glvisual.doubleBufferMode)
|
||||
return;
|
||||
|
||||
/* check if swapping currently bound buffer */
|
||||
if (fbdevctx->drawBuffer == buffer) {
|
||||
/* flush pending rendering */
|
||||
_mesa_notifySwapBuffers(&fbdevctx->glcontext);
|
||||
}
|
||||
|
||||
ASSERT(buffer->frontStart);
|
||||
ASSERT(buffer->backStart);
|
||||
_mesa_memcpy(buffer->frontStart, buffer->backStart, buffer->size);
|
||||
}
|
||||
|
||||
|
||||
GLFBDevContextPtr
|
||||
glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
|
||||
{
|
||||
GLFBDevContextPtr ctx;
|
||||
GLcontext *glctx;
|
||||
|
||||
ASSERT(visual);
|
||||
|
||||
ctx = CALLOC_STRUCT(GLFBDevContextRec);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual,
|
||||
share ? &share->glcontext : NULL,
|
||||
(void *) ctx, GL_FALSE)) {
|
||||
_mesa_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->visual = visual;
|
||||
|
||||
/* Create module contexts */
|
||||
glctx = (GLcontext *) &ctx->glcontext;
|
||||
init_core_functions( glctx );
|
||||
_swrast_CreateContext( glctx );
|
||||
_ac_CreateContext( glctx );
|
||||
_tnl_CreateContext( glctx );
|
||||
_swsetup_CreateContext( glctx );
|
||||
_swsetup_Wakeup( glctx );
|
||||
|
||||
/* swrast init */
|
||||
{
|
||||
struct swrast_device_driver *swdd;
|
||||
swdd = _swrast_GetDeviceDriverReference( glctx );
|
||||
swdd->SetBuffer = set_buffer;
|
||||
if (visual->pixelFormat == PF_B8G8R8) {
|
||||
swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
|
||||
swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
|
||||
swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
|
||||
swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
|
||||
swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
|
||||
swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
|
||||
swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
|
||||
}
|
||||
else if (visual->pixelFormat == PF_B8G8R8A8) {
|
||||
swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
|
||||
swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
|
||||
swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
|
||||
swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
|
||||
swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
|
||||
swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
|
||||
swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
|
||||
}
|
||||
else if (visual->pixelFormat == PF_B5G6R5) {
|
||||
swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
|
||||
swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
|
||||
swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
|
||||
swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
|
||||
swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
|
||||
swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
|
||||
swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
|
||||
}
|
||||
else if (visual->pixelFormat == PF_B5G5R5) {
|
||||
swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
|
||||
swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
|
||||
swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
|
||||
swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
|
||||
swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
|
||||
swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
|
||||
swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
|
||||
}
|
||||
else if (visual->pixelFormat == PF_CI8) {
|
||||
swdd->WriteCI32Span = write_index32_span_CI8;
|
||||
swdd->WriteCI8Span = write_index8_span_CI8;
|
||||
swdd->WriteMonoCISpan = write_monoindex_span_CI8;
|
||||
swdd->WriteCI32Pixels = write_index_pixels_CI8;
|
||||
swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
|
||||
swdd->ReadCI32Span = read_index_span_CI8;
|
||||
swdd->ReadCI32Pixels = read_index_pixels_CI8;
|
||||
}
|
||||
else {
|
||||
_mesa_printf("bad pixelformat: %d\n", visual->pixelFormat);
|
||||
}
|
||||
}
|
||||
|
||||
/* use default TCL pipeline */
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(glctx);
|
||||
tnl->Driver.RunPipeline = _tnl_run_pipeline;
|
||||
}
|
||||
|
||||
_mesa_enable_sw_extensions(glctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
glFBDevDestroyContext( GLFBDevContextPtr context )
|
||||
{
|
||||
GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
|
||||
|
||||
if (context) {
|
||||
if (fbdevctx == context) {
|
||||
/* destroying current context */
|
||||
_mesa_make_current2(NULL, NULL, NULL);
|
||||
_mesa_notifyDestroy(&context->glcontext);
|
||||
}
|
||||
_mesa_free_context_data(&context->glcontext);
|
||||
_mesa_free(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib)
|
||||
{
|
||||
(void) context;
|
||||
(void) attrib;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
GLFBDevContextPtr
|
||||
glFBDevGetCurrentContext( void )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
return (GLFBDevContextPtr) ctx;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glFBDevMakeCurrent( GLFBDevContextPtr context,
|
||||
GLFBDevBufferPtr drawBuffer,
|
||||
GLFBDevBufferPtr readBuffer )
|
||||
{
|
||||
if (context && drawBuffer && readBuffer) {
|
||||
/* Make sure the context's visual and the buffers' visuals match.
|
||||
* XXX we might do this by comparing specific fields like bits_per_pixel,
|
||||
* visual, etc. in the future.
|
||||
*/
|
||||
if (context->visual != drawBuffer->visual ||
|
||||
context->visual != readBuffer->visual) {
|
||||
return 0;
|
||||
}
|
||||
_mesa_make_current2( &context->glcontext,
|
||||
&drawBuffer->glframebuffer,
|
||||
&readBuffer->glframebuffer );
|
||||
context->drawBuffer = drawBuffer;
|
||||
context->readBuffer = readBuffer;
|
||||
context->curBuffer = drawBuffer;
|
||||
}
|
||||
else {
|
||||
/* unbind */
|
||||
_mesa_make_current2( NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* USE_GLFBDEV_DRIVER */
|
||||
|
Loading…
Reference in New Issue