1/*
2 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "rom_calls.h"
8#include "console.h"
9#include "video.h"
10//#include "mmu.h"
11//#include "images.h"
12
13#include <arch/cpu.h>
14#include <boot/stage2.h>
15#include <boot/platform.h>
16#include <boot/menu.h>
17#include <boot/kernel_args.h>
18#include <boot/platform/generic/video.h>
19#include <util/list.h>
20#include <drivers/driver_settings.h>
21#include <GraphicsDefs.h>
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27
28//#define TRACE_VIDEO
29#ifdef TRACE_VIDEO
30#	define TRACE(x) dprintf x
31#else
32#	define TRACE(x) ;
33#endif
34
35static addr_t sFrameBuffer;
36
37
38static void
39probe_video_mode()
40{
41	if (gScreen == NULL) {
42		gKernelArgs.frame_buffer.enabled = false;
43		return;
44	}
45	/*
46	if (gScreen->RastPort.BitMap->Depth < 8) {
47		gKernelArgs.frame_buffer.enabled = false;
48		return;
49	}
50	*/
51
52	/*
53	dprintf("Video mode:\n");
54	dprintf("BytesPerRow %d\n", gScreen->RastPort.BitMap->BytesPerRow);
55	dprintf("Rows %d\n", gScreen->RastPort.BitMap->Rows);
56	dprintf("Flags %02x\n", gScreen->RastPort.BitMap->Flags);
57	dprintf("Depth %d\n", gScreen->RastPort.BitMap->Depth);
58	for (int i = 0; i < 8; i++)
59		dprintf("Planes[%d] %p\n", i, gScreen->RastPort.BitMap->Planes[i]);
60	*/
61
62	//XXX how do we tell it's a planar framebuffer ??
63
64	gKernelArgs.frame_buffer.width = gScreen->RastPort.BitMap->BytesPerRow * 8;
65	gKernelArgs.frame_buffer.height = gScreen->RastPort.BitMap->Rows;
66	gKernelArgs.frame_buffer.bytes_per_row = gScreen->RastPort.BitMap->BytesPerRow;
67	gKernelArgs.frame_buffer.depth = gScreen->RastPort.BitMap->Depth;
68	gKernelArgs.frame_buffer.physical_buffer.size
69		= gKernelArgs.frame_buffer.width
70		* gKernelArgs.frame_buffer.height
71		* gScreen->RastPort.BitMap->Depth / 8;
72	gKernelArgs.frame_buffer.physical_buffer.start
73		= (phys_addr_t)(gScreen->RastPort.BitMap->Planes[0]);
74
75	dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
76		gKernelArgs.frame_buffer.height, gKernelArgs.frame_buffer.depth);
77
78	gKernelArgs.frame_buffer.enabled = true;
79}
80
81
82//	#pragma mark -
83
84
85bool
86video_mode_hook(Menu *menu, MenuItem *item)
87{
88	// nothing yet
89	return true;
90}
91
92
93Menu *
94video_mode_menu()
95{
96	Menu *menu = new(nothrow) Menu(CHOICE_MENU, "Select Video Mode");
97	MenuItem *item;
98
99	menu->AddItem(item = new(nothrow) MenuItem("Default"));
100	item->SetMarked(true);
101	item->Select(true);
102	item->SetHelpText("The Default video mode is the one currently configured "
103		"in the system. If there is no mode configured yet, a viable mode will "
104		"be chosen automatically.");
105
106/*
107	video_mode *mode = NULL;
108	while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) {
109		char label[64];
110		sprintf(label, "%ux%u %u bit", mode->width, mode->height,
111			mode->bits_per_pixel);
112
113		menu->AddItem(item = new(nothrow) MenuItem(label));
114		item->SetData(mode);
115	}
116*/
117#if 1
118	uint32 modeID = INVALID_ID;
119	while ((modeID = NextDisplayInfo(modeID)) != INVALID_ID) {
120		//DisplayInfoHandle handle = FindDisplayInfo(modeID);
121		//if (handle == NULL)
122		//	continue;
123		struct DisplayInfo info;
124		struct DimensionInfo dimension;
125		struct NameInfo name;
126		if (GetDisplayInfoData(NULL, (uint8 *)&info, sizeof(info),
127			DTAG_DISP, modeID) < 48/*sizeof(struct DisplayInfo)*/)
128			continue;
129		if (GetDisplayInfoData(NULL, (uint8 *)&dimension, sizeof(dimension),
130			DTAG_DIMS, modeID) < 66)
131			continue;
132		/*if (GetDisplayInfoData(NULL, (uint8 *)&name, sizeof(name),
133			DTAG_NAME, modeID) < sizeof(name) - 8)
134			continue;*/
135		if (info.NotAvailable)
136			continue;
137		if (info.PropertyFlags & DIPF_IS_HAM)
138			continue;
139		if (info.PropertyFlags & DIPF_IS_DUALPF)
140			continue;
141		if (dimension.MaxDepth < 4)
142			continue;
143		// skip 5 & 6 bit modes
144		if (dimension.MaxDepth < 8 && dimension.MaxDepth != 4)
145			continue;
146		//dprintf("name: %s\n", name.Name);
147		/*
148		dprintf("mode 0x%08lx: %dx%d flags: 0x%08lx bpp: %d\n",
149			modeID, info.Resolution.x, info.Resolution.y, info.PropertyFlags,
150			info.RedBits + info.GreenBits + info.BlueBits);
151		dprintf("mode: %dx%d -> %dx%d\n",
152			dimension.MinRasterWidth, dimension.MinRasterHeight,
153			dimension.MaxRasterWidth, dimension.MaxRasterHeight);
154		*/
155		dprintf("mode: %dx%d %dbpp flags: 0x%08lx\n",
156			dimension.Nominal.MaxX - dimension.Nominal.MinX + 1,
157			dimension.Nominal.MaxY - dimension.Nominal.MinY + 1,
158			dimension.MaxDepth, info.PropertyFlags);
159
160		char label[128];
161		sprintf(label, "%ux%u %u bit %08lx%s%s",
162			dimension.Nominal.MaxX - dimension.Nominal.MinX + 1,
163			dimension.Nominal.MaxY - dimension.Nominal.MinY + 1,
164			dimension.MaxDepth, info.PropertyFlags,
165			(info.PropertyFlags & DIPF_IS_LACE) ? " i" : "",
166			(info.PropertyFlags & DIPF_IS_PAL) ? " pal" : "");
167
168		menu->AddItem(item = new(nothrow) MenuItem(label));
169		item->SetData((void *)modeID);
170	}
171
172#endif
173	dprintf("done\n");
174
175	menu->AddSeparatorItem();
176	menu->AddItem(item = new(nothrow) MenuItem("Return to main menu"));
177	item->SetType(MENU_ITEM_NO_CHOICE);
178
179	return menu;
180}
181
182
183//	#pragma mark - blit
184
185
186extern "C" void
187platform_blit4(addr_t frameBuffer, const uint8 *data,
188	uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
189{
190	if (!data)
191		return;
192	// TODO
193}
194
195
196extern "C" void
197platform_set_palette(const uint8 *palette)
198{
199	switch (gKernelArgs.frame_buffer.depth) {
200		case 4:
201			//vga_set_palette((const uint8 *)kPalette16, 0, 16);
202			break;
203		case 8:
204			//if (vesa_set_palette((const uint8 *)palette, 0, 256) != B_OK)
205			//	dprintf("set palette failed!\n");
206
207			break;
208		default:
209			break;
210	}
211}
212
213
214//	#pragma mark -
215
216
217extern "C" void
218platform_switch_to_logo(void)
219{
220	return;
221	// in debug mode, we'll never show the logo
222	if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0)
223		return;
224
225	addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start;
226	size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size;
227
228	// TODO: implement me
229
230	probe_video_mode();
231
232	// map to virtual memory
233	// (should be ok in bootloader thanks to TT0)
234
235	sFrameBuffer = gKernelArgs.frame_buffer.physical_buffer.start;
236
237	//video_display_splash(sFrameBuffer);
238
239}
240
241
242extern "C" void
243platform_switch_to_text_mode(void)
244{
245	// TODO: implement me
246	// force Intuition to redraw everything
247	RemakeDisplay();
248}
249
250
251extern "C" status_t
252platform_init_video(void)
253{
254	// TODO: implement me
255	probe_video_mode();
256
257	return B_OK;
258}
259
260