1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/graphlcd-base/glcddrivers/framebuffer.c Wed Feb 06 17:32:55 2008 +0000
1.3 @@ -0,0 +1,249 @@
1.4 +/*
1.5 + * GraphLCD driver library
1.6 + *
1.7 + * framebuffer.h - framebuffer device
1.8 + * Output goes to a framebuffer device
1.9 + *
1.10 + * This file is released under the GNU General Public License. Refer
1.11 + * to the COPYING file distributed with this package.
1.12 + *
1.13 + * (c) 2004 Stephan Skrodzki
1.14 + */
1.15 +
1.16 +#include <fcntl.h>
1.17 +#include <stdio.h>
1.18 +#include <syslog.h>
1.19 +#include <unistd.h>
1.20 +#include <sys/mman.h>
1.21 +#include <sys/ioctl.h>
1.22 +
1.23 +#include "common.h"
1.24 +#include "config.h"
1.25 +#include "framebuffer.h"
1.26 +
1.27 +
1.28 +namespace GLCD
1.29 +{
1.30 +
1.31 +cDriverFramebuffer::cDriverFramebuffer(cDriverConfig * config)
1.32 +: config(config),
1.33 + offbuff(0),
1.34 + fbfd(-1)
1.35 +{
1.36 + oldConfig = new cDriverConfig(*config);
1.37 +}
1.38 +
1.39 +cDriverFramebuffer::~cDriverFramebuffer()
1.40 +{
1.41 + delete oldConfig;
1.42 +}
1.43 +
1.44 +int cDriverFramebuffer::Init()
1.45 +{
1.46 + // default values
1.47 + width = config->width;
1.48 + if (width <= 0)
1.49 + width = 320;
1.50 + height = config->height;
1.51 + if (height <= 0)
1.52 + height = 240;
1.53 + zoom = 1;
1.54 +
1.55 + for (unsigned int i = 0; i < config->options.size(); i++)
1.56 + {
1.57 + if (config->options[i].name == "Zoom")
1.58 + {
1.59 + int z = atoi(config->options[i].value.c_str());
1.60 + if (z == 0 || z == 1)
1.61 + zoom = z;
1.62 + else
1.63 + syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",
1.64 + config->name.c_str(), z, zoom);
1.65 + }
1.66 + }
1.67 +
1.68 + // Open the file for reading and writing
1.69 + fbfd = open("/dev/fb0", O_RDWR);
1.70 + if (1 == fbfd)
1.71 + {
1.72 + syslog(LOG_ERR, "%s: cannot open framebuffer device.\n", config->name.c_str());
1.73 + return -1;
1.74 + }
1.75 + syslog(LOG_INFO, "%s: The framebuffer device was opened successfully.\n", config->name.c_str());
1.76 +
1.77 + // Get fixed screen information
1.78 + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
1.79 + {
1.80 + syslog(LOG_ERR, "%s: Error reading fixed information.\n", config->name.c_str());
1.81 + return -1;
1.82 + }
1.83 +
1.84 + // Get variable screen information
1.85 + if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
1.86 + {
1.87 + syslog(LOG_ERR, "%s: Error reading variable information.\n", config->name.c_str());
1.88 + return -1;
1.89 + }
1.90 +
1.91 + // Figure out the size of the screen in bytes
1.92 + screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
1.93 +
1.94 + syslog(LOG_INFO, "%s: V01: xres: %d, yres %d, vyres: %d, bpp: %d, linelenght: %d\n", config->name.c_str(),vinfo.xres,vinfo.yres,vinfo.yres_virtual,vinfo.bits_per_pixel,finfo.line_length);
1.95 +
1.96 + // reserve another memory to draw into
1.97 + offbuff = new char[screensize];
1.98 + if (!offbuff)
1.99 + {
1.100 + syslog(LOG_ERR, "%s: failed to alloc memory for framebuffer device.\n", config->name.c_str());
1.101 + return -1;
1.102 + }
1.103 +
1.104 + // Map the device to memory
1.105 + fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
1.106 + if (fbp == MAP_FAILED)
1.107 + {
1.108 + syslog(LOG_ERR, "%s: failed to map framebuffer device to memory.\n", config->name.c_str());
1.109 + return -1;
1.110 + }
1.111 + syslog(LOG_INFO, "%s: The framebuffer device was mapped to memory successfully.\n", config->name.c_str());
1.112 +
1.113 + *oldConfig = *config;
1.114 +
1.115 + // clear display
1.116 + Refresh(true);
1.117 +
1.118 + syslog(LOG_INFO, "%s: Framebuffer initialized.\n", config->name.c_str());
1.119 + return 0;
1.120 +}
1.121 +
1.122 +int cDriverFramebuffer::DeInit()
1.123 +{
1.124 + if (offbuff)
1.125 + delete[] offbuff;
1.126 + munmap(fbp, screensize);
1.127 + if (-1 != fbfd)
1.128 + close(fbfd);
1.129 + return 0;
1.130 +}
1.131 +
1.132 +int cDriverFramebuffer::CheckSetup()
1.133 +{
1.134 + if (config->device != oldConfig->device ||
1.135 + config->port != oldConfig->port ||
1.136 + config->width != oldConfig->width ||
1.137 + config->height != oldConfig->height)
1.138 + {
1.139 + DeInit();
1.140 + Init();
1.141 + return 0;
1.142 + }
1.143 +
1.144 + if (config->upsideDown != oldConfig->upsideDown ||
1.145 + config->invert != oldConfig->invert)
1.146 + {
1.147 + oldConfig->upsideDown = config->upsideDown;
1.148 + oldConfig->invert = config->invert;
1.149 + return 1;
1.150 + }
1.151 + return 0;
1.152 +}
1.153 +
1.154 +void cDriverFramebuffer::SetPixel(int x, int y)
1.155 +{
1.156 + int location;
1.157 + int outcol;
1.158 +
1.159 + if (x >= width || y >= height)
1.160 + return;
1.161 +
1.162 + if (config->upsideDown)
1.163 + {
1.164 + x = width - 1 - x;
1.165 + y = height - 1 - y;
1.166 + }
1.167 +
1.168 + // Figure out where in memory to put the pixel
1.169 + location = (x*(1+zoom)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
1.170 + (y*(1+zoom)+vinfo.yoffset) * finfo.line_length;
1.171 +
1.172 + if (vinfo.bits_per_pixel <= 8)
1.173 + {
1.174 + outcol = 15;
1.175 + }
1.176 + else
1.177 + {
1.178 + outcol = 255;
1.179 + }
1.180 +
1.181 + if (vinfo.bits_per_pixel <= 8)
1.182 + {
1.183 + *(offbuff + location) = outcol;
1.184 + if (zoom == 1)
1.185 + {
1.186 + *(offbuff + location + 1) = outcol;
1.187 + *(offbuff + location + finfo.line_length) = outcol;
1.188 + *(offbuff + location + finfo.line_length + 1) = outcol;
1.189 + }
1.190 + }
1.191 + else if (vinfo.bits_per_pixel <= 16)
1.192 + {
1.193 + *(offbuff + location) = outcol;
1.194 + *(offbuff + location + 1) = outcol;
1.195 + if (zoom == 1)
1.196 + {
1.197 + *(offbuff + location + 2) = outcol;
1.198 + *(offbuff + location + 3) = outcol;
1.199 + *(offbuff + location + finfo.line_length) = outcol;
1.200 + *(offbuff + location + finfo.line_length + 1) = outcol;
1.201 + *(offbuff + location + finfo.line_length + 2) = outcol;
1.202 + *(offbuff + location + finfo.line_length + 3) = outcol;
1.203 + }
1.204 + }
1.205 + else
1.206 + {
1.207 + *(offbuff + location) = outcol;
1.208 + *(offbuff + location + 1) = outcol;
1.209 + *(offbuff + location + 2) = outcol;
1.210 + *(offbuff + location + 3) = 0; /* should be transparency */
1.211 + if (zoom == 1)
1.212 + {
1.213 + *(offbuff + location + 4) = outcol;
1.214 + *(offbuff + location + 5) = outcol;
1.215 + *(offbuff + location + 6) = outcol;
1.216 + *(offbuff + location + 7) = 0;
1.217 + *(offbuff + location + finfo.line_length) = outcol;
1.218 + *(offbuff + location + finfo.line_length + 1) = outcol;
1.219 + *(offbuff + location + finfo.line_length + 2) = outcol;
1.220 + *(offbuff + location + finfo.line_length + 3) = 0;
1.221 + *(offbuff + location + finfo.line_length + 4) = outcol;
1.222 + *(offbuff + location + finfo.line_length + 5) = outcol;
1.223 + *(offbuff + location + finfo.line_length + 6) = outcol;
1.224 + *(offbuff + location + finfo.line_length + 7) = 0;
1.225 + }
1.226 + }
1.227 +}
1.228 +
1.229 +void cDriverFramebuffer::Clear()
1.230 +{
1.231 + memset(offbuff, 0, screensize);
1.232 +}
1.233 +
1.234 +void cDriverFramebuffer::Set8Pixels(int x, int y, unsigned char data)
1.235 +{
1.236 + int n;
1.237 +
1.238 + x &= 0xFFF8;
1.239 +
1.240 + for (n = 0; n < 8; ++n)
1.241 + {
1.242 + if (data & (0x80 >> n)) // if bit is set
1.243 + SetPixel(x + n, y);
1.244 + }
1.245 +}
1.246 +
1.247 +void cDriverFramebuffer::Refresh(bool refreshAll)
1.248 +{
1.249 + memcpy(fbp, offbuff, screensize);
1.250 +}
1.251 +
1.252 +} // end of namespace