Improve FPS on lower end hardware

This commit is contained in:
Lorenzooone 2024-07-04 22:09:32 +02:00 committed by GitHub
parent e9084745b9
commit 83b6dd522a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 59 additions and 27 deletions

View File

@ -51,7 +51,7 @@ struct DisplayData {
#pragma pack(push, 1)
struct PACKED VideoOutputData {
uint8_t screen_data[MAX_IN_VIDEO_SIZE][4];
uint8_t screen_data[MAX_IN_VIDEO_SIZE][3];
};
#pragma pack(pop)

View File

@ -175,6 +175,7 @@ private:
volatile bool scheduled_work_on_window;
volatile bool is_thread_done;
sf::Shader *in_top_shader, *in_bot_shader, *top_shader, *bot_shader;
sf::RectangleShape m_in_rect_top, m_in_rect_bot;
out_rect_data m_out_rect_top, m_out_rect_bot;
ScreenType m_stype;
@ -238,6 +239,7 @@ private:
void prepare_screen_rendering();
bool window_needs_work();
void window_factory(bool is_main_thread);
void update_texture();
void pre_texture_conversion_processing();
void post_texture_conversion_processing(out_rect_data &rect_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug);
void window_bg_processing();

View File

@ -265,19 +265,11 @@ void ftd3_capture_cleanup(CaptureData* capture_data) {
}
static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
for(int i = 0; i < iters; i++) {
for(int u = 0; u < 3; u++)
p_out->screen_data[start_out + i][u] = p_in->screen_data[start_in + i][u];
p_out->screen_data[start_out + i][3] = 0xff;
}
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
for(int i = 0; i < iters; i++) {
for(int u = 0; u < 3; u++)
p_out->screen_data[start_out + i][u] = p_in->screen_data[start_in + i][u];
p_out->screen_data[start_out + i][3] = 0xff;
}
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) {

View File

@ -1,5 +1,6 @@
#include "frontend.hpp"
#include <SFML/OpenGL.hpp>
#include <cstring>
#include "font_ttf.h"
@ -12,6 +13,17 @@
#define FALLBACK_FS_RESOLUTION_HEIGHT 1080
#define FALLBACK_FS_RESOLUTION_BPP 32
const std::string no_effect_fragment_shader = \
"uniform sampler2D Texture0;" \
"" \
"void main() {" \
" gl_FragColor = texture2D(Texture0, gl_TexCoord[0].xy);" \
"}";
static bool loaded_shaders = false;
static int n_shader_refs = 0;
static sf::Shader *base_shader;
WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, AudioData* audio_data, ExtraButtonShortcuts* extra_button_shortcuts) {
this->m_stype = stype;
insert_basic_crops(this->possible_crops, this->m_stype, false, false);
@ -55,6 +67,16 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
this->capture_status = capture_status;
if(this->display_data->mono_app_mode && this->m_stype == ScreenType::JOINT)
this->m_info.is_fullscreen = true;
if(!loaded_shaders) {
base_shader = new sf::Shader();
base_shader->loadFromMemory(no_effect_fragment_shader, sf::Shader::Fragment);
loaded_shaders = true;
}
n_shader_refs += 1;
this->in_top_shader = base_shader;
this->in_bot_shader = base_shader;
this->top_shader = base_shader;
this->bot_shader = base_shader;
}
WindowScreen::~WindowScreen() {
@ -66,6 +88,11 @@ WindowScreen::~WindowScreen() {
FPSArrayDestroy(&this->in_fps);
FPSArrayDestroy(&this->draw_fps);
FPSArrayDestroy(&this->poll_fps);
if(n_shader_refs == 1) {
delete base_shader;
loaded_shaders = false;
}
n_shader_refs -= 1;
}
void WindowScreen::build() {
@ -385,13 +412,28 @@ std::string WindowScreen::title_factory() {
return title;
}
void WindowScreen::update_texture() {
unsigned int m_texture = this->in_tex.getNativeHandle();
if (this->saved_buf && m_texture)
{
// Copy pixels from the given array to the texture
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(0), static_cast<GLint>(0), static_cast<GLsizei>(this->capture_status->device.width), static_cast<GLsizei>(this->capture_status->device.height), GL_RGB, GL_UNSIGNED_BYTE, this->saved_buf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Force an OpenGL flush, so that the texture data will appear updated
// in all contexts immediately (solves problems in multi-threaded apps)
glFlush();
}
}
void WindowScreen::pre_texture_conversion_processing() {
if(this->loaded_menu == CONNECT_MENU_TYPE)
return;
//Place preprocessing window-specific effects here
if(!this->capture_status->connected)
return;
this->in_tex.update((uint8_t*)this->saved_buf, this->capture_status->device.width, this->capture_status->device.height, 0, 0);
this->update_texture();
}
void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data, const sf::RectangleShape &in_rect, bool actually_draw, bool is_top, bool is_debug) {
@ -409,7 +451,10 @@ void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data,
else {
rect_data.out_tex.clear();
if(this->capture_status->connected && actually_draw) {
rect_data.out_tex.draw(in_rect);
sf::Shader* chosen_shader = this->in_top_shader;
if(!is_top)
chosen_shader = this->in_bot_shader;
rect_data.out_tex.draw(in_rect, chosen_shader);
//Place postprocessing effects here
}
}
@ -431,9 +476,9 @@ void WindowScreen::display_data_to_window(bool actually_draw, bool is_debug) {
this->window_bg_processing();
if(this->loaded_menu != CONNECT_MENU_TYPE) {
if(this->m_stype != ScreenType::BOTTOM)
this->m_win.draw(this->m_out_rect_top.out_rect);
this->m_win.draw(this->m_out_rect_top.out_rect, this->top_shader);
if(this->m_stype != ScreenType::TOP)
this->m_win.draw(this->m_out_rect_bot.out_rect);
this->m_win.draw(this->m_out_rect_bot.out_rect, this->bot_shader);
}
this->execute_menu_draws();
this->notification->draw(this->m_win);

View File

@ -277,7 +277,6 @@ static inline void usb_oldDSconvertVideoToOutputRGBA(USBOldDSPixelData data, uin
target[0] = xbits_to_8bits(data.r, OLD_DS_PIXEL_R_BITS);
target[1] = xbits_to_8bits(data.g, OLD_DS_PIXEL_G_BITS);
target[2] = xbits_to_8bits(data.b, OLD_DS_PIXEL_B_BITS);
target[3] = 255;
}
static inline void usb_oldDSconvertVideoToOutputHalfLine(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) {
@ -292,12 +291,12 @@ static inline void usb_oldDSconvertVideoToOutputHalfLine(USBOldDSCaptureReceived
static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out) {
if(!p_in->frameinfo.valid) { //LCD was off
memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * 4);
memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * 3);
return;
}
// Handle first line being off, if needed
memset(p_out->screen_data, 0, WIDTH_DS * 4);
memset(p_out->screen_data, 0, WIDTH_DS * 3);
int input_halfline = 0;
for(int i = 0; i < 2; i++) {
@ -309,20 +308,14 @@ static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOu
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, input_halfline++, i);
else { // deal with missing half-line
memcpy(p_out->screen_data[i * (WIDTH_DS / 2)], p_out->screen_data[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * 4);
memcpy(p_out->screen_data[(i * (WIDTH_DS / 2)) + (WIDTH_DS * HEIGHT_DS)], p_out->screen_data[((i - 2) * (WIDTH_DS / 2)) + (WIDTH_DS * HEIGHT_DS)], (WIDTH_DS / 2) * 4);
memcpy(p_out->screen_data[i * (WIDTH_DS / 2)], p_out->screen_data[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * 3);
memcpy(p_out->screen_data[(i * (WIDTH_DS / 2)) + (WIDTH_DS * HEIGHT_DS)], p_out->screen_data[((i - 2) * (WIDTH_DS / 2)) + (WIDTH_DS * HEIGHT_DS)], (WIDTH_DS / 2) * 3);
}
}
}
static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) {
for(int i = 0; i < IN_VIDEO_HEIGHT_3DS; i++)
for(int j = 0; j < IN_VIDEO_WIDTH_3DS; j++) {
int pixel = (i * IN_VIDEO_WIDTH_3DS) + j;
for(int u = 0; u < 3; u++)
p_out->screen_data[pixel][u] = p_in->video_in.screen_data[pixel][u];
p_out->screen_data[pixel][3] = 255;
}
memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3);
}
void list_devices_usb_ds_3ds(std::vector<CaptureDevice> &devices_list) {