SayoriOS 0.3.3

screen.c
1 #include <io/screen.h>
2 #include <multiboot.h>
3 #include <lib/stdlib.h>
4 #include <sys/timer.h>
5 #include <io/ports.h>
6 #include <common.h>
7 #include "mem/pmm.h"
8 #include "mem/vmm.h"
9 #include "sys/mtrr.h"
10
11 uint8_t *framebuffer_addr = 0;
12 uint32_t framebuffer_pitch;
13 uint32_t framebuffer_bpp;
14 uint32_t framebuffer_width;
15 uint32_t framebuffer_height;
16 uint32_t framebuffer_size;
17 uint8_t *back_framebuffer_addr = 0;
18 bool lazyDraw = true;
19 bool tty_oem_mode = false;
20
21 size_t fb_mtrr_idx = 0;
22 size_t bfb_mtrr_idx = 0;
23
29 size_t getDisplayAddr(){
30 return (size_t)framebuffer_addr;
31 }
32
33 size_t getFrameBufferAddr() {
34 return (size_t)back_framebuffer_addr;
35 }
36
42 uint32_t getDisplayPitch(){
43 return framebuffer_pitch;
44 }
45
51 uint32_t getDisplayBpp(){
52 return framebuffer_bpp;
53 }
54
55 void create_back_framebuffer() {
56 qemu_log("^---- 1. Allocating");
57
58 back_framebuffer_addr = (uint8_t*)kmalloc_common(framebuffer_size, PAGE_SIZE);
59 memset(back_framebuffer_addr, 0, framebuffer_size);
60
61 size_t phys_bfb = virt2phys(get_kernel_page_directory(), (virtual_addr_t) back_framebuffer_addr);
62
63 qemu_log("Physical is: %x", phys_bfb);
64
65 bfb_mtrr_idx = find_free_mtrr();
66 write_mtrr_size(bfb_mtrr_idx, phys_bfb, framebuffer_size, 1);
67
68 // map_pages(
69 // get_kernel_page_directory(),
70 // phys_bfb,
71 // (virtual_addr_t) back_framebuffer_addr,
72 // framebuffer_size,
73 // PAGE_WRITEABLE | PAGE_CACHE_DISABLE
74 // );
75
76 phys_set_flags(get_kernel_page_directory(), (virtual_addr_t)back_framebuffer_addr, PAGE_WRITEABLE | PAGE_CACHE_DISABLE);
77
78 qemu_log("framebuffer_size = %d (%dK) (%dM)", framebuffer_size, framebuffer_size/1024, framebuffer_size/(1024*1024));
79 qemu_log("back_framebuffer_addr = %x", back_framebuffer_addr);
80 }
81
87 void init_vbe(multiboot_header_t *mboot) {
88 // FIXME: Something wrong with `svga_mode_info_t` structure!
89 // svga_mode_info_t *svga_mode = (svga_mode_info_t*) mboot->vbe_mode_info;
90 // framebuffer_addr = (uint8_t*)svga_mode->physbase;
91 // framebuffer_pitch = svga_mode->pitch;
92 // framebuffer_bpp = svga_mode->bpp;
93 // framebuffer_width = svga_mode->screen_width;
94 // framebuffer_height = svga_mode->screen_height;
95 // framebuffer_size = framebuffer_height * framebuffer_pitch;
96
97 // qemu_log("[VBE] [Install] Width: %d; Height: %d; Pitch: %d; BPP: %d; Size: %d; Address: %x",
98 // framebuffer_width,
99 // framebuffer_height,
100 // framebuffer_pitch,
101 // framebuffer_bpp,
102 // framebuffer_size,
103 // framebuffer_addr
104 // );
105
106
107 framebuffer_addr = (uint8_t *) mboot->framebuffer_addr;
108 framebuffer_pitch = mboot->framebuffer_pitch;
109 framebuffer_bpp = mboot->framebuffer_bpp;
110 framebuffer_width = mboot->framebuffer_width;
111 framebuffer_height = mboot->framebuffer_height;
112 // framebuffer_pitch = framebuffer_width * (framebuffer_bpp >> 3);
113 framebuffer_size = framebuffer_height * framebuffer_pitch;
114
115 qemu_log("[VBE] [USING LEGACY INFO] Width: %d; Height: %d; Pitch: %d; BPP: %d; Size: %d; Address: %x",
116 mboot->framebuffer_width,
117 mboot->framebuffer_height,
118 mboot->framebuffer_pitch,
119 mboot->framebuffer_bpp,
120 mboot->framebuffer_height * mboot->framebuffer_pitch,
121 mboot->framebuffer_addr
122 );
123
124 physical_addr_t frame = (physical_addr_t)framebuffer_addr;
125 virtual_addr_t virt = (virtual_addr_t)framebuffer_addr;
126
127 size_t start_tk = getTicks();
128
129 map_pages(get_kernel_page_directory(),
130 frame,
131 virt,
132 framebuffer_size,
133 PAGE_WRITEABLE | PAGE_CACHE_DISABLE);
134
135 qemu_log("Okay mapping! (took %d millis)", (getTicks() - start_tk)/(getFrequency()/1000));
136
137 qemu_log("Creating second framebuffer");
138
139 create_back_framebuffer();
140
141 qemu_log("^---- OKAY");
142
143 fb_mtrr_idx = find_free_mtrr();
144
145 write_mtrr_size(fb_mtrr_idx, frame, framebuffer_size, 1);
146 }
147
156 size_t getPixel(int32_t x, int32_t y){
157 if (x < 0 || y < 0 ||
158 x >= (int) VESA_WIDTH ||
159 y >= (int) VESA_HEIGHT) {
160 return 0x000000;
161 }
162
163 size_t where = x * (framebuffer_bpp >> 3) + y * framebuffer_pitch;
164
165 return ((back_framebuffer_addr[where+2] & 0xff) << 16) + ((back_framebuffer_addr[where+1] & 0xff) << 8) + (back_framebuffer_addr[where] & 0xff);
166 }
167
168 void rgba_blend(uint8_t result[4], const uint8_t fg[4], const uint8_t bg[4])
169 {
170 uint32_t alpha = fg[3] + 1;
171 uint32_t inv_alpha = 256 - fg[3];
172
173 result[0] = (uint8_t)((alpha * fg[0] + inv_alpha * bg[0]) >> 8);
174 result[1] = (uint8_t)((alpha * fg[1] + inv_alpha * bg[1]) >> 8);
175 result[2] = (uint8_t)((alpha * fg[2] + inv_alpha * bg[2]) >> 8);
176 result[3] = 0xff;
177 }
178
179 void setPixelAlpha(uint32_t x, uint32_t y, rgba_color color) {
180 if (x >= VESA_WIDTH ||
181 y >= VESA_HEIGHT) {
182 return;
183 }
184
185 unsigned where = x * (framebuffer_bpp / 8) + y * framebuffer_pitch;
186
187 if (color.a != 255) {
188 if (color.a != 0) {
189 uint8_t bg[4] = {back_framebuffer_addr[where], back_framebuffer_addr[where + 1], back_framebuffer_addr[where + 2], 255};
190 uint8_t fg[4] = {(uint8_t)color.b, (uint8_t)color.g, (uint8_t)color.r, (uint8_t)color.a};
191 uint8_t res[4];
192
193 rgba_blend(res, fg, bg);
194
195 // framebuffer_addr[where] = res[0];
196 // framebuffer_addr[where + 1] = res[1];
197 // framebuffer_addr[where + 2] = res[2];
198
199 back_framebuffer_addr[where] = res[0];
200 back_framebuffer_addr[where + 1] = res[1];
201 back_framebuffer_addr[where + 2] = res[2];
202
203 } else { // if absolutely transparent don't draw anything
204 return;
205 }
206 } else { // if non transparent just draw rgb
207 // framebuffer_addr[where] = color.b & 255;
208 // framebuffer_addr[where + 1] = color.g & 255;
209 // framebuffer_addr[where + 2] = color.r & 255;
210
211 back_framebuffer_addr[where] = color.b & 255;
212 back_framebuffer_addr[where + 1] = color.g & 255;
213 back_framebuffer_addr[where + 2] = color.r & 255;
214 }
215 }
216
222 uint32_t getScreenWidth(){
223 return framebuffer_width;
224 }
225
226
232 uint32_t getScreenHeight(){
233 return framebuffer_height;
234 }
235
236 void graphics_update(uint32_t new_width, uint32_t new_height, uint32_t new_pitch) {
237 unmap_pages_overlapping(get_kernel_page_directory(), (virtual_addr_t)framebuffer_addr, framebuffer_size);
238
239 framebuffer_size = ALIGN((new_width + 32) * new_height * 4, PAGE_SIZE);
240
241 map_pages(get_kernel_page_directory(),
242 (physical_addr_t)framebuffer_addr,
243 (virtual_addr_t)framebuffer_addr,
244 framebuffer_size,
245 PAGE_WRITEABLE | PAGE_CACHE_DISABLE
246 );
247
248 framebuffer_width = new_width;
249 framebuffer_height = new_height;
250 framebuffer_pitch = new_pitch;
251
252 back_framebuffer_addr = krealloc(back_framebuffer_addr, framebuffer_size);
253 memset(back_framebuffer_addr, 0x00, framebuffer_size);
254
255 phys_set_flags(get_kernel_page_directory(), (virtual_addr_t)back_framebuffer_addr, PAGE_WRITEABLE | PAGE_CACHE_DISABLE);
256
257 uint32_t bfb_new_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t)back_framebuffer_addr);
258
259 write_mtrr_size(fb_mtrr_idx, (uint32_t)framebuffer_addr, framebuffer_size, 1);
260 write_mtrr_size(bfb_mtrr_idx, (uint32_t)bfb_new_phys, framebuffer_size, 1);
261 }
262
267 void clean_screen(){
268 memset(back_framebuffer_addr, 0, framebuffer_size); // Optimized variant
269 }
270
271 void rect_copy(int x, int y, int width, int height) {
272 unsigned char* src = (unsigned char*)back_framebuffer_addr + (y * framebuffer_pitch) + (x * (framebuffer_bpp/8));
273 unsigned char* dest = (unsigned char*)framebuffer_addr + (y * framebuffer_pitch) + (x * (framebuffer_bpp/8));
274 size_t bytes_per_line = width * (framebuffer_bpp/8);
275
276 for(int i = 0; i < height; i++) {
277 memcpy(dest, src, bytes_per_line);
278 src += framebuffer_pitch;
279 dest += framebuffer_pitch;
280 }
281 }
common.h
Основные определения ядра
memset
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
memcpy
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
multiboot_header
Definition: multiboot.h:24
rgba_struct
Definition: screen.h:20
getFrequency
size_t getFrequency()
Получить частоту таймера
Definition: timer.c:43
getTicks
size_t getTicks()
Получить количество тиков
Definition: timer.c:26