graphlcd-base/glcddrivers/framebuffer.c
author root@rika
Wed, 06 Feb 2008 17:32:55 +0000
changeset 4 df6a40031aa5
permissions -rw-r--r--
added graphlcd-base
root@4
     1
/*
root@4
     2
 * GraphLCD driver library
root@4
     3
 *
root@4
     4
 * framebuffer.h  -  framebuffer device
root@4
     5
 *                   Output goes to a framebuffer device
root@4
     6
 *
root@4
     7
 * This file is released under the GNU General Public License. Refer
root@4
     8
 * to the COPYING file distributed with this package.
root@4
     9
 *
root@4
    10
 * (c) 2004 Stephan Skrodzki
root@4
    11
 */
root@4
    12
root@4
    13
#include <fcntl.h>
root@4
    14
#include <stdio.h>
root@4
    15
#include <syslog.h>
root@4
    16
#include <unistd.h>
root@4
    17
#include <sys/mman.h>
root@4
    18
#include <sys/ioctl.h>
root@4
    19
root@4
    20
#include "common.h"
root@4
    21
#include "config.h"
root@4
    22
#include "framebuffer.h"
root@4
    23
root@4
    24
root@4
    25
namespace GLCD
root@4
    26
{
root@4
    27
root@4
    28
cDriverFramebuffer::cDriverFramebuffer(cDriverConfig * config)
root@4
    29
:   config(config),
root@4
    30
    offbuff(0),
root@4
    31
    fbfd(-1)
root@4
    32
{
root@4
    33
    oldConfig = new cDriverConfig(*config);
root@4
    34
}
root@4
    35
root@4
    36
cDriverFramebuffer::~cDriverFramebuffer()
root@4
    37
{
root@4
    38
    delete oldConfig;
root@4
    39
}
root@4
    40
root@4
    41
int cDriverFramebuffer::Init()
root@4
    42
{
root@4
    43
    // default values
root@4
    44
    width = config->width;
root@4
    45
    if (width <= 0)
root@4
    46
        width = 320;
root@4
    47
    height = config->height;
root@4
    48
    if (height <= 0)
root@4
    49
        height = 240;
root@4
    50
    zoom = 1;
root@4
    51
root@4
    52
    for (unsigned int i = 0; i < config->options.size(); i++)
root@4
    53
    {
root@4
    54
        if (config->options[i].name == "Zoom")
root@4
    55
        {
root@4
    56
            int z = atoi(config->options[i].value.c_str());
root@4
    57
            if (z == 0 || z == 1)
root@4
    58
                zoom = z;
root@4
    59
            else
root@4
    60
                syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",
root@4
    61
                       config->name.c_str(), z, zoom);
root@4
    62
        }
root@4
    63
    }
root@4
    64
root@4
    65
    // Open the file for reading and writing
root@4
    66
    fbfd = open("/dev/fb0", O_RDWR);
root@4
    67
    if (1 == fbfd)
root@4
    68
    {
root@4
    69
        syslog(LOG_ERR, "%s: cannot open framebuffer device.\n", config->name.c_str());
root@4
    70
        return -1;
root@4
    71
    }
root@4
    72
    syslog(LOG_INFO, "%s: The framebuffer device was opened successfully.\n", config->name.c_str());
root@4
    73
root@4
    74
    // Get fixed screen information
root@4
    75
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
root@4
    76
    {
root@4
    77
        syslog(LOG_ERR, "%s: Error reading fixed information.\n", config->name.c_str());
root@4
    78
        return -1;
root@4
    79
    }
root@4
    80
root@4
    81
    // Get variable screen information
root@4
    82
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
root@4
    83
    {
root@4
    84
        syslog(LOG_ERR, "%s: Error reading variable information.\n", config->name.c_str());
root@4
    85
        return -1;
root@4
    86
    }
root@4
    87
root@4
    88
    // Figure out the size of the screen in bytes
root@4
    89
    screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
root@4
    90
root@4
    91
    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);
root@4
    92
root@4
    93
    // reserve another memory to draw into
root@4
    94
    offbuff = new char[screensize];
root@4
    95
    if (!offbuff)
root@4
    96
    {
root@4
    97
        syslog(LOG_ERR, "%s: failed to alloc memory for framebuffer device.\n", config->name.c_str());
root@4
    98
        return -1;
root@4
    99
    }
root@4
   100
root@4
   101
    // Map the device to memory
root@4
   102
    fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
root@4
   103
    if (fbp == MAP_FAILED)
root@4
   104
    {
root@4
   105
        syslog(LOG_ERR, "%s: failed to map framebuffer device to memory.\n", config->name.c_str());
root@4
   106
        return -1;
root@4
   107
    }
root@4
   108
    syslog(LOG_INFO, "%s: The framebuffer device was mapped to memory successfully.\n", config->name.c_str());
root@4
   109
root@4
   110
    *oldConfig = *config;
root@4
   111
root@4
   112
    // clear display
root@4
   113
    Refresh(true);
root@4
   114
root@4
   115
    syslog(LOG_INFO, "%s: Framebuffer initialized.\n", config->name.c_str());
root@4
   116
    return 0;
root@4
   117
}
root@4
   118
root@4
   119
int cDriverFramebuffer::DeInit()
root@4
   120
{
root@4
   121
    if (offbuff)
root@4
   122
        delete[] offbuff;
root@4
   123
    munmap(fbp, screensize);
root@4
   124
    if (-1 != fbfd)
root@4
   125
        close(fbfd);
root@4
   126
    return 0;
root@4
   127
}
root@4
   128
root@4
   129
