From 96e1ae42729c38f11bc29196323dffe5b6537e20 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 20 Aug 2021 18:59:30 -0700 Subject: [PATCH 01/19] CMake: Bring up DMG distribution on macOS --- CMakeLists.txt | 10 +++++++++- src/platform/cmake/DMGOverrides.cmake.in | 6 ++++++ src/platform/qt/CMakeLists.txt | 13 +++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 src/platform/cmake/DMGOverrides.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 63c25d001..030a31344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,6 +119,10 @@ else() set(CMAKE_INSTALL_INCLUDEDIR "include") endif() +if(APPLE AND DISTBUILD) + set(CMAKE_INSTALL_DOCDIR ".") +endif() + if(NOT DEFINED LIBDIR) set(LIBDIR "${CMAKE_INSTALL_LIBDIR}") endif() @@ -1064,6 +1068,9 @@ endif() if(DISTBUILD) set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + set(CPACK_DMG_FILESYSTEM "HFS+") + set(CPACK_DMG_FORMAT "UDBZ") + set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME} ${VERSION_STRING}") if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" AND BUILD_SHARED) if(NOT APPLE) add_custom_command(TARGET ${BINARY_NAME} POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.debug") @@ -1074,7 +1081,8 @@ if(DISTBUILD) endif() if(APPLE) set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf) - set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/cmake/DMGOverrides.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/DMGOverrides.cmake @ONLY) + set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/DMGOverrides.cmake) elseif(WIN32) set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf installer) elseif(3DS) diff --git a/src/platform/cmake/DMGOverrides.cmake.in b/src/platform/cmake/DMGOverrides.cmake.in new file mode 100644 index 000000000..906853946 --- /dev/null +++ b/src/platform/cmake/DMGOverrides.cmake.in @@ -0,0 +1,6 @@ +message(FATAL ${CPACK_GENERATOR}) +if(CPACK_GENERATOR STREQUAL "DragNDrop") + set(CPACK_COMPONENTS_ALL @BINARY_NAME@ @BINARY_NAME@-qt @BINARY_NAME@-qt-dbg) + set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) + unset(CPACK_RESOURCE_FILE_LICENSE) +endif() diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 032d01d07..b2f77d1ae 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -241,6 +241,11 @@ if(APPLE) set(MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}) set(MACOSX_BUNDLE_GUI_IDENTIFIER com.endrift.${BINARY_NAME}-qt) set_source_files_properties(${CMAKE_SOURCE_DIR}/res/mgba.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + if(DISTBUILD) + set(APPDIR ".") + else() + set(APPDIR "Applications") + endif() endif() if(WIN32) configure_file(${CMAKE_SOURCE_DIR}/res/mgba.rc.in ${CMAKE_BINARY_DIR}/res/mgba.rc) @@ -249,7 +254,7 @@ if(WIN32) endif() if(NOT DEFINED DATADIR) if(APPLE) - set(DATADIR Applications/${PROJECT_NAME}.app/Contents/Resources) + set(DATADIR ${APPDIR}/${PROJECT_NAME}.app/Contents/Resources) elseif(WIN32 AND NOT WIN32_UNIX_PATHS) set(DATADIR ".") else() @@ -336,11 +341,11 @@ set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE) install(TARGETS ${BINARY_NAME}-qt RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt - BUNDLE DESTINATION Applications COMPONENT ${BINARY_NAME}-qt) + BUNDLE DESTINATION ${APPDIR} COMPONENT ${BINARY_NAME}-qt) if(UNIX AND NOT APPLE) install(FILES ${CMAKE_SOURCE_DIR}/res/mgba-qt.desktop DESTINATION share/applications COMPONENT ${BINARY_NAME}-qt) endif() -if(UNIX) +if(UNIX AND NOT (APPLE AND DISTBUILD)) install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba-qt.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-qt) endif() if(APPLE OR WIN32) @@ -373,7 +378,7 @@ if(APPLE) if(DEFINED CROSS_ROOT) set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -R "${CROSS_ROOT}") endif() - install(CODE "execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/tools/deploy-mac.py\" -v ${DEPLOY_OPTIONS} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/Applications/${PROJECT_NAME}.app\")") + install(CODE "execute_process(COMMAND \"${CMAKE_SOURCE_DIR}/tools/deploy-mac.py\" -v ${DEPLOY_OPTIONS} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${APPDIR}/${PROJECT_NAME}.app\")") endif() elseif(WIN32) if(CMAKE_MAJOR_VERSION EQUAL 3 AND CMAKE_MINOR_VERSION EQUAL 8) From 471e55f7de054b95ec962372336cd817308ef19a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Aug 2021 17:42:29 -0700 Subject: [PATCH 02/19] FFmpeg: Don't attempt to use YUV 4:2:0 for lossless videos (fixes #2084) --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 67cb60ecc..0356ef0c8 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Emulation fixes: - GBA Video: Fix backdrop color if DISPCNT is first set to 0 (fixes mgba.io/i/2260) Other fixes: - Core: Don't attempt to restore rewind diffs past start of rewind + - FFmpeg: Don't attempt to use YUV 4:2:0 for lossless videos (fixes mgba.io/i/2084) - GB Video: Fix memory leak when reseting SGB games - GBA: Fix out of bounds ROM accesses on patched ROMs smaller than 32 MiB - Libretro: Fix crash when using Game Boy codes (fixes mgba.io/i/2281) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index b3a8fff0c..17cf11e6c 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -343,9 +343,9 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0); if (encoder->audio->codec->id == AV_CODEC_ID_AAC && - (strcasecmp(encoder->containerFormat, "mp4") || - strcasecmp(encoder->containerFormat, "m4v") || - strcasecmp(encoder->containerFormat, "mov"))) { + (strcasecmp(encoder->containerFormat, "mp4") == 0|| + strcasecmp(encoder->containerFormat, "m4v") == 0 || + strcasecmp(encoder->containerFormat, "mov") == 0)) { // MP4 container doesn't support the raw ADTS AAC format that the encoder spits out #ifdef FFMPEG_USE_NEW_BSF av_bsf_alloc(av_bsf_get_by_name("aac_adtstoasc"), &encoder->absf); @@ -387,9 +387,9 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { } if (encoder->video->codec->id == AV_CODEC_ID_H264 && - (strcasecmp(encoder->containerFormat, "mp4") || - strcasecmp(encoder->containerFormat, "m4v") || - strcasecmp(encoder->containerFormat, "mov"))) { + (strcasecmp(encoder->containerFormat, "mp4") == 0 || + strcasecmp(encoder->containerFormat, "m4v") == 0 || + strcasecmp(encoder->containerFormat, "mov") == 0)) { // QuickTime and a few other things require YUV420 encoder->video->pix_fmt = AV_PIX_FMT_YUV420P; } From 2ade2f921741a7559d50e1ee02a10882c393ef8b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Aug 2021 18:07:59 -0700 Subject: [PATCH 03/19] FFmpeg: Drop support for libavcodec 54 and below --- src/feature/ffmpeg/ffmpeg-decoder.c | 18 +---------------- src/feature/ffmpeg/ffmpeg-encoder.c | 30 ----------------------------- 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/src/feature/ffmpeg/ffmpeg-decoder.c b/src/feature/ffmpeg/ffmpeg-decoder.c index 5d3c3aa08..c3bb6d1c5 100644 --- a/src/feature/ffmpeg/ffmpeg-decoder.c +++ b/src/feature/ffmpeg/ffmpeg-decoder.c @@ -81,20 +81,12 @@ bool FFmpegDecoderOpen(struct FFmpegDecoder* decoder, const char* infile) { decoder->videoStream = i; decoder->width = -1; decoder->height = -1; -#if LIBAVCODEC_VERSION_MAJOR >= 55 decoder->videoFrame = av_frame_alloc(); -#else - decoder->videoFrame = avcodec_alloc_frame(); -#endif } if (type == AVMEDIA_TYPE_AUDIO) { decoder->audioStream = i; -#if LIBAVCODEC_VERSION_MAJOR >= 55 decoder->audioFrame = av_frame_alloc(); -#else - decoder->audioFrame = avcodec_alloc_frame(); -#endif } } return true; @@ -102,11 +94,7 @@ bool FFmpegDecoderOpen(struct FFmpegDecoder* decoder, const char* infile) { void FFmpegDecoderClose(struct FFmpegDecoder* decoder) { if (decoder->audioFrame) { -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&decoder->audioFrame); -#else - avcodec_free_frame(&decoder->audioFrame); -#endif } if (decoder->audio) { @@ -124,11 +112,7 @@ void FFmpegDecoderClose(struct FFmpegDecoder* decoder) { } if (decoder->videoFrame) { -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&decoder->videoFrame); -#else - avcodec_free_frame(&decoder->videoFrame); -#endif } if (decoder->pixels) { @@ -216,4 +200,4 @@ bool FFmpegDecoderRead(struct FFmpegDecoder* decoder) { #endif } return readPacket; -} \ No newline at end of file +} diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 17cf11e6c..662bdedee 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -311,11 +311,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { FFmpegEncoderClose(encoder); return false; } -#if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->audioFrame = av_frame_alloc(); -#else - encoder->audioFrame = avcodec_alloc_frame(); -#endif if (!encoder->audio->frame_size) { encoder->audio->frame_size = 1; } @@ -493,11 +489,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { return false; } -#if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->sinkFrame = av_frame_alloc(); -#else - encoder->sinkFrame = avcodec_alloc_frame(); -#endif } AVDictionary* opts = 0; av_dict_set(&opts, "strict", "-2", 0); @@ -507,11 +499,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { FFmpegEncoderClose(encoder); return false; } -#if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->videoFrame = av_frame_alloc(); -#else - encoder->videoFrame = avcodec_alloc_frame(); -#endif encoder->videoFrame->format = encoder->video->pix_fmt != AV_PIX_FMT_PAL8 ? encoder->video->pix_fmt : encoder->ipixFormat; encoder->videoFrame->width = encoder->video->width; encoder->videoFrame->height = encoder->video->height; @@ -585,11 +573,7 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { } if (encoder->audioFrame) { -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&encoder->audioFrame); -#else - avcodec_free_frame(&encoder->audioFrame); -#endif } if (encoder->audio) { #ifdef FFMPEG_USE_CODECPAR @@ -620,19 +604,11 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { if (encoder->videoFrame) { av_freep(encoder->videoFrame->data); -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&encoder->videoFrame); -#else - avcodec_free_frame(&encoder->videoFrame); -#endif } if (encoder->sinkFrame) { -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&encoder->sinkFrame); -#else - avcodec_free_frame(&encoder->sinkFrame); -#endif encoder->sinkFrame = NULL; } @@ -701,14 +677,10 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) { return; } -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->audioFrame); -#endif int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); #else -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->audioFrame); -#endif if (swr_get_out_samples(encoder->resampleContext, 1) < encoder->audioFrame->nb_samples) { swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); return; @@ -794,9 +766,7 @@ void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size } stride *= BYTES_PER_PIXEL; -#if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_make_writable(encoder->videoFrame); -#endif if (encoder->video->codec->id == AV_CODEC_ID_WEBP) { // TODO: Figure out why WebP is rescaling internally (should video frames not be rescaled externally?) encoder->videoFrame->pts = encoder->currentVideoFrame; From c18bc1baa5cf9009948a8244e38c4200ca4d55e0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Aug 2021 18:27:06 -0700 Subject: [PATCH 04/19] FFmpeg: Use refcounted buffers for frame data --- src/feature/ffmpeg/ffmpeg-encoder.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 662bdedee..51863ab3b 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -318,6 +318,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { encoder->audioFrame->nb_samples = encoder->audio->frame_size; encoder->audioFrame->format = encoder->audio->sample_fmt; encoder->audioFrame->pts = 0; + encoder->audioFrame->channel_layout = AV_CH_LAYOUT_STEREO; #ifdef USE_LIBAVRESAMPLE encoder->resampleContext = avresample_alloc_context(); av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); @@ -334,9 +335,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { #endif encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4; encoder->audioBuffer = av_malloc(encoder->audioBufferSize); - encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0); - encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize); - avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0); + av_frame_get_buffer(encoder->audioFrame, 0); if (encoder->audio->codec->id == AV_CODEC_ID_AAC && (strcasecmp(encoder->containerFormat, "mp4") == 0|| @@ -505,7 +504,7 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { encoder->videoFrame->height = encoder->video->height; encoder->videoFrame->pts = 0; _ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight); - av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->videoFrame->width, encoder->videoFrame->height, encoder->videoFrame->format, 32); + av_frame_get_buffer(encoder->videoFrame, 32); #ifdef FFMPEG_USE_CODECPAR avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video); #endif @@ -603,7 +602,6 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { } if (encoder->videoFrame) { - av_freep(encoder->videoFrame->data); av_frame_free(&encoder->videoFrame); } @@ -668,7 +666,6 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right return; } - int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt); encoder->currentAudioSample = 0; #ifdef USE_LIBAVRESAMPLE avresample_convert(encoder->resampleContext, 0, 0, 0, @@ -678,14 +675,14 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right return; } av_frame_make_writable(encoder->audioFrame); - int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize); + int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->audioFrame->nb_samples); #else av_frame_make_writable(encoder->audioFrame); if (swr_get_out_samples(encoder->resampleContext, 1) < encoder->audioFrame->nb_samples) { swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); return; } - int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize, + int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->audioFrame->nb_samples, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4); #endif From 0e0ce67778a656949cf7634b671592e9535e9fcc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Aug 2021 18:27:41 -0700 Subject: [PATCH 05/19] FFmpeg: Stop using deprecated AVPacket API --- src/feature/ffmpeg/ffmpeg-encoder.c | 90 ++++++++++++++++++----------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 51863ab3b..4be2b5b15 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -693,61 +693,76 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right } bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame) { - AVPacket packet; - av_init_packet(&packet); - packet.data = 0; - packet.size = 0; + AVPacket* packet; +#ifdef FFMPEG_USE_PACKET_UNREF + packet = av_packet_alloc(); +#else + packet = av_malloc(sizeof(*packet)); + av_init_packet(packet); +#endif + packet->data = 0; + packet->size = 0; int gotData; #ifdef FFMPEG_USE_PACKETS avcodec_send_frame(encoder->audio, audioFrame); - gotData = avcodec_receive_packet(encoder->audio, &packet); - gotData = (gotData == 0) && packet.size; + gotData = avcodec_receive_packet(encoder->audio, packet); + gotData = (gotData == 0) && packet->size; #else - avcodec_encode_audio2(encoder->audio, &packet, audioFrame, &gotData); + avcodec_encode_audio2(encoder->audio, packet, audioFrame, &gotData); #endif - packet.pts = av_rescale_q(packet.pts, encoder->audio->time_base, encoder->audioStream->time_base); - packet.dts = packet.pts; + packet->pts = av_rescale_q(packet->pts, encoder->audio->time_base, encoder->audioStream->time_base); + packet->dts = packet->pts; if (gotData) { if (encoder->absf) { - AVPacket tempPacket; + AVPacket* tempPacket; +#ifdef FFMPEG_USE_PACKETS + tempPacket = av_packet_alloc(); +#else + tempPacket = av_malloc(sizeof(*tempPacket)); + av_init_packet(tempPacket); +#endif #ifdef FFMPEG_USE_NEW_BSF - int success = av_bsf_send_packet(encoder->absf, &packet); + int success = av_bsf_send_packet(encoder->absf, packet); if (success >= 0) { - success = av_bsf_receive_packet(encoder->absf, &tempPacket); + success = av_bsf_receive_packet(encoder->absf, tempPacket); } #else int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0, - &tempPacket.data, &tempPacket.size, - packet.data, packet.size, 0); + &tempPacket->data, &tempPacket->size, + packet->data, packet->size, 0); #endif if (success >= 0) { #if LIBAVUTIL_VERSION_MAJOR >= 53 - tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0); + tempPacket->buf = av_buffer_create(tempPacket->data, tempPacket->size, av_buffer_default_free, 0, 0); #endif #ifdef FFMPEG_USE_PACKET_UNREF - av_packet_move_ref(&packet, &tempPacket); + av_packet_move_ref(packet, tempPacket); + av_packet_free(&packet); #else - av_free_packet(&packet); + av_free_packet(packet); + av_freep(&packet); packet = tempPacket; #endif - packet.stream_index = encoder->audioStream->index; - av_interleaved_write_frame(encoder->context, &packet); + packet->stream_index = encoder->audioStream->index; + av_interleaved_write_frame(encoder->context, packet); } } else { - packet.stream_index = encoder->audioStream->index; - av_interleaved_write_frame(encoder->context, &packet); + packet->stream_index = encoder->audioStream->index; + av_interleaved_write_frame(encoder->context, packet); } } #ifdef FFMPEG_USE_PACKET_UNREF - av_packet_unref(&packet); + av_packet_unref(packet); + av_packet_free(&packet); #else - av_free_packet(&packet); + av_free_packet(packet); + av_freep(&packet); #endif return gotData; } @@ -792,32 +807,39 @@ void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size } bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame) { - AVPacket packet; + AVPacket* packet; - av_init_packet(&packet); - packet.data = 0; - packet.size = 0; +#ifdef FFMPEG_USE_PACKET_UNREF + packet = av_packet_alloc(); +#else + packet = av_malloc(sizeof(*packet)); + av_init_packet(packet); +#endif + packet->data = 0; + packet->size = 0; int gotData; #ifdef FFMPEG_USE_PACKETS avcodec_send_frame(encoder->video, videoFrame); - gotData = avcodec_receive_packet(encoder->video, &packet) == 0; + gotData = avcodec_receive_packet(encoder->video, packet) == 0; #else - avcodec_encode_video2(encoder->video, &packet, videoFrame, &gotData); + avcodec_encode_video2(encoder->video, packet, videoFrame, &gotData); #endif if (gotData) { #ifndef FFMPEG_USE_PACKET_UNREF if (encoder->video->coded_frame->key_frame) { - packet.flags |= AV_PKT_FLAG_KEY; + packet->flags |= AV_PKT_FLAG_KEY; } #endif - packet.stream_index = encoder->videoStream->index; - av_interleaved_write_frame(encoder->context, &packet); + packet->stream_index = encoder->videoStream->index; + av_interleaved_write_frame(encoder->context, packet); } #ifdef FFMPEG_USE_PACKET_UNREF - av_packet_unref(&packet); + av_packet_unref(packet); + av_packet_free(&packet); #else - av_free_packet(&packet); + av_free_packet(packet); + av_freep(&packet); #endif return gotData; From 000be71c5a95f6a1d5a7b746cadd68570bd30147 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 21 Aug 2021 18:29:24 -0700 Subject: [PATCH 06/19] FFmpeg: Remove disused fields --- src/feature/ffmpeg/ffmpeg-encoder.c | 5 ----- src/feature/ffmpeg/ffmpeg-encoder.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 4be2b5b15..21f298157 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -86,7 +86,6 @@ void FFmpegEncoderInit(struct FFmpegEncoder* encoder) { encoder->audioStream = NULL; encoder->audioFrame = NULL; encoder->audioBuffer = NULL; - encoder->postaudioBuffer = NULL; encoder->video = NULL; encoder->videoStream = NULL; encoder->videoFrame = NULL; @@ -562,10 +561,6 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { avio_close(encoder->context->pb); } - if (encoder->postaudioBuffer) { - av_free(encoder->postaudioBuffer); - encoder->postaudioBuffer = NULL; - } if (encoder->audioBuffer) { av_free(encoder->audioBuffer); encoder->audioBuffer = NULL; diff --git a/src/feature/ffmpeg/ffmpeg-encoder.h b/src/feature/ffmpeg/ffmpeg-encoder.h index 26e21184d..a484a9673 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.h +++ b/src/feature/ffmpeg/ffmpeg-encoder.h @@ -33,8 +33,6 @@ struct FFmpegEncoder { int sampleRate; uint16_t* audioBuffer; size_t audioBufferSize; - uint16_t* postaudioBuffer; - size_t postaudioBufferSize; AVFrame* audioFrame; size_t currentAudioSample; int64_t currentAudioFrame; From 7398eb5d725daa1a8bf520c51e68303e2aa507bc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Aug 2021 02:40:58 -0700 Subject: [PATCH 07/19] Updater: More MSVC build fixes --- src/feature/updater-main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index 0e547cd27..8487581ec 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -22,6 +22,10 @@ #include #endif +#ifndef W_OK +#define W_OK 02 +#endif + bool extractArchive(struct VDir* archive, const char* root) { char path[PATH_MAX] = {0}; struct VDirEntry* vde; From 80a502bcc99ca8464767ce00304868fbd5d0d446 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Aug 2021 15:01:40 -0700 Subject: [PATCH 08/19] CMake: Yet more MSVC buildfixes --- CMakeLists.txt | 4 +++- src/feature/updater-main.c | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 030a31344..8c59c62e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -921,7 +921,9 @@ endif() if(BUILD_UPDATER) add_executable(updater-stub WIN32 ${CMAKE_CURRENT_SOURCE_DIR}/src/feature/updater-main.c) target_link_libraries(updater-stub ${OS_LIB} ${PLATFORM_LIBRARY} ${BINARY_NAME}) - if(NOT MSVC) + if(MSVC) + set_target_properties(updater-stub PROPERTIES LINK_FLAGS /ENTRY:mainCRTStartup) + else() set_target_properties(updater-stub PROPERTIES LINK_FLAGS_RELEASE -s) set_target_properties(updater-stub PROPERTIES LINK_FLAGS_RELWITHDEBINFO -s) endif() diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index 8487581ec..367dff9f5 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -16,6 +16,7 @@ #include #include #include +#include #define mkdir(X, Y) _mkdir(X) #elif defined(_POSIX_C_SOURCE) @@ -52,7 +53,11 @@ bool extractArchive(struct VDir* archive, const char* root) { errno = 0; vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); if (!vfOut && errno == EACCES) { +#ifdef _WIN32 + Sleep(1000); +#else sleep(1); +#endif vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); } if (!vfOut) { From 143a336b04f805199ec8ecae7aa36e9dacb44277 Mon Sep 17 00:00:00 2001 From: gifvex Date: Sat, 21 Aug 2021 09:18:05 -0400 Subject: [PATCH 09/19] CInema: Fix Windows/MSYS2 build --- CMakeLists.txt | 3 +-- src/platform/qt/CMakeLists.txt | 3 +++ src/platform/test/cinema-main.c | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c59c62e6..8f7c87403 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,8 +212,7 @@ if(WIN32) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) add_definitions(-D_UNICODE -DUNICODE) else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -municode") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") + add_definitions(-D_GNU_SOURCE) endif() list(APPEND OS_LIB ws2_32 shlwapi) list(APPEND CORE_VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-fd.c ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/vfs-w32.c) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index b2f77d1ae..b6a06d900 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -310,6 +310,9 @@ set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CM if(WIN32) set_target_properties(${BINARY_NAME}-qt PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + if(NOT MSVC) + target_link_libraries(${BINARY_NAME}-qt -municode) + endif() endif() list(APPEND QT_LIBRARIES Qt5::Widgets Qt5::Network) diff --git a/src/platform/test/cinema-main.c b/src/platform/test/cinema-main.c index 55a7bcfa6..88fcf2a66 100644 --- a/src/platform/test/cinema-main.c +++ b/src/platform/test/cinema-main.c @@ -715,7 +715,11 @@ static struct VDir* _makeOutDir(const char* testName) { strncpy(pathEnd, testName, len); pathEnd += len; +#ifndef _WIN32 mkdir(path, 0777); +#else + mkdir(path); +#endif if (!pos) { break; From 250262bfe70ac3e79f447982f9396f922b39f689 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Aug 2021 22:31:39 -0700 Subject: [PATCH 10/19] Updater: Partial macOS support --- CMakeLists.txt | 2 +- src/feature/updater-main.c | 104 +++++++++++++++++++++++-- src/feature/updater.c | 10 +++ src/platform/qt/ApplicationUpdater.cpp | 3 +- 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f7c87403..272190669 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -913,7 +913,7 @@ if(BUILD_OPENEMU) install(TARGETS ${BINARY_NAME}-openemu LIBRARY DESTINATION ${OE_LIBDIR} COMPONENT ${BINARY_NAME}.oecoreplugin NAMELINK_SKIP) endif() -if(BUILD_QT AND WIN32) +if(BUILD_QT AND (WIN32 OR APPLE)) set(BUILD_UPDATER ON) endif() diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index 367dff9f5..158ae1f96 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -4,7 +4,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include +#include #include #include @@ -27,7 +29,7 @@ #define W_OK 02 #endif -bool extractArchive(struct VDir* archive, const char* root) { +bool extractArchive(struct VDir* archive, const char* root, bool prefix) { char path[PATH_MAX] = {0}; struct VDirEntry* vde; uint8_t block[8192]; @@ -35,17 +37,37 @@ bool extractArchive(struct VDir* archive, const char* root) { while ((vde = archive->listNext(archive))) { struct VFile* vfIn; struct VFile* vfOut; - const char* fname = strchr(vde->name(vde), '/'); - if (!fname) { + const char* fname; + if (prefix) { + fname = strchr(vde->name(vde), '/'); + if (!fname) { + continue; + } + snprintf(path, sizeof(path), "%s/%s", root, &fname[1]); + } else { + fname = vde->name(vde); + snprintf(path, sizeof(path), "%s/%s", root, fname); + } + if (fname[0] == '.') { continue; } - snprintf(path, sizeof(path), "%s/%s", root, &fname[1]); switch (vde->type(vde)) { case VFS_DIRECTORY: printf("mkdir %s\n", fname); if (mkdir(path, 0755) < 0 && errno != EEXIST) { return false; } + if (!prefix) { + struct VDir* subdir = archive->openDir(archive, fname); + if (!subdir) { + return false; + } + if (!extractArchive(subdir, path, false)) { + subdir->close(subdir); + return false; + } + subdir->close(subdir); + } break; case VFS_FILE: printf("extract %s\n", fname); @@ -96,13 +118,68 @@ int main(int argc, char* argv[]) { } else if (access(root, W_OK)) { puts("Cannot write to update path"); } else { +#ifdef __APPLE__ + char subdir[PATH_MAX]; + char devpath[PATH_MAX] = {0}; + bool needsUnmount = false; +#endif bool isPortable = mCoreConfigIsPortable(); - struct VDir* archive = VDirOpenArchive(updateArchive); + const char* extension = mUpdateGetArchiveExtension(&config); + struct VDir* archive = NULL; + bool prefix = true; + if (strcmp(extension, "dmg") == 0) { +#ifdef __APPLE__ + char mountpoint[PATH_MAX]; + // Make a slightly random directory name for the updater mountpoint + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + int printed = snprintf(mountpoint, sizeof(mountpoint), "/Volumes/%s Updater %04lX", projectName, (t.tv_nsec >> 14) & 0xFFFF); + + // Fork hdiutil to mount it + char* args[] = {"hdiutil", "attach", "-nobrowse", "-mountpoint", mountpoint, updateArchive, NULL}; + int fds[2]; + pipe(fds); + pid_t pid = fork(); + if (pid == 0) { + dup2(fds[1], STDOUT_FILENO); + execvp("hdiutil", args); + _exit(1); + } else { + // Parse out the disk ID so we can detach it when we're done + char buffer[1024] = {0}; + ssize_t size; + while ((size = read(fds[0], buffer, sizeof(buffer) - 1)) > 0) { // Leave the last byte null + char* devinfo = strnstr(buffer, "\n/dev/disk", size); + if (!devinfo) { + continue; + } + char* devend = strpbrk(&devinfo[9], "s \t"); + if (!devend) { + continue; + } + off_t diff = devend - devinfo - 1; + memcpy(devpath, &devinfo[1], diff); + puts(devpath); + break; + } + int retstat; + wait4(pid, &retstat, 0, NULL); + } + snprintf(&mountpoint[printed], sizeof(mountpoint) - printed, "/%s.app", projectName); + snprintf(subdir, sizeof(subdir), "%s/%s.app", root, projectName); + root = subdir; + archive = VDirOpen(mountpoint); + prefix = false; + needsUnmount = true; +#endif + } else { + archive = VDirOpenArchive(updateArchive); + } if (!archive) { puts("Cannot open update archive"); } else { puts("Extracting update"); - if (extractArchive(archive, root)) { + if (extractArchive(archive, root, prefix)) { puts("Complete"); ok = 0; mUpdateDeregister(&config); @@ -112,6 +189,19 @@ int main(int argc, char* argv[]) { archive->close(archive); unlink(updateArchive); } +#ifdef __APPLE__ + if (needsUnmount) { + char* args[] = {"hdiutil", "detach", devpath, NULL}; + pid_t pid = vfork(); + if (pid == 0) { + execvp("hdiutil", args); + _exit(0); + } else { + int retstat; + wait4(pid, &retstat, 0, NULL); + } + } +#endif if (!isPortable) { char portableIni[PATH_MAX] = {0}; snprintf(portableIni, sizeof(portableIni), "%s/portable.ini", root); @@ -124,7 +214,7 @@ int main(int argc, char* argv[]) { const char* argv[] = { bin, NULL }; #ifdef _WIN32 _execv(bin, argv); -#elif defined(_POSIX_C_SOURCE) +#elif defined(_POSIX_C_SOURCE) || defined(__APPLE__) execv(bin, argv); #endif } diff --git a/src/feature/updater.c b/src/feature/updater.c index 21c4aa146..dec380d9c 100644 --- a/src/feature/updater.c +++ b/src/feature/updater.c @@ -185,6 +185,16 @@ void mUpdateRegister(struct mCoreConfig* config, const char* arg0, const char* u #endif if (last) { last[0] = '\0'; +#ifdef __APPLE__ + ssize_t len = strlen(filename); + if (len > 19 && strcmp(&filename[len - 19], ".app/Contents/MacOS") == 0) { + filename[len - 19] = '\0'; + last = strrchr(filename, '/'); + if (last) { + last[0] = '\0'; + } + } +#endif } ConfigurationSetValue(cfg, UPDATE_SECTION, "bin", arg0); ConfigurationSetValue(cfg, UPDATE_SECTION, "root", filename); diff --git a/src/platform/qt/ApplicationUpdater.cpp b/src/platform/qt/ApplicationUpdater.cpp index 2d0e7cccc..9895711e0 100644 --- a/src/platform/qt/ApplicationUpdater.cpp +++ b/src/platform/qt/ApplicationUpdater.cpp @@ -44,8 +44,7 @@ ApplicationUpdater::ApplicationUpdater(ConfigController* config, QObject* parent config->setQtOption("lastUpdateCheck", m_lastCheck); if (available && currentVersion() < updateInfo()) { -#ifdef Q_OS_WIN - // Only works on Windows at the moment +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) ApplicationUpdatePrompt* prompt = new ApplicationUpdatePrompt; connect(prompt, &QDialog::accepted, GBAApp::app(), &GBAApp::restartForUpdate); prompt->setAttribute(Qt::WA_DeleteOnClose); From 5c3229b4fae22e04e3cc9caaf8c481f341bcc953 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Aug 2021 23:05:22 -0700 Subject: [PATCH 11/19] Updater: MacOS fixes --- src/feature/updater-main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index 158ae1f96..154702637 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -107,6 +107,7 @@ int main(int argc, char* argv[]) { UNUSED(argv); struct mCoreConfig config; char updateArchive[PATH_MAX] = {0}; + char bin[PATH_MAX] = {0}; const char* root; int ok = 1; @@ -131,9 +132,9 @@ int main(int argc, char* argv[]) { #ifdef __APPLE__ char mountpoint[PATH_MAX]; // Make a slightly random directory name for the updater mountpoint - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - int printed = snprintf(mountpoint, sizeof(mountpoint), "/Volumes/%s Updater %04lX", projectName, (t.tv_nsec >> 14) & 0xFFFF); + struct timeval t; + gettimeofday(&t, NULL); + int printed = snprintf(mountpoint, sizeof(mountpoint), "/Volumes/%s Updater %04X", projectName, (t.tv_usec >> 2) & 0xFFFF); // Fork hdiutil to mount it char* args[] = {"hdiutil", "attach", "-nobrowse", "-mountpoint", mountpoint, updateArchive, NULL}; @@ -181,6 +182,8 @@ int main(int argc, char* argv[]) { puts("Extracting update"); if (extractArchive(archive, root, prefix)) { puts("Complete"); + const char* command = mUpdateGetCommand(&config); + strlcpy(bin, command, sizeof(bin)); ok = 0; mUpdateDeregister(&config); } else { @@ -208,7 +211,6 @@ int main(int argc, char* argv[]) { unlink(portableIni); } } - const char* bin = mUpdateGetCommand(&config); mCoreConfigDeinit(&config); if (ok == 0) { const char* argv[] = { bin, NULL }; From c6167470ebfa5b95b5db21ef11191b13ffdfd362 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 26 Aug 2021 03:35:19 -0700 Subject: [PATCH 12/19] All: Fix indentation errors --- include/mgba-util/common.h | 6 +++--- include/mgba/feature/updater.h | 14 +++++++------- src/debugger/gdb-stub.c | 2 +- src/platform/test/perf-main.c | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index 50dfec942..e908c40ea 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -252,9 +252,9 @@ typedef intptr_t ssize_t; #define ATTRIBUTE_NOINLINE // Adapted from https://stackoverflow.com/a/2390626 #define _CONSTRUCTOR(FN, PRE) \ - static void FN(void); \ - __declspec(allocate(".CRT$XCU")) void (*_CONSTRUCTOR_ ## FN)(void) = FN; \ - static void FN(void) + static void FN(void); \ + __declspec(allocate(".CRT$XCU")) void (*_CONSTRUCTOR_ ## FN)(void) = FN; \ + static void FN(void) #ifdef _WIN64 #define CONSTRUCTOR(FN) _CONSTRUCTOR(FN, "") #else diff --git a/include/mgba/feature/updater.h b/include/mgba/feature/updater.h index 323ff749c..bacd45294 100644 --- a/include/mgba/feature/updater.h +++ b/include/mgba/feature/updater.h @@ -17,16 +17,16 @@ struct StringList; struct Table; struct mUpdaterContext { - struct Configuration manifest; + struct Configuration manifest; }; struct mUpdate { - const char* path; - size_t size; - int rev; - const char* version; - const char* commit; - const char* sha256; + const char* path; + size_t size; + int rev; + const char* version; + const char* commit; + const char* sha256; }; bool mUpdaterInit(struct mUpdaterContext*, const char* manifest); diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index 518425b83..706e1fde8 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -662,7 +662,7 @@ size_t _parseGDBMessage(struct GDBStub* stub, const char* message) { break; case 'X': _writeMemoryBinary(stub, message); - break; + break; case 'Z': _setBreakpoint(stub, message); break; diff --git a/src/platform/test/perf-main.c b/src/platform/test/perf-main.c index 345216be0..2e1736390 100644 --- a/src/platform/test/perf-main.c +++ b/src/platform/test/perf-main.c @@ -83,8 +83,8 @@ static Socket _server = INVALID_SOCKET; int main(int argc, char** argv) { #ifdef _3DS UNUSED(_mPerfShutdown); - gfxInitDefault(); - osSetSpeedupEnable(true); + gfxInitDefault(); + osSetSpeedupEnable(true); consoleInit(GFX_BOTTOM, NULL); #elif defined(__SWITCH__) UNUSED(_mPerfShutdown); From bc37f48e291394bd3b8383d16395fc788ed6ee87 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 28 Aug 2021 22:05:49 -0700 Subject: [PATCH 13/19] CMake: Attempt to fix #1839 again --- CMakeLists.txt | 10 ++++++---- include/mgba/internal/gba/renderers/gl.h | 2 +- src/gba/core.c | 20 ++++++++++---------- src/gba/renderers/gl.c | 2 +- src/platform/opengl/gles2.c | 20 ++++++++++++++++++-- src/platform/opengl/gles2.h | 2 ++ 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 272190669..12d4572df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ if(NOT LIBMGBA_ONLY) set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)") set(BUILD_GL ON CACHE BOOL "Build with OpenGL") set(BUILD_GLES2 ON CACHE BOOL "Build with OpenGL|ES 2") - set(BUILD_GLES3 OFF CACHE BOOL "Build with OpenGL|ES 3") + set(BUILD_GLES3 ON CACHE BOOL "Build with OpenGL|ES 3") set(USE_EPOXY ON CACHE STRING "Build with libepoxy") set(DISABLE_DEPS OFF CACHE BOOL "Build without dependencies") set(DISTBUILD OFF CACHE BOOL "Build distribution packages") @@ -408,14 +408,14 @@ endif() if(NOT BUILD_GL AND NOT LIBMGBA_ONLY) set(OPENGL_LIBRARY "" CACHE PATH "" FORCE) endif() -if(BUILD_GLES2 AND NOT BUILD_RASPI AND NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|Darwin|Linux|.*BSD|DragonFly|Haiku)$") +if(BUILD_GLES2 AND NOT BUILD_GL) find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h) find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM) if(NOT OPENGLES2_INCLUDE_DIR OR NOT OPENGLES2_LIBRARY) set(BUILD_GLES2 OFF CACHE BOOL "OpenGL|ES 2 not found" FORCE) endif() endif() -if(NOT BUILD_GLES2 AND NOT LIBMGBA_ONLY) +if(NOT BUILD_GLES2 AND NOT BUILD_GLES3 AND NOT LIBMGBA_ONLY) set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE) endif() if(BUILD_GL) @@ -436,6 +436,8 @@ if(BUILD_GLES3) list(APPEND FEATURE_DEFINES BUILD_GLES3) if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY) set(BUILD_GLES3 OFF CACHE BOOL "OpenGL|ES 3 not found" FORCE) + else() + set(OPENGLES2_LIBRARY ${OPENGLES3_LIBRARY} CACHE PATH "" FORCE) endif() endif() @@ -678,7 +680,7 @@ endif() if(USE_EPOXY) list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) - list(APPEND FEATURE_DEFINES BUILD_GL BUILD_GLES2) + list(APPEND FEATURE_DEFINES BUILD_GL BUILD_GLES2 BUILD_GLES3) list(APPEND FEATURES EPOXY) include_directories(AFTER ${EPOXY_INCLUDE_DIRS}) link_directories(${EPOXY_LIBRARY_DIRS}) diff --git a/include/mgba/internal/gba/renderers/gl.h b/include/mgba/internal/gba/renderers/gl.h index 2908e48d9..773d5dee0 100644 --- a/include/mgba/internal/gba/renderers/gl.h +++ b/include/mgba/internal/gba/renderers/gl.h @@ -16,7 +16,7 @@ CXX_GUARD_START #include #include -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #ifdef USE_EPOXY #include diff --git a/src/gba/core.c b/src/gba/core.c index 88171fbeb..3bd31b776 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -18,7 +18,7 @@ #ifndef DISABLE_THREADING #include #endif -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #include #endif #include @@ -134,7 +134,7 @@ struct GBACore { struct mCore d; struct GBAVideoRenderer dummyRenderer; struct GBAVideoSoftwareRenderer renderer; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 struct GBAVideoGLRenderer glRenderer; #endif #ifndef MINIMAL_CORE @@ -192,7 +192,7 @@ static bool _GBACoreInit(struct mCore* core) { GBAVideoSoftwareRendererCreate(&gbacore->renderer); gbacore->renderer.outputBuffer = NULL; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 GBAVideoGLRendererCreate(&gbacore->glRenderer); gbacore->glRenderer.outputTex = -1; #endif @@ -248,7 +248,7 @@ static bool _GBACoreSupportsFeature(const struct mCore* core, enum mCoreFeature UNUSED(core); switch (feature) { case mCORE_FEATURE_OPENGL: -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 return true; #else return false; @@ -362,7 +362,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } struct GBACore* gbacore = (struct GBACore*) core; -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (strcmp("videoScale", option) == 0) { if (config != &core->config) { mCoreConfigCopyValue(&core->config, config, "videoScale"); @@ -380,7 +380,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c if (gbacore->renderer.outputBuffer) { renderer = &gbacore->renderer.d; } -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); renderer = &gbacore->glRenderer.d; @@ -402,7 +402,7 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } static void _GBACoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) { -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 const struct GBACore* gbacore = (const struct GBACore*) core; int scale = gbacore->glRenderer.scale; #else @@ -422,7 +422,7 @@ static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t s } static void _GBACoreSetVideoGLTex(struct mCore* core, unsigned texid) { -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 struct GBACore* gbacore = (struct GBACore*) core; gbacore->glRenderer.outputTex = texid; #else @@ -562,7 +562,7 @@ static void _GBACoreReset(struct mCore* core) { struct GBA* gba = (struct GBA*) core->board; int fakeBool; if (gbacore->renderer.outputBuffer -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 || gbacore->glRenderer.outputTex != (unsigned) -1 #endif ) { @@ -570,7 +570,7 @@ static void _GBACoreReset(struct mCore* core) { if (gbacore->renderer.outputBuffer) { renderer = &gbacore->renderer.d; } -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); renderer = &gbacore->glRenderer.d; diff --git a/src/gba/renderers/gl.c b/src/gba/renderers/gl.c index dff331fc4..7dab8f13c 100644 --- a/src/gba/renderers/gl.c +++ b/src/gba/renderers/gl.c @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include -#if defined(BUILD_GLES2) || defined(BUILD_GLES3) +#ifdef BUILD_GLES3 #include #include diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index d9f6705e5..14f0db18b 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -159,6 +159,7 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) { mGLES2ShaderInit(&context->finalShader, 0, 0, 0, 0, false, 0, 0); mGLES2ShaderInit(&context->interframeShader, 0, _interframeFragmentShader, -1, -1, false, 0, 0); +#ifdef BUILD_GLES3 if (context->initialShader.vao != (GLuint) -1) { glBindVertexArray(context->initialShader.vao); glBindBuffer(GL_ARRAY_BUFFER, context->vbo); @@ -168,6 +169,7 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) { glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glBindVertexArray(0); } +#endif glDeleteFramebuffers(1, &context->finalShader.fbo); glDeleteTextures(1, &context->finalShader.tex); @@ -297,9 +299,12 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) { glUseProgram(shader->program); glUniform1i(shader->texLocation, 0); glUniform2f(shader->texSizeLocation, context->d.width - padW, context->d.height - padH); +#ifdef BUILD_GLES3 if (shader->vao != (GLuint) -1) { glBindVertexArray(shader->vao); - } else { + } else +#endif + { glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glEnableVertexAttribArray(shader->positionLocation); glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); @@ -391,9 +396,11 @@ void mGLES2ContextDrawFrame(struct VideoBackend* v) { } glBindFramebuffer(GL_FRAMEBUFFER, 0); glUseProgram(0); +#ifdef BUILD_GLES3 if (context->finalShader.vao != (GLuint) -1) { glBindVertexArray(0); } +#endif } void mGLES2ContextPostFrame(struct VideoBackend* v, const void* frame) { @@ -508,6 +515,7 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f shader->uniforms[i].location = glGetUniformLocation(shader->program, shader->uniforms[i].name); } +#ifdef BUILD_GLES3 const GLubyte* extensions = glGetString(GL_EXTENSIONS); if (shaderBuffer[0] == _gles2Header || version[0] >= '3' || (extensions && strstr((const char*) extensions, "_vertex_array_object") != NULL)) { glGenVertexArrays(1, &shader->vao); @@ -515,7 +523,9 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f glEnableVertexAttribArray(shader->positionLocation); glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); glBindVertexArray(0); - } else { + } else +#endif + { shader->vao = -1; } @@ -527,9 +537,11 @@ void mGLES2ShaderDeinit(struct mGLES2Shader* shader) { glDeleteShader(shader->fragmentShader); glDeleteProgram(shader->program); glDeleteFramebuffers(1, &shader->fbo); +#ifdef BUILD_GLES3 if (shader->vao != (GLuint) -1) { glDeleteVertexArrays(1, &shader->vao); } +#endif } void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shaders, size_t nShaders) { @@ -547,16 +559,20 @@ void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shad glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT); +#ifdef BUILD_GLES3 if (context->shaders[i].vao != (GLuint) -1) { glBindVertexArray(context->shaders[i].vao); glBindBuffer(GL_ARRAY_BUFFER, context->vbo); glEnableVertexAttribArray(context->shaders[i].positionLocation); glVertexAttribPointer(context->shaders[i].positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL); } +#endif } +#ifdef BUILD_GLES3 if (context->initialShader.vao != (GLuint) -1) { glBindVertexArray(0); } +#endif glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/platform/opengl/gles2.h b/src/platform/opengl/gles2.h index 8cf5b2b0e..4f9f504f5 100644 --- a/src/platform/opengl/gles2.h +++ b/src/platform/opengl/gles2.h @@ -20,6 +20,8 @@ CXX_GUARD_START #include #include #endif +#elif defined(BUILD_GLES3) +#include #else #include #endif From c21780282928eda63fe9ca998bddd3edea6b6384 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 28 Aug 2021 22:29:27 -0700 Subject: [PATCH 14/19] OpenGL: Buildfixes and CMake cleanup --- CMakeLists.txt | 37 +++++++++++++++++++++------------- src/platform/qt/CMakeLists.txt | 2 +- src/platform/qt/Display.cpp | 13 ++++++------ src/platform/qt/DisplayGL.cpp | 20 +++++++++--------- src/platform/qt/DisplayGL.h | 2 +- src/platform/sdl/main.h | 4 ++-- 6 files changed, 44 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12d4572df..ca652ca09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -397,6 +397,7 @@ if(CMAKE_SYSTEM_NAME MATCHES ".*BSD|DragonFly") else() find_feature(USE_EDITLINE "libedit") endif() + if(BUILD_GL) find_package(OpenGL QUIET) if(NOT OPENGL_FOUND) @@ -405,9 +406,16 @@ if(BUILD_GL) set(OPENGL_LIBRARY OpenGL::GL) endif() endif() +if(BUILD_GL) + list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c) + list(APPEND FEATURE_DEFINES BUILD_GL) + list(APPEND DEPENDENCY_LIB ${OPENGL_LIBRARY}) + include_directories(${OPENGL_INCLUDE_DIR}) +endif() if(NOT BUILD_GL AND NOT LIBMGBA_ONLY) set(OPENGL_LIBRARY "" CACHE PATH "" FORCE) endif() + if(BUILD_GLES2 AND NOT BUILD_GL) find_path(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h) find_library(OPENGLES2_LIBRARY NAMES GLESv2 GLESv2_CM) @@ -415,31 +423,32 @@ if(BUILD_GLES2 AND NOT BUILD_GL) set(BUILD_GLES2 OFF CACHE BOOL "OpenGL|ES 2 not found" FORCE) endif() endif() -if(NOT BUILD_GLES2 AND NOT BUILD_GLES3 AND NOT LIBMGBA_ONLY) - set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE) -endif() -if(BUILD_GL) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gl.c) - list(APPEND FEATURE_DEFINES BUILD_GL) - list(APPEND DEPENDENCY_LIB ${OPENGL_LIBRARY}) - include_directories(${OPENGL_INCLUDE_DIR}) -endif() if(BUILD_GLES2) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) list(APPEND FEATURE_DEFINES BUILD_GLES2) list(APPEND DEPENDENCY_LIB ${OPENGLES2_LIBRARY}) include_directories(${OPENGLES2_INCLUDE_DIR}) endif() -if(BUILD_GLES3) + +if(BUILD_GLES3 AND NOT BUILD_GL) find_path(OPENGLES3_INCLUDE_DIR NAMES GLES3/gl3.h) find_library(OPENGLES3_LIBRARY NAMES GLESv3 GLESv2) - list(APPEND FEATURE_DEFINES BUILD_GLES3) if(NOT OPENGLES3_INCLUDE_DIR OR NOT OPENGLES3_LIBRARY) set(BUILD_GLES3 OFF CACHE BOOL "OpenGL|ES 3 not found" FORCE) - else() - set(OPENGLES2_LIBRARY ${OPENGLES3_LIBRARY} CACHE PATH "" FORCE) endif() endif() +if(BUILD_GLES3) + list(APPEND FEATURE_DEFINES BUILD_GLES3) + list(APPEND DEPENDENCY_LIB ${OPENGLES3_LIBRARY}) + include_directories(${OPENGLES3_INCLUDE_DIR}) +endif() + +if(BUILD_GLES2 OR BUILD_GLES3) + list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/opengl/gles2.c) +endif() + +if(NOT BUILD_GLES2 AND NOT BUILD_GLES3 AND NOT LIBMGBA_ONLY) + set(OPENGLES2_LIBRARY "" CACHE PATH "" FORCE) +endif() if(DISABLE_DEPS) set(USE_GDB_STUB OFF) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index b6a06d900..062bfd5a1 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -24,7 +24,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(Qt5 COMPONENTS Core Widgets Network Multimedia) -if(NOT BUILD_GL AND NOT BUILD_GLES2) +if(NOT BUILD_GL AND NOT BUILD_GLES2 AND NOT BUILD_GLES3) message(WARNING "OpenGL is recommended to build the Qt port") endif() diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 853d02d12..5c427eb69 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Display.h" +#include "CoreController.h" #include "ConfigController.h" #include "DisplayGL.h" #include "DisplayQt.h" @@ -14,23 +15,23 @@ using namespace QGBA; -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) Display::Driver Display::s_driver = Display::Driver::OPENGL; #else Display::Driver Display::s_driver = Display::Driver::QT; #endif Display* Display::create(QWidget* parent) { -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) QSurfaceFormat format; format.setSwapInterval(1); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); #endif switch (s_driver) { -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) case Driver::OPENGL: -#if defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { format.setVersion(2, 0); } else { @@ -65,7 +66,7 @@ Display* Display::create(QWidget* parent) { return new DisplayQt(parent); default: -#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) return new DisplayGL(format, parent); #else return new DisplayQt(parent); @@ -101,7 +102,7 @@ void Display::configure(ConfigController* config) { interframeBlending(opts->interframeBlending); filter(opts->resampleVideo); config->updateOption("showOSD"); -#if defined(BUILD_GL) || defined(BUILD_GLES2) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) if (opts->shader) { struct VDir* shader = VDirOpen(opts->shader); if (shader && supportsShaders()) { diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 90d22702a..4feb70f83 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "DisplayGL.h" -#if defined(BUILD_GL) || defined(BUILD_GLES2) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) #include #include @@ -24,7 +24,7 @@ #ifdef BUILD_GL #include "platform/opengl/gl.h" #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) #include "platform/opengl/gles2.h" #ifdef _WIN32 #include @@ -294,13 +294,13 @@ void PainterGL::create() { #ifdef BUILD_GL mGLContext* glBackend; #endif -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) mGLES2Context* gl2Backend; #endif m_window = std::make_unique(); -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) auto version = m_format.version(); if (version >= qMakePair(2, 0)) { gl2Backend = static_cast(malloc(sizeof(mGLES2Context))); @@ -326,7 +326,7 @@ void PainterGL::create() { }; m_backend->init(m_backend, 0); -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_supportsShaders) { m_shader.preprocessShader = static_cast(&reinterpret_cast(m_backend)->initialShader); } @@ -343,7 +343,7 @@ void PainterGL::destroy() { return; } makeCurrent(); -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_shader.passes) { mGLES2ShaderFree(&m_shader); } @@ -420,7 +420,7 @@ void PainterGL::filter(bool filter) { void PainterGL::start() { makeCurrent(); -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_supportsShaders && m_shader.passes) { mGLES2ShaderAttach(reinterpret_cast(m_backend), static_cast(m_shader.passes), m_shader.nPasses); } @@ -598,7 +598,7 @@ void PainterGL::setShaders(struct VDir* dir) { if (!supportsShaders()) { return; } -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast(m_backend)); mGLES2ShaderFree(&m_shader); @@ -612,7 +612,7 @@ void PainterGL::clearShaders() { if (!supportsShaders()) { return; } -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast(m_backend)); mGLES2ShaderFree(&m_shader); @@ -625,7 +625,7 @@ VideoShader* PainterGL::shaders() { } int PainterGL::glTex() { -#ifdef BUILD_GLES2 +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (supportsShaders()) { mGLES2Context* gl2Backend = reinterpret_cast(m_backend); return gl2Backend->tex; diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 39cdb1d8e..d31921151 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once -#if defined(BUILD_GL) || defined(BUILD_GLES2) +#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) #include "Display.h" diff --git a/src/platform/sdl/main.h b/src/platform/sdl/main.h index 5f52f5e19..c97e50e33 100644 --- a/src/platform/sdl/main.h +++ b/src/platform/sdl/main.h @@ -29,7 +29,7 @@ CXX_GUARD_START #pragma GCC diagnostic pop #endif -#if defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) #include "gl-common.h" #include "platform/opengl/gles2.h" #endif @@ -72,7 +72,7 @@ struct mSDLRenderer { #ifdef BUILD_GL struct mGLContext gl; #endif -#if defined(BUILD_GLES2) || defined(USE_EPOXY) +#if defined(BUILD_GLES2) || defined(BUILD_GLES3) || defined(USE_EPOXY) struct mGLES2Context gl2; #endif From 19c57e0c19b24e5081602c585b582f6b2a2bda5b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 30 Aug 2021 17:24:54 -0700 Subject: [PATCH 15/19] Vita: Build fixes --- CMakeLists.txt | 2 +- src/platform/psp2/CMakeLists.txt | 2 +- src/platform/psp2/sce-vfs.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca652ca09..6998ef3a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,7 +330,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") find_function(localtime_r) # The strtof_l on Linux not actually exposed nor actually strtof_l set(HAVE_STRTOF_L OFF) -elseif(NOT DEFINED PSP2) +else() find_function(localtime_r) find_function(strtof_l) endif() diff --git a/src/platform/psp2/CMakeLists.txt b/src/platform/psp2/CMakeLists.txt index 60d37e070..393f63a4d 100644 --- a/src/platform/psp2/CMakeLists.txt +++ b/src/platform/psp2/CMakeLists.txt @@ -3,7 +3,7 @@ include("${VITASDK}/share/vita.cmake" REQUIRED) find_program(OBJCOPY ${cross_prefix}objcopy) find_file(NIDDB db.json PATHS ${VITASDK} ${VITASDK}/bin ${VITASDK}/share) -set(OS_DEFINES IOAPI_NO_64) +set(OS_DEFINES IOAPI_NO_64 _GNU_SOURCE) set(OS_DEFINES ${OS_DEFINES} PARENT_SCOPE) file(GLOB OS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/psp2-*.c) diff --git a/src/platform/psp2/sce-vfs.c b/src/platform/psp2/sce-vfs.c index 22b05950f..d5a52f177 100644 --- a/src/platform/psp2/sce-vfs.c +++ b/src/platform/psp2/sce-vfs.c @@ -90,7 +90,7 @@ struct VFile* VFileOpenSce(const char* path, int flags, SceMode mode) { bool _vfsceClose(struct VFile* vf) { struct VFileSce* vfsce = (struct VFileSce*) vf; - sceIoSyncByFd(vfsce->fd); + sceIoSyncByFd(vfsce->fd, 0); return sceIoClose(vfsce->fd) >= 0; } @@ -128,7 +128,7 @@ static void _vfsceUnmap(struct VFile* vf, void* memory, size_t size) { sceIoLseek(vfsce->fd, 0, SEEK_SET); sceIoWrite(vfsce->fd, memory, size); sceIoLseek(vfsce->fd, cur, SEEK_SET); - sceIoSyncByFd(vfsce->fd); + sceIoSyncByFd(vfsce->fd, 0); mappedMemoryFree(memory, size); } @@ -155,7 +155,7 @@ bool _vfsceSync(struct VFile* vf, void* buffer, size_t size) { sceIoLseek(vfsce->fd, cur, SEEK_SET); return res == size; } - return sceIoSyncByFd(vfsce->fd) >= 0; + return sceIoSyncByFd(vfsce->fd, 0) >= 0; } struct VDir* VDirOpen(const char* path) { From f2f75b3b0071ebfa813c8c15ad08efca4b89336e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 4 Sep 2021 22:13:09 -0700 Subject: [PATCH 16/19] Qt: Only use a QPainter with OpenGL is the OSD is enabled --- src/platform/qt/DisplayGL.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 4feb70f83..d949eb016 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -521,19 +521,17 @@ void PainterGL::unpause() { } void PainterGL::performDraw() { - m_painter.begin(m_window.get()); - m_painter.beginNativePainting(); float r = m_surface->devicePixelRatio(); m_backend->resized(m_backend, m_size.width() * r, m_size.height() * r); if (m_buffer) { m_backend->postFrame(m_backend, m_buffer); } m_backend->drawFrame(m_backend); - m_painter.endNativePainting(); if (m_showOSD && m_messagePainter) { + m_painter.begin(m_window.get()); m_messagePainter->paint(&m_painter); + m_painter.end(); } - m_painter.end(); } void PainterGL::enqueue(const uint32_t* backing) { From 337ca2cfaf4c5dee0ce8c2de86bfb29507040735 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Sep 2021 12:20:46 -0700 Subject: [PATCH 17/19] GB I/O: Fix incrementing SGB controller when P14 is low (fixes #2202) --- CHANGES | 1 + src/gb/io.c | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 0356ef0c8..a90532f6c 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Features: - Discord Rich Presence now supports time elapsed - Additional scaling shaders Emulation fixes: + - GB I/O: Fix incrementing SGB controller when P14 is low (fixes mgba.io/i/2202) - GB Memory: Add cursory cartridge open bus emulation (fixes mgba.io/i/2032) - GB Video: Render SGB border when unmasking with ATTR/PAL_SET (fixes mgba.io/i/2261) - GBA: Improve timing when not booting from BIOS diff --git a/src/gb/io.c b/src/gb/io.c index 00f75ffd7..74ce4caee 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -119,19 +119,15 @@ static void _writeSGBBits(struct GB* gb, int bits) { if (bits == gb->currentSgbBits) { return; } - switch (bits) { - case 0: - case 1: - if (gb->currentSgbBits & 2) { - gb->sgbIncrement = !gb->sgbIncrement; - } - break; - case 3: + if (bits & 2) { if (gb->sgbIncrement) { gb->sgbIncrement = false; gb->sgbCurrentController = (gb->sgbCurrentController + 1) & gb->sgbControllers; } - break; + } else { + if (gb->currentSgbBits & 2) { + gb->sgbIncrement = !gb->sgbIncrement; + } } gb->currentSgbBits = bits; if (gb->sgbBit == 128 && bits == 2) { From f603fcdb727819eca0d79e1c90fd0331b71f5c49 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Sep 2021 16:54:40 -0700 Subject: [PATCH 18/19] mGUI: Add 9-slice drawing --- include/mgba-util/gui/font.h | 33 ++++++++++++++++++++++ res/icons.png | Bin 619 -> 663 bytes res/icons2x.png | Bin 1421 -> 1494 bytes src/util/gui/font-metrics.c | 25 +++++++++++++++++ src/util/gui/font.c | 52 +++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) diff --git a/include/mgba-util/gui/font.h b/include/mgba-util/gui/font.h index 1751898c3..5ad318e65 100644 --- a/include/mgba-util/gui/font.h +++ b/include/mgba-util/gui/font.h @@ -59,6 +59,31 @@ enum GUIIcon { GUI_ICON_UP, GUI_ICON_RIGHT, GUI_ICON_DOWN, + GUI_ICON_9SLICE_EMPTY_NW, + GUI_ICON_9SLICE_EMPTY_N, + GUI_ICON_9SLICE_EMPTY_NE, + GUI_ICON_9SLICE_EMPTY_W, + GUI_ICON_9SLICE_EMPTY_E, + GUI_ICON_9SLICE_EMPTY_SW, + GUI_ICON_9SLICE_EMPTY_S, + GUI_ICON_9SLICE_EMPTY_SE, + GUI_ICON_9SLICE_FILLED_NW, + GUI_ICON_9SLICE_FILLED_N, + GUI_ICON_9SLICE_FILLED_NE, + GUI_ICON_9SLICE_FILLED_W, + GUI_ICON_9SLICE_FILLED_C, + GUI_ICON_9SLICE_FILLED_E, + GUI_ICON_9SLICE_FILLED_SW, + GUI_ICON_9SLICE_FILLED_S, + GUI_ICON_9SLICE_FILLED_SE, + GUI_ICON_9SLICE_CAP_NNW, + GUI_ICON_9SLICE_CAP_NWW, + GUI_ICON_9SLICE_CAP_NNE, + GUI_ICON_9SLICE_CAP_NEE, + GUI_ICON_9SLICE_CAP_SSW, + GUI_ICON_9SLICE_CAP_SWW, + GUI_ICON_9SLICE_CAP_SSE, + GUI_ICON_9SLICE_CAP_SEE, GUI_ICON_MAX, }; @@ -80,6 +105,12 @@ struct GUIIconMetric { int height; }; +enum GUI9SliceStyle { + GUI_9SLICE_FILLED, + GUI_9SLICE_EMPTY, + GUI_9SLICE_EMPTY_CAPPED, +}; + unsigned GUIFontHeight(const struct GUIFont*); unsigned GUIFontGlyphWidth(const struct GUIFont*, uint32_t glyph); unsigned GUIFontSpanWidth(const struct GUIFont*, const char* text); @@ -96,6 +127,8 @@ void GUIFontDrawIconSize(struct GUIFont* font, int x, int y, int w, int h, uint3 void GUIFontDrawSubmit(struct GUIFont* font); #endif +void GUIFontDraw9Slice(struct GUIFont*, int x, int y, int width, int height, uint32_t color, enum GUI9SliceStyle style); + CXX_GUARD_END #endif diff --git a/res/icons.png b/res/icons.png index b52df6688a4da7d6a5b85df6d7fe4146a0c0282c..1b75cddd9aea8606378eab9000b6d1919ae55c5c 100644 GIT binary patch delta 604 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 Date: Mon, 6 Sep 2021 17:36:33 -0700 Subject: [PATCH 19/19] mGUI: Fix metrics on backtick --- src/util/gui/font-metrics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/gui/font-metrics.c b/src/util/gui/font-metrics.c index db640e501..bf30cb4f0 100644 --- a/src/util/gui/font-metrics.c +++ b/src/util/gui/font-metrics.c @@ -102,7 +102,7 @@ const struct GUIFontGlyphMetric defaultFontMetrics[128] = { { 6, 11, { 2, 5, 3, 5 }}, // 0x5D "]" { 8, 7, { 2, 4, 7, 4 }}, // 0x5E "^" { 10, 3, { 10, 3, 3, 3 }}, // 0x5F "_" - { 6, 5, { 8, 6, 3, 4 }}, // 0x60 "`" + { 6, 5, { 3, 4, 8, 6 }}, // 0x60 "`" { 8, 7, { 6, 4, 3, 4 }}, // 0x61 "a" { 8, 11, { 2, 4, 3, 4 }}, // 0x62 "b" { 8, 7, { 6, 4, 3, 4 }}, // 0x63 "c"