1/*
2 * Copyright 2006-2009, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "vga.h"
8#include "driver.h"
9
10#include <vga.h>
11
12#include <KernelExport.h>
13
14
15status_t
16vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count)
17{
18	if (first + count > 256)
19		count = 256 - first;
20
21	gISA->write_io_8(VGA_COLOR_WRITE_MODE, first);
22
23	// write VGA palette
24	for (int32 i = first; i < count; i++) {
25		uint8 color[3];
26		if (user_memcpy(color, &colors[i * 3], 3) < B_OK)
27			return B_BAD_ADDRESS;
28
29		// VGA (usually) has only 6 bits per gun
30		gISA->write_io_8(VGA_COLOR_DATA, color[0] >> 2);
31		gISA->write_io_8(VGA_COLOR_DATA, color[1] >> 2);
32		gISA->write_io_8(VGA_COLOR_DATA, color[2] >> 2);
33	}
34	return B_OK;
35}
36
37
38status_t
39vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
40	int32 left, int32 top, int32 right, int32 bottom)
41{
42	// If we don't actually have a frame_buffer, bail.
43	if (info->frame_buffer == NULL)
44		return B_BAD_ADDRESS;
45
46	int32 dstBPR = info->bytes_per_row;
47	uint8 *dst = info->frame_buffer + top * dstBPR + left / 8;
48
49	// TODO: this is awfully slow...
50	// TODO: assumes BGR order
51	for (int32 y = top; y <= bottom; y++) {
52		for (int32 plane = 0; plane < 4; plane++) {
53			// select the plane we intend to write to and read from
54			gISA->write_io_16(VGA_SEQUENCER_INDEX, (1 << (plane + 8)) | 0x02);
55			gISA->write_io_16(VGA_GRAPHICS_INDEX, (plane << 8) | 0x04);
56
57			uint8* srcHandle = src;
58			uint8* dstHandle = dst;
59			uint8 current8 = dstHandle[0];
60				// we store 8 pixels before writing them back
61
62			int32 x = left;
63			for (; x <= right; x++) {
64				uint8 rgba[4];
65				if (user_memcpy(rgba, srcHandle, 4) < B_OK)
66					return B_BAD_ADDRESS;
67				uint8 pixel = (308 * rgba[2] + 600 * rgba[1]
68					+ 116 * rgba[0]) / 16384;
69				srcHandle += 4;
70
71				if (pixel & (1 << plane))
72					current8 |= 0x80 >> (x & 7);
73				else
74					current8 &= ~(0x80 >> (x & 7));
75
76				if ((x & 7) == 7) {
77					// last pixel in 8 pixel group
78					dstHandle[0] = current8;
79					dstHandle++;
80					current8 = dstHandle[0];
81				}
82			}
83
84			if (x & 7) {
85				// last pixel has not been written yet
86				dstHandle[0] = current8;
87			}
88		}
89		dst += dstBPR;
90		src += srcBPR;
91	}
92	return B_OK;
93}
94
95