diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index 1b62c0877..cbb732b7b 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -9,6 +9,9 @@ import lime.graphics.ConsoleRenderContext; import lime.graphics.GLRenderContext; import lime.graphics.RenderContext; import lime.graphics.Renderer; +import lime.math.Rectangle; +import lime.system.Display; +import lime.system.DisplayMode; import lime.system.System; import lime.ui.Gamepad; import lime.ui.Window; @@ -17,6 +20,7 @@ import lime.ui.Window; @:access(lime._backend.native.NativeRenderer) @:access(lime.app.Application) @:access(lime.graphics.Renderer) +@:access(lime.system.Display) @:access(lime.ui.Gamepad) @:access(lime.ui.Window) @@ -55,6 +59,33 @@ class NativeApplication { handle = lime_application_create (null); + #if !lime_console + + // TODO: Evolve this more + + var displays:Array = lime_display_get_details (); + + for (displayInfo in displays) { + + var display = new Display (); + display.name = displayInfo.name; + display.supportedModes = []; + display.bounds = new Rectangle (displayInfo.bounds.x, displayInfo.bounds.y, displayInfo.bounds.width, displayInfo.bounds.height); + + for (mode in cast (displayInfo.supportedModes, Array)) { + + var displayMode = new DisplayMode (mode.width, mode.height, mode.refreshRate, mode.pixelFormat); + display.supportedModes.push (displayMode); + + } + + display.currentMode = display.supportedModes[displayInfo.currentMode]; + Display.devices.push (display); + + } + + #end + if (config != null) { setFrameRate (config.fps); @@ -444,6 +475,7 @@ class NativeApplication { private static var lime_application_set_frame_rate = System.load ("lime", "lime_application_set_frame_rate", 2); private static var lime_application_update = System.load ("lime", "lime_application_update", 1); private static var lime_application_quit = System.load ("lime", "lime_application_quit", 1); + private static var lime_display_get_details = System.load ("lime", "lime_display_get_details", 0); private static var lime_gamepad_event_manager_register = System.load ("lime", "lime_gamepad_event_manager_register", 2); private static var lime_key_event_manager_register = System.load ("lime", "lime_key_event_manager_register", 2); private static var lime_mouse_event_manager_register = System.load ("lime", "lime_mouse_event_manager_register", 2); diff --git a/lime/system/Display.hx b/lime/system/Display.hx index 4b7280a0d..51312293e 100644 --- a/lime/system/Display.hx +++ b/lime/system/Display.hx @@ -1,184 +1,40 @@ package lime.system; + + import lime.math.Rectangle; -import lime.math.Vector2; -import lime.system.Display; -/** - * ... - * @author larsiusprime - */ + class Display { - - /********STATIC*********/ - public static var devices = new Map (); - /**How many display devices are currently connected and actively displaying visuals**/ - public static var numDisplays(get, null):Int; + public static var devices = new Array (); /** - * Sync with the OS to get the current display device information - */ - - public static function init():Void { - - for (i in 0...numDisplays) { - - var d = new Display(i); - d.sync(); - devices.set(i, d); - - } - - } + * The desktop area represented by this display, with the upper-leftmost display at 0,0 + **/ + public var bounds (default, null):Rectangle; /** - * Get the display device with the given id - * @param id - * @return - */ - - public static function get(id:Int):Display { - - if (devices.exists(id)) { - - return devices.get(id); - - } - - return null; - } + * The current display mode + **/ + public var currentMode (default, null):DisplayMode; /** - * Get the total number of connected displays - * @return - */ - - private static function get_numDisplays():Int { - - return lime_display_get_num_devices(); - - } - - /*********INSTANCE**********/ - - - /**Which number is assigned to the display device by the OS**/ - public var id (default, null):Int; - - /**The name of the device, such as "Samsung SyncMaster P2350", "iPhone 6", "Occulus Rift DK2", etc.**/ + * The name of the device, such as "Samsung SyncMaster P2350", "iPhone 6", "Occulus Rift DK2", etc. + **/ public var name (default, null):String; - /**Number of horizontal and vertical pixels currently being displayed**/ - public var resolution(default, null):Resolution; - - /**Horizontal resolution / Vertical resolution**/ - public var aspectRatio(get, null):Float; - - /**The current display mode**/ - public var mode(default, null):DisplayMode; - - /**All of the display modes supported by this device**/ - public var modes(default, null):Array; - - /**The desktop area represented by this display, with the upper-leftmost display at 0,0**/ - public var bounds(default, null):Rectangle; - - private function new(id:Int) { - - this.id = id; - sync(); - - } - - /** - * Updates this object's data with the latest information from the OS about the device - */ - public function sync():Void { - - name = lime_display_get_name(id); - - var obj = null; - - obj = lime_display_get_current_display_mode(id); - mode = new DisplayMode(obj.width, obj.height, obj.refresh_rate, obj.format); - resolution = new Resolution(mode.width, mode.height); - - obj = lime_display_get_display_bounds(id); - bounds = new Rectangle(obj.x, obj.y, obj.width, obj.height); - - modes = []; - var numModes = lime_display_get_num_display_modes(id); - - for (i in 0...numModes) { - - obj = lime_display_get_display_mode(id, i); - modes.push(new DisplayMode(obj.width, obj.height, obj.refresh_rate, obj.format)); - - } - } + * All of the display modes supported by this device + **/ + public var supportedModes (default, null):Array; - /**GET / SET**/ - private function get_aspectRatio():Float { + private function new () { - if (resolution.height != 0) { - return resolution.width / resolution.height; - - } - - return 0; - } - - // Native Methods - - #if (cpp || neko || nodejs) - - private static var lime_display_get_num_devices = System.load("lime", "lime_display_get_num_devices", 0); - private static var lime_display_get_name = System.load ("lime", "lime_display_get_name", 1); - private static var lime_display_get_num_display_modes = System.load ("lime", "lime_display_get_num_display_modes", 1); - private static var lime_display_get_display_bounds = System.load ("lime", "lime_display_get_display_bounds", 1); - private static var lime_display_get_display_mode = System.load ("lime", "lime_display_get_display_mode", 2); - private static var lime_display_get_current_display_mode = System.load ("lime", "lime_display_get_current_display_mode", 1); - - #end -} - -class DisplayMode { - - /**horizontal resolution**/ - public var width(default, null):Int; - - /**vertical resolution**/ - public var height(default, null):Int; - - /**refresh rate in Hz**/ - public var refreshRate(default, null):Int; - - /**pixel color format**/ - public var format(default, null):Int; - - public function new(width:Int, height:Int, refreshRate:Int, format:Int) { - - this.width = width; - this.height = height; - this.refreshRate = refreshRate; - this.format = format; } -} - -abstract Resolution (Vector2) from Vector2 { - - public inline function new (width:Float = 0, height:Float = 0) this = new Vector2(width, height); - - public var width(get, never):Float; - public var height(get, never):Float; - - inline function get_width ():Float return this.x; - inline function get_height ():Float return this.y; } \ No newline at end of file diff --git a/lime/system/DisplayMode.hx b/lime/system/DisplayMode.hx new file mode 100644 index 000000000..aefe6598d --- /dev/null +++ b/lime/system/DisplayMode.hx @@ -0,0 +1,41 @@ +package lime.system; + + +import lime.graphics.PixelFormat; + + +class DisplayMode { + + + /** + * vertical resolution + **/ + public var height (default, null):Int; + + /** + * pixel format + **/ + public var pixelFormat (default, null):PixelFormat; + + /** + * refresh rate in Hz + **/ + public var refreshRate (default, null):Int; + + /** + * horizontal resolution + **/ + public var width (default, null):Int; + + + public function new (width:Int, height:Int, refreshRate:Int, pixelFormat:PixelFormat) { + + this.width = width; + this.height = height; + this.refreshRate = refreshRate; + this.pixelFormat = pixelFormat; + + } + + +} \ No newline at end of file diff --git a/project/include/math/Rectangle.h b/project/include/math/Rectangle.h index 5c3cbf84d..405b9322b 100644 --- a/project/include/math/Rectangle.h +++ b/project/include/math/Rectangle.h @@ -18,6 +18,7 @@ namespace lime { Rectangle (value rect); void Contract (double x, double y, double width, double height); + value Value (); double height; double width; diff --git a/project/include/system/Display.h b/project/include/system/Display.h index 93e2111a2..47c4edf27 100644 --- a/project/include/system/Display.h +++ b/project/include/system/Display.h @@ -1,24 +1,24 @@ #ifndef LIME_SYSTEM_DISPLAY_H #define LIME_SYSTEM_DISPLAY_H -#include + #include + namespace lime { class Display { + public: - static value GetCurrentDisplayMode (int displayIndex); - static value GetDisplayMode (int displayIndex, int modeIndex); - static value GetDisplayBounds (int displayIndex); - static int GetNumDevices (); - static const char* GetDisplayName (int displayIndex); - static int GetNumDisplayModes (int displayIndex); - + static value GetDetails (); + + }; + + } diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index bc295fbc6..9d88f8921 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -161,6 +161,13 @@ namespace lime { } + value lime_display_get_details () { + + return Display::GetDetails (); + + } + + void lime_font_destroy (value handle) { Font *font = (Font*)(intptr_t)val_float (handle); @@ -391,41 +398,6 @@ namespace lime { } - value lime_display_get_display_bounds (value displayIndex) { - - return Display::GetDisplayBounds(val_int(displayIndex)); - - } - - value lime_display_get_current_display_mode (value displayIndex) { - - return Display::GetCurrentDisplayMode(val_int(displayIndex)); - - } - - value lime_display_get_display_mode (value displayIndex, value modeIndex) { - - return Display::GetDisplayMode(val_int(displayIndex), val_int(modeIndex)); - - } - - value lime_display_get_name (value displayIndex) { - - return alloc_string (Display::GetDisplayName (val_int (displayIndex))); - - } - - value lime_display_get_num_devices () { - - return alloc_int (Display::GetNumDevices()); - - } - - value lime_display_get_num_display_modes (value displayIndex) { - - return alloc_int (Display::GetNumDisplayModes(val_int (displayIndex))); - - } value lime_gamepad_add_mappings (value mappings) { @@ -1192,6 +1164,7 @@ namespace lime { DEFINE_PRIM (lime_bytes_from_data_pointer, 2); DEFINE_PRIM (lime_bytes_get_data_pointer, 1); DEFINE_PRIM (lime_bytes_read_file, 1); + DEFINE_PRIM (lime_display_get_details, 0); DEFINE_PRIM (lime_font_get_ascender, 1); DEFINE_PRIM (lime_font_get_descender, 1); DEFINE_PRIM (lime_font_get_family_name, 1); @@ -1208,12 +1181,6 @@ namespace lime { DEFINE_PRIM (lime_font_render_glyph, 3); DEFINE_PRIM (lime_font_render_glyphs, 3); DEFINE_PRIM (lime_font_set_size, 2); - DEFINE_PRIM (lime_display_get_display_bounds, 1); - DEFINE_PRIM (lime_display_get_current_display_mode, 1); - DEFINE_PRIM (lime_display_get_display_mode, 2); - DEFINE_PRIM (lime_display_get_name, 1); - DEFINE_PRIM (lime_display_get_num_devices, 0); - DEFINE_PRIM (lime_display_get_num_display_modes, 1); DEFINE_PRIM (lime_gamepad_add_mappings, 1); DEFINE_PRIM (lime_gamepad_event_manager_register, 2); DEFINE_PRIM (lime_gamepad_get_device_guid, 1); diff --git a/project/src/backend/sdl/SDLDisplay.cpp b/project/src/backend/sdl/SDLDisplay.cpp index ec9bafa0e..5c67b904b 100644 --- a/project/src/backend/sdl/SDLDisplay.cpp +++ b/project/src/backend/sdl/SDLDisplay.cpp @@ -1,67 +1,106 @@ +#include +#include #include +#include namespace lime { - value Display::GetDisplayBounds (int displayIndex) { + static int id_bounds; + static int id_currentMode; + static int id_height; + static int id_name; + static int id_pixelFormat; + static int id_refreshRate; + static int id_supportedModes; + static int id_width; + static bool init = false; + + + value Display::GetDetails () { - SDL_Rect rect = { 0, 0, 0, 0}; - SDL_GetDisplayBounds(displayIndex, &rect); + if (!init) { + + id_bounds = val_id ("bounds"); + id_currentMode = val_id ("currentMode"); + id_height = val_id ("height"); + id_name = val_id ("name"); + id_pixelFormat = val_id ("pixelFormat"); + id_refreshRate = val_id ("refreshRate"); + id_supportedModes = val_id ("supportedModes"); + id_width = val_id ("width"); + init = true; + + } - value mValue = alloc_empty_object (); - alloc_field (mValue, val_id("x"), alloc_int(rect.x)); - alloc_field (mValue, val_id("y"), alloc_int(rect.y)); - alloc_field (mValue, val_id("width"), alloc_int(rect.w)); - alloc_field (mValue, val_id("height"), alloc_int(rect.h)); - return mValue; + int numDevices = SDL_GetNumVideoDisplays (); + value devices = alloc_array (numDevices); + + value display, supportedModes, mode; + int numDisplayModes; + SDL_Rect bounds = { 0, 0, 0, 0 }; + SDL_DisplayMode currentDisplayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; + SDL_DisplayMode displayMode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; + + for (int i = 0; i < numDevices; i++) { + + display = alloc_empty_object (); + alloc_field (display, id_name, alloc_string (SDL_GetDisplayName (i))); + SDL_GetDisplayBounds (i, &bounds); + alloc_field (display, id_bounds, Rectangle (bounds.x, bounds.y, bounds.w, bounds.h).Value ()); + + SDL_GetCurrentDisplayMode (i, ¤tDisplayMode); + numDisplayModes = SDL_GetNumDisplayModes (i); + supportedModes = alloc_array (numDisplayModes); + + for (int j = 0; j < numDisplayModes; j++) { + + SDL_GetDisplayMode (i, j, &displayMode); + + if (displayMode.format == currentDisplayMode.format && displayMode.w == currentDisplayMode.w && displayMode.h == currentDisplayMode.h && displayMode.refresh_rate == currentDisplayMode.refresh_rate) { + + alloc_field (display, id_currentMode, alloc_int (j)); + + } + + mode = alloc_empty_object (); + alloc_field (mode, id_height, alloc_int (displayMode.h)); + + switch (displayMode.format) { + + case SDL_PIXELFORMAT_ARGB8888: + + alloc_field (mode, id_pixelFormat, alloc_int (ARGB32)); + break; + + case SDL_PIXELFORMAT_BGRA8888: + case SDL_PIXELFORMAT_BGRX8888: + + alloc_field (mode, id_pixelFormat, alloc_int (BGRA32)); + break; + + default: + + alloc_field (mode, id_pixelFormat, alloc_int (RGBA32)); + + } + + alloc_field (mode, id_refreshRate, alloc_int (displayMode.refresh_rate)); + alloc_field (mode, id_width, alloc_int (displayMode.w)); + + val_array_set_i (supportedModes, j, mode); + + } + + alloc_field (display, id_supportedModes, supportedModes); + val_array_set_i (devices, i, display); + + } + + return devices; } - value Display::GetCurrentDisplayMode (int displayIndex) { - - SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; - SDL_GetCurrentDisplayMode(displayIndex, &mode); - - value mValue = alloc_empty_object (); - alloc_field (mValue, val_id("width"), alloc_int(mode.w)); - alloc_field (mValue, val_id("height"), alloc_int(mode.h)); - alloc_field (mValue, val_id("refresh_rate"), alloc_int(mode.refresh_rate)); - alloc_field (mValue, val_id("format"), alloc_int(mode.format)); - return mValue; - - } - - value Display::GetDisplayMode (int displayIndex, int modeIndex) { - - SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; - SDL_GetDisplayMode(displayIndex, modeIndex, &mode); - - value mValue = alloc_empty_object (); - alloc_field (mValue, val_id("width"), alloc_int(mode.w)); - alloc_field (mValue, val_id("height"), alloc_int(mode.h)); - alloc_field (mValue, val_id("refresh_rate"), alloc_int(mode.refresh_rate)); - alloc_field (mValue, val_id("format"), alloc_int(mode.format)); - return mValue; - - } - - int Display::GetNumDevices() { - - return SDL_GetNumVideoDisplays(); - - } - - const char* Display::GetDisplayName (int displayIndex) { - - return SDL_GetDisplayName(displayIndex); - - } - - int Display::GetNumDisplayModes (int displayIndex) { - - return SDL_GetNumDisplayModes(displayIndex); - - } } \ No newline at end of file diff --git a/project/src/math/Rectangle.cpp b/project/src/math/Rectangle.cpp index 0ce21c467..eff5db309 100644 --- a/project/src/math/Rectangle.cpp +++ b/project/src/math/Rectangle.cpp @@ -70,4 +70,26 @@ namespace lime { } + value Rectangle::Value () { + + if (!init) { + + id_height = val_id ("height"); + id_width = val_id ("width"); + id_x = val_id ("x"); + id_y = val_id ("y"); + init = true; + + } + + value rect = alloc_empty_object (); + alloc_field (rect, id_height, alloc_float (height)); + alloc_field (rect, id_width, alloc_float (width)); + alloc_field (rect, id_x, alloc_float (x)); + alloc_field (rect, id_y, alloc_float (y)); + return rect; + + } + + } \ No newline at end of file diff --git a/project/src/system/Display.cpp b/project/src/system/Display.cpp new file mode 100644 index 000000000..4129d06fa --- /dev/null +++ b/project/src/system/Display.cpp @@ -0,0 +1,144 @@ +#include + + +namespace lime { + + + static int id_bitsPerPixel; + static int id_buffer; + static int id_data; + static int id_format; + static int id_height; + static int id_premultiplied; + static int id_transparent; + static int id_width; + static bool init = false; + + + ImageBuffer::ImageBuffer () { + + width = 0; + height = 0; + bitsPerPixel = 32; + format = RGBA32; + data = 0; + premultiplied = false; + transparent = false; + + } + + + ImageBuffer::ImageBuffer (value imageBuffer) { + + if (!init) { + + id_bitsPerPixel = val_id ("bitsPerPixel"); + id_transparent = val_id ("transparent"); + id_buffer = val_id ("buffer"); + id_width = val_id ("width"); + id_height = val_id ("height"); + id_data = val_id ("data"); + id_format = val_id ("format"); + id_premultiplied = val_id ("premultiplied"); + init = true; + + } + + width = val_int (val_field (imageBuffer, id_width)); + height = val_int (val_field (imageBuffer, id_height)); + bitsPerPixel = val_int (val_field (imageBuffer, id_bitsPerPixel)); + format = (PixelFormat)val_int (val_field (imageBuffer, id_format)); + transparent = val_bool (val_field (imageBuffer, id_transparent)); + value data_value = val_field (imageBuffer, id_data); + value buffer_value = val_field (data_value, id_buffer); + premultiplied = val_bool (val_field (imageBuffer, id_premultiplied)); + data = new Bytes (buffer_value); + + } + + + ImageBuffer::~ImageBuffer () { + + delete data; + + } + + + void ImageBuffer::Blit (const unsigned char *data, int x, int y, int width, int height) { + + if (x < 0 || x + width > this->width || y < 0 || y + height > this->height) { + + return; + + } + + int stride = Stride (); + unsigned char *bytes = this->data->Data (); + + for (int i = 0; i < height; i++) { + + memcpy (&bytes[(i + y) * this->width + x], &data[i * width], stride); + + } + + } + + + void ImageBuffer::Resize (int width, int height, int bitsPerPixel) { + + this->bitsPerPixel = bitsPerPixel; + this->width = width; + this->height = height; + + int stride = Stride (); + + if (!this->data) { + + this->data = new Bytes (height * stride); + + } else { + + this->data->Resize (height * stride); + + } + + } + + + int ImageBuffer::Stride () { + + return width * (((bitsPerPixel + 3) & ~0x3) >> 3); + + } + + + value ImageBuffer::Value () { + + if (!init) { + + id_bitsPerPixel = val_id ("bitsPerPixel"); + id_transparent = val_id ("transparent"); + id_buffer = val_id ("buffer"); + id_width = val_id ("width"); + id_height = val_id ("height"); + id_data = val_id ("data"); + id_format = val_id ("format"); + id_premultiplied = val_id ("premultiplied"); + init = true; + + } + + mValue = alloc_empty_object (); + alloc_field (mValue, id_width, alloc_int (width)); + alloc_field (mValue, id_height, alloc_int (height)); + alloc_field (mValue, id_bitsPerPixel, alloc_int (bitsPerPixel)); + alloc_field (mValue, id_data, data ? data->Value () : alloc_null ()); + alloc_field (mValue, id_transparent, alloc_bool (transparent)); + alloc_field (mValue, id_format, alloc_int (format)); + alloc_field (mValue, id_premultiplied, alloc_bool (premultiplied)); + return mValue; + + } + + +} \ No newline at end of file