Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen mode cleanup and extended API #730

Merged
merged 10 commits into from
Jan 6, 2022
63 changes: 53 additions & 10 deletions 32blit-pico/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

using namespace blit;

static SurfaceInfo cur_surf_info;

#ifdef DISPLAY_ST7789
// height rounded up to handle the 135px display
static const int lores_page_size = (ST7789_WIDTH / 2) * ((ST7789_HEIGHT + 1) / 2) * 2;
Expand All @@ -37,12 +39,12 @@ uint8_t screen_fb[lores_page_size * 2]; // double-buffered
#endif
static bool have_vsync = false;

static Surface lores_screen(screen_fb, PixelFormat::RGB565, Size(ST7789_WIDTH / 2, ST7789_HEIGHT / 2));
static Surface hires_screen(screen_fb, PixelFormat::RGB565, Size(ST7789_WIDTH, ST7789_HEIGHT));
//static Surface hires_palette_screen(screen_fb, PixelFormat::P, Size(320, 240));
static const blit::SurfaceTemplate lores_screen{screen_fb, Size(ST7789_WIDTH / 2, ST7789_HEIGHT / 2), blit::PixelFormat::RGB565, nullptr};
static const blit::SurfaceTemplate hires_screen{screen_fb, Size(ST7789_WIDTH, ST7789_HEIGHT), blit::PixelFormat::RGB565, nullptr};

#elif defined(DISPLAY_SCANVIDEO)
uint8_t screen_fb[160 * 120 * 4];
static Surface lores_screen(screen_fb, PixelFormat::RGB565, Size(160, 120));
static const blit::SurfaceTemplate lores_screen{screen_fb, Size(160, 120), blit::PixelFormat::RGB565, nullptr};
#endif

static blit::AudioChannel channels[CHANNEL_COUNT];
Expand All @@ -54,10 +56,10 @@ static volatile int buf_index = 0;

static volatile bool do_render = true;

static Surface &set_screen_mode(ScreenMode mode) {
static SurfaceInfo &set_screen_mode(ScreenMode mode) {
switch(mode) {
case ScreenMode::lores:
screen = lores_screen;
cur_surf_info = lores_screen;
// window
#ifdef DISPLAY_ST7789
if(have_vsync)
Expand All @@ -72,11 +74,11 @@ static Surface &set_screen_mode(ScreenMode mode) {
if(have_vsync)
do_render = true;

screen = hires_screen;
cur_surf_info = hires_screen;
st7789::frame_buffer = (uint16_t *)screen_fb;
st7789::set_pixel_double(false);
#else
return screen;
return cur_surf_info;
#endif
break;

Expand All @@ -87,7 +89,47 @@ static Surface &set_screen_mode(ScreenMode mode) {

cur_screen_mode = mode;

return blit::screen;
return cur_surf_info;
}

static void set_screen_palette(const Pen *colours, int num_cols) {

}

static bool set_screen_mode_format(ScreenMode new_mode, SurfaceTemplate &new_surf_template) {
new_surf_template.data = screen_fb;

switch(new_mode) {
case ScreenMode::lores:
new_surf_template.bounds = lores_screen.bounds;
break;
case ScreenMode::hires:
case ScreenMode::hires_palette:
#if defined(DISPLAY_ST7789) && ALLOW_HIRES
new_surf_template.bounds = hires_screen.bounds;
break;
#else
return false; // no hires for scanvideo
#endif
}

#ifdef DISPLAY_ST7789
if(have_vsync)
do_render = true; // prevent starting an update during switch

st7789::set_pixel_double(new_mode == ScreenMode::lores);

if(new_mode == ScreenMode::hires)
st7789::frame_buffer = (uint16_t *)screen_fb;
#endif

// don't support any other formats for various reasons (RAM, no format conversion, pixel double PIO)
if(new_surf_template.format != PixelFormat::RGB565)
return false;

cur_screen_mode = new_mode;

return true;
}

static uint32_t now() {
Expand Down Expand Up @@ -245,7 +287,8 @@ int main() {
api.channels = ::channels;

api.set_screen_mode = ::set_screen_mode;
// api.set_screen_palette = ::set_screen_palette;
api.set_screen_palette = ::set_screen_palette;
api.set_screen_mode_format = ::set_screen_mode_format;
api.now = ::now;
api.random = ::random;
// api.exit = ::exit;
Expand Down
25 changes: 13 additions & 12 deletions 32blit-sdl/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <iostream>
#include "SDL.h"

#include "graphics/surface.hpp"

#include "Renderer.hpp"
#include "System.hpp"

Expand All @@ -25,11 +27,18 @@ Renderer::Renderer(SDL_Window *window, int width, int height) : sys_width(width)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);

fb_lores_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, sys_width/2, sys_height/2);
fb_hires_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, sys_width, sys_height);
fb_lores_565_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR565, SDL_TEXTUREACCESS_STREAMING, sys_width/2, sys_height/2);
fb_hires_565_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR565, SDL_TEXTUREACCESS_STREAMING, sys_width, sys_height);
}

