* Moved VGA planar mode blitting into the VESA kernel driver.
* In grayscale mode, the AccelerantHWInterface now sets the palette correctly. * HWInterface now has a fVGADevice set by AccelerantHWInterface which will be used to talk to the VESA driver. * Completed planar blitting for all 4 planes; we now have a perfect 16 color grayscale mode when you choose "Standard VGA mode" in the boot loader with an unsupported graphics card (such as in Qemu). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19567 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
30b0fe7561
commit
0c6f77951e
@ -47,6 +47,24 @@ struct vesa_info {
|
||||
enum {
|
||||
VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
||||
VESA_GET_DEVICE_NAME,
|
||||
|
||||
VGA_SET_INDEXED_COLORS,
|
||||
VGA_PLANAR_BLIT,
|
||||
};
|
||||
|
||||
struct vga_set_indexed_colors_args {
|
||||
uint8 first;
|
||||
uint16 count;
|
||||
uint8 *colors;
|
||||
};
|
||||
|
||||
struct vga_planar_blit_args {
|
||||
uint8 *source;
|
||||
int32 source_bytes_per_row;
|
||||
int32 left;
|
||||
int32 top;
|
||||
int32 right;
|
||||
int32 bottom;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
@ -231,8 +231,13 @@ vesa_get_timing_constraints(display_timing_constraints *dtc)
|
||||
|
||||
|
||||
void
|
||||
vesa_set_indexed_colors(uint count, uint8 first, uint8 *color_data, uint32 flags)
|
||||
vesa_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags)
|
||||
{
|
||||
TRACE(("vesa_set_indexed_colors()\n"));
|
||||
vga_set_indexed_colors_args args;
|
||||
args.first = first;
|
||||
args.count = count;
|
||||
args.colors = colors;
|
||||
ioctl(gInfo->device, VGA_SET_INDEXED_COLORS, &args, sizeof(args));
|
||||
}
|
||||
|
||||
|
@ -6,5 +6,6 @@ KernelAddon vesa :
|
||||
device.cpp
|
||||
driver.cpp
|
||||
vesa.cpp
|
||||
vga.cpp
|
||||
;
|
||||
|
||||
|
@ -1,9 +1,15 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "device.h"
|
||||
#include "driver.h"
|
||||
#include "utility.h"
|
||||
#include "vesa_info.h"
|
||||
#include "vga.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
@ -15,11 +21,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "driver.h"
|
||||
#include "device.h"
|
||||
#include "vesa_info.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
//#define TRACE_DEVICE
|
||||
#ifdef TRACE_DEVICE
|
||||
@ -141,6 +142,26 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
|
||||
return B_BAD_ADDRESS;
|
||||
return B_OK;
|
||||
|
||||
case VGA_SET_INDEXED_COLORS:
|
||||
{
|
||||
vga_set_indexed_colors_args args;
|
||||
if (user_memcpy(&args, buffer, sizeof(args)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return vga_set_indexed_colors(args.first, args.colors, args.count);
|
||||
}
|
||||
|
||||
case VGA_PLANAR_BLIT:
|
||||
{
|
||||
vga_planar_blit_args args;
|
||||
if (user_memcpy(&args, buffer, sizeof(args)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return vga_planar_blit(info->shared_info, args.source,
|
||||
args.source_bytes_per_row, args.left, args.top,
|
||||
args.right, args.bottom);
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -32,6 +32,7 @@ int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
||||
char *gDeviceNames[MAX_CARDS + 1];
|
||||
vesa_info *gDeviceInfo[MAX_CARDS];
|
||||
isa_module_info *gISA;
|
||||
lock gLock;
|
||||
|
||||
|
||||
@ -88,10 +89,21 @@ init_driver(void)
|
||||
else
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = get_module(B_ISA_MODULE_NAME, (module_info **)&gISA);
|
||||
if (status < B_OK)
|
||||
goto err1;
|
||||
|
||||
gDeviceNames[0] = strdup("graphics/vesa");
|
||||
gDeviceNames[1] = NULL;
|
||||
|
||||
return init_lock(&gLock, "vesa lock");
|
||||
status = init_lock(&gLock, "vesa lock");
|
||||
if (status == B_OK)
|
||||
return B_OK;
|
||||
|
||||
put_module(B_ISA_MODULE_NAME);
|
||||
err1:
|
||||
free(gDeviceInfo[0]);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -100,6 +112,7 @@ uninit_driver(void)
|
||||
{
|
||||
TRACE((DEVICE_NAME ": uninit_driver()\n"));
|
||||
|
||||
put_module(B_ISA_MODULE_NAME);
|
||||
uninit_lock(&gLock);
|
||||
|
||||
// free device related structures
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DRIVER_H
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <PCI.h>
|
||||
#include <ISA.h>
|
||||
|
||||
#include "vesa_info.h"
|
||||
#include "lock.h"
|
||||
@ -15,6 +15,7 @@
|
||||
|
||||
extern char *gDeviceNames[];
|
||||
extern vesa_info *gDeviceInfo[];
|
||||
extern isa_module_info *gISA;
|
||||
extern lock gLock;
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
|
87
src/add-ons/kernel/drivers/graphics/vesa/vga.cpp
Normal file
87
src/add-ons/kernel/drivers/graphics/vesa/vga.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "vga.h"
|
||||
#include "driver.h"
|
||||
|
||||
#include <vga.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
|
||||
status_t
|
||||
vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count)
|
||||
{
|
||||
gISA->write_io_8(VGA_COLOR_WRITE_MODE, first);
|
||||
|
||||
// write VGA palette
|
||||
for (int32 i = first; i < count; i++) {
|
||||
uint8 color[3];
|
||||
if (user_memcpy(color, &colors[i * 3], 3) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
// VGA (usually) has only 6 bits per gun
|
||||
gISA->write_io_8(VGA_COLOR_DATA, color[0] >> 2);
|
||||
gISA->write_io_8(VGA_COLOR_DATA, color[1] >> 2);
|
||||
gISA->write_io_8(VGA_COLOR_DATA, color[2] >> 2);
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
|
||||
int32 left, int32 top, int32 right, int32 bottom)
|
||||
{
|
||||
int32 dstBPR = info->bytes_per_row;
|
||||
uint8 *dst = info->frame_buffer + top * dstBPR + left / 8;
|
||||
|
||||
// TODO: this is awfully slow...
|
||||
// TODO: assumes BGR order
|
||||
for (int32 y = top; y <= bottom; y++) {
|
||||
for (int32 plane = 0; plane < 4; plane++) {
|
||||
// select the plane we intend to write to and read from
|
||||
gISA->write_io_16(VGA_SEQUENCER_INDEX, (1 << (plane + 8)) | 0x02);
|
||||
gISA->write_io_16(VGA_GRAPHICS_INDEX, (plane << 8) | 0x04);
|
||||
|
||||
uint8* srcHandle = src;
|
||||
uint8* dstHandle = dst;
|
||||
uint8 current8 = dstHandle[0];
|
||||
// we store 8 pixels before writing them back
|
||||
|
||||
int32 x = left;
|
||||
for (; x <= right; x++) {
|
||||
uint8 rgba[4];
|
||||
if (user_memcpy(rgba, srcHandle, 4) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
uint8 pixel = (308 * rgba[2] + 600 * rgba[1]
|
||||
+ 116 * rgba[0]) / 16384;
|
||||
srcHandle += 4;
|
||||
|
||||
if (pixel & (1 << plane))
|
||||
current8 |= 0x80 >> (x & 7);
|
||||
else
|
||||
current8 &= ~(0x80 >> (x & 7));
|
||||
|
||||
if ((x & 7) == 7) {
|
||||
// last pixel in 8 pixel group
|
||||
dstHandle[0] = current8;
|
||||
dstHandle++;
|
||||
current8 = dstHandle[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (x & 7) {
|
||||
// last pixel has not been written yet
|
||||
dstHandle[0] = current8;
|
||||
}
|
||||
}
|
||||
dst += dstBPR;
|
||||
src += srcBPR;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
16
src/add-ons/kernel/drivers/graphics/vesa/vga.h
Normal file
16
src/add-ons/kernel/drivers/graphics/vesa/vga.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _VGA_H
|
||||
#define _VGA_H
|
||||
|
||||
|
||||
#include <vesa_info.h>
|
||||
|
||||
|
||||
status_t vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count);
|
||||
status_t vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
|
||||
int32 left, int32 top, int32 right, int32 bottom);
|
||||
|
||||
#endif /* _VGA_H */
|
@ -153,14 +153,14 @@ AccelerantHWInterface::Initialize()
|
||||
ATRACE(("Failed to open graphics device\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (_OpenAccelerant(fCardFD) == B_OK)
|
||||
break;
|
||||
|
||||
|
||||
close(fCardFD);
|
||||
// _OpenAccelerant() failed, try to open next graphics card
|
||||
}
|
||||
|
||||
|
||||
return fCardFD >= 0 ? B_OK : fCardFD;
|
||||
}
|
||||
return ret;
|
||||
@ -214,6 +214,8 @@ AccelerantHWInterface::_OpenGraphicsDevice(int deviceNumber)
|
||||
if (deviceNumber == 1) {
|
||||
sprintf(path, "/dev/graphics/vesa");
|
||||
device = open(path, B_READ_WRITE);
|
||||
fVGADevice = device;
|
||||
// store the device, so that we can access the planar blitter
|
||||
} else {
|
||||
close(device);
|
||||
device = B_ENTRY_NOT_FOUND;
|
||||
@ -528,6 +530,8 @@ AccelerantHWInterface::SetMode(const display_mode& mode)
|
||||
|
||||
if (fDisplayMode.space == B_CMAP8)
|
||||
_SetSystemPalette();
|
||||
else if (fDisplayMode.space == B_GRAY8)
|
||||
_SetGrayscalePalette();
|
||||
|
||||
// update acceleration hooks
|
||||
fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode);
|
||||
@ -1155,3 +1159,36 @@ AccelerantHWInterface::_SetSystemPalette()
|
||||
|
||||
setIndexedColors(256, 0, colors, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccelerantHWInterface::_SetGrayscalePalette()
|
||||
{
|
||||
set_indexed_colors setIndexedColors = (set_indexed_colors)fAccelerantHook(
|
||||
B_SET_INDEXED_COLORS, NULL);
|
||||
if (setIndexedColors == NULL)
|
||||
return;
|
||||
|
||||
uint8 colors[3 * 256];
|
||||
// the color table is an array with 3 bytes per color
|
||||
uint32 j = 0;
|
||||
|
||||
if (fFrontBuffer->Width() > fFrontBuffer->BytesPerRow()) {
|
||||
// VGA 16 color grayscale planar mode
|
||||
for (int32 i = 0; i < 16; i++) {
|
||||
colors[j++] = i * 17;
|
||||
colors[j++] = i * 17;
|
||||
colors[j++] = i * 17;
|
||||
}
|
||||
|
||||
setIndexedColors(16, 0, colors, 0);
|
||||
} else {
|
||||
for (int32 i = 0; i < 256; i++) {
|
||||
colors[j++] = i;
|
||||
colors[j++] = i;
|
||||
colors[j++] = i;
|
||||
}
|
||||
|
||||
setIndexedColors(256, 0, colors, 0);
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ private:
|
||||
uint32 _NativeColor(const RGBColor& color) const;
|
||||
status_t _SetFallbackMode(display_mode& mode) const;
|
||||
void _SetSystemPalette();
|
||||
void _SetGrayscalePalette();
|
||||
|
||||
int fCardFD;
|
||||
image_id fAccelerantImage;
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "SystemPalette.h"
|
||||
#include "UpdateQueue.h"
|
||||
|
||||
#include <vesa/vesa_info.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -39,6 +41,7 @@ HWInterface::HWInterface(bool doubleBuffered)
|
||||
fCursorObscured(false),
|
||||
fCursorLocation(0, 0),
|
||||
fDoubleBuffered(doubleBuffered),
|
||||
fVGADevice(-1),
|
||||
// fUpdateExecutor(new UpdateQueue(this))
|
||||
fUpdateExecutor(NULL),
|
||||
fListeners(20)
|
||||
@ -669,49 +672,54 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR,
|
||||
case B_GRAY8:
|
||||
if (frontBuffer->Width() > dstBPR) {
|
||||
// VGA 16 color grayscale planar mode
|
||||
if (fVGADevice > 0) {
|
||||
vga_planar_blit_args args;
|
||||
args.source = src;
|
||||
args.source_bytes_per_row = srcBPR;
|
||||
args.left = x;
|
||||
args.top = y;
|
||||
args.right = right;
|
||||
args.bottom = bottom;
|
||||
if (ioctl(fVGADevice, VGA_PLANAR_BLIT, &args, sizeof(args)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Since we cannot set the plane, we do monochrome output
|
||||
dst += y * dstBPR + x / 8;
|
||||
uint8* dstBase = dst;
|
||||
uint8* srcBase = src;
|
||||
int32 left = x;
|
||||
|
||||
// TODO: this is awfully slow...
|
||||
// TODO: assumes BGR order
|
||||
for (int32 plane = 0; plane < 1; plane++) {
|
||||
// TODO: we need to select the plane here!
|
||||
src = srcBase;
|
||||
dst = dstBase;
|
||||
for (; y <= bottom; y++) {
|
||||
uint8* srcHandle = src;
|
||||
uint8* dstHandle = dst;
|
||||
uint8 current8 = dstHandle[0];
|
||||
// we store 8 pixels before writing them back
|
||||
|
||||
for (; y <= bottom; y++) {
|
||||
uint8* srcHandle = src;
|
||||
uint8* dstHandle = dst;
|
||||
uint8 current8 = dstHandle[0];
|
||||
// we store 8 pixels before writing them back
|
||||
for (x = left; x <= right; x++) {
|
||||
uint8 pixel = (308 * srcHandle[2] + 600 * srcHandle[1]
|
||||
+ 116 * srcHandle[0]) / 1024;
|
||||
srcHandle += 4;
|
||||
|
||||
for (x = left; x <= right; x++) {
|
||||
uint8 pixel = (308 * srcHandle[2] + 600 * srcHandle[1]
|
||||
+ 116 * srcHandle[0]) / 1024;
|
||||
srcHandle += 4;
|
||||
if (pixel > 128)
|
||||
current8 |= 0x80 >> (x & 7);
|
||||
else
|
||||
current8 &= ~(0x80 >> (x & 7));
|
||||
|
||||
if (pixel > 128)
|
||||
current8 |= 0x80 >> (x & 7);
|
||||
else
|
||||
current8 &= ~(0x80 >> (x & 7));
|
||||
|
||||
if ((x & 7) == 7) {
|
||||
// last pixel in 8 pixel group
|
||||
dstHandle[0] = current8;
|
||||
dstHandle++;
|
||||
current8 = dstHandle[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (x & 7) {
|
||||
// last pixel has not been written yet
|
||||
if ((x & 7) == 7) {
|
||||
// last pixel in 8 pixel group
|
||||
dstHandle[0] = current8;
|
||||
dstHandle++;
|
||||
current8 = dstHandle[0];
|
||||
}
|
||||
dst += dstBPR;
|
||||
src += srcBPR;
|
||||
}
|
||||
|
||||
if (x & 7) {
|
||||
// last pixel has not been written yet
|
||||
dstHandle[0] = current8;
|
||||
}
|
||||
dst += dstBPR;
|
||||
src += srcBPR;
|
||||
}
|
||||
} else {
|
||||
// offset to left top pixel in dest buffer
|
||||
|
@ -220,6 +220,7 @@ class HWInterface : protected MultiLocker {
|
||||
bool fCursorObscured;
|
||||
BPoint fCursorLocation;
|
||||
bool fDoubleBuffered;
|
||||
int fVGADevice;
|
||||
|
||||
private:
|
||||
UpdateQueue* fUpdateExecutor;
|
||||
|
Loading…
Reference in New Issue
Block a user