diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/export/export.cpp | 175 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 8 | ||||
-rw-r--r-- | platform/x11/detect.py | 8 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 75 | ||||
-rw-r--r-- | platform/x11/os_x11.h | 22 |
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; |