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 }
Основные определения ядра
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
size_t getFrequency()
Получить частоту таймера
Definition: timer.c:43
size_t getTicks()
Получить количество тиков
Definition: timer.c:26