diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 4aefc1354..31c8a1f6d 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -1110,7 +1110,7 @@ void gfx_opengl_select_texture_fb(int fb_id) { glBindTexture(GL_TEXTURE_2D, framebuffers[fb_id].clrbuf); } -void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool use_back) { +void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back) { if (!gfx_framebuffers_enabled || fb_dst >= (int)framebuffers.size() || fb_src >= (int)framebuffers.size()) { return; } @@ -1144,9 +1144,12 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool glBindFramebuffer(GL_READ_FRAMEBUFFER, src.fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst.fbo); - if (fb_src == 0) { + if (flip_y) { // flip the dst rect to mirror the image vertically std::swap(dstY0, dstY1); + } + + if (fb_src == 0) { glReadBuffer(use_back ? GL_BACK : GL_FRONT); } else { glReadBuffer(GL_COLOR_ATTACHMENT0); diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 70e467f1c..d8319040e 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -2883,14 +2883,23 @@ extern "C" void gfx_set_framebuffer(int fb, float noise_scale) { } extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back) { - if (fb_src == 0 && left > 0 && top > 0) { - // upscale the position - left = left * gfx_current_dimensions.width / gfx_current_native_viewport.width; - top = top * gfx_current_dimensions.height / gfx_current_native_viewport.height; - // flip Y - top = gfx_current_dimensions.height - top - 1; - } - gfx_rapi->copy_framebuffer(fb_dst, fb_src, left, top, (bool)use_back); + const bool is_main_fb = (fb_src == 0); + + if (is_main_fb) { + if (left > 0 && top > 0) { + // upscale the position + left = left * gfx_current_dimensions.width / gfx_current_native_viewport.width; + top = top * gfx_current_dimensions.height / gfx_current_native_viewport.height; + // flip Y + top = gfx_current_dimensions.height - top - 1; + } + if (use_back && gfx_msaa_level > 1) { + // read from the framebuffer we've been rendering to + fb_src = game_framebuffer; + } + } + + gfx_rapi->copy_framebuffer(fb_dst, fb_src, left, top, is_main_fb, (bool)use_back); } extern "C" void gfx_reset_framebuffer(void) { diff --git a/port/fast3d/gfx_rendering_api.h b/port/fast3d/gfx_rendering_api.h index 86c5f6852..b31aa4ba7 100644 --- a/port/fast3d/gfx_rendering_api.h +++ b/port/fast3d/gfx_rendering_api.h @@ -44,7 +44,7 @@ struct GfxRenderingAPI { bool opengl_invert_y, bool render_target, bool has_depth_buffer, bool can_extract_depth); bool (*start_draw_to_framebuffer)(int fb_id, float noise_scale); - void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top, bool use_back); + void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back); void (*clear_framebuffer)(void); void (*resolve_msaa_color_buffer)(int fb_id_target, int fb_id_source); void* (*get_framebuffer_texture_id)(int fb_id); diff --git a/port/include/video.h b/port/include/video.h index bd734c763..b067ecbc3 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -28,6 +28,7 @@ void videoSetFramebuffer(s32 target); void videoResetFramebuffer(void); void videoCopyFramebuffer(s32 dst, s32 src, s32 left, s32 top); void videoResizeFramebuffer(s32 target, u32 w, u32 h, s32 upscale, s32 autoresize); +s32 videoFramebuffersSupported(void); void videoResetTextureCache(void); void videoFreeCachedTexture(const void *texptr); diff --git a/port/src/video.c b/port/src/video.c index 7bc86c270..c023524ae 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -163,6 +163,11 @@ void videoResetFramebuffer(void) return gfx_reset_framebuffer(); } +s32 videoFramebuffersSupported(void) +{ + return gfx_framebuffers_enabled; +} + void videoResizeFramebuffer(s32 target, u32 w, u32 h, s32 upscale, s32 autoresize) { gfx_resize_framebuffer(target, w, h, upscale, autoresize); diff --git a/src/game/bondview.c b/src/game/bondview.c index 9f4691c34..b30dc3369 100644 --- a/src/game/bondview.c +++ b/src/game/bondview.c @@ -284,6 +284,12 @@ Gfx *bviewDrawMotionBlur(Gfx *gdl, u32 colour, u32 alpha) var8007f844 = 0; +#ifndef PLATFORM_N64 + if (!videoFramebuffersSupported()) { + return gdl; + } +#endif + mainOverrideVariable("sfxxx", &sfxxx); fxxx = sfxxx / 1000.0f; mainOverrideVariable("sfyyy", &sfyyy); @@ -510,6 +516,12 @@ Gfx *bviewDrawZoomBlur(Gfx *gdl, u32 colour, s32 alpha, f32 arg3, f32 arg4) return gdl; } +#ifndef PLATFORM_N64 + if (!videoFramebuffersSupported()) { + return gdl; + } +#endif + strcpy(var800a41c0, "stretchBlurGfx"); gDPPipeSync(gdl++); @@ -567,15 +579,21 @@ f32 bview0f142d74(s32 arg0, f32 arg1, f32 arg2, f32 arg3) static inline Gfx *bviewDrawFisheyeLine(Gfx *gdl, s32 viewleft, s32 viewwidth, s32 y, f32 scale) { + if (!videoFramebuffersSupported()) { + return gdl; + } + const f32 orighalfw = viewwidth * 0.5f; const f32 xcenter = viewleft + orighalfw; const f32 halfw = orighalfw * scale; const s32 left = xcenter - halfw; const s32 right = xcenter + halfw; + gSPImageRectangleEXT(gdl++, left << 2, y << 2, viewleft, y, right << 2, (y + 1) << 2, viewleft + viewwidth, y + 1, 0, videoGetNativeWidth(), videoGetNativeHeight()); + return gdl; }