From 4153a625b9ba298398b99e977ef74bd381adc74d Mon Sep 17 00:00:00 2001 From: Recolic Keghart <root@recolic.net> Date: Mon, 30 Dec 2019 23:59:56 +0800 Subject: [PATCH] > Manual commit: Fixed SDL async-rendering bug. U201614531 recolic Linux RECOLICPC 5.4.6-arch3-1 #1 SMP PREEMPT Tue, 24 Dec 2019 04:36:53 +0000 x86_64 GNU/Linux 23:59:55 up 2 days, 5:33, 1 user, load average: 0.51, 0.76, 0.77 8785745a2ae9e4aea8bad5d7389f9d353592de5 --- nemu/src/device/vga.cc | 29 ++++++++++++++----- nexus-am/am/arch/x86-nemu/src/devices/video.c | 10 ++----- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/nemu/src/device/vga.cc b/nemu/src/device/vga.cc index 6644584..906196d 100644 --- a/nemu/src/device/vga.cc +++ b/nemu/src/device/vga.cc @@ -18,16 +18,15 @@ static SDL_Texture *texture; static uint32_t (*vmem) [SCREEN_W]; static uint32_t *screensize_port_base; -void update_screen() { - SDL_UpdateTexture(texture, NULL, vmem, SCREEN_W * sizeof(vmem[0][0])); - SDL_RenderClear(renderer); - SDL_RenderCopy(renderer, texture, NULL, NULL); - SDL_RenderPresent(renderer); +inline void SDL_ErrorCheck(int ret) { + if(ret != 0) { + rlib::println("SDL_Error: ret=", ret, ", GETERR=", SDL_GetError()); + } } -void init_vga() { - SDL_Init(SDL_INIT_VIDEO); - SDL_CreateWindowAndRenderer(SCREEN_W * 2, SCREEN_H * 2, 0, &window, &renderer); +static void init_vga_impl() { + SDL_ErrorCheck(SDL_Init(SDL_INIT_VIDEO)); + SDL_ErrorCheck(SDL_CreateWindowAndRenderer(SCREEN_W * 2, SCREEN_H * 2, 0, &window, &renderer)); SDL_SetWindowTitle(window, "NEMU"); texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, SCREEN_W, SCREEN_H); @@ -36,4 +35,18 @@ void init_vga() { *screensize_port_base = ((SCREEN_W) << 16) | (SCREEN_H); vmem = reinterpret_cast<decltype(vmem)>(add_mmio_map(VMEM, 0x80000, nullptr)); } + +void update_screen() { + if(window == nullptr) init_vga_impl(); + SDL_ErrorCheck(SDL_UpdateTexture(texture, NULL, vmem, SCREEN_W * sizeof(vmem[0][0]))); + SDL_ErrorCheck(SDL_RenderClear(renderer)); + SDL_ErrorCheck(SDL_RenderCopy(renderer, texture, NULL, NULL)); + SDL_RenderPresent(renderer); +} + +void init_vga() { + // Because of fucking SDL design, vga_init should be done in updating thread. + // Do nothing in main thread. +} + #endif /* HAS_IOE */ diff --git a/nexus-am/am/arch/x86-nemu/src/devices/video.c b/nexus-am/am/arch/x86-nemu/src/devices/video.c index 00cb3ab..2baa1f5 100644 --- a/nexus-am/am/arch/x86-nemu/src/devices/video.c +++ b/nexus-am/am/arch/x86-nemu/src/devices/video.c @@ -23,13 +23,9 @@ size_t video_write(uintptr_t reg, void *buf, size_t size) { switch (reg) { case _DEVREG_VIDEO_FBCTL: { _FBCtlReg *ctl = (_FBCtlReg *)buf; -int i; -int size = screen_width() * screen_height(); -for (i = 0; i < size; i ++) fb[i] = i; -// for(int i = 0; i < ctl->h; ++i) -// { -// memcpy(fb+(ctl->y+i)*screen_width()+ctl->x,ctl->pixels+i*ctl->w,ctl->w*4); -// } + for(int i = 0; i < ctl->h; ++i) { + memcpy(fb+(ctl->y+i)*screen_width()+ctl->x,ctl->pixels+i*ctl->w,ctl->w*4); + } if (ctl->sync) { // do nothing, hardware syncs. } -- GitLab