mirror of
https://github.com/RGBCube/serenity
synced 2025-10-17 09:12:25 +00:00

We were going about this the wrong way: * We should not send `SDL_QUIT` events; SDL2 is doing this for us already when the last window is closed, for example. * The `SDL_WINDOWEVENT_CLOSE` event does not represent a closed window, but rather a _request_ from the window manager to close a window. This resolves the issue with the PrBoom+ port where the quit screen would not be shown when trying to close the main window.
1592 lines
55 KiB
Diff
1592 lines
55 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Kling <kling@serenityos.org>
|
|
Date: Sat, 27 Mar 2021 22:05:09 +0100
|
|
Subject: [PATCH] Add SerenityOS platform support
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Co-Authored-By: Robin Burchell <robin+git@viroteck.net>
|
|
Co-Authored-By: tgsm <doodrabbit@hotmail.com>
|
|
Co-Authored-By: TheMorc <r.gracik@gmail.com>
|
|
Co-Authored-By: thatdutchguy <thatdutchguy@users.noreply.github.com>
|
|
Co-Authored-By: Oleg Sikorskiy <olegsik@gmail.com>
|
|
Co-Authored-By: Gunnar Beutner <gunnar@beutner.name>
|
|
Co-Authored-By: AnicJov <contact.andrija@gmail.com>
|
|
Co-Authored-By: Jelle Raaijmakers <jelle@gmta.nl>
|
|
Co-Authored-By: Kenneth Myhra <kennethmyhra@gmail.com>
|
|
Co-Authored-By: Stephan Unverwerth <s.unverwerth@gmx.de>
|
|
Co-Authored-By: Tim Schumacher <timschumi@gmx.de>
|
|
Co-Authored-By: circl <circl.lastname@gmail.com>
|
|
Co-Authored-By: kleines Filmröllchen <filmroellchen@serenityos.org>
|
|
---
|
|
CMakeLists.txt | 25 +-
|
|
build-scripts/config.sub | 3 +
|
|
cmake/sdlchecks.cmake | 20 +
|
|
include/SDL_config.h.cmake | 2 +
|
|
src/SDL_error.c | 7 +-
|
|
src/audio/SDL_audio.c | 3 +
|
|
src/audio/SDL_sysaudio.h | 1 +
|
|
src/audio/serenity/SDL_serenityaudio.cpp | 166 +++++
|
|
src/audio/serenity/SDL_serenityaudio.h | 38 ++
|
|
src/stdlib/SDL_stdlib.c | 2 +-
|
|
src/video/SDL_sysvideo.h | 1 +
|
|
src/video/SDL_video.c | 13 +
|
|
src/video/serenity/SDL_serenityevents.cpp | 52 ++
|
|
src/video/serenity/SDL_serenityevents_c.h | 33 +
|
|
src/video/serenity/SDL_serenitymessagebox.cpp | 40 ++
|
|
src/video/serenity/SDL_serenitymessagebox.h | 38 ++
|
|
src/video/serenity/SDL_serenitymouse.cpp | 142 ++++
|
|
src/video/serenity/SDL_serenitymouse.h | 39 ++
|
|
src/video/serenity/SDL_serenityvideo.cpp | 607 ++++++++++++++++++
|
|
src/video/serenity/SDL_serenityvideo.h | 101 +++
|
|
20 files changed, 1308 insertions(+), 25 deletions(-)
|
|
create mode 100644 src/audio/serenity/SDL_serenityaudio.cpp
|
|
create mode 100644 src/audio/serenity/SDL_serenityaudio.h
|
|
create mode 100644 src/video/serenity/SDL_serenityevents.cpp
|
|
create mode 100644 src/video/serenity/SDL_serenityevents_c.h
|
|
create mode 100644 src/video/serenity/SDL_serenitymessagebox.cpp
|
|
create mode 100644 src/video/serenity/SDL_serenitymessagebox.h
|
|
create mode 100644 src/video/serenity/SDL_serenitymouse.cpp
|
|
create mode 100644 src/video/serenity/SDL_serenitymouse.h
|
|
create mode 100644 src/video/serenity/SDL_serenityvideo.cpp
|
|
create mode 100644 src/video/serenity/SDL_serenityvideo.h
|
|
|
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
index 6b536993781c9a4705667a4f74f1e26d9e03c7c4..e910dc45199af426bda5d09be813757c7ceb18b7 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -26,6 +26,9 @@ set(EXTRA_LDFLAGS)
|
|
# etc. See https://github.com/libsdl-org/SDL/issues/4150
|
|
add_library(sdl-build-options INTERFACE)
|
|
|
|
+set(UNIX 1)
|
|
+set(VIDEO_WAYLAND OFF)
|
|
+
|
|
if(WINDOWS_STORE)
|
|
cmake_minimum_required(VERSION 3.11.0)
|
|
target_compile_definitions(sdl-build-options INTERFACE "-DSDL_BUILDING_WINRT=1")
|
|
@@ -448,7 +451,7 @@ set_option(SDL_DUMMYVIDEO "Use dummy video driver" ON)
|
|
set_option(SDL_OPENGL "Include OpenGL support" ON)
|
|
set_option(SDL_OPENGLES "Include OpenGL ES support" ON)
|
|
set_option(SDL_PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT})
|
|
-dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" ON "SDL_PTHREADS" OFF)
|
|
+dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" OFF "SDL_PTHREADS" OFF)
|
|
dep_option(SDL_OSS "Support the OSS audio API" ON "UNIX_SYS OR RISCOS" OFF)
|
|
set_option(SDL_ALSA "Support the ALSA audio API" ${UNIX_SYS})
|
|
dep_option(SDL_ALSA_SHARED "Dynamically load ALSA audio support" ON "SDL_ALSA" OFF)
|
|
@@ -1345,25 +1348,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
|
CheckFusionSound()
|
|
endif()
|
|
|
|
- if(SDL_VIDEO)
|
|
- # Need to check for Raspberry PI first and add platform specific compiler flags, otherwise the test for GLES fails!
|
|
- CheckRPI()
|
|
- CheckX11()
|
|
- CheckDirectFB()
|
|
- # Need to check for EGL first because KMSDRM and Wayland depends on it.
|
|
- CheckEGL()
|
|
- CheckKMSDRM()
|
|
- CheckGLX()
|
|
- CheckOpenGL()
|
|
- CheckOpenGLES()
|
|
- CheckWayland()
|
|
- CheckVivante()
|
|
- # FIXME: implement CheckVulkan()
|
|
- if(SDL_VULKAN)
|
|
- set(SDL_VIDEO_VULKAN 1)
|
|
- set(HAVE_VULKAN TRUE)
|
|
- endif()
|
|
- endif()
|
|
+ CheckSerenity()
|
|
|
|
if(UNIX)
|
|
file(GLOB CORE_UNIX_SOURCES ${SDL2_SOURCE_DIR}/src/core/unix/*.c)
|
|
diff --git a/build-scripts/config.sub b/build-scripts/config.sub
|
|
index dba16e84c77c7d25871d80c24deff717faf4c094..39c9ecb7358ff0e2b32994027395eb8962483e02 100755
|
|
--- a/build-scripts/config.sub
|
|
+++ b/build-scripts/config.sub
|
|
@@ -1427,6 +1427,9 @@ case $os in
|
|
os400*)
|
|
os=os400
|
|
;;
|
|
+ serenity*)
|
|
+ os=serenity
|
|
+ ;;
|
|
sunos5*)
|
|
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
|
|
;;
|
|
diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake
|
|
index 7e2507505e589f4893388b346d548db77ca18800..1d094870718df3a95c9832d942fb8a0adb8a1ba2 100644
|
|
--- a/cmake/sdlchecks.cmake
|
|
+++ b/cmake/sdlchecks.cmake
|
|
@@ -785,6 +785,26 @@ macro(CheckDirectFB)
|
|
endif()
|
|
endmacro()
|
|
|
|
+# Requires:
|
|
+# - n/a
|
|
+macro(CheckSerenity)
|
|
+ message_warn("Configuring SerenityOS!")
|
|
+ set(HAVE_VIDEO_SERENITY TRUE)
|
|
+ set(HAVE_AUDIO_SERENITY TRUE)
|
|
+ set(HAVE_SDL_VIDEO TRUE)
|
|
+ set(HAVE_SDL_AUDIO TRUE)
|
|
+
|
|
+ set(CMAKE_CXX_FLAGS "-std=c++2a ${CMAKE_CXX_FLAGS}")
|
|
+ file(GLOB SERENITY_SOURCES ${SDL2_SOURCE_DIR}/src/video/serenity/*.cpp ${SDL2_SOURCE_DIR}/src/audio/serenity/*.cpp)
|
|
+ set(SOURCE_FILES ${SOURCE_FILES} ${SERENITY_SOURCES})
|
|
+ set(SDL_VIDEO_DRIVER_SERENITY 1)
|
|
+ set(SDL_AUDIO_DRIVER_SERENITY 1)
|
|
+ set(SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1)
|
|
+ set(HAVE_VIDEO_OPENGL TRUE)
|
|
+ set(SDL_VIDEO_OPENGL 1)
|
|
+ list(APPEND EXTRA_LIBS ipc gui gfx gl core)
|
|
+endmacro(CheckSerenity)
|
|
+
|
|
# Requires:
|
|
# - n/a
|
|
macro(CheckVivante)
|
|
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
|
|
index 2d21b37ddce1e517185e574d1f3b510a672d24e7..370ffcf8d4674a8031b469cec063d4810f30a7e0 100644
|
|
--- a/include/SDL_config.h.cmake
|
|
+++ b/include/SDL_config.h.cmake
|
|
@@ -318,6 +318,7 @@
|
|
#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@
|
|
#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@
|
|
#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@
|
|
+#cmakedefine SDL_AUDIO_DRIVER_SERENITY @SDL_AUDIO_DRIVER_SERENITY@
|
|
#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
|
|
#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
|
|
#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@
|
|
@@ -404,6 +405,7 @@
|
|
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
|
|
#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
|
|
#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN @SDL_VIDEO_DRIVER_OFFSCREEN@
|
|
+#cmakedefine SDL_VIDEO_DRIVER_SERENITY @SDL_VIDEO_DRIVER_SERENITY@
|
|
#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
|
|
#cmakedefine SDL_VIDEO_DRIVER_WINRT @SDL_VIDEO_DRIVER_WINRT@
|
|
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
|
|
diff --git a/src/SDL_error.c b/src/SDL_error.c
|
|
index 1ca460a6903359df2bd8aafa354b67df94d53751..b08d742e55f338a52e139cde0c50bd7524082aaf 100644
|
|
--- a/src/SDL_error.c
|
|
+++ b/src/SDL_error.c
|
|
@@ -53,10 +53,9 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
|
}
|
|
|
|
|
|
- if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
|
|
- /* If we are in debug mode, print out the error message */
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
|
|
- }
|
|
+ // # HACK(SerenityOS): show everything that's going on
|
|
+ dbgputstr(error->str, strlen(error->str));
|
|
+ dbgputstr("\n", 1);
|
|
}
|
|
|
|
return -1;
|
|
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
|
|
index e2f7412c994eb8f2d54e8f746f37bb1b1cc0645b..7181100bb0f824bf21199cd8af87b3b642572cf8 100644
|
|
--- a/src/audio/SDL_audio.c
|
|
+++ b/src/audio/SDL_audio.c
|
|
@@ -125,6 +125,9 @@ static const AudioBootStrap *const bootstrap[] = {
|
|
#endif
|
|
#if SDL_AUDIO_DRIVER_DUMMY
|
|
&DUMMYAUDIO_bootstrap,
|
|
+#endif
|
|
+#if SDL_AUDIO_DRIVER_SERENITY
|
|
+ &SERENITYAUDIO_bootstrap,
|
|
#endif
|
|
NULL
|
|
};
|
|
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
|
|
index 6afaae195c6cedb6f9d7b00ca840907e280c0575..6c7009afd966ab384848a63b51c35ec2ef61b8f5 100644
|
|
--- a/src/audio/SDL_sysaudio.h
|
|
+++ b/src/audio/SDL_sysaudio.h
|
|
@@ -211,6 +211,7 @@ extern AudioBootStrap PSPAUDIO_bootstrap;
|
|
extern AudioBootStrap VITAAUD_bootstrap;
|
|
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
|
|
extern AudioBootStrap OS2AUDIO_bootstrap;
|
|
+extern AudioBootStrap SERENITYAUDIO_bootstrap;
|
|
|
|
#endif /* SDL_sysaudio_h_ */
|
|
|
|
diff --git a/src/audio/serenity/SDL_serenityaudio.cpp b/src/audio/serenity/SDL_serenityaudio.cpp
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e1cd5348b67c23c49b25f99f4f36e020658aa049
|
|
--- /dev/null
|
|
+++ b/src/audio/serenity/SDL_serenityaudio.cpp
|
|
@@ -0,0 +1,166 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#if SDL_AUDIO_DRIVER_SERENITY
|
|
+# define AK_DONT_REPLACE_STD
|
|
+
|
|
+extern "C" {
|
|
+
|
|
+# include "SDL_audio.h"
|
|
+
|
|
+# include "../SDL_audio_c.h"
|
|
+# include "../SDL_audiodev_c.h"
|
|
+}
|
|
+
|
|
+# include <AK/Time.h>
|
|
+# include <LibAudio/ConnectionToServer.h>
|
|
+# include <LibAudio/SampleFormats.h>
|
|
+# include <time.h>
|
|
+# include "SDL_serenityaudio.h"
|
|
+
|
|
+static Array<Audio::Sample, Audio::AUDIO_BUFFER_SIZE> output_buffer {};
|
|
+static size_t output_buffer_samples_remaining { 0 };
|
|
+
|
|
+static void SERENITYAUDIO_CloseDevice(_THIS)
|
|
+{
|
|
+ dbgln("SERENITYAUDIO_CloseDevice");
|
|
+
|
|
+ struct SDL_PrivateAudioData* h = that->hidden;
|
|
+ if (h->client)
|
|
+ h->client->die();
|
|
+
|
|
+ SDL_free(that->hidden->mixbuf);
|
|
+ SDL_free(that->hidden);
|
|
+}
|
|
+
|
|
+static int SERENITYAUDIO_OpenDevice(_THIS, char const*)
|
|
+{
|
|
+ /* Initialize all variables that we clean on shutdown */
|
|
+ that->hidden = static_cast<struct SDL_PrivateAudioData*>(SDL_malloc(sizeof *that->hidden));
|
|
+ if (!that->hidden)
|
|
+ return SDL_OutOfMemory();
|
|
+ SDL_zerop(that->hidden);
|
|
+
|
|
+ that->spec.freq = 44100;
|
|
+ that->spec.format = AUDIO_S16LSB;
|
|
+ that->spec.channels = 2;
|
|
+ that->spec.samples = 1024;
|
|
+
|
|
+ /* Calculate the final parameters for this audio specification */
|
|
+ SDL_CalculateAudioSpec(&that->spec);
|
|
+
|
|
+ /* Allocate mixing buffer */
|
|
+ if (!that->iscapture) {
|
|
+ that->hidden->mixlen = that->spec.size;
|
|
+ that->hidden->mixbuf = (Uint8*)SDL_malloc(that->hidden->mixlen);
|
|
+ if (!that->hidden->mixbuf)
|
|
+ return SDL_OutOfMemory();
|
|
+ SDL_memset(that->hidden->mixbuf, that->spec.silence, that->spec.size);
|
|
+ }
|
|
+
|
|
+ /* We're ready to rock and roll. :-) */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void SERENITYAUDIO_PlayDevice(_THIS)
|
|
+{
|
|
+ struct SDL_PrivateAudioData* h = that->hidden;
|
|
+
|
|
+ // We need to create our audio connection and event loop here, in order to register them with SDL's audio thread
|
|
+ if (!h->event_loop)
|
|
+ h->event_loop = make<Core::EventLoop>();
|
|
+ if (!h->client)
|
|
+ h->client = MUST(Audio::ConnectionToServer::try_create());
|
|
+
|
|
+ h->client->async_start_playback();
|
|
+
|
|
+ auto convert_i16_to_double = [](i16 input) -> auto {
|
|
+ return (static_cast<double>(input) - NumericLimits<i16>::min()) / NumericLimits<u16>::max() * 2. - 1.;
|
|
+ };
|
|
+
|
|
+ auto const sleep_spec = Time::from_nanoseconds(100).to_timespec();
|
|
+ auto input_buffer = reinterpret_cast<i16*>(h->mixbuf);
|
|
+ auto input_samples = h->mixlen / that->spec.channels / sizeof(i16);
|
|
+ size_t input_position = 0;
|
|
+
|
|
+ while (input_samples > 0) {
|
|
+ // Fill up the output buffer
|
|
+ auto const input_samples_to_process = min(input_samples, Audio::AUDIO_BUFFER_SIZE - output_buffer_samples_remaining);
|
|
+ for (size_t i = 0; i < input_samples_to_process; ++i) {
|
|
+ auto left = convert_i16_to_double(input_buffer[input_position]);
|
|
+ auto right = convert_i16_to_double(input_buffer[input_position + 1]);
|
|
+ output_buffer[output_buffer_samples_remaining + i] = Audio::Sample(left, right);
|
|
+ input_position += 2;
|
|
+ }
|
|
+ output_buffer_samples_remaining += input_samples_to_process;
|
|
+ input_samples -= input_samples_to_process;
|
|
+
|
|
+ // Stop if we don't have enough samples to fill a buffer
|
|
+ if (output_buffer_samples_remaining < Audio::AUDIO_BUFFER_SIZE)
|
|
+ break;
|
|
+
|
|
+ // Try to enqueue our output buffer
|
|
+ for (;;) {
|
|
+ auto enqueue_result = h->client->realtime_enqueue(output_buffer);
|
|
+ if (!enqueue_result.is_error())
|
|
+ break;
|
|
+ if (enqueue_result.error() != Audio::AudioQueue::QueueStatus::Full)
|
|
+ return;
|
|
+
|
|
+ nanosleep(&sleep_spec, nullptr);
|
|
+ }
|
|
+ output_buffer_samples_remaining = 0;
|
|
+ }
|
|
+
|
|
+ // Pump our event loop - should just be the IPC call to start playback
|
|
+ for (;;) {
|
|
+ auto number_of_events_pumped = h->event_loop->pump(Core::EventLoop::WaitMode::PollForEvents);
|
|
+ if (number_of_events_pumped == 0)
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static Uint8* SERENITYAUDIO_GetDeviceBuf(_THIS)
|
|
+{
|
|
+ return that->hidden->mixbuf;
|
|
+}
|
|
+
|
|
+static SDL_bool SERENITYAUDIO_Init(SDL_AudioDriverImpl* impl)
|
|
+{
|
|
+ /* Set the function pointers */
|
|
+ impl->OpenDevice = SERENITYAUDIO_OpenDevice;
|
|
+ impl->PlayDevice = SERENITYAUDIO_PlayDevice;
|
|
+ impl->GetDeviceBuf = SERENITYAUDIO_GetDeviceBuf;
|
|
+ impl->CloseDevice = SERENITYAUDIO_CloseDevice;
|
|
+
|
|
+ impl->AllowsArbitraryDeviceNames = SDL_TRUE;
|
|
+ impl->HasCaptureSupport = SDL_FALSE;
|
|
+ impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
|
|
+
|
|
+ return SDL_TRUE; // this audio target is available.
|
|
+}
|
|
+
|
|
+AudioBootStrap SERENITYAUDIO_bootstrap = {
|
|
+ "serenity", "Serenity using AudioServer", SERENITYAUDIO_Init, SDL_FALSE
|
|
+};
|
|
+
|
|
+#endif
|
|
diff --git a/src/audio/serenity/SDL_serenityaudio.h b/src/audio/serenity/SDL_serenityaudio.h
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..8d152ca843e732d2d5a8127fc191ca22ce690a83
|
|
--- /dev/null
|
|
+++ b/src/audio/serenity/SDL_serenityaudio.h
|
|
@@ -0,0 +1,38 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "../SDL_sysaudio.h"
|
|
+#include <AK/OwnPtr.h>
|
|
+#include <AK/RefPtr.h>
|
|
+#include <LibAudio/ConnectionToServer.h>
|
|
+#include <LibCore/EventLoop.h>
|
|
+
|
|
+#define _THIS SDL_AudioDevice* that
|
|
+
|
|
+struct SDL_PrivateAudioData {
|
|
+ RefPtr<Audio::ConnectionToServer> client;
|
|
+ OwnPtr<Core::EventLoop> event_loop;
|
|
+ Uint8* mixbuf { nullptr };
|
|
+ size_t mixlen { 0 };
|
|
+};
|
|
diff --git a/src/stdlib/SDL_stdlib.c b/src/stdlib/SDL_stdlib.c
|
|
index 2af18b1f05e1f1ce2c06de81d844bdb72777b640..fbef9e7f7987aea4dd66e2d4e54ba57c45c371b6 100644
|
|
--- a/src/stdlib/SDL_stdlib.c
|
|
+++ b/src/stdlib/SDL_stdlib.c
|
|
@@ -637,7 +637,7 @@ SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len)
|
|
#endif /* HAVE_MEMSET */
|
|
}
|
|
|
|
-#if defined(HAVE_CTYPE_H) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
|
+#if defined(HAVE_CTYPE_H) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && !defined(__serenity__)
|
|
int SDL_isblank(int x) { return isblank(x); }
|
|
#else
|
|
int SDL_isblank(int x) { return ((x) == ' ') || ((x) == '\t'); }
|
|
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
|
|
index 4ea7705e959b8a2d120b4d1c8599c93f450b7d9f..83b9bba4ff81ff7030f2f6fa2235c91641f18a22 100644
|
|
--- a/src/video/SDL_sysvideo.h
|
|
+++ b/src/video/SDL_sysvideo.h
|
|
@@ -470,6 +470,7 @@ extern VideoBootStrap OFFSCREEN_bootstrap;
|
|
extern VideoBootStrap NGAGE_bootstrap;
|
|
extern VideoBootStrap OS2DIVE_bootstrap;
|
|
extern VideoBootStrap OS2VMAN_bootstrap;
|
|
+extern VideoBootStrap SERENITYVIDEO_bootstrap;
|
|
|
|
/* Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work */
|
|
extern SDL_bool SDL_OnVideoThread(void);
|
|
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
|
|
index 21c516265f75b61ec11aeb50e5a8e6cad7a44dd0..2e765deecce851935434c17f662463607fc7fadf 100644
|
|
--- a/src/video/SDL_video.c
|
|
+++ b/src/video/SDL_video.c
|
|
@@ -128,6 +128,9 @@ static VideoBootStrap *bootstrap[] = {
|
|
&OS2DIVE_bootstrap,
|
|
&OS2VMAN_bootstrap,
|
|
#endif
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+ &SERENITYVIDEO_bootstrap,
|
|
+#endif
|
|
#if SDL_VIDEO_DRIVER_DUMMY
|
|
&DUMMY_bootstrap,
|
|
#if SDL_INPUT_LINUXEV
|
|
@@ -4258,6 +4261,10 @@ SDL_WM_SetIcon(SDL_Surface * icon, Uint8 * mask)
|
|
}
|
|
}
|
|
#endif
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+#include "serenity/SDL_serenitymessagebox.h"
|
|
+#endif
|
|
+
|
|
|
|
SDL_bool
|
|
SDL_GetWindowWMInfo(SDL_Window * window, struct SDL_SysWMinfo *info)
|
|
@@ -4543,6 +4550,12 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|
VITA_ShowMessageBox(messageboxdata, buttonid) == 0) {
|
|
retval = 0;
|
|
}
|
|
+#endif
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+ if (retval == -1 &&
|
|
+ SERENITY_ShowMessageBox(messageboxdata, buttonid) == 0) {
|
|
+ retval = 0;
|
|
+ }
|
|
#endif
|
|
if (retval == -1) {
|
|
const char *error = SDL_GetError();
|
|
diff --git a/src/video/serenity/SDL_serenityevents.cpp b/src/video/serenity/SDL_serenityevents.cpp
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..04cbf21ce74fb11e6713ba3a4beaad808751e80b
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityevents.cpp
|
|
@@ -0,0 +1,52 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+#define AK_DONT_REPLACE_STD
|
|
+
|
|
+#include "../../events/SDL_events_c.h"
|
|
+
|
|
+#include "SDL_serenityvideo.h"
|
|
+#include "SDL_serenityevents_c.h"
|
|
+#include "SDL_timer.h"
|
|
+
|
|
+#include <LibCore/EventLoop.h>
|
|
+
|
|
+void
|
|
+SERENITY_PumpEvents(_THIS)
|
|
+{
|
|
+ auto& loop = Core::EventLoop::current();
|
|
+ if (loop.was_exit_requested())
|
|
+ exit(0);
|
|
+
|
|
+ auto const event_loop_timeout_ms = SDL_GetTicks() + 100;
|
|
+ while (loop.pump(Core::EventLoop::WaitMode::PollForEvents) > 0) {
|
|
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), event_loop_timeout_ms))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenityevents_c.h b/src/video/serenity/SDL_serenityevents_c.h
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..89e9e919e319c701144da8f6d73bbb2ea519758d
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityevents_c.h
|
|
@@ -0,0 +1,33 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+
|
|
+#ifndef SDL_serenityevents_c_h_
|
|
+#define SDL_serenityevents_c_h_
|
|
+
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#include "SDL_serenityvideo.h"
|
|
+
|
|
+extern void SERENITY_PumpEvents(_THIS);
|
|
+
|
|
+#endif /* SDL_serenityevents_c_h_ */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenitymessagebox.cpp b/src/video/serenity/SDL_serenitymessagebox.cpp
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..fe41a8beecc4f1e6b9cc17831d53b43c05f167f1
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymessagebox.cpp
|
|
@@ -0,0 +1,40 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+ */
|
|
+
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+# define AK_DONT_REPLACE_STD
|
|
+
|
|
+# include "SDL_messagebox.h"
|
|
+# include "SDL_serenitymessagebox.h"
|
|
+
|
|
+# include <LibGUI/MessageBox.h>
|
|
+
|
|
+extern "C" int SERENITY_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|
+{
|
|
+ GUI::MessageBox::show(nullptr, { messageboxdata->message, strlen(messageboxdata->message) }, { messageboxdata->title, strlen(messageboxdata->title) });
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenitymessagebox.h b/src/video/serenity/SDL_serenitymessagebox.h
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..34e607783310310ac8956bccf584b5ab12d45907
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymessagebox.h
|
|
@@ -0,0 +1,38 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#ifndef SDL_serenitymessagebox_h_
|
|
+#define SDL_serenitymessagebox_h_
|
|
+
|
|
+#ifdef __cplusplus
|
|
+extern "C" {
|
|
+#endif
|
|
+
|
|
+int SERENITY_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
|
+
|
|
+#ifdef __cplusplus
|
|
+}
|
|
+#endif
|
|
+
|
|
+#endif /* SDL_serenitymessagebox_h_ */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenitymouse.cpp b/src/video/serenity/SDL_serenitymouse.cpp
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..5d0cb527a03dc0ac775ed68d66451495bf993ec6
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymouse.cpp
|
|
@@ -0,0 +1,142 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+#define AK_DONT_REPLACE_STD
|
|
+
|
|
+/*
|
|
+ * SDL includes:
|
|
+ */
|
|
+extern "C" {
|
|
+#include "../../events/SDL_mouse_c.h"
|
|
+#include "../../events/SDL_touch_c.h"
|
|
+#include "../SDL_sysvideo.h"
|
|
+#include "SDL_events.h"
|
|
+}
|
|
+
|
|
+#include "SDL_serenitymouse.h"
|
|
+#include "SDL_serenityvideo.h"
|
|
+
|
|
+#include <LibGfx/StandardCursor.h>
|
|
+
|
|
+struct SerenityCursorData final {
|
|
+ Gfx::StandardCursor cursor_type;
|
|
+};
|
|
+
|
|
+static SDL_Cursor*
|
|
+SERENITY_CreateSystemCursor(SDL_SystemCursor id)
|
|
+{
|
|
+ auto cursor = static_cast<SDL_Cursor*>(SDL_calloc(1, sizeof(SDL_Cursor)));
|
|
+ if (!cursor)
|
|
+ SDL_OutOfMemory();
|
|
+
|
|
+ auto cursor_data = static_cast<SerenityCursorData*>(SDL_calloc(1, sizeof(SerenityCursorData)));
|
|
+ if (!cursor_data)
|
|
+ SDL_OutOfMemory();
|
|
+ cursor->driverdata = static_cast<void*>(cursor_data);
|
|
+
|
|
+ switch(id)
|
|
+ {
|
|
+ case SDL_SYSTEM_CURSOR_ARROW: cursor_data->cursor_type = Gfx::StandardCursor::Arrow; break;
|
|
+ case SDL_SYSTEM_CURSOR_IBEAM: cursor_data->cursor_type = Gfx::StandardCursor::IBeam; break;
|
|
+ case SDL_SYSTEM_CURSOR_WAIT: cursor_data->cursor_type = Gfx::StandardCursor::Wait; break;
|
|
+ case SDL_SYSTEM_CURSOR_CROSSHAIR: cursor_data->cursor_type = Gfx::StandardCursor::Crosshair; break;
|
|
+ case SDL_SYSTEM_CURSOR_WAITARROW: cursor_data->cursor_type = Gfx::StandardCursor::Wait; break;
|
|
+ case SDL_SYSTEM_CURSOR_SIZENWSE: cursor_data->cursor_type = Gfx::StandardCursor::ResizeDiagonalTLBR; break;
|
|
+ case SDL_SYSTEM_CURSOR_SIZENESW: cursor_data->cursor_type = Gfx::StandardCursor::ResizeDiagonalBLTR; break;
|
|
+ case SDL_SYSTEM_CURSOR_SIZEWE: cursor_data->cursor_type = Gfx::StandardCursor::ResizeHorizontal; break;
|
|
+ case SDL_SYSTEM_CURSOR_SIZENS: cursor_data->cursor_type = Gfx::StandardCursor::ResizeVertical; break;
|
|
+ case SDL_SYSTEM_CURSOR_SIZEALL: cursor_data->cursor_type = Gfx::StandardCursor::Move; break;
|
|
+ case SDL_SYSTEM_CURSOR_NO: cursor_data->cursor_type = Gfx::StandardCursor::Disallowed; break;
|
|
+ case SDL_SYSTEM_CURSOR_HAND: cursor_data->cursor_type = Gfx::StandardCursor::Hand; break;
|
|
+ default:
|
|
+ SDL_assert(0);
|
|
+ return nullptr;
|
|
+ }
|
|
+ return cursor;
|
|
+}
|
|
+
|
|
+static SDL_Cursor*
|
|
+SERENITY_CreateDefaultCursor()
|
|
+{
|
|
+ return SERENITY_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
|
|
+}
|
|
+
|
|
+static void
|
|
+SERENITY_FreeCursor(SDL_Cursor* cursor)
|
|
+{
|
|
+ if (cursor->driverdata)
|
|
+ SDL_free(cursor->driverdata);
|
|
+ SDL_free(cursor);
|
|
+}
|
|
+
|
|
+static int
|
|
+SERENITY_ShowCursor(SDL_Cursor* cursor)
|
|
+{
|
|
+ auto focused_window = SDL_GetMouseFocus();
|
|
+ if (!focused_window)
|
|
+ return -1;
|
|
+
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(focused_window);
|
|
+
|
|
+ // Hide the cursor
|
|
+ if (cursor == nullptr) {
|
|
+ platform_window->window()->set_cursor(Gfx::StandardCursor::Hidden);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ auto cursor_data = static_cast<SerenityCursorData*>(cursor->driverdata);
|
|
+ if (!cursor_data)
|
|
+ return -1;
|
|
+
|
|
+ platform_window->window()->set_cursor(cursor_data->cursor_type);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void
|
|
+SERENITY_InitMouse(_THIS)
|
|
+{
|
|
+ dbgln("SERENITY_InitMouse");
|
|
+
|
|
+ auto mouse = SDL_GetMouse();
|
|
+
|
|
+ mouse->CreateSystemCursor = SERENITY_CreateSystemCursor;
|
|
+ mouse->ShowCursor = SERENITY_ShowCursor;
|
|
+ mouse->FreeCursor = SERENITY_FreeCursor;
|
|
+
|
|
+ // FIXME: implement below methods
|
|
+ //mouse->CreateCursor = ...;
|
|
+ //mouse->WarpMouse = ...;
|
|
+ //mouse->SetRelativeMouseMode = ...;
|
|
+
|
|
+ SDL_SetDefaultCursor(SERENITY_CreateDefaultCursor());
|
|
+}
|
|
+
|
|
+void
|
|
+SERENITY_QuitMouse(_THIS)
|
|
+{
|
|
+ dbgln("SERENITY_QuitMouse");
|
|
+}
|
|
+
|
|
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenitymouse.h b/src/video/serenity/SDL_serenitymouse.h
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..039f0361b3d1b248e218ea69495f58e52ad532c6
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenitymouse.h
|
|
@@ -0,0 +1,39 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "SDL_config.h"
|
|
+
|
|
+#ifndef SDL_serenitymouse_h_
|
|
+#define SDL_serenitymouse_h_
|
|
+
|
|
+#ifdef __cplusplus
|
|
+extern "C" {
|
|
+#endif
|
|
+
|
|
+extern void SERENITY_InitMouse(_THIS);
|
|
+extern void SERENITY_QuitMouse(_THIS);
|
|
+
|
|
+#ifdef __cplusplus
|
|
+}
|
|
+#endif
|
|
+
|
|
+#endif /* SDL_serenitymouse_h_ */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenityvideo.cpp b/src/video/serenity/SDL_serenityvideo.cpp
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f26040845dd05f425ba464af385e133c6c3eab93
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityvideo.cpp
|
|
@@ -0,0 +1,607 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+ */
|
|
+extern "C" {
|
|
+
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#if SDL_VIDEO_DRIVER_SERENITY
|
|
+# define AK_DONT_REPLACE_STD
|
|
+
|
|
+# include "../../events/SDL_events_c.h"
|
|
+# include "../SDL_pixels_c.h"
|
|
+# include "../SDL_sysvideo.h"
|
|
+# include "SDL_mouse.h"
|
|
+# include "SDL_video.h"
|
|
+}
|
|
+
|
|
+# include "SDL_serenityevents_c.h"
|
|
+# include "SDL_serenitymouse.h"
|
|
+# include "SDL_serenityvideo.h"
|
|
+
|
|
+# include <LibCore/EventLoop.h>
|
|
+# include <LibGUI/Application.h>
|
|
+# include <LibGUI/Desktop.h>
|
|
+# include <LibGUI/Painter.h>
|
|
+# include <LibGUI/Widget.h>
|
|
+# include <LibGUI/Window.h>
|
|
+# include <LibGfx/Bitmap.h>
|
|
+# include <dlfcn.h>
|
|
+
|
|
+static SDL_Scancode scancode_map[] = {
|
|
+ SDL_SCANCODE_UNKNOWN,
|
|
+ SDL_SCANCODE_ESCAPE,
|
|
+ SDL_SCANCODE_TAB,
|
|
+ SDL_SCANCODE_BACKSPACE,
|
|
+ SDL_SCANCODE_RETURN,
|
|
+ SDL_SCANCODE_INSERT,
|
|
+ SDL_SCANCODE_DELETE,
|
|
+ SDL_SCANCODE_PRINTSCREEN,
|
|
+ SDL_SCANCODE_SYSREQ,
|
|
+ SDL_SCANCODE_HOME,
|
|
+ SDL_SCANCODE_END,
|
|
+ SDL_SCANCODE_LEFT,
|
|
+ SDL_SCANCODE_UP,
|
|
+ SDL_SCANCODE_RIGHT,
|
|
+ SDL_SCANCODE_DOWN,
|
|
+ SDL_SCANCODE_PAGEUP,
|
|
+ SDL_SCANCODE_PAGEDOWN,
|
|
+ SDL_SCANCODE_LSHIFT,
|
|
+ SDL_SCANCODE_RSHIFT,
|
|
+ SDL_SCANCODE_LCTRL,
|
|
+ SDL_SCANCODE_LALT,
|
|
+ SDL_SCANCODE_CAPSLOCK,
|
|
+ SDL_SCANCODE_NUMLOCKCLEAR,
|
|
+ SDL_SCANCODE_SCROLLLOCK,
|
|
+ SDL_SCANCODE_F1,
|
|
+ SDL_SCANCODE_F2,
|
|
+ SDL_SCANCODE_F3,
|
|
+ SDL_SCANCODE_F4,
|
|
+ SDL_SCANCODE_F5,
|
|
+ SDL_SCANCODE_F6,
|
|
+ SDL_SCANCODE_F7,
|
|
+ SDL_SCANCODE_F8,
|
|
+ SDL_SCANCODE_F9,
|
|
+ SDL_SCANCODE_F10,
|
|
+ SDL_SCANCODE_F11,
|
|
+ SDL_SCANCODE_F12,
|
|
+ SDL_SCANCODE_SPACE,
|
|
+ SDL_SCANCODE_1,
|
|
+ SDL_SCANCODE_APOSTROPHE,
|
|
+ SDL_SCANCODE_3,
|
|
+ SDL_SCANCODE_4,
|
|
+ SDL_SCANCODE_5,
|
|
+ SDL_SCANCODE_7,
|
|
+ SDL_SCANCODE_APOSTROPHE,
|
|
+ SDL_SCANCODE_9,
|
|
+ SDL_SCANCODE_0,
|
|
+ SDL_SCANCODE_8,
|
|
+ SDL_SCANCODE_EQUALS,
|
|
+ SDL_SCANCODE_COMMA,
|
|
+ SDL_SCANCODE_MINUS,
|
|
+ SDL_SCANCODE_PERIOD,
|
|
+ SDL_SCANCODE_SLASH,
|
|
+ SDL_SCANCODE_0,
|
|
+ SDL_SCANCODE_1,
|
|
+ SDL_SCANCODE_2,
|
|
+ SDL_SCANCODE_3,
|
|
+ SDL_SCANCODE_4,
|
|
+ SDL_SCANCODE_5,
|
|
+ SDL_SCANCODE_6,
|
|
+ SDL_SCANCODE_7,
|
|
+ SDL_SCANCODE_8,
|
|
+ SDL_SCANCODE_9,
|
|
+ SDL_SCANCODE_SEMICOLON,
|
|
+ SDL_SCANCODE_SEMICOLON,
|
|
+ SDL_SCANCODE_COMMA,
|
|
+ SDL_SCANCODE_EQUALS,
|
|
+ SDL_SCANCODE_PERIOD,
|
|
+ SDL_SCANCODE_SLASH,
|
|
+ SDL_SCANCODE_2,
|
|
+ SDL_SCANCODE_A,
|
|
+ SDL_SCANCODE_B,
|
|
+ SDL_SCANCODE_C,
|
|
+ SDL_SCANCODE_D,
|
|
+ SDL_SCANCODE_E,
|
|
+ SDL_SCANCODE_F,
|
|
+ SDL_SCANCODE_G,
|
|
+ SDL_SCANCODE_H,
|
|
+ SDL_SCANCODE_I,
|
|
+ SDL_SCANCODE_J,
|
|
+ SDL_SCANCODE_K,
|
|
+ SDL_SCANCODE_L,
|
|
+ SDL_SCANCODE_M,
|
|
+ SDL_SCANCODE_N,
|
|
+ SDL_SCANCODE_O,
|
|
+ SDL_SCANCODE_P,
|
|
+ SDL_SCANCODE_Q,
|
|
+ SDL_SCANCODE_R,
|
|
+ SDL_SCANCODE_S,
|
|
+ SDL_SCANCODE_T,
|
|
+ SDL_SCANCODE_U,
|
|
+ SDL_SCANCODE_V,
|
|
+ SDL_SCANCODE_W,
|
|
+ SDL_SCANCODE_X,
|
|
+ SDL_SCANCODE_Y,
|
|
+ SDL_SCANCODE_Z,
|
|
+ SDL_SCANCODE_LEFTBRACKET,
|
|
+ SDL_SCANCODE_RIGHTBRACKET,
|
|
+ SDL_SCANCODE_BACKSLASH,
|
|
+ SDL_SCANCODE_6,
|
|
+ SDL_SCANCODE_MINUS,
|
|
+ SDL_SCANCODE_LEFTBRACKET,
|
|
+ SDL_SCANCODE_RIGHTBRACKET,
|
|
+ SDL_SCANCODE_BACKSLASH,
|
|
+ SDL_SCANCODE_GRAVE,
|
|
+ SDL_SCANCODE_GRAVE,
|
|
+ SDL_SCANCODE_UNKNOWN,
|
|
+};
|
|
+
|
|
+/* Initialization/Query functions */
|
|
+static int SERENITY_VideoInit(_THIS);
|
|
+static int SERENITY_SetDisplayMode(_THIS, SDL_VideoDisplay* display,
|
|
+ SDL_DisplayMode* mode);
|
|
+static void SERENITY_VideoQuit(_THIS);
|
|
+
|
|
+/* SERENITY driver bootstrap functions */
|
|
+
|
|
+static int SERENITY_Available(void) { return (1); }
|
|
+
|
|
+static void SERENITY_DeleteDevice(SDL_VideoDevice* device)
|
|
+{
|
|
+ dbgln("SERENITY_DeleteDevice");
|
|
+ SDL_free(device);
|
|
+}
|
|
+
|
|
+extern int Serenity_CreateWindow(_THIS, SDL_Window* window);
|
|
+extern void Serenity_ShowWindow(_THIS, SDL_Window* window);
|
|
+extern void Serenity_HideWindow(_THIS, SDL_Window* window);
|
|
+extern void Serenity_SetWindowTitle(_THIS, SDL_Window* window);
|
|
+extern void Serenity_SetWindowSize(_THIS, SDL_Window* window);
|
|
+extern void Serenity_SetWindowFullscreen(_THIS, SDL_Window* window,
|
|
+ SDL_VideoDisplay* display,
|
|
+ SDL_bool fullscreen);
|
|
+extern void Serenity_SetWindowIcon(_THIS, SDL_Window* window, SDL_Surface* icon);
|
|
+extern void Serenity_DestroyWindow(_THIS, SDL_Window* window);
|
|
+extern int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window,
|
|
+ Uint32* format, void** pixels,
|
|
+ int* pitch);
|
|
+extern int Serenity_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
|
|
+ const SDL_Rect* rects,
|
|
+ int numrects);
|
|
+extern void Serenity_DestroyWindowFramebuffer(_THIS, SDL_Window* window);
|
|
+extern SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window);
|
|
+extern void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context);
|
|
+extern void* Serenity_GL_GetProcAddress(_THIS, const char* proc);
|
|
+extern int Serenity_GL_LoadLibrary(_THIS, const char* path);
|
|
+extern int Serenity_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context);
|
|
+extern int Serenity_GL_SwapWindow(_THIS, SDL_Window* window);
|
|
+
|
|
+static SDL_VideoDevice* SERENITY_CreateDevice(void)
|
|
+{
|
|
+ SDL_VideoDevice* device;
|
|
+
|
|
+ /* Initialize all variables that we clean on shutdown */
|
|
+ device = (SDL_VideoDevice*)SDL_calloc(1, sizeof(SDL_VideoDevice));
|
|
+ if (!device) {
|
|
+ SDL_OutOfMemory();
|
|
+ return (0);
|
|
+ }
|
|
+ device->is_dummy = SDL_FALSE;
|
|
+
|
|
+ /* Set the function pointers */
|
|
+ device->VideoInit = SERENITY_VideoInit;
|
|
+ device->VideoQuit = SERENITY_VideoQuit;
|
|
+ device->SetDisplayMode = SERENITY_SetDisplayMode;
|
|
+ device->PumpEvents = SERENITY_PumpEvents;
|
|
+
|
|
+ device->CreateWindowFramebuffer = Serenity_CreateWindowFramebuffer;
|
|
+ device->UpdateWindowFramebuffer = Serenity_UpdateWindowFramebuffer;
|
|
+ device->DestroyWindowFramebuffer = Serenity_DestroyWindowFramebuffer;
|
|
+ device->CreateSDLWindow = Serenity_CreateWindow;
|
|
+ device->ShowWindow = Serenity_ShowWindow;
|
|
+ device->HideWindow = Serenity_HideWindow;
|
|
+ device->SetWindowTitle = Serenity_SetWindowTitle;
|
|
+ device->SetWindowSize = Serenity_SetWindowSize;
|
|
+ device->SetWindowFullscreen = Serenity_SetWindowFullscreen;
|
|
+ device->SetWindowIcon = Serenity_SetWindowIcon;
|
|
+ device->DestroyWindow = Serenity_DestroyWindow;
|
|
+
|
|
+ device->GL_CreateContext = Serenity_GL_CreateContext;
|
|
+ device->GL_DeleteContext = Serenity_GL_DeleteContext;
|
|
+ device->GL_GetProcAddress = Serenity_GL_GetProcAddress;
|
|
+ device->GL_LoadLibrary = Serenity_GL_LoadLibrary;
|
|
+ device->GL_MakeCurrent = Serenity_GL_MakeCurrent;
|
|
+ device->GL_SwapWindow = Serenity_GL_SwapWindow;
|
|
+
|
|
+ device->free = SERENITY_DeleteDevice;
|
|
+
|
|
+ Serenity_GL_LoadLibrary(device, nullptr);
|
|
+
|
|
+ return device;
|
|
+}
|
|
+
|
|
+VideoBootStrap SERENITYVIDEO_bootstrap = { "serenity", "SDL serenity video driver", SERENITY_CreateDevice };
|
|
+
|
|
+static RefPtr<GUI::Application> g_app;
|
|
+
|
|
+int SERENITY_VideoInit(_THIS)
|
|
+{
|
|
+ dbgln("{}: Initialising SDL application", __FUNCTION__);
|
|
+
|
|
+ if (!g_app) {
|
|
+ g_app = GUI::Application::construct(0, nullptr);
|
|
+ g_app->set_quit_when_last_window_deleted(false);
|
|
+ }
|
|
+
|
|
+ SERENITY_InitMouse(_this);
|
|
+
|
|
+ // We only add the active desktop resolution until we properly support multiple
|
|
+ // fullscreen resolutions
|
|
+ auto desktop_rect = GUI::Desktop::the().rect();
|
|
+
|
|
+ SDL_DisplayMode mode;
|
|
+ mode.format = SDL_PIXELFORMAT_RGB888;
|
|
+ mode.w = desktop_rect.width();
|
|
+ mode.h = desktop_rect.height();
|
|
+ mode.refresh_rate = 60;
|
|
+ mode.driverdata = nullptr;
|
|
+
|
|
+ if (SDL_AddBasicVideoDisplay(&mode) < 0)
|
|
+ return -1;
|
|
+
|
|
+ SDL_AddDisplayMode(&_this->displays[0], &mode);
|
|
+
|
|
+ /* We're done! */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int SERENITY_SetDisplayMode(_THIS, SDL_VideoDisplay* display,
|
|
+ SDL_DisplayMode* mode)
|
|
+{
|
|
+ dbgln("SERENITY_SetDisplayMode");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void SERENITY_VideoQuit(_THIS)
|
|
+{
|
|
+ dbgln("SERENITY_VideoQuit");
|
|
+ SERENITY_QuitMouse(_this);
|
|
+}
|
|
+
|
|
+SerenitySDLWidget::SerenitySDLWidget(SDL_Window* sdl_window)
|
|
+ : m_sdl_window(sdl_window)
|
|
+{
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::paint_event(GUI::PaintEvent& event)
|
|
+{
|
|
+ if (!m_buffer)
|
|
+ return;
|
|
+
|
|
+ GUI::Painter painter(*this);
|
|
+ painter.add_clip_rect(event.rect());
|
|
+ painter.blit(event.rect().location(), *m_buffer, event.rect());
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::resize_event(GUI::ResizeEvent&)
|
|
+{
|
|
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_RESIZED, width(), height());
|
|
+}
|
|
+void SerenitySDLWidget::show_event(GUI::ShowEvent&)
|
|
+{
|
|
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_SHOWN, 0, 0);
|
|
+}
|
|
+void SerenitySDLWidget::hide_event(GUI::HideEvent&)
|
|
+{
|
|
+ SDL_SendWindowEvent(m_sdl_window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
|
|
+}
|
|
+
|
|
+static int map_button(GUI::MouseButton button)
|
|
+{
|
|
+ switch (button) {
|
|
+ case GUI::MouseButton::Primary:
|
|
+ return SDL_BUTTON_LEFT;
|
|
+ case GUI::MouseButton::Middle:
|
|
+ return SDL_BUTTON_MIDDLE;
|
|
+ case GUI::MouseButton::Secondary:
|
|
+ return SDL_BUTTON_RIGHT;
|
|
+ case GUI::MouseButton::Forward:
|
|
+ return SDL_BUTTON_X1;
|
|
+ case GUI::MouseButton::Backward:
|
|
+ return SDL_BUTTON_X2;
|
|
+ }
|
|
+
|
|
+ VERIFY_NOT_REACHED();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::mousedown_event(GUI::MouseEvent& event)
|
|
+{
|
|
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
|
|
+ SDL_SendMouseButton(m_sdl_window, 0, SDL_PRESSED, map_button(event.button()));
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::mousemove_event(GUI::MouseEvent& event)
|
|
+{
|
|
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::mouseup_event(GUI::MouseEvent& event)
|
|
+{
|
|
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
|
|
+ SDL_SendMouseButton(m_sdl_window, 0, SDL_RELEASED, map_button(event.button()));
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::mousewheel_event(GUI::MouseEvent& event)
|
|
+{
|
|
+ SDL_SendMouseMotion(m_sdl_window, 0, 0, event.x(), event.y());
|
|
+ SDL_SendMouseWheel(m_sdl_window, 0, (float)event.wheel_raw_delta_x(), -(float)event.wheel_raw_delta_y(), SDL_MOUSEWHEEL_NORMAL);
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::keydown_event(GUI::KeyEvent& event)
|
|
+{
|
|
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode_map[event.key()]);
|
|
+ auto text = event.text();
|
|
+ if (!text.is_empty())
|
|
+ SDL_SendKeyboardText(text.characters());
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::keyup_event(GUI::KeyEvent& event)
|
|
+{
|
|
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode_map[event.key()]);
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::enter_event(Core::Event&)
|
|
+{
|
|
+ SDL_SetMouseFocus(m_sdl_window);
|
|
+}
|
|
+
|
|
+void SerenitySDLWidget::leave_event(Core::Event&)
|
|
+{
|
|
+ SDL_SetMouseFocus(nullptr);
|
|
+}
|
|
+
|
|
+int Serenity_CreateWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ dbgln("{}: Creating new window of size {}x{}", __FUNCTION__, window->w, window->h);
|
|
+
|
|
+ auto w = new SerenityPlatformWindow(window);
|
|
+ window->driverdata = w;
|
|
+ w->window()->set_double_buffering_enabled(false);
|
|
+ w->widget()->set_fill_with_background_color(false);
|
|
+ w->window()->set_main_widget(w->widget());
|
|
+ w->window()->on_close_request = [window] {
|
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
|
+ return GUI::Window::CloseRequestDecision::StayOpen;
|
|
+ };
|
|
+ w->window()->on_active_window_change = [window](bool is_active_window) {
|
|
+ SDL_SetKeyboardFocus(is_active_window ? window : nullptr);
|
|
+ };
|
|
+ w->window()->on_input_preemption_change = [window](bool is_preempted) {
|
|
+ SDL_SetKeyboardFocus(is_preempted ? nullptr : window);
|
|
+ };
|
|
+ SERENITY_PumpEvents(_this);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void Serenity_ShowWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ SerenityPlatformWindow::from_sdl_window(window)->window()->show();
|
|
+}
|
|
+
|
|
+void Serenity_HideWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ SerenityPlatformWindow::from_sdl_window(window)->window()->hide();
|
|
+}
|
|
+
|
|
+void Serenity_SetWindowTitle(_THIS, SDL_Window* window)
|
|
+{
|
|
+ SerenityPlatformWindow::from_sdl_window(window)->window()->set_title(window->title);
|
|
+}
|
|
+
|
|
+void Serenity_SetWindowSize(_THIS, SDL_Window* window)
|
|
+{
|
|
+ SerenityPlatformWindow::from_sdl_window(window)->window()->resize(window->w, window->h);
|
|
+}
|
|
+
|
|
+void Serenity_SetWindowFullscreen(_THIS, SDL_Window* window,
|
|
+ SDL_VideoDisplay* display,
|
|
+ SDL_bool fullscreen)
|
|
+{
|
|
+ dbgln("Attempting to set SDL Window fullscreen to {}", (bool)fullscreen);
|
|
+ SerenityPlatformWindow::from_sdl_window(window)->window()->set_fullscreen(fullscreen);
|
|
+}
|
|
+
|
|
+static Gfx::Color get_color_from_sdl_pixel(SDL_PixelFormat const& format, u32 pixel)
|
|
+{
|
|
+ u8 r = ((pixel & format.Rmask) >> format.Rshift) << format.Rloss;
|
|
+ u8 g = ((pixel & format.Gmask) >> format.Gshift) << format.Gloss;
|
|
+ u8 b = ((pixel & format.Bmask) >> format.Bshift) << format.Bloss;
|
|
+ u8 a = ((pixel & format.Amask) >> format.Ashift) << format.Aloss;
|
|
+ return {r, g, b, a};
|
|
+}
|
|
+
|
|
+static RefPtr<Gfx::Bitmap> create_bitmap_from_surface(SDL_Surface& icon)
|
|
+{
|
|
+ auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, {icon.w, icon.h});
|
|
+ if (bitmap_or_error.is_error())
|
|
+ return {};
|
|
+ auto bitmap = bitmap_or_error.release_value();
|
|
+
|
|
+ SDL_LockSurface(&icon);
|
|
+
|
|
+ auto const& pixel_format = *icon.format;
|
|
+ auto pixels = static_cast<u32*>(icon.pixels);
|
|
+ size_t offset = 0;
|
|
+ switch (pixel_format.format) {
|
|
+ case SDL_PIXELFORMAT_ARGB8888:
|
|
+ for (size_t y = 0; y < icon.h; ++y) {
|
|
+ for (size_t x = 0; x < icon.w; ++x) {
|
|
+ bitmap->set_pixel({x, y}, get_color_from_sdl_pixel(pixel_format, pixels[offset]));
|
|
+ ++offset;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ warnln("Unable to convert SDL_Surface with format {} to bitmap", SDL_GetPixelFormatName(pixel_format.format));
|
|
+ }
|
|
+
|
|
+ SDL_UnlockSurface(&icon);
|
|
+
|
|
+ return bitmap;
|
|
+}
|
|
+
|
|
+void Serenity_SetWindowIcon(_THIS, SDL_Window* window, SDL_Surface* icon)
|
|
+{
|
|
+ auto serenity_window = SerenityPlatformWindow::from_sdl_window(window)->window();
|
|
+ if (!icon) {
|
|
+ serenity_window->set_icon(nullptr);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ auto icon_bitmap = create_bitmap_from_surface(*icon);
|
|
+ if (icon_bitmap)
|
|
+ serenity_window->set_icon(icon_bitmap);
|
|
+}
|
|
+
|
|
+void Serenity_DestroyWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ delete platform_window;
|
|
+ window->driverdata = nullptr;
|
|
+}
|
|
+
|
|
+int Serenity_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
|
|
+ void** pixels, int* pitch)
|
|
+{
|
|
+ dbgln("{}: Creating a new framebuffer of size {}x{}", __FUNCTION__, window->w, window->h);
|
|
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ *format = SDL_PIXELFORMAT_RGB888;
|
|
+ auto bitmap_or_error = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, {window->w, window->h});
|
|
+ if (bitmap_or_error.is_error())
|
|
+ return SDL_OutOfMemory();
|
|
+ win->widget()->m_buffer = bitmap_or_error.release_value();
|
|
+ *pitch = win->widget()->m_buffer->pitch();
|
|
+ *pixels = win->widget()->m_buffer->scanline(0);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int Serenity_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
|
|
+ const SDL_Rect* rects, int numrects)
|
|
+{
|
|
+ auto win = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ for (int i = 0; i < numrects; i++) {
|
|
+ win->widget()->update(Gfx::IntRect(rects[i].x, rects[i].y, rects[i].w, rects[i].h));
|
|
+ }
|
|
+ SERENITY_PumpEvents(_this);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void Serenity_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto widget = SerenityPlatformWindow::from_sdl_window(window)->widget();
|
|
+ dbgln("{}: Destroy framebuffer {}", __FUNCTION__, widget->m_buffer->size());
|
|
+ widget->m_buffer = nullptr;
|
|
+}
|
|
+
|
|
+SDL_GLContext Serenity_GL_CreateContext(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
|
|
+
|
|
+ Uint32 format;
|
|
+ void* pixels;
|
|
+ int pitch;
|
|
+ Serenity_CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch);
|
|
+
|
|
+ auto gl_context_or_error = GL::create_context(*platform_window->widget()->m_buffer);
|
|
+ if (gl_context_or_error.is_error()) {
|
|
+ SDL_SetError("Failed to initialize the GL context");
|
|
+ return nullptr;
|
|
+ }
|
|
+ auto gl_context = gl_context_or_error.release_value();
|
|
+ auto serenity_gl_context = new SerenityGLContext(move(gl_context));
|
|
+ platform_window->set_serenity_gl_context(serenity_gl_context);
|
|
+ GL::make_context_current(&serenity_gl_context->gl_context());
|
|
+ return serenity_gl_context;
|
|
+}
|
|
+
|
|
+void Serenity_GL_DeleteContext(_THIS, SDL_GLContext context)
|
|
+{
|
|
+ auto platform_context = static_cast<SerenityGLContext*>(context);
|
|
+ delete platform_context;
|
|
+}
|
|
+
|
|
+int Serenity_GL_LoadLibrary(_THIS, const char* path)
|
|
+{
|
|
+ if (_this->gl_config.driver_loaded) {
|
|
+ SDL_SetError("OpenGL library is already loaded");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ _this->gl_config.dll_handle = dlopen("libgl.so.serenity", RTLD_LAZY | RTLD_LOCAL);
|
|
+ if (!_this->gl_config.dll_handle) {
|
|
+ dbgln("Could not load OpenGL library: {}", dlerror());
|
|
+ _this->gl_config.driver_loaded = SDL_FALSE;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ _this->gl_config.driver_loaded = SDL_TRUE;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void* Serenity_GL_GetProcAddress(_THIS, const char* proc)
|
|
+{
|
|
+ if (!_this->gl_config.dll_handle) {
|
|
+ SDL_SetError("OpenGL library not available");
|
|
+ return nullptr;
|
|
+ }
|
|
+ auto* res = dlsym(_this->gl_config.dll_handle, proc);
|
|
+ dbgln("GetProcAddress: {} -> {}", proc, res);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+int Serenity_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
|
|
+{
|
|
+ if (!window || !context)
|
|
+ return 0;
|
|
+
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ auto serenity_gl_context = static_cast<SerenityGLContext*>(context);
|
|
+ platform_window->set_serenity_gl_context(serenity_gl_context);
|
|
+ GL::make_context_current(&serenity_gl_context->gl_context());
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int Serenity_GL_SwapWindow(_THIS, SDL_Window* window)
|
|
+{
|
|
+ auto platform_window = SerenityPlatformWindow::from_sdl_window(window);
|
|
+ if (platform_window->serenity_gl_context())
|
|
+ platform_window->serenity_gl_context()->gl_context().present();
|
|
+
|
|
+ platform_window->widget()->repaint();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif /* SDL_VIDEO_DRIVER_SERENITY */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|
|
diff --git a/src/video/serenity/SDL_serenityvideo.h b/src/video/serenity/SDL_serenityvideo.h
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f74e1bd981734caf023b77a9b9fa30c46be40e4c
|
|
--- /dev/null
|
|
+++ b/src/video/serenity/SDL_serenityvideo.h
|
|
@@ -0,0 +1,101 @@
|
|
+/*
|
|
+ Simple DirectMedia Layer
|
|
+ Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
|
+
|
|
+ This software is provided 'as-is', without any express or implied
|
|
+ warranty. In no event will the authors be held liable for any damages
|
|
+ arising from the use of this software.
|
|
+
|
|
+ Permission is granted to anyone to use this software for any purpose,
|
|
+ including commercial applications, and to alter it and redistribute it
|
|
+ freely, subject to the following restrictions:
|
|
+
|
|
+ 1. The origin of this software must not be misrepresented; you must not
|
|
+ claim that you wrote the original software. If you use this software
|
|
+ in a product, an acknowledgment in the product documentation would be
|
|
+ appreciated but is not required.
|
|
+ 2. Altered source versions must be plainly marked as such, and must not be
|
|
+ misrepresented as being the original software.
|
|
+ 3. This notice may not be removed or altered from any source distribution.
|
|
+*/
|
|
+#include "../../SDL_internal.h"
|
|
+
|
|
+#ifndef SDL_serenityvideo_h_
|
|
+#define SDL_serenityvideo_h_
|
|
+
|
|
+#include "../SDL_sysvideo.h"
|
|
+
|
|
+#include <LibGL/GLContext.h>
|
|
+#include <LibGUI/Widget.h>
|
|
+#include <LibGUI/Window.h>
|
|
+
|
|
+class SerenitySDLWidget final : public GUI::Widget {
|
|
+ C_OBJECT(SerenitySDLWidget)
|
|
+public:
|
|
+ explicit SerenitySDLWidget(SDL_Window*);
|
|
+ RefPtr<Gfx::Bitmap> m_buffer;
|
|
+
|
|
+protected:
|
|
+ void paint_event(GUI::PaintEvent&) override;
|
|
+ void resize_event(GUI::ResizeEvent&) override;
|
|
+ void show_event(GUI::ShowEvent&) override;
|
|
+ void hide_event(GUI::HideEvent&) override;
|
|
+
|
|
+ void mousedown_event(GUI::MouseEvent&) override;
|
|
+ void mousemove_event(GUI::MouseEvent&) override;
|
|
+ void mouseup_event(GUI::MouseEvent&) override;
|
|
+ void mousewheel_event(GUI::MouseEvent&) override;
|
|
+
|
|
+ void keydown_event(GUI::KeyEvent& event) override;
|
|
+ void keyup_event(GUI::KeyEvent& event) override;
|
|
+
|
|
+ void enter_event(Core::Event&) override;
|
|
+ void leave_event(Core::Event&) override;
|
|
+
|
|
+private:
|
|
+ SDL_Window* m_sdl_window = nullptr;
|
|
+};
|
|
+
|
|
+class SerenityGLContext final {
|
|
+public:
|
|
+ explicit SerenityGLContext(NonnullOwnPtr<GL::GLContext> gl_context)
|
|
+ : m_gl_context(move(gl_context))
|
|
+ {
|
|
+ }
|
|
+
|
|
+ GL::GLContext& gl_context() { return *m_gl_context; }
|
|
+
|
|
+private:
|
|
+ NonnullOwnPtr<GL::GLContext> m_gl_context;
|
|
+};
|
|
+
|
|
+class SerenityPlatformWindow final {
|
|
+public:
|
|
+ explicit SerenityPlatformWindow(SDL_Window* sdl_window)
|
|
+ : m_window(MUST(GUI::Window::try_create()))
|
|
+ , m_widget(MUST(SerenitySDLWidget::try_create(sdl_window)))
|
|
+ {
|
|
+ m_window->resize(sdl_window->w, sdl_window->h);
|
|
+ m_window->set_resizable(false);
|
|
+ }
|
|
+
|
|
+ static SerenityPlatformWindow* from_sdl_window(SDL_Window* window)
|
|
+ {
|
|
+ return static_cast<SerenityPlatformWindow*>(window->driverdata);
|
|
+ }
|
|
+
|
|
+ SerenityGLContext* serenity_gl_context() { return m_serenity_gl_context; }
|
|
+ void set_serenity_gl_context(SerenityGLContext* serenity_gl_context) { m_serenity_gl_context = serenity_gl_context; }
|
|
+
|
|
+ NonnullRefPtr<GUI::Window> window() { return m_window; }
|
|
+ NonnullRefPtr<SerenitySDLWidget> widget() { return m_widget; }
|
|
+
|
|
+private:
|
|
+ SerenityGLContext* m_serenity_gl_context;
|
|
+ NonnullRefPtr<GUI::Window> m_window;
|
|
+ NonnullRefPtr<SerenitySDLWidget> m_widget;
|
|
+};
|
|
+
|
|
+#endif /* SDL_serenityvideo_h_ */
|
|
+
|
|
+/* vi: set ts=4 sw=4 expandtab: */
|