* 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:
@@ -47,6 +47,24 @@ struct vesa_info {
|
|||||||
enum {
|
enum {
|
||||||
VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
||||||
VESA_GET_DEVICE_NAME,
|
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
|
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"));
|
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
|
device.cpp
|
||||||
driver.cpp
|
driver.cpp
|
||||||
vesa.cpp
|
vesa.cpp
|
||||||
|
vga.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* 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 <OS.h>
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
@@ -15,11 +21,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "driver.h"
|
|
||||||
#include "device.h"
|
|
||||||
#include "vesa_info.h"
|
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_DEVICE
|
//#define TRACE_DEVICE
|
||||||
#ifdef 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_BAD_ADDRESS;
|
||||||
return B_OK;
|
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:
|
default:
|
||||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength));
|
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* 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];
|
char *gDeviceNames[MAX_CARDS + 1];
|
||||||
vesa_info *gDeviceInfo[MAX_CARDS];
|
vesa_info *gDeviceInfo[MAX_CARDS];
|
||||||
|
isa_module_info *gISA;
|
||||||
lock gLock;
|
lock gLock;
|
||||||
|
|
||||||
|
|
||||||
@@ -88,10 +89,21 @@ init_driver(void)
|
|||||||
else
|
else
|
||||||
return B_NO_MEMORY;
|
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[0] = strdup("graphics/vesa");
|
||||||
gDeviceNames[1] = NULL;
|
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"));
|
TRACE((DEVICE_NAME ": uninit_driver()\n"));
|
||||||
|
|
||||||
|
put_module(B_ISA_MODULE_NAME);
|
||||||
uninit_lock(&gLock);
|
uninit_lock(&gLock);
|
||||||
|
|
||||||
// free device related structures
|
// free device related structures
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2005-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef DRIVER_H
|
#ifndef DRIVER_H
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <PCI.h>
|
#include <ISA.h>
|
||||||
|
|
||||||
#include "vesa_info.h"
|
#include "vesa_info.h"
|
||||||
#include "lock.h"
|
#include "lock.h"
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
extern char *gDeviceNames[];
|
extern char *gDeviceNames[];
|
||||||
extern vesa_info *gDeviceInfo[];
|
extern vesa_info *gDeviceInfo[];
|
||||||
|
extern isa_module_info *gISA;
|
||||||
extern lock gLock;
|
extern lock gLock;
|
||||||
|
|
||||||
#endif /* DRIVER_H */
|
#endif /* DRIVER_H */
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, [email protected]. 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 */
|
||||||
@@ -214,6 +214,8 @@ AccelerantHWInterface::_OpenGraphicsDevice(int deviceNumber)
|
|||||||
if (deviceNumber == 1) {
|
if (deviceNumber == 1) {
|
||||||
sprintf(path, "/dev/graphics/vesa");
|
sprintf(path, "/dev/graphics/vesa");
|
||||||
device = open(path, B_READ_WRITE);
|
device = open(path, B_READ_WRITE);
|
||||||
|
fVGADevice = device;
|
||||||
|
// store the device, so that we can access the planar blitter
|
||||||
} else {
|
} else {
|
||||||
close(device);
|
close(device);
|
||||||
device = B_ENTRY_NOT_FOUND;
|
device = B_ENTRY_NOT_FOUND;
|
||||||
@@ -528,6 +530,8 @@ AccelerantHWInterface::SetMode(const display_mode& mode)
|
|||||||
|
|
||||||
if (fDisplayMode.space == B_CMAP8)
|
if (fDisplayMode.space == B_CMAP8)
|
||||||
_SetSystemPalette();
|
_SetSystemPalette();
|
||||||
|
else if (fDisplayMode.space == B_GRAY8)
|
||||||
|
_SetGrayscalePalette();
|
||||||
|
|
||||||
// update acceleration hooks
|
// update acceleration hooks
|
||||||
fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode);
|
fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode);
|
||||||
@@ -1155,3 +1159,36 @@ AccelerantHWInterface::_SetSystemPalette()
|
|||||||
|
|
||||||
setIndexedColors(256, 0, colors, 0);
|
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;
|
uint32 _NativeColor(const RGBColor& color) const;
|
||||||
status_t _SetFallbackMode(display_mode& mode) const;
|
status_t _SetFallbackMode(display_mode& mode) const;
|
||||||
void _SetSystemPalette();
|
void _SetSystemPalette();
|
||||||
|
void _SetGrayscalePalette();
|
||||||
|
|
||||||
int fCardFD;
|
int fCardFD;
|
||||||
image_id fAccelerantImage;
|
image_id fAccelerantImage;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "SystemPalette.h"
|
#include "SystemPalette.h"
|
||||||
#include "UpdateQueue.h"
|
#include "UpdateQueue.h"
|
||||||
|
|
||||||
|
#include <vesa/vesa_info.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ HWInterface::HWInterface(bool doubleBuffered)
|
|||||||
fCursorObscured(false),
|
fCursorObscured(false),
|
||||||
fCursorLocation(0, 0),
|
fCursorLocation(0, 0),
|
||||||
fDoubleBuffered(doubleBuffered),
|
fDoubleBuffered(doubleBuffered),
|
||||||
|
fVGADevice(-1),
|
||||||
// fUpdateExecutor(new UpdateQueue(this))
|
// fUpdateExecutor(new UpdateQueue(this))
|
||||||
fUpdateExecutor(NULL),
|
fUpdateExecutor(NULL),
|
||||||
fListeners(20)
|
fListeners(20)
|
||||||
@@ -669,18 +672,24 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR,
|
|||||||
case B_GRAY8:
|
case B_GRAY8:
|
||||||
if (frontBuffer->Width() > dstBPR) {
|
if (frontBuffer->Width() > dstBPR) {
|
||||||
// VGA 16 color grayscale planar mode
|
// 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;
|
dst += y * dstBPR + x / 8;
|
||||||
uint8* dstBase = dst;
|
|
||||||
uint8* srcBase = src;
|
|
||||||
int32 left = x;
|
int32 left = x;
|
||||||
|
|
||||||
// TODO: this is awfully slow...
|
// TODO: this is awfully slow...
|
||||||
// TODO: assumes BGR order
|
// 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++) {
|
for (; y <= bottom; y++) {
|
||||||
uint8* srcHandle = src;
|
uint8* srcHandle = src;
|
||||||
uint8* dstHandle = dst;
|
uint8* dstHandle = dst;
|
||||||
@@ -712,7 +721,6 @@ HWInterface::_CopyToFront(uint8* src, uint32 srcBPR,
|
|||||||
dst += dstBPR;
|
dst += dstBPR;
|
||||||
src += srcBPR;
|
src += srcBPR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// offset to left top pixel in dest buffer
|
// offset to left top pixel in dest buffer
|
||||||
dst += y * dstBPR + x;
|
dst += y * dstBPR + x;
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ class HWInterface : protected MultiLocker {
|
|||||||
bool fCursorObscured;
|
bool fCursorObscured;
|
||||||
BPoint fCursorLocation;
|
BPoint fCursorLocation;
|
||||||
bool fDoubleBuffered;
|
bool fDoubleBuffered;
|
||||||
|
int fVGADevice;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UpdateQueue* fUpdateExecutor;
|
UpdateQueue* fUpdateExecutor;
|
||||||
|
|||||||
Reference in New Issue
Block a user