xref: /haiku/src/add-ons/kernel/drivers/graphics/vesa/vga.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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 
15 status_t
16 vga_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 
38 status_t
39 vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR,
40 	int32 left, int32 top, int32 right, int32 bottom)
41 {
42 	int32 dstBPR = info->bytes_per_row;
43 	uint8 *dst = info->frame_buffer + top * dstBPR + left / 8;
44 
45 	// TODO: this is awfully slow...
46 	// TODO: assumes BGR order
47 	for (int32 y = top; y <= bottom; y++) {
48 		for (int32 plane = 0; plane < 4; plane++) {
49 			// select the plane we intend to write to and read from
50 			gISA->write_io_16(VGA_SEQUENCER_INDEX, (1 << (plane + 8)) | 0x02);
51 			gISA->write_io_16(VGA_GRAPHICS_INDEX, (plane << 8) | 0x04);
52 
53 			uint8* srcHandle = src;
54 			uint8* dstHandle = dst;
55 			uint8 current8 = dstHandle[0];
56 				// we store 8 pixels before writing them back
57 
58 			int32 x = left;
59 			for (; x <= right; x++) {
60 				uint8 rgba[4];
61 				if (user_memcpy(rgba, srcHandle, 4) < B_OK)
62 					return B_BAD_ADDRESS;
63 				uint8 pixel = (308 * rgba[2] + 600 * rgba[1]
64 					+ 116 * rgba[0]) / 16384;
65 				srcHandle += 4;
66 
67 				if (pixel & (1 << plane))
68 					current8 |= 0x80 >> (x & 7);
69 				else
70 					current8 &= ~(0x80 >> (x & 7));
71 
72 				if ((x & 7) == 7) {
73 					// last pixel in 8 pixel group
74 					dstHandle[0] = current8;
75 					dstHandle++;
76 					current8 = dstHandle[0];
77 				}
78 			}
79 
80 			if (x & 7) {
81 				// last pixel has not been written yet
82 				dstHandle[0] = current8;
83 			}
84 		}
85 		dst += dstBPR;
86 		src += srcBPR;
87 	}
88 	return B_OK;
89 }
90 
91