9f56e9c67bfe48925d50a0ddeea849881e7ddcb9
[rpikern] / src / video.c
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include "rpi.h"
6 #include "video.h"
7 #include "mem.h"
8 #include "debug.h"
9 #include "sysctl.h"
10
11 static void *fb_pixels;
12 static int scr_width, scr_height;
13 static int fb_width, fb_height, fb_depth, fb_size, fb_pitch;
14 static int fb_xoffs, fb_yoffs;
15
16 int video_init(void)
17 {
18         int i, j;
19         struct rpi_prop *prop;
20         uint32_t *fbptr;
21
22         scr_width = 1024;
23         scr_height = 576;
24         /*fb_width = 1920;
25         fb_height = 1024;*/
26         fb_width = scr_width;
27         fb_height = scr_height;
28         fb_depth = 32;
29
30         printf("Requesting video mode: %dx%d %d bpp (fb:%dx%d)\n", scr_width, scr_height,
31                         fb_depth, fb_width, fb_height);
32
33         rpi_prop(RPI_TAG_ALLOCFB, 16);
34         rpi_prop(RPI_TAG_SETFBVIRT, scr_width, scr_height);
35         rpi_prop(RPI_TAG_SETFBPHYS, fb_width, fb_height);
36         rpi_prop(RPI_TAG_SETFBDEPTH, fb_depth);
37
38         rpi_prop_send();
39
40         while((prop = rpi_prop_next())) {
41                 switch(prop->id) {
42                 case RPI_TAG_SETFBPHYS:
43                         printf(" setfbphys");
44                         fb_width = prop->data[0];
45                         fb_height = prop->data[1];
46                         break;
47
48                 case RPI_TAG_SETFBVIRT:
49                         printf(" setfbvirt");
50                         scr_width = prop->data[0];
51                         scr_height = prop->data[1];
52                         break;
53
54                 case RPI_TAG_SETFBDEPTH:
55                         printf(" setfbdepth");
56                         fb_depth = prop->data[0];
57                         break;
58
59                 case RPI_TAG_ALLOCFB:
60                         printf(" allocfb");
61                         fb_pixels = (void*)(prop->data[0] & 0x3fffffff);
62                         fb_size = prop->data[1];
63                         break;
64
65                 default:
66                         printf(" tag %x", prop->id);
67                         break;
68                 }
69
70                 printf(" %08x (%u bytes):", prop->res, prop->size);
71                 for(i=0; i<prop->size / 4; i++) {
72                         printf(" %u", prop->data[i]);
73                 }
74                 putchar('\n');
75         }
76
77         if(!fb_pixels) {
78                 rpi_prop(RPI_TAG_ALLOCFB, 16);
79                 if(rpi_prop_send() == -1 || !(prop = rpi_prop_find(RPI_TAG_ALLOCFB))) {
80                         printf("Failed to allocate framebuffer\n");
81                         return -1;
82                 }
83                 fb_pixels = (void*)(prop->data[0] & 0x3fffffff);
84                 fb_size = prop->data[1];
85         }
86
87         rpi_prop(RPI_TAG_GETFBPITCH);
88         rpi_prop(RPI_TAG_GETFBOFFS);
89         rpi_prop_send();
90         /*
91         if(rpi_prop_send() == -1) {
92                 printf("Failed to get pitch\n");
93                 return -1;
94         }
95         */
96
97         while((prop = rpi_prop_next())) {
98                 switch(prop->id) {
99                 case RPI_TAG_GETFBPITCH:
100                         fb_pitch = prop->data[0];
101                         break;
102
103                 case RPI_TAG_GETFBOFFS:
104                         fb_xoffs = prop->data[0];
105                         fb_yoffs = prop->data[1];
106                         break;
107
108                 default:
109                         break;
110                 }
111         }
112
113         printf("Got video mode: %dx%d (%d bpp)\n", scr_width, scr_height, fb_depth);
114         printf("Framebuffer: %dx%d at %p (%d bytes)\n", fb_width, fb_height, fb_pixels, fb_size);
115         printf("  virtual offset: %d, %d\n", fb_xoffs, fb_yoffs);
116         printf("  scanline pitch: %d\n", fb_pitch);
117
118         fbptr = fb_pixels;
119         for(i=0; i<fb_height; i++) {
120                 for(j=0; j<fb_width; j++) {
121                         int r = i ^ j;
122                         int g = (i ^ j) >> 1;
123                         int b = (i ^ j) >> 2;
124                         fbptr[j] = b | (g << 8) | (r << 16) | 0xff000000;
125                 }
126                 fbptr += fb_pitch >> 2;
127         }
128
129         sysctl_dcache_clean_inval((uint32_t)fb_pixels, fb_size);
130         return 0;
131 }
132
133 int video_scroll(int x, int y)
134 {
135         struct rpi_prop *prop;
136
137         rpi_prop(RPI_TAG_SETFBOFFS, x, y);
138         if(rpi_prop_send() == -1 || !(prop = rpi_prop_find(RPI_TAG_SETFBOFFS))) {
139                 return -1;
140         }
141
142         fb_xoffs = prop->data[0];
143         fb_yoffs = prop->data[1];
144         return 0;
145 }
146
147 void video_update(int dt)
148 {
149         static int dirx = 1, diry = 1;
150         int nx, ny;
151
152         nx = fb_xoffs + dirx * dt;
153         ny = fb_yoffs + diry * dt;
154
155         if(nx < 0) {
156                 nx = 0;
157                 dirx = -dirx;
158         } else if(nx + scr_width >= fb_width) {
159                 nx = fb_width - scr_width;
160                 dirx = -dirx;
161         }
162         if(ny < 0) {
163                 ny = 0;
164                 diry = -diry;
165         } else if(ny + scr_height >= fb_height) {
166                 ny = fb_height - scr_height;
167                 diry = -diry;
168         }
169
170         video_scroll(nx, ny);
171 }