diff --git a/include/display_structs.hpp b/include/display_structs.hpp index c0679fb..3b024dc 100755 --- a/include/display_structs.hpp +++ b/include/display_structs.hpp @@ -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) diff --git a/include/frontend.hpp b/include/frontend.hpp index e667236..1555709 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -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(); diff --git a/source/3dscapture_ftd3.cpp b/source/3dscapture_ftd3.cpp index 846ac2e..6776e93 100755 --- a/source/3dscapture_ftd3.cpp +++ b/source/3dscapture_ftd3.cpp @@ -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) { diff --git a/source/WindowScreen.cpp b/source/WindowScreen.cpp index f5072ee..af55a42 100755 --- a/source/WindowScreen.cpp +++ b/source/WindowScreen.cpp @@ -1,5 +1,6 @@ #include "frontend.hpp" +#include #include #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(0), static_cast(0), static_cast(this->capture_status->device.width), static_cast(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); diff --git a/source/usb_ds_3ds_capture.cpp b/source/usb_ds_3ds_capture.cpp index 49596b5..bf63032 100755 --- a/source/usb_ds_3ds_capture.cpp +++ b/source/usb_ds_3ds_capture.cpp @@ -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 &devices_list) {