int cDriverFramebuffer::CheckSetup()
root@4
   130
{
root@4
   131
    if (config->device != oldConfig->device ||
root@4
   132
        config->port != oldConfig->port ||
root@4
   133
        config->width != oldConfig->width ||
root@4
   134
        config->height != oldConfig->height)
root@4
   135
    {
root@4
   136
        DeInit();
root@4
   137
        Init();
root@4
   138
        return 0;
root@4
   139
    }
root@4
   140
root@4
   141
    if (config->upsideDown != oldConfig->upsideDown ||
root@4
   142
        config->invert != oldConfig->invert)
root@4
   143
    {
root@4
   144
        oldConfig->upsideDown = config->upsideDown;
root@4
   145
        oldConfig->invert = config->invert;
root@4
   146
        return 1;
root@4
   147
    }
root@4
   148
    return 0;
root@4
   149
}
root@4
   150
root@4
   151
void cDriverFramebuffer::SetPixel(int x, int y)
root@4
   152
{
root@4
   153
    int location;
root@4
   154
    int outcol;
root@4
   155
root@4
   156
    if (x >= width || y >= height)
root@4
   157
        return;
root@4
   158
root@4
   159
    if (config->upsideDown)
root@4
   160
    {
root@4
   161
        x = width - 1 - x;
root@4
   162
        y = height - 1 - y;
root@4
   163
    }
root@4
   164
root@4
   165
    // Figure out where in memory to put the pixel
root@4
   166
    location = (x*(1+zoom)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
root@4
   167
               (y*(1+zoom)+vinfo.yoffset) * finfo.line_length;
root@4
   168
root@4
   169
    if (vinfo.bits_per_pixel <= 8)
root@4
   170
    {
root@4
   171
        outcol = 15;
root@4
   172
    }
root@4
   173
    else
root@4
   174
    {
root@4
   175
        outcol = 255;
root@4
   176
    }
root@4
   177
root@4
   178
    if (vinfo.bits_per_pixel <= 8)
root@4
   179
    {
root@4
   180
        *(offbuff + location) = outcol;
root@4
   181
        if (zoom == 1)
root@4
   182
        {
root@4
   183
            *(offbuff + location + 1) = outcol;
root@4
   184
            *(offbuff + location + finfo.line_length) = outcol;
root@4
   185
            *(offbuff + location + finfo.line_length + 1) = outcol;
root@4
   186
        }
root@4
   187
    }
root@4
   188
    else if (vinfo.bits_per_pixel <= 16)
root@4
   189
    {
root@4
   190
        *(offbuff + location) = outcol;
root@4
   191
        *(offbuff + location + 1) = outcol;
root@4
   192
        if (zoom == 1)
root@4
   193
        {
root@4
   194
            *(offbuff + location + 2) = outcol;
root@4
   195
            *(offbuff + location + 3) = outcol;
root@4
   196
            *(offbuff + location + finfo.line_length) = outcol;
root@4
   197
            *(offbuff + location + finfo.line_length + 1) = outcol;
root@4
   198
            *(offbuff + location + finfo.line_length + 2) = outcol;
root@4
   199
            *(offbuff + location + finfo.line_length + 3) = outcol;
root@4
   200
        }
root@4
   201
    }
root@4
   202
    else
root@4
   203
    {
root@4
   204
        *(offbuff + location) = outcol;
root@4
   205
        *(offbuff + location + 1) = outcol;
root@4
   206
        *(offbuff + location + 2) = outcol;
root@4
   207
        *(offbuff + location + 3) = 0;     /* should be transparency */
root@4
   208
        if (zoom == 1)
root@4
   209
        {
root@4
   210
            *(offbuff + location + 4) = outcol;
root@4
   211
            *(offbuff + location + 5) = outcol;
root@4
   212
            *(offbuff + location + 6) = outcol;
root@4
   213
            *(offbuff + location + 7) = 0;
root@4
   214
            *(offbuff + location + finfo.line_length) = outcol;
root@4
   215
            *(offbuff + location + finfo.line_length + 1) = outcol;
root@4
   216
            *(offbuff + location + finfo.line_length + 2) = outcol;
root@4
   217
            *(offbuff + location + finfo.line_length + 3) = 0;
root@4
   218
            *(offbuff + location + finfo.line_length + 4) = outcol;
root@4
   219
            *(offbuff + location + finfo.line_length + 5) = outcol;
root@4
   220
            *(offbuff + location + finfo.line_length + 6) = outcol;
root@4
   221
            *(offbuff + location + finfo.line_length + 7) = 0;
root@4
   222
        }
root@4
   223
    }
root@4
   224
}
root@4
   225
root@4
   226
void cDriverFramebuffer::Clear()
root@4
   227
{
root@4
   228
    memset(offbuff, 0, screensize);
root@4
   229
}
root@4
   230
root@4
   231
void cDriverFramebuffer::Set8Pixels(int x, int y, unsigned char data)
root@4
   232
{
root@4
   233
    int n;
root@4
   234
root@4
   235
    x &= 0xFFF8;
root@4
   236
root@4
   237
    for (n = 0; n < 8; ++n)
root@4
   238
    {
root@4
   239
        if (data & (0x80 >> n))      // if bit is set
root@4
   240
            SetPixel(x + n, y);
root@4
   241
    }
root@4
   242
}
root@4
   243
root@4
   244
void cDriverFramebuffer::Refresh(bool refreshAll)
root@4
   245
{
root@4
   246
    memcpy(fbp, offbuff, screensize);
root@4
   247
}
root@4
   248
root@4
   249
} // end of namespace