1/*
2 * Copyright 2004-2009, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2008, Stephan A��mus <superstippi@gmx.de>
4 * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com>
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include <arch/cpu.h>
10#include <boot/stage2.h>
11#include <boot/platform.h>
12#include <boot/platform/generic/video.h>
13#include <boot/kernel_args.h>
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19
20#define TRACE_VIDEO
21#ifdef TRACE_VIDEO
22#	define TRACE(x) dprintf x
23#else
24#	define TRACE(x) ;
25#endif
26
27
28static void
29blit32(addr_t frameBuffer, const uint8 *data, uint16 width,
30	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
31{
32	uint32 *start = (uint32 *)(frameBuffer
33		+ gKernelArgs.frame_buffer.bytes_per_row * top + 4 * left);
34
35	for (int32 y = 0; y < height; y++) {
36		const uint8* src = data;
37		uint32* dst = start;
38		for (int32 x = 0; x < width; x++) {
39			dst[0] = (src[2] << 16) | (src[1] << 8) | (src[0]);
40			dst++;
41			src += 3;
42		}
43
44		data += imageWidth * 3;
45		start = (uint32 *)((addr_t)start
46			+ gKernelArgs.frame_buffer.bytes_per_row);
47	}
48}
49
50
51static void
52blit24(addr_t frameBuffer, const uint8 *data, uint16 width,
53	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
54{
55	uint8 *start = (uint8 *)frameBuffer
56		+ gKernelArgs.frame_buffer.bytes_per_row * top + 3 * left;
57
58	for (int32 y = 0; y < height; y++) {
59		const uint8* src = data;
60		uint8* dst = start;
61		for (int32 x = 0; x < width; x++) {
62			dst[0] = src[0];
63			dst[1] = src[1];
64			dst[2] = src[2];
65			dst += 3;
66			src += 3;
67		}
68
69		data += imageWidth * 3;
70		start = start + gKernelArgs.frame_buffer.bytes_per_row;
71	}
72}
73
74
75static void
76blit16(addr_t frameBuffer, const uint8 *data, uint16 width,
77	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
78{
79	uint16 *start = (uint16 *)(frameBuffer
80		+ gKernelArgs.frame_buffer.bytes_per_row * top + 2 * left);
81
82	for (int32 y = 0; y < height; y++) {
83		const uint8* src = data;
84		uint16* dst = start;
85		for (int32 x = 0; x < width; x++) {
86			dst[0] = ((src[2] >> 3) << 11)
87				| ((src[1] >> 2) << 5)
88				| ((src[0] >> 3));
89			dst++;
90			src += 3;
91		}
92
93		data += imageWidth * 3;
94		start = (uint16 *)((addr_t)start
95			+ gKernelArgs.frame_buffer.bytes_per_row);
96	}
97}
98
99
100static void
101blit15(addr_t frameBuffer, const uint8 *data, uint16 width,
102	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
103{
104	uint16 *start = (uint16 *)(frameBuffer
105		+ gKernelArgs.frame_buffer.bytes_per_row * top + 2 * left);
106
107	for (int32 y = 0; y < height; y++) {
108		const uint8* src = data;
109		uint16* dst = start;
110		for (int32 x = 0; x < width; x++) {
111			dst[0] = ((src[2] >> 3) << 10)
112				| ((src[1] >> 3) << 5)
113				| ((src[0] >> 3));
114			dst++;
115			src += 3;
116		}
117
118		data += imageWidth * 3;
119		start = (uint16 *)((addr_t)start
120			+ gKernelArgs.frame_buffer.bytes_per_row);
121	}
122}
123
124
125static void
126blit8(addr_t frameBuffer, const uint8 *data, uint16 width,
127	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
128{
129	if (!data)
130		return;
131
132	addr_t start = frameBuffer + gKernelArgs.frame_buffer.bytes_per_row * top
133		+ left;
134
135	for (int32 i = 0; i < height; i++) {
136		memcpy((void *)(start + gKernelArgs.frame_buffer.bytes_per_row * i),
137			&data[i * imageWidth], width);
138	}
139}
140
141
142static void
143blit4(addr_t frameBuffer, const uint8 *data, uint16 width,
144	uint16 height, uint16 imageWidth, uint16 left, uint16 top)
145{
146	if (!data)
147		return;
148	// call back platform specific code since it's really platform-specific.
149	platform_blit4(frameBuffer, data, width, height,
150		imageWidth, left, top);
151}
152
153
154void
155video_blit_image(addr_t frameBuffer, const uint8 *data,
156	uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
157{
158	switch (gKernelArgs.frame_buffer.depth) {
159		case 4:
160			return blit4(frameBuffer, data,
161				width, height, imageWidth, left, top);
162		case 8:
163			return blit8(frameBuffer, data,
164				width, height, imageWidth, left, top);
165		case 15:
166			return blit15(frameBuffer, data,
167				width, height, imageWidth, left, top);
168		case 16:
169			return blit16(frameBuffer, data,
170				width, height, imageWidth, left, top);
171		case 24:
172			return blit24(frameBuffer, data,
173				width, height, imageWidth, left, top);
174		case 32:
175			return blit32(frameBuffer, data,
176				width, height, imageWidth, left, top);
177	}
178}
179
180