summaryrefslogtreecommitdiff
path: root/src/drivers/video/video.c
blob: 7e062a50af07affe35358f955ea4f2bbea0ce60f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "video.h"

#include "string.h"
#include "kernel.h"

#undef DEBUG

static video_vtable_t const video_vtable = {
	{
	video_activate,
	video_deactivate,
	video_deinit,
	video_print_info
	}
};

void video_init( video_t *video, interrupt_t *interrupt, void *context )
{
	memset( video, 0, sizeof( video_t ) );

	driver_init( (driver_t *)video, DRIVER_TYPE_VIDEO, interrupt, context );

	video->nof_modes = 0;

	((driver_t *)video)->vtable = (driver_vtable_t *)&video_vtable;
}

void video_activate( void *obj )
{
	kernel_panic( "Activating generic video driver should not be called directly." );
}

void video_deactivate( void *obj )
{
	kernel_panic( "Deactivating generic video driver should not be called directly." );
}

void video_deinit( void *obj )
{
	// nothing to be done
}

void video_print_info( void *obj )
{
	kernel_panic( "Printing info of generic video driver should not be called directly." );
}

video_mode_t video_make_mode( const video_mode_type_t mode_type, const int x, const int y, const int color_depth )
{
	video_mode_t mode;

	mode.mode_type = mode_type;
	mode.x = x;
	mode.y = y;
	mode.color_depth = color_depth;

	return mode;
}

void video_register_mode( void *obj, const video_mode_t *mode )
{
	video_t *video = (video_t *)obj;

	if( video->nof_modes >= MAX_NOF_VIDEO_MODES ) {
		kernel_panic( "Trying to register too many video modes, see MAX_NOF_VIDEO_MODES: %d", MAX_NOF_VIDEO_MODES );
	}

	video->modes[video->nof_modes++] = mode;
}

static int get_matching_mode_idx( video_t *video, const video_mode_t mode )
{
	for( int i = 0; video->modes[i]->x != 0; i++ ) {
		if( 	mode.mode_type == video->modes[i]->mode_type &&
			mode.x == video->modes[i]->x &&
			mode.y == video->modes[i]->y &&
			mode.color_depth == video->modes[i]->color_depth ) {
			return i;
		}
	}

	return -1;
}

bool video_supports_mode( void *obj, const video_mode_t mode )
{
	video_t *video = (video_t *)obj;

	for( int i = 0; video->modes[i]->x != 0; i++ ) {
		if( 	mode.mode_type == video->modes[i]->mode_type &&
			mode.x == video->modes[i]->x &&
			mode.y == video->modes[i]->y &&
			mode.color_depth == video->modes[i]->color_depth ) {
			return true;
		}
	}

	return false;
}

bool video_set_mode( void *obj, const video_mode_t mode )
{
	video_t *video = (video_t *)obj;

	// do not allow unknown timings!
	if( !((video_vtable_t *)(video->base.vtable))->supports_mode( obj, mode ) ) {
		return false;
	}

	const video_mode_t *matching_mode = video->modes[get_matching_mode_idx( video, mode )];

	return ((video_vtable_t *)(video->base.vtable))->switch_mode( obj, matching_mode );
}

bool video_switch_mode( void *obj, const video_mode_t *mode )
{
	kernel_panic( "Switching mode function of abstract video driver should not be called directly." );
}