From 0a6ef9d42ac008c7b8bf6b3d0f112ce040e3568c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 7 Jan 2018 14:37:14 +0100 Subject: Add many sdl_video functions --- README.asciidoc | 60 +++++++-------- c_src/esdl2.h | 13 ++++ c_src/sdl_rect.c | 18 +++++ c_src/sdl_video.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ebin/esdl2.app | 2 +- src/esdl2.erl | 44 +++++++++++ src/sdl_video.erl | 75 +++++++++++++++++++ 7 files changed, 396 insertions(+), 36 deletions(-) create mode 100644 c_src/sdl_video.c create mode 100644 src/sdl_video.erl diff --git a/README.asciidoc b/README.asciidoc index 163e813..52e4c1b 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -86,42 +86,32 @@ corresponding to the public headers. * 'SDL_video.h': The following elements are missing: ** `SDL_WindowFlags` values SDL_WINDOW_ALWAYS_ON_TOP, SDL_WINDOW_SKIP_TASKBAR, SDL_WINDOW_UTILITY, SDL_WINDOW_TOOLTIP, SDL_WINDOW_POPUP_MENU, SDL_WINDOW_VULKAN ** `SDL_WINDOWPOS_*` values for different displays -** `SDL_GetNumVideoDrivers` -** `SDL_GetVideoDriver` -** `SDL_VideoInit` -** `SDL_VideoQuit` -** `SDL_GetCurrentVideoDriver` -** `SDL_GetNumVideoDisplays` -** `SDL_GetDisplayName` -** `SDL_GetDisplayBounds` -** `SDL_GetDisplayDPI` -** `SDL_GetDisplayUsableBounds` -** `SDL_GetNumDisplayModes` -** `SDL_GetDisplayMode` -** `SDL_GetDesktopDisplayMode` -** `SDL_GetCurrentDisplayMode` -** `SDL_GetClosestDisplayMode` -** `SDL_GetWindowDisplayIndex` -** `SDL_SetWindowDisplayMode` -** `SDL_GetWindowDisplayMode` -** `SDL_GetWindowPixelFormat` -** `SDL_CreateWindowFrom` -** `SDL_GetWindowFromID` +** `SDL_GetNumDisplayModes` (video) +** `SDL_GetDisplayMode` (video) +** `SDL_GetDesktopDisplayMode` (video) +** `SDL_GetCurrentDisplayMode` (video) +** `SDL_GetClosestDisplayMode` (video) +** `SDL_GetWindowDisplayIndex` (window) +** `SDL_SetWindowDisplayMode` (window) +** `SDL_GetWindowDisplayMode` (window) +** `SDL_GetWindowPixelFormat` (window) +** `SDL_CreateWindowFrom` (window) +** `SDL_GetWindowFromID` (window) ** We currently do not support UTF-8. We should probably switch to binaries as input/output to support it for `SDL_SetWindowTitle` and `SDL_GetWindowTitle` -** `SDL_SetWindowData` -** `SDL_GetWindowData` -** `SDL_GetWindowBordersSize` -** `SDL_SetWindowResizable` -** `SDL_GetWindowSurface` -** `SDL_UpdateWindowSurface` -** `SDL_UpdateWindowSurfaceRects` -** `SDL_GetGrabbedWindow` -** `SDL_SetWindowOpacity` -** `SDL_GetWindowOpacity` -** `SDL_SetWindowModalFor` -** `SDL_SetWindowInputFocus` -** `SDL_SetWindowGammaRamp` -** `SDL_GetWindowGammaRamp` +** `SDL_SetWindowData` (window) +** `SDL_GetWindowData` (window) +** `SDL_GetWindowBordersSize` (window) +** `SDL_SetWindowResizable` (window) +** `SDL_GetWindowSurface` (window) +** `SDL_UpdateWindowSurface` (window) +** `SDL_UpdateWindowSurfaceRects` (window) +** `SDL_GetGrabbedWindow` (window) +** `SDL_SetWindowOpacity` (window) +** `SDL_GetWindowOpacity` (window) +** `SDL_SetWindowModalFor` (window) +** `SDL_SetWindowInputFocus` (window) +** `SDL_SetWindowGammaRamp` (window) +** `SDL_GetWindowGammaRamp` (window) ** `SDL_SetWindowHitTest` and the related callback `SDL_HitTestResult` ** `SDL_IsScreenSaverEnabled` ** `SDL_EnableScreenSaver` diff --git a/c_src/esdl2.h b/c_src/esdl2.h index a860b7f..6285981 100644 --- a/c_src/esdl2.h +++ b/c_src/esdl2.h @@ -71,6 +71,7 @@ A(crosshair) \ A(data1) \ A(data2) \ + A(diagonal) \ A(direction) \ A(dollar_gesture) \ A(dollar_record) \ @@ -392,6 +393,17 @@ /* sdl_version */ \ F(get_version, 0) \ F(get_revision, 0) \ + /* sdl_video */ \ + F(get_current_video_driver, 0) \ + F(get_display_bounds, 1) \ + F(get_display_dpi, 1) \ + F(get_display_name, 1) \ + F(get_display_usable_bounds, 1) \ + F(get_num_video_displays, 0) \ + F(get_num_video_drivers, 0) \ + F(get_video_driver, 1) \ + F(video_init, 1) \ + F(video_quit, 0) \ /* sdl_window */ \ F(create_window, 6) \ F(create_window_and_renderer, 3) \ @@ -445,6 +457,7 @@ NIF_FLAGS_TO_LIST_FUNCTION_DECL(keymod_flags_to_list, Uint16) int map_to_point(ErlNifEnv*, ERL_NIF_TERM, SDL_Point*); int map_to_rect(ErlNifEnv*, ERL_NIF_TERM, SDL_Rect*); +ERL_NIF_TERM rect_to_map(ErlNifEnv*, SDL_Rect*); ERL_NIF_TERM mouse_state_to_list(ErlNifEnv*, Uint32); diff --git a/c_src/sdl_rect.c b/c_src/sdl_rect.c index eb04d5b..737c920 100644 --- a/c_src/sdl_rect.c +++ b/c_src/sdl_rect.c @@ -55,3 +55,21 @@ int map_to_rect(ErlNifEnv* env, ERL_NIF_TERM map, SDL_Rect* rect) return 1; } + +ERL_NIF_TERM rect_to_map(ErlNifEnv* env, SDL_Rect* rect) +{ + ERL_NIF_TERM map; + + map = enif_make_new_map(env); + + enif_make_map_put(env, map, atom_x, + enif_make_int(env, rect->x), &map); + enif_make_map_put(env, map, atom_y, + enif_make_int(env, rect->y), &map); + enif_make_map_put(env, map, atom_w, + enif_make_int(env, rect->w), &map); + enif_make_map_put(env, map, atom_h, + enif_make_int(env, rect->h), &map); + + return map; +} diff --git a/c_src/sdl_video.c b/c_src/sdl_video.c new file mode 100644 index 0000000..f559583 --- /dev/null +++ b/c_src/sdl_video.c @@ -0,0 +1,220 @@ +// Copyright (c) 2018, Loïc Hoguin +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +#include "esdl2.h" + +// get_current_video_driver + +NIF_CALL_HANDLER(thread_get_current_video_driver) +{ + const char* name; + ErlNifBinary bin; + + name = SDL_GetCurrentVideoDriver(); + + if (!name) + return atom_undefined; + + enif_alloc_binary(strlen(name), &bin); + memcpy(bin.data, name, bin.size); + + return enif_make_binary(env, &bin); +} + +NIF_FUNCTION(get_current_video_driver) +{ + return nif_thread_call(env, thread_get_current_video_driver, 0); +} + +// get_display_bounds + +NIF_CALL_HANDLER(thread_get_display_bounds) +{ + SDL_Rect rect; + + if (SDL_GetDisplayBounds((long)args[0], &rect)) + return atom_undefined; + + return rect_to_map(env, &rect); +} + +NIF_FUNCTION(get_display_bounds) +{ + int index; + + BADARG_IF(!enif_get_int(env, argv[0], &index)); + + return nif_thread_call(env, thread_get_display_bounds, 1, index); +} + +// get_display_dpi + +NIF_CALL_HANDLER(thread_get_display_dpi) +{ + float ddpi, hdpi, vdpi; + ERL_NIF_TERM map; + + if (SDL_GetDisplayDPI((long)args[0], &ddpi, &hdpi, &vdpi)) + return atom_undefined; + + map = enif_make_new_map(env); + + enif_make_map_put(env, map, atom_diagonal, + enif_make_double(env, ddpi), &map); + enif_make_map_put(env, map, atom_horizontal, + enif_make_double(env, hdpi), &map); + enif_make_map_put(env, map, atom_vertical, + enif_make_double(env, vdpi), &map); + + return map; +} + +NIF_FUNCTION(get_display_dpi) +{ + int index; + + BADARG_IF(!enif_get_int(env, argv[0], &index)); + + return nif_thread_call(env, thread_get_display_dpi, 1, index); +} + +// get_display_name + +NIF_CALL_HANDLER(thread_get_display_name) +{ + const char* name; + ErlNifBinary bin; + + name = SDL_GetDisplayName((long)args[0]); + + if (!name) + return atom_undefined; + + enif_alloc_binary(strlen(name), &bin); + memcpy(bin.data, name, bin.size); + + return enif_make_binary(env, &bin); +} + +NIF_FUNCTION(get_display_name) +{ + int index; + + BADARG_IF(!enif_get_int(env, argv[0], &index)); + + return nif_thread_call(env, thread_get_display_name, 1, index); +} + +// get_display_usable_bounds + +NIF_CALL_HANDLER(thread_get_display_usable_bounds) +{ + SDL_Rect rect; + + if (SDL_GetDisplayUsableBounds((long)args[0], &rect)) + return atom_undefined; + + return rect_to_map(env, &rect); +} + +NIF_FUNCTION(get_display_usable_bounds) +{ + int index; + + BADARG_IF(!enif_get_int(env, argv[0], &index)); + + return nif_thread_call(env, thread_get_display_usable_bounds, 1, index); +} + +// get_num_video_displays + +NIF_CALL_HANDLER(thread_get_num_video_displays) +{ + return enif_make_int(env, SDL_GetNumVideoDisplays()); +} + +NIF_FUNCTION(get_num_video_displays) +{ + return nif_thread_call(env, thread_get_num_video_displays, 0); +} + +// get_num_video_drivers + +NIF_FUNCTION(get_num_video_drivers) +{ + return enif_make_int(env, SDL_GetNumVideoDrivers()); +} + +// get_video_driver + +NIF_FUNCTION(get_video_driver) +{ + int index; + const char* name; + ErlNifBinary bin; + + BADARG_IF(!enif_get_int(env, argv[0], &index)); + + name = SDL_GetVideoDriver(index); + + if (!name) + return atom_undefined; + + enif_alloc_binary(strlen(name), &bin); + memcpy(bin.data, name, bin.size); + + return enif_make_binary(env, &bin); +} + +// video_init + +NIF_CALL_HANDLER(thread_video_init) +{ + int result; + + result = SDL_VideoInit(args[0]); + + free(args[0]); + + if (result) + return sdl_error_tuple(env); + + return atom_ok; +} + +NIF_FUNCTION(video_init) +{ + ErlNifBinary bin; + char* name; + + BADARG_IF(!enif_inspect_binary(env, argv[0], &bin)); + + name = malloc(bin.size + 1); + memcpy(name, bin.data, bin.size); + name[bin.size] = '\0'; + + return nif_thread_call(env, thread_video_init, 1, name); +} + +// video_quit + +NIF_CAST_HANDLER(thread_video_quit) +{ + SDL_VideoQuit(); +} + +NIF_FUNCTION(video_quit) +{ + return nif_thread_cast(env, thread_video_quit, 0); +} diff --git a/ebin/esdl2.app b/ebin/esdl2.app index c2bd838..9dd11ea 100644 --- a/ebin/esdl2.app +++ b/ebin/esdl2.app @@ -1,7 +1,7 @@ {application, 'esdl2', [ {description, "SDL2 Erlang NIF."}, {vsn, "0.1.0"}, - {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_blend_mode','sdl_clipboard','sdl_cpu_info','sdl_cursor','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_keycode','sdl_mouse','sdl_pixels','sdl_platform','sdl_power','sdl_rect','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_window']}, + {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_blend_mode','sdl_clipboard','sdl_cpu_info','sdl_cursor','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_keycode','sdl_mouse','sdl_pixels','sdl_platform','sdl_power','sdl_rect','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_video','sdl_window']}, {registered, [esdl2_sup]}, {applications, [kernel,stdlib]}, {mod, {esdl2_app, []}}, diff --git a/src/esdl2.erl b/src/esdl2.erl index 435451b..015fd62 100644 --- a/src/esdl2.erl +++ b/src/esdl2.erl @@ -165,6 +165,18 @@ -export([get_version/0]). -export([get_revision/0]). +%% sdl_video +-export([get_current_video_driver/0]). +-export([get_display_bounds/1]). +-export([get_display_dpi/1]). +-export([get_display_name/1]). +-export([get_display_usable_bounds/1]). +-export([get_num_video_displays/0]). +-export([get_num_video_drivers/0]). +-export([get_video_driver/1]). +-export([video_init/1]). +-export([video_quit/0]). + %% sdl_window -export([create_window/6]). -export([create_window_and_renderer/3]). @@ -588,6 +600,38 @@ get_version() -> get_revision() -> erlang:nif_error({not_loaded, ?MODULE}). +%% sdl_video + +get_current_video_driver() -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_display_bounds(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_display_dpi(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_display_name(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_display_usable_bounds(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_num_video_displays() -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_num_video_drivers() -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_video_driver(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +video_init(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +video_quit() -> + erlang:nif_error({not_loaded, ?MODULE}). + %% sdl_window create_window(_, _, _, _, _, _) -> diff --git a/src/sdl_video.erl b/src/sdl_video.erl new file mode 100644 index 0000000..37e2947 --- /dev/null +++ b/src/sdl_video.erl @@ -0,0 +1,75 @@ +%% Copyright (c) 2018, Loïc Hoguin +%% +%% Permission to use, copy, modify, and/or distribute this software for any +%% purpose with or without fee is hereby granted, provided that the above +%% copyright notice and this permission notice appear in all copies. +%% +%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-module(sdl_video). + +-export([get_current_driver/0]). +-export([get_display_bounds/1]). +-export([get_display_dpi/1]). +-export([get_display_name/1]). +-export([get_display_usable_bounds/1]). +-export([get_driver/1]). +-export([get_num_displays/0]). +-export([get_num_drivers/0]). +-export([start/1]). +-export([stop/0]). + +-spec get_current_driver() -> binary() | undefined. +get_current_driver() -> + esdl2:get_current_video_driver(), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_display_bounds(integer()) -> sdl_rect:rect() | undefined. +get_display_bounds(Index) -> + esdl2:get_display_bounds(Index), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_display_dpi(integer()) + -> #{diagonal := float(), horizontal := float(), vertical := float()} + | undefined. +get_display_dpi(Index) -> + esdl2:get_display_dpi(Index), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_display_name(integer()) -> binary() | undefined. +get_display_name(Index) -> + esdl2:get_display_name(Index), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_display_usable_bounds(integer()) -> sdl_rect:rect() | undefined. +get_display_usable_bounds(Index) -> + esdl2:get_display_usable_bounds(Index), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_driver(integer()) -> binary() | undefined. +get_driver(Index) -> + esdl2:get_video_driver(Index). + +-spec get_num_displays() -> integer(). +get_num_displays() -> + esdl2:get_num_video_displays(), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_num_drivers() -> integer(). +get_num_drivers() -> + esdl2:get_num_video_drivers(). + +-spec start(binary()) -> ok | sdl:error(). +start(DriverName) -> + esdl2:video_init(DriverName), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec stop() -> ok. +stop() -> + esdl2:video_quit(). -- cgit v1.2.3