Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

228 lines (191 sloc) 5.388 kb
/*
* guilib - a minimal pixel framework
*
* Copyright (c) 2009 Openmoko Inc.
*
* Authors Daniel Mack <daniel@caiaq.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <file-io.h>
#include <msg.h>
#include <string.h>
#include "guilib.h"
#include "glyph.h"
#include <regs.h>
#include <lcd.h>
#include <samo.h>
// just redfine, fix later
#define FRAMEBUFFER_WIDTH LCD_WIDTH_PIXELS
#define FRAMEBUFFER_HEIGHT LCD_HEIGHT_LINES
#define FRAMEBUFFER_SCANLINE LCD_VRAM_WIDTH_PIXELS
#define FRAMEBUFFER_SIZE LCD_VRAM_SIZE
#define EXTRACT_PIXEL(x, y) \
unsigned int byte = (x + FRAMEBUFFER_SCANLINE * y) / 8; \
unsigned int bit = (x + FRAMEBUFFER_SCANLINE * y) % 8; \
\
if (byte >= FRAMEBUFFER_SIZE) \
return;
unsigned int guilib_framebuffer_width(void)
{
return FRAMEBUFFER_WIDTH;
}
unsigned int guilib_framebuffer_height(void)
{
return FRAMEBUFFER_HEIGHT;
}
unsigned int guilib_framebuffer_size(void)
{
return FRAMEBUFFER_SIZE;
}
/*
* Special version for really setting the pixel as it
* should be... This does not take DISPLAY_INVERTED into
* account.
*/
static void guilib_set_pixel_plain(int x, int y, int v)
{
EXTRACT_PIXEL(x, y)
if (v)
framebuffer[byte] |= 0x80 >> bit;
else
framebuffer[byte] &= ~(0x80 >> bit);
}
void guilib_set_pixel(int x, int y, int v)
{
EXTRACT_PIXEL(x, y)
if (v)
#ifdef DISPLAY_INVERTED
framebuffer[byte] &= ~(1 << (7 - bit));
else
framebuffer[byte] |= (1 << (7 - bit));
#else
framebuffer[byte] |= (1 << (7 - bit));
else
framebuffer[byte] &= ~(1 << (7 - bit));
#endif
}
int guilib_get_pixel(int x, int y)
{
unsigned int byte = (x + FRAMEBUFFER_SCANLINE * y) / 8;
unsigned int bit = (x + FRAMEBUFFER_SCANLINE * y) % 8;
int bit_set = (framebuffer[byte] & 0x80>>bit) != 0;
#ifdef DISPLAY_INVERTED
bit_set = !bit_set;
#endif
return bit_set;
}
/**
* Invert the pixels of lines starting at @param start_line
* and the following @param height lines.
*/
void guilib_invert(int start_line, int height)
{
int x, y;
for (y = 0; y < height; ++y) {
for (x = 0; x < FRAMEBUFFER_SCANLINE; x += 8) {
unsigned int byte = (x + FRAMEBUFFER_SCANLINE * (start_line + y)) / 8;
framebuffer[byte] = ~framebuffer[byte];
}
}
}
/**
* Invert the area specified on the screen.
*/
void guilib_invert_area(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
{
unsigned int x, y;
for (y = start_y; y <= end_y; ++y) {
for (x = start_x; x <= end_x; x++) {
unsigned int pixel = guilib_get_pixel(x, y);
guilib_set_pixel_plain(x, y, !pixel);
}
}
}
/**
* Clear the content of the screen.
*/
void guilib_clear(void)
{
#ifdef DISPLAY_INVERTED
memset(framebuffer, ~0, FRAMEBUFFER_SIZE);
#else
memset(framebuffer, 0, FRAMEBUFFER_SIZE);
#endif
}
/**
* Clear the area specified on the screen.
*/
void guilib_clear_area(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
{
unsigned int x, y;
for (y = start_y; y <= end_y; ++y) {
for (x = start_x; x <= end_x; x++)
#ifdef DISPLAY_INVERTE
guilib_set_pixel_plain(x, y, 1);
#else
guilib_set_pixel_plain(x, y, 0);
#endif
}
}
/* The idea is that every function which calls painting routines calls
* guilib_fb_lock() before any operation and guilib_fb_unlock() after
* it. This way, only the last of these functions in the calling stack
* will actually execute fb_refresh(). */
static int fb_ref = 0;
void guilib_fb_lock(void)
{
fb_ref++;
}
void guilib_fb_unlock(void)
{
if (fb_ref == 0)
return;
if (--fb_ref == 0)
fb_refresh();
}
#define IMG_GET_PIXEL(img,x,y) \
(img->data[(x + img->width * y) / 8] >> (7 - (x + img->width * y) % 8) & 1)
void guilib_blit_image(const struct guilib_image *img, int x, int y)
{
unsigned int xx, yy;
/* special case: the image has the same width than the
* height and is rendered at y=0. Then we can go for a
* simple memcpy() */
if (y == 0 && img->width == FRAMEBUFFER_SCANLINE) {
memcpy(framebuffer + (x + FRAMEBUFFER_SCANLINE * y) / 8,
img->data, (img->width * img->height) / 8);
return;
}
/* special case: the image will be blitted byte aligned.
* we can simply copy over all the bytes, without bit
* fiddling. We can copy it line by line*/
if ((x & 7) == 0 && img->width == FRAMEBUFFER_WIDTH) {
unsigned int i;
for (i = 0; i < img->height; ++i) {
unsigned char *d = framebuffer + (x + FRAMEBUFFER_SCANLINE * (y+i)) / 8;
memcpy(d, &img->data[(i*img->width) / 8], img->width / 8);
}
return;
}
/* hardest case - go for bit fiddling */
for (xx = 0; xx < img->width; xx++)
for (yy = 0; yy < img->height; yy++)
guilib_set_pixel_plain(x + xx, y + yy,
IMG_GET_PIXEL(img, xx, yy));
}
void guilib_init(void)
{
guilib_clear();
}
Jump to Line
Something went wrong with that request. Please try again.