summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/export/export.cpp175
-rw-r--r--platform/windows/os_windows.cpp8
-rw-r--r--platform/x11/detect.py8
-rw-r--r--platform/x11/os_x11.cpp75
-rw-r--r--platform/x11/os_x11.h22
5 files changed, 270 insertions, 18 deletions
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 060819b90e..b35e3a8055 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -9,6 +9,7 @@
#include "os/file_access.h"
#include "os/os.h"
#include "platform/android/logo.h"
+#include <string.h>
static const char* android_perms[]={
@@ -231,6 +232,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
void _fix_manifest(Vector<uint8_t>& p_manifest, bool p_give_internet);
void _fix_resources(Vector<uint8_t>& p_manifest);
static Error save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
+ static bool _should_compress_asset(const String& p_path);
protected:
@@ -1001,7 +1003,7 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
NULL,
0,
NULL,
- Z_DEFLATED,
+ _should_compress_asset(p_path) ? Z_DEFLATED : 0,
Z_DEFAULT_COMPRESSION);
@@ -1012,13 +1014,63 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
}
+bool EditorExportPlatformAndroid::_should_compress_asset(const String& p_path) {
+
+ /*
+ * By not compressing files with little or not benefit in doing so,
+ * a performance gain is expected at runtime. Moreover, if the APK is
+ * zip-aligned, assets stored as they are can be efficiently read by
+ * Android by memory-mapping them.
+ */
+
+ // -- Unconditional uncompress to mimic AAPT plus some other
+
+ static const char* unconditional_compress_ext[] = {
+ // From https://github.com/android/platform_frameworks_base/blob/master/tools/aapt/Package.cpp
+ // These formats are already compressed, or don't compress well:
+ ".jpg", ".jpeg", ".png", ".gif",
+ ".wav", ".mp2", ".mp3", ".ogg", ".aac",
+ ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
+ ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
+ ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
+ ".amr", ".awb", ".wma", ".wmv",
+ // Godot-specific:
+ ".webp", // Same reasoning as .png
+ ".cfb", // Don't let small config files slow-down startup
+ // Trailer for easier processing
+ NULL
+ };
+
+ for (const char** ext=unconditional_compress_ext; *ext; ++ext) {
+ if (p_path.to_lower().ends_with(String(*ext))) {
+ return false;
+ }
+ }
+
+ // -- Compressed resource?
+
+ FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
+ ERR_FAIL_COND_V(!f,true);
+
+ uint8_t header[4];
+ f->get_buffer(header,4);
+ if (header[0]=='R' && header[1]=='S' && header[2]=='C' && header[3]=='C') {
+ // Already compressed
+ return false;
+ }
+
+ // --- TODO: Decide on texture resources according to their image compression setting
+
+ return true;
+}
+
Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, int p_flags) {
String src_apk;
- EditorProgress ep("export","Exporting for Android",104);
+ EditorProgress ep("export","Exporting for Android",105);
if (p_debug)
src_apk=custom_debug_package;
@@ -1058,7 +1110,8 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
zlib_filefunc_def io2=io;
FileAccess *dst_f=NULL;
io2.opaque=&dst_f;
- zipFile apk=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
+ String unaligned_path=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport-unaligned.apk";
+ zipFile unaligned_apk=zipOpen2(unaligned_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
while(ret==UNZ_OK) {
@@ -1137,7 +1190,11 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
print_line("ADDING: "+file);
if (!skip) {
- zipOpenNewFileInZip(apk,
+
+ // Respect decision on compression made by AAPT for the export template
+ const bool uncompressed = info.compression_method == 0;
+
+ zipOpenNewFileInZip(unaligned_apk,
file.utf8().get_data(),
NULL,
NULL,
@@ -1145,11 +1202,11 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
NULL,
0,
NULL,
- Z_DEFLATED,
+ uncompressed ? 0 : Z_DEFLATED,
Z_DEFAULT_COMPRESSION);
- zipWriteInFileInZip(apk,data.ptr(),data.size());
- zipCloseFileInZip(apk);
+ zipWriteInFileInZip(unaligned_apk,data.ptr(),data.size());
+ zipCloseFileInZip(unaligned_apk);
}
ret = unzGoToNextFile(pkg);
@@ -1206,7 +1263,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
APKExportData ed;
ed.ep=&ep;
- ed.apk=apk;
+ ed.apk=unaligned_apk;
err = export_project_files(save_apk_file,&ed,false);
}
@@ -1235,7 +1292,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
print_line(itos(i)+" param: "+cl[i]);
}
- zipOpenNewFileInZip(apk,
+ zipOpenNewFileInZip(unaligned_apk,
"assets/_cl_",
NULL,
NULL,
@@ -1243,15 +1300,15 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
NULL,
0,
NULL,
- Z_DEFLATED,
+ 0, // No compress (little size gain and potentially slower startup)
Z_DEFAULT_COMPRESSION);
- zipWriteInFileInZip(apk,clf.ptr(),clf.size());
- zipCloseFileInZip(apk);
+ zipWriteInFileInZip(unaligned_apk,clf.ptr(),clf.size());
+ zipCloseFileInZip(unaligned_apk);
}
- zipClose(apk,NULL);
+ zipClose(unaligned_apk,NULL);
unzClose(pkg);
if (err) {
@@ -1308,7 +1365,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
args.push_back(keystore);
args.push_back("-storepass");
args.push_back(password);
- args.push_back(p_path);
+ args.push_back(unaligned_path);
args.push_back(user);
int retval;
int err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
@@ -1321,16 +1378,102 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
args.clear();
args.push_back("-verify");
- args.push_back(p_path);
+ args.push_back(unaligned_path);
args.push_back("-verbose");
err = OS::get_singleton()->execute(jarsigner,args,true,NULL,NULL,&retval);
if (retval) {
- EditorNode::add_io_error("'jarsigner' verificaiton of APK failed. Make sure to use jarsigner from Java 6.");
+ EditorNode::add_io_error("'jarsigner' verification of APK failed. Make sure to use jarsigner from Java 6.");
return ERR_CANT_CREATE;
}
}
+
+
+
+ // Let's zip-align (must be done after signing)
+
+ static const int ZIP_ALIGNMENT = 4;
+
+ ep.step("Aligning APK..",105);
+
+ unzFile tmp_unaligned = unzOpen2(unaligned_path.utf8().get_data(), &io);
+ if (!tmp_unaligned) {
+
+ EditorNode::add_io_error("Could not find temp unaligned APK.");
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ ERR_FAIL_COND_V(!tmp_unaligned, ERR_CANT_OPEN);
+ ret = unzGoToFirstFile(tmp_unaligned);
+
+ io2=io;
+ dst_f=NULL;
+ io2.opaque=&dst_f;
+ zipFile final_apk=zipOpen2(p_path.utf8().get_data(),APPEND_STATUS_CREATE,NULL,&io2);
+
+ // Take files from the unaligned APK and write them out to the aligned one
+ // in raw mode, i.e. not uncompressing and recompressing, aligning them as needed,
+ // following what is done in https://github.com/android/platform_build/blob/master/tools/zipalign/ZipAlign.cpp
+ int bias = 0;
+ while(ret==UNZ_OK) {
+
+ unz_file_info info;
+ memset(&info, 0, sizeof(info));
+
+ char fname[16384];
+ char extra[16384];
+ ret = unzGetCurrentFileInfo(tmp_unaligned,&info,fname,16384,extra,16384-ZIP_ALIGNMENT,NULL,0);
+
+ String file=fname;
+
+ Vector<uint8_t> data;
+ data.resize(info.compressed_size);
+
+ // read
+ int method, level;
+ unzOpenCurrentFile2(tmp_unaligned, &method, &level, 1); // raw read
+ long file_offset = unzGetCurrentFileZStreamPos64(tmp_unaligned);
+ unzReadCurrentFile(tmp_unaligned,data.ptr(),data.size());
+ unzCloseCurrentFile(tmp_unaligned);
+
+ // align
+ int padding = 0;
+ if (!info.compression_method) {
+ // Uncompressed file => Align
+ long new_offset = file_offset + bias;
+ padding = (ZIP_ALIGNMENT - (new_offset % ZIP_ALIGNMENT)) % ZIP_ALIGNMENT;
+ }
+
+ memset(extra + info.size_file_extra, 0, padding);
+
+ // write
+ zipOpenNewFileInZip2(final_apk,
+ file.utf8().get_data(),
+ NULL,
+ extra,
+ info.size_file_extra + padding,
+ NULL,
+ 0,
+ NULL,
+ method,
+ level,
+ 1); // raw write
+ zipWriteInFileInZip(final_apk,data.ptr(),data.size());
+ zipCloseFileInZipRaw(final_apk,info.uncompressed_size,info.crc);
+
+ bias += padding;
+
+ ret = unzGoToNextFile(tmp_unaligned);
+ }
+
+ zipClose(final_apk,NULL);
+ unzClose(tmp_unaligned);
+
+ if (err) {
+ return err;
+ }
+
return OK;
}
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 9034541f37..630d5715e9 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1834,6 +1834,11 @@ uint64_t OS_Windows::get_unix_time() const {
};
uint64_t OS_Windows::get_system_time_secs() const {
+
+
+ const uint64_t WINDOWS_TICK = 10000000;
+ const uint64_t SEC_TO_UNIX_EPOCH = 11644473600LL;
+
SYSTEMTIME st;
GetSystemTime(&st);
FILETIME ft;
@@ -1842,7 +1847,8 @@ uint64_t OS_Windows::get_system_time_secs() const {
ret=ft.dwHighDateTime;
ret<<=32;
ret|=ft.dwLowDateTime;
- return ret;
+
+ return (uint64_t)(ret / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
}
void OS_Windows::delay_usec(uint32_t p_usec) const {
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 0362756f7c..5f272536ba 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -45,6 +45,11 @@ def can_build():
print("xinerama not found.. x11 disabled.")
return False
+ x11_error=os.system("pkg-config xrandr --modversion > /dev/null ")
+ if (x11_error):
+ print("xrandr not found.. x11 disabled.")
+ return False
+
return True # X11 enabled
@@ -134,6 +139,7 @@ def configure(env):
env.ParseConfig('pkg-config x11 --cflags --libs')
env.ParseConfig('pkg-config xinerama --cflags --libs')
env.ParseConfig('pkg-config xcursor --cflags --libs')
+ env.ParseConfig('pkg-config xrandr --cflags --libs')
if (env["openssl"]=="yes"):
env.ParseConfig('pkg-config openssl --cflags --libs')
@@ -176,7 +182,7 @@ def configure(env):
print("PulseAudio development libraries not found, disabling driver")
env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES_OVER_GL'])
- env.Append(LIBS=['GL', 'GLU', 'pthread', 'z'])
+ env.Append(LIBS=['GL', 'GLU', 'pthread', 'z', 'dl'])
#env.Append(CPPFLAGS=['-DMPC_FIXED_POINT'])
#host compiler is default..
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index b089436a17..1ca779ef7c 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -57,6 +57,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <dlfcn.h>
//stupid linux.h
#ifdef KEY_TAB
@@ -117,6 +118,37 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
char * modifiers = XSetLocaleModifiers ("@im=none");
ERR_FAIL_COND( modifiers == NULL );
+ const char* err;
+ xrr_get_monitors = NULL;
+ xrr_free_monitors = NULL;
+ int xrandr_major = 0;
+ int xrandr_minor = 0;
+ int event_base, error_base;
+ xrandr_ext_ok = XRRQueryExtension(x11_display,&event_base, &error_base);
+ xrandr_handle = dlopen("libXrandr.so", RTLD_LAZY);
+ err = dlerror();
+ if (!xrandr_handle) {
+ fprintf(stderr, "could not load libXrandr.so, Error: %s\n", err);
+ }
+ else {
+ XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor);
+ if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) {
+ xrr_get_monitors = (xrr_get_monitors_t) dlsym(xrandr_handle, "XRRGetMonitors");
+ if (!xrr_get_monitors) {
+ err = dlerror();
+ fprintf(stderr, "could not find symbol XRRGetMonitors\nError: %s\n", err);
+ }
+ else {
+ xrr_free_monitors = (xrr_free_monitors_t) dlsym(xrandr_handle, "XRRFreeMonitors");
+ if (!xrr_free_monitors) {
+ err = dlerror();
+ fprintf(stderr, "could not find XRRFreeMonitors\nError: %s\n", err);
+ xrr_get_monitors = NULL;
+ }
+ }
+ }
+ }
+
xim = XOpenIM (x11_display, NULL, NULL, NULL);
@@ -480,6 +512,9 @@ void OS_X11::finalize() {
physics_2d_server->finish();
memdelete(physics_2d_server);
+ if (xrandr_handle)
+ dlclose(xrandr_handle);
+
XUnmapWindow( x11_display, x11_window );
XDestroyWindow( x11_display, x11_window );
@@ -722,6 +757,46 @@ Size2 OS_X11::get_screen_size(int p_screen) const {
return size;
}
+int OS_X11::get_screen_dpi(int p_screen) const {
+
+ //invalid screen?
+ ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0);
+
+ //Get physical monitor Dimensions through XRandR and calculate dpi
+ Size2 sc = get_screen_size(p_screen);
+ if (xrandr_ext_ok) {
+ int count = 0;
+ if (xrr_get_monitors) {
+ xrr_monitor_info *monitors = xrr_get_monitors(x11_display, x11_window, true, &count);
+ if (p_screen < count) {
+ double xdpi = sc.width / (double) monitors[p_screen].mwidth * 25.4;
+ double ydpi = sc.height / (double) monitors[p_screen].mheight * 25.4;
+ xrr_free_monitors(monitors);
+ return (xdpi + ydpi) / 2;
+ }
+ xrr_free_monitors(monitors);
+ }
+ else if (p_screen == 0) {
+ XRRScreenSize *sizes = XRRSizes(x11_display, 0, &count);
+ if (sizes) {
+ double xdpi = sc.width / (double) sizes[0].mwidth * 25.4;
+ double ydpi = sc.height / (double) sizes[0].mheight * 25.4;
+ return (xdpi + ydpi) / 2;
+ }
+ }
+ }
+
+ int width_mm = DisplayWidthMM(x11_display, p_screen);
+ int height_mm = DisplayHeightMM(x11_display, p_screen);
+ double xdpi = (width_mm ? sc.width / (double) width_mm * 25.4 : 0);
+ double ydpi = (height_mm ? sc.height / (double) height_mm * 25.4 : 0);
+ if (xdpi || xdpi)
+ return (xdpi + ydpi)/(xdpi && ydpi ? 2 : 1);
+
+ //could not get dpi
+ return 96;
+}
+
Point2 OS_X11::get_window_position() const {
int x,y;
Window child;
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 311f26d4d3..71bbe726dd 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -52,6 +52,7 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
+#include <X11/extensions/Xrandr.h>
// Hints for X11 fullscreen
typedef struct {
@@ -62,6 +63,20 @@ typedef struct {
unsigned long status;
} Hints;
+typedef struct _xrr_monitor_info {
+ Atom name;
+ Bool primary;
+ Bool automatic;
+ int noutput;
+ int x;
+ int y;
+ int width;
+ int height;
+ int mwidth;
+ int mheight;
+ RROutput *outputs;
+} xrr_monitor_info;
+
#undef CursorShape
/**
@author Juan Linietsky <reduzio@gmail.com>
@@ -162,6 +177,12 @@ class OS_X11 : public OS_Unix {
//void set_wm_border(bool p_enabled);
void set_wm_fullscreen(bool p_enabled);
+ typedef xrr_monitor_info* (*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors);
+ typedef void (*xrr_free_monitors_t)(xrr_monitor_info* monitors);
+ xrr_get_monitors_t xrr_get_monitors;
+ xrr_free_monitors_t xrr_free_monitors;
+ void *xrandr_handle;
+ Bool xrandr_ext_ok;
protected:
@@ -219,6 +240,7 @@ public:
virtual void set_current_screen(int p_screen);
virtual Point2 get_screen_position(int p_screen=0) const;
virtual Size2 get_screen_size(int p_screen=0) const;
+ virtual int get_screen_dpi(int p_screen=0) const;
virtual Point2 get_window_position() const;
virtual void set_window_position(const Point2& p_position);
virtual Size2 get_window_size() const;