Renderer::~Renderer() {
SDL_DestroyTexture(fb_lores_texture);
SDL_DestroyTexture(fb_hires_texture);
SDL_DestroyTexture(fb_lores_565_texture);
SDL_DestroyTexture(fb_hires_565_texture);
SDL_DestroyRenderer(renderer);
}

Expand All @@ -56,23 +65,15 @@ void Renderer::resize(int width, int height) {

if (mode == Stretch)
set_mode(mode);

if (fb_lores_texture) {
SDL_DestroyTexture(fb_lores_texture);
}
if (fb_hires_texture) {
SDL_DestroyTexture(fb_hires_texture);
}

fb_lores_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, sys_width/2, sys_height/2);
fb_hires_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, sys_width, sys_height);
}

void Renderer::update(System *sys) {
auto format = blit::PixelFormat(sys->format());

if (sys->mode() == 0) {
current = fb_lores_texture;
current = format == blit::PixelFormat::RGB565 ? fb_lores_565_texture : fb_lores_texture;
} else {
current = fb_hires_texture;
current = format == blit::PixelFormat::RGB565 ? fb_hires_565_texture : fb_hires_texture;
}

if(is_lores != (sys->mode() == 0)) {
Expand Down
2 changes: 2 additions & 0 deletions 32blit-sdl/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ class Renderer {

SDL_Texture *fb_lores_texture = nullptr;
SDL_Texture *fb_hires_texture = nullptr;
SDL_Texture *fb_lores_565_texture = nullptr;
SDL_Texture *fb_hires_565_texture = nullptr;
SDL_Texture *current = nullptr;
};
114 changes: 76 additions & 38 deletions 32blit-sdl/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,76 @@
#include "engine/api_private.hpp"

// blit framebuffer memory
uint8_t framebuffer[320 * 240 * 3];
blit::Surface __fb_hires((uint8_t *)framebuffer, blit::PixelFormat::RGB, blit::Size(320, 240));
blit::Surface __fb_hires_pal((uint8_t *)framebuffer, blit::PixelFormat::P, blit::Size(320, 240));
blit::Surface __fb_lores((uint8_t *)framebuffer, blit::PixelFormat::RGB, blit::Size(160, 120));

static uint8_t framebuffer[320 * 240 * 3];
static blit::Pen palette[256];

static const blit::SurfaceTemplate __fb_hires{framebuffer, blit::Size(320, 240), blit::PixelFormat::RGB, nullptr};
static const blit::SurfaceTemplate __fb_hires_pal{framebuffer, blit::Size(320, 240), blit::PixelFormat::P, palette};
static const blit::SurfaceTemplate __fb_lores{framebuffer, blit::Size(160, 120), blit::PixelFormat::RGB, nullptr};

// blit debug callback
void blit_debug(const char *message) {
std::cout << message;
}

// blit screenmode callback
blit::ScreenMode _mode = blit::ScreenMode::lores;
blit::Surface &set_screen_mode(blit::ScreenMode new_mode) {
_mode = new_mode;
switch(_mode) {
case blit::ScreenMode::lores:
blit::screen = __fb_lores;
break;
case blit::ScreenMode::hires:
blit::screen = __fb_hires;
break;
case blit::ScreenMode::hires_palette:
blit::screen = __fb_hires_pal;
break;
}
static blit::PixelFormat cur_format = blit::PixelFormat::RGB;

return blit::screen;
blit::SurfaceInfo cur_surf_info;
blit::SurfaceInfo &set_screen_mode(blit::ScreenMode new_mode) {
_mode = new_mode;
switch(_mode) {
case blit::ScreenMode::lores:
cur_surf_info = __fb_lores;
break;
case blit::ScreenMode::hires:
cur_surf_info = __fb_hires;
break;
case blit::ScreenMode::hires_palette:
cur_surf_info = __fb_hires_pal;
break;
}

cur_format = cur_surf_info.format;
return cur_surf_info;
}

static void set_screen_palette(const blit::Pen *colours, int num_cols) {
memcpy(palette, colours, num_cols * sizeof(blit::Pen));
}

static bool set_screen_mode_format(blit::ScreenMode new_mode, blit::SurfaceTemplate &new_surf_template) {
new_surf_template.data = framebuffer;

switch(new_mode) {
case blit::ScreenMode::lores:
new_surf_template.bounds = __fb_lores.bounds;
break;
case blit::ScreenMode::hires:
case blit::ScreenMode::hires_palette:
new_surf_template.bounds = __fb_hires.bounds;
break;
}

switch(new_surf_template.format) {
case blit::PixelFormat::RGB:
case blit::PixelFormat::RGB565:
break;
case blit::PixelFormat::P:
new_surf_template.palette = palette;
break;

default:
return false;
}

_mode = new_mode;
cur_format = new_surf_template.format;

return true;
}

// blit timer callback
std::chrono::steady_clock::time_point start;
uint32_t now() {
Expand Down Expand Up @@ -146,8 +181,6 @@ System::System() {
s_loop_update = SDL_CreateSemaphore(0);
s_loop_redraw = SDL_CreateSemaphore(0);
s_loop_ended = SDL_CreateSemaphore(0);

__fb_hires_pal.palette = palette;
}

System::~System() {
Expand All @@ -168,6 +201,7 @@ void System::run() {
blit::api.debug = ::blit_debug;
blit::api.set_screen_mode = ::set_screen_mode;
blit::api.set_screen_palette = ::set_screen_palette;
blit::api.set_screen_mode_format = ::set_screen_mode_format;
blit::update = ::update;
blit::render = ::render;

Expand Down Expand Up @@ -202,7 +236,7 @@ void System::run() {

blit::api.get_metadata = ::get_metadata;

::set_screen_mode(blit::lores);
blit::set_screen_mode(blit::lores);

#ifdef __EMSCRIPTEN__
::init();
Expand Down Expand Up @@ -277,26 +311,30 @@ Uint32 System::mode() {
return _mode;
}

Uint32 System::format() {
return Uint32(cur_format);
}

void System::update_texture(SDL_Texture *texture) {
if (_mode == blit::ScreenMode::lores) {
SDL_UpdateTexture(texture, nullptr, __fb_lores.data, 160 * 3);
}
else if(_mode == blit::ScreenMode::hires) {
SDL_UpdateTexture(texture, nullptr, __fb_hires.data, 320 * 3);
} else {
uint8_t col_fb[320 * 240 * 3];
bool is_lores = _mode == blit::ScreenMode::lores;
auto stride = (is_lores ? 160 : 320) * blit::pixel_format_stride[int(cur_format)];

auto in = __fb_hires_pal.data, out = col_fb;
if(cur_format == blit::PixelFormat::P) {
uint8_t col_fb[320 * 240 * 3];

for(int i = 0; i < 320 * 240; i++) {
uint8_t index = *(in++);
(*out++) = palette[index].r;
(*out++) = palette[index].g;
(*out++) = palette[index].b;
}
auto in = framebuffer, out = col_fb;
auto size = is_lores ? 160 * 120 : 320 * 240;

SDL_UpdateTexture(texture, nullptr, col_fb, 320 * 3);
}
for(int i = 0; i < size; i++) {
uint8_t index = *(in++);
(*out++) = palette[index].r;
(*out++) = palette[index].g;
(*out++) = palette[index].b;
}

SDL_UpdateTexture(texture, nullptr, col_fb, stride * 3);
} else
SDL_UpdateTexture(texture, nullptr, framebuffer, stride);
}

void System::notify_redraw() {
Expand Down
2 changes: 2 additions & 0 deletions 32blit-sdl/System.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class System {
void loop();

Uint32 mode();
Uint32 format();

void update_texture(SDL_Texture *);
void notify_redraw();

Expand Down
23 changes: 15 additions & 8 deletions 32blit-stm32/Inc/display.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,34 @@ extern "C" {

using namespace blit;

namespace blit {
struct SurfaceTemplate;
struct SurfaceInfo;
}

namespace display {

extern ScreenMode mode;
extern bool needs_render;

void init();
void init();

void enable_vblank_interrupt();
void enable_vblank_interrupt();

Surface &set_screen_mode(ScreenMode new_mode);
SurfaceInfo &set_screen_mode(ScreenMode new_mode);
void set_screen_palette(const Pen *colours, int num_cols);
bool set_screen_mode_format(ScreenMode new_mode, SurfaceTemplate &new_surf_template);

void flip(const Surface &source);

void screen_init();
void ltdc_init();

uint32_t get_dma2d_count(void);
void dma2d_lores_flip_Step2(void);
void dma2d_lores_flip_Step3(void);
void dma2d_lores_flip_Step4(void);

void dma2d_lores_flip_step2(void);
void dma2d_lores_flip_step3(void);
void dma2d_lores_flip_step4(void);
}


Expand Down
Loading