Replaced the old frame buffer console driver with a built-in frame buffer

console module which is used by the console driver, and will be used by
the on-screen KDL.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11350 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-02-12 03:45:01 +00:00
parent c48c2a976f
commit f80973f6c2
2 changed files with 349 additions and 0 deletions

View File

@ -0,0 +1,9 @@
SubDir OBOS_TOP src kernel core debug ;
UsePrivateHeaders [ FDirName kernel debug ] ;
KernelMergeObject kernel_debug.o :
frame_buffer_console.cpp
: -fno-pic -Wno-unused -D_KERNEL_MODE
;

View File

@ -0,0 +1,340 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <lock.h>
#include <devfs.h>
#include <boot/kernel_args.h>
#include <frame_buffer_console.h>
#include "font.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
//#define TRACE_FB_CONSOLE
#ifdef TRACE_FB_CONSOLE
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
struct console_info {
mutex lock;
area_id area;
addr_t frame_buffer;
int32 width;
int32 height;
int32 depth;
int32 bytes_per_pixel;
int32 bytes_per_row;
int32 columns;
int32 rows;
int32 cursor_x;
int32 cursor_y;
};
// Palette is (white and black are exchanged):
// 0 - white, 1 - blue, 2 - green, 3 - cyan, 4 - red, 5 - magenta, 6 - yellow, 7 - black
// 8-15 - same but bright (we're ignoring those)
static uint8 sPalette8[] = {
63, 32, 52, 70, 42, 88, 67, 0,
};
static uint16 sPalette15[] = {
// 0bbbbbgggggrrrrr (5-5-5)
0x7fff, 0x001f, 0x03e0, 0x03ff, 0x7c00, 0x7c1f, 0x7fe0, 0x0000,
};
static uint16 sPalette16[] = {
// bbbbbggggggrrrrr (5-6-5)
0xffff, 0x001f, 0x07e0, 0x07ff, 0xf800, 0xf81f, 0xffe0, 0x0000,
};
static uint32 sPalette32[] = {
// is also used by 24 bit modes
0xffffff, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00, 0x000000,
};
static struct console_info sConsole;
static inline uint8
foreground_color(uint8 attr)
{
return attr & 0x7;
}
static inline uint8
background_color(uint8 attr)
{
return (attr >> 4) & 0x7;
}
static uint8 *
get_palette_entry(uint8 index)
{
switch (sConsole.depth) {
case 8:
return &sPalette8[index];
case 15:
return (uint8 *)&sPalette15[index];
case 16:
return (uint8 *)&sPalette16[index];
default:
return (uint8 *)&sPalette32[index];
}
}
static void
render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
{
uint8 *base = (uint8 *)(sConsole.frame_buffer + sConsole.bytes_per_row * y * CHAR_HEIGHT
+ x * CHAR_WIDTH * sConsole.bytes_per_pixel);
uint8 *color = get_palette_entry(foreground_color(attr));
uint8 *backgroundColor = get_palette_entry(background_color(attr));
for (y = 0; y < CHAR_HEIGHT; y++) {
uint8 bits = FONT[CHAR_HEIGHT * glyph + y];
for (x = 0; x < CHAR_WIDTH; x++) {
for (int32 i = 0; i < sConsole.bytes_per_pixel; i++) {
if (bits & 1)
base[x * sConsole.bytes_per_pixel + i] = color[i];
else
base[x * sConsole.bytes_per_pixel + i] = backgroundColor[i];
}
bits >>= 1;
}
base += sConsole.bytes_per_row;
}
}
static void
draw_cursor(int32 x, int32 y)
{
if (x < 0 || y < 0)
return;
x *= CHAR_WIDTH * sConsole.bytes_per_pixel;
y *= CHAR_HEIGHT;
int32 endX = x + CHAR_WIDTH * sConsole.bytes_per_pixel;
int32 endY = y + CHAR_HEIGHT;
uint8 *base = (uint8 *)(sConsole.frame_buffer + y * sConsole.bytes_per_row);
for (; y < endY; y++) {
for (int32 x2 = x; x2 < endX; x2++)
base[x2] = ~base[x2];
base += sConsole.bytes_per_row;
}
}
static status_t
console_get_size(int32 *_width, int32 *_height)
{
*_width = sConsole.columns;
*_height = sConsole.rows;
return B_OK;
}
static void
console_move_cursor(int32 x, int32 y)
{
draw_cursor(sConsole.cursor_x, sConsole.cursor_y);
draw_cursor(x, y);
sConsole.cursor_x = x;
sConsole.cursor_y = y;
}
static void
console_put_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
{
if (x >= sConsole.columns || y >= sConsole.rows)
return;
render_glyph(x, y, glyph, attr);
}
static void
console_fill_glyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr)
{
if (x >= sConsole.columns || y >= sConsole.rows)
return;
int32 left = x + width;
if (left > sConsole.columns)
left = sConsole.columns;
int32 bottom = y + height;
if (bottom > sConsole.rows)
bottom = sConsole.rows;
for (; y < bottom; y++) {
for (int32 x2 = x; x2 < left; x2++) {
render_glyph(x2, y, glyph, attr);
}
}
}
static void
console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty)
{
height *= CHAR_HEIGHT;
width *= CHAR_WIDTH * sConsole.bytes_per_pixel;
srcx *= CHAR_WIDTH * sConsole.bytes_per_pixel;
srcy *= CHAR_HEIGHT;
destx *= CHAR_WIDTH * sConsole.bytes_per_pixel;
desty *= CHAR_HEIGHT;
for (int32 y = 0; y < height; y++) {
memmove((void *)(sConsole.frame_buffer + (desty + y) * sConsole.bytes_per_row + destx),
(void *)(sConsole.frame_buffer + (srcy + y) * sConsole.bytes_per_row + srcx), width);
}
}
static void
console_clear(uint8 attr)
{
switch (sConsole.bytes_per_pixel) {
case 1:
memset((void *)sConsole.frame_buffer, sPalette8[background_color(attr)],
sConsole.height * sConsole.bytes_per_row);
break;
default:
{
uint8 *base = (uint8 *)sConsole.frame_buffer;
uint8 *color = get_palette_entry(background_color(attr));
for (int32 y = 0; y < sConsole.height; y++) {
for (int32 x = 0; x < sConsole.width; x++) {
for (int32 i = 0; i < sConsole.bytes_per_pixel; i++) {
base[x * sConsole.bytes_per_pixel + i] = color[i];
}
}
base += sConsole.bytes_per_row;
}
break;
}
}
sConsole.cursor_x = -1;
sConsole.cursor_y = -1;
}
static status_t
console_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return sConsole.frame_buffer != NULL ? B_OK : B_ERROR;
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
console_module_info gFrameBufferConsoleModule = {
{
FRAME_BUFFER_CONSOLE_MODULE_NAME,
0,
console_std_ops
},
&console_get_size,
&console_move_cursor,
&console_put_glyph,
&console_fill_glyph,
&console_blit,
&console_clear,
};
// #pragma mark -
status_t
frame_buffer_update(addr_t baseAddress, int32 width, int32 height, int32 depth, int32 bytesPerRow)
{
TRACE(("frame_buffer_update(buffer = %p, width = %ld, height = %ld, depth = %ld, bytesPerRow = %ld)\n",
(void *)baseAddress, width, height, depth, bytesPerRow));
mutex_lock(&sConsole.lock);
sConsole.frame_buffer = baseAddress;
sConsole.width = width;
sConsole.height = height;
sConsole.depth = depth;
sConsole.bytes_per_pixel = (depth + 7) / 8;
sConsole.bytes_per_row = bytesPerRow;
sConsole.columns = sConsole.width / CHAR_WIDTH;
sConsole.rows = sConsole.height / CHAR_HEIGHT;
// initially, the cursor is hidden
sConsole.cursor_x = -1;
sConsole.cursor_y = -1;
TRACE(("framebuffer mapped at %p, %ld columns, %ld rows\n",
(void *)sConsole.frame_buffer, sConsole.columns, sConsole.rows));
mutex_unlock(&sConsole.lock);
return B_OK;
}
status_t
frame_buffer_console_init(kernel_args *args)
{
if (!args->frame_buffer.enabled)
return B_OK;
void *frameBuffer;
sConsole.area = map_physical_memory("vesa_fb",
(void *)args->frame_buffer.physical_buffer.start,
args->frame_buffer.physical_buffer.size, B_ANY_KERNEL_ADDRESS,
B_READ_AREA | B_WRITE_AREA, &frameBuffer);
if (sConsole.area < B_OK)
return sConsole.area;
mutex_init(&sConsole.lock, "console_lock");
int32 bytesPerRow = args->frame_buffer.width;
switch (args->frame_buffer.depth) {
case 15:
case 16:
bytesPerRow *= 2;
break;
case 24:
bytesPerRow *= 3;
break;
case 32:
bytesPerRow *= 4;
break;
}
frame_buffer_update((addr_t)frameBuffer, args->frame_buffer.width, args->frame_buffer.height,
args->frame_buffer.depth, bytesPerRow);
return B_OK;
}