From 0d9a704dbba8b980f3048d5fc739761a10a9dc23 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sat, 7 Jul 2018 15:36:41 +0200 Subject: [PATCH] Optimized memory usage, batch export and conversion, multi resolution export, new standalone executable for windows and linux. --- .gitignore | 6 +- .travis.yml | 12 +- Tests/build.gradle | 12 +- Tests/src/test/java/tests/InteractiveCLI.java | 7 +- build.gradle | 13 + build.sh | 29 ++ .../src/main/java/ddswriter/DDSDelegate.java | 9 +- .../java/ddswriter/DDSSlicedDelegate.java | 13 +- .../src/main/java/ddswriter/DDSWriter.java | 4 + dds_writer/src/main/java/ddswriter/Pixel.java | 155 +++++++++++ dds_writer/src/main/java/ddswriter/Texel.java | 114 +++----- .../java/ddswriter/TexelMipmapGenerator.java | 27 +- .../ddswriter/delegates/GenericDelegate.java | 12 +- .../ddswriter/encoders/ARGB8ColorBit.java | 13 +- .../java/ddswriter/encoders/ColorBit.java | 4 +- .../ddswriter/encoders/RGB565ColorBit.java | 41 +-- .../java/ddswriter/encoders/RGB8ColorBit.java | 11 +- dds_writer/src/test/java/TexelTest.java | 15 +- dds_writer__cli/build.gradle | 22 +- .../src/main/java/ddswriter/cli/CLI109.java | 212 +++++++++++--- dds_writer__cli/src/main/resources/log4j2.xml | 17 ++ .../lwjgl2/LWJGLBlockCompressionDelegate.java | 12 +- .../delegates/lwjgl2/LWJGLCliModule.java | 30 ++ dds_writer__rgtc_lwjgl2_delegate/build.gradle | 22 +- .../RGTC_LWJGL2CompressionDelegate.java | 7 +- .../lwjgl2_rgtc/RgtcCLI109Module.java | 21 +- dds_writer__s3tc_lwjgl2_delegate/build.gradle | 22 +- .../S3TC_LWJGL2CompressionDelegate.java | 6 +- .../lwjgl2_s3tc/S3tcCLI109Module.java | 21 +- res/Launcher.c | 263 ++++++++++++++++++ res/LinuxLauncher.sh | 17 ++ res/WindowsLauncher.bat | 13 + res/make-generic-bundle.sh | 6 + res/make-linux-bundle.sh | 49 ++++ res/make-windows-bundle.sh | 69 +++++ 35 files changed, 1062 insertions(+), 244 deletions(-) create mode 100644 build.sh create mode 100644 dds_writer/src/main/java/ddswriter/Pixel.java create mode 100644 dds_writer__cli/src/main/resources/log4j2.xml create mode 100644 res/Launcher.c create mode 100644 res/LinuxLauncher.sh create mode 100644 res/WindowsLauncher.bat create mode 100644 res/make-generic-bundle.sh create mode 100644 res/make-linux-bundle.sh create mode 100644 res/make-windows-bundle.sh diff --git a/.gitignore b/.gitignore index 54c8455..73f2da3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,8 @@ *.so *.dll *.dylib -**/hs_err_pid*.log \ No newline at end of file +**/hs_err_pid*.log +**/.vscode +.classpath +.settings +.project \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 126fa0b..86c565c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,15 @@ os: - linux notifications: email: true +env: + - LINUX=1 + - WINDOWS=1 script: -- ./gradlew build +- ./build.sh travis +deploy: + provider: releases + api_key: "" + file: "build/libs/dist/*" + skip_cleanup: true + on: + tags: true \ No newline at end of file diff --git a/Tests/build.gradle b/Tests/build.gradle index 5ecbc5d..c8d7b5a 100644 --- a/Tests/build.gradle +++ b/Tests/build.gradle @@ -2,13 +2,13 @@ dependencies { compileOnly "${jme_group}:jme3-core:${jme_version}" - testCompile project(':dds_writer__cli') - testCompile project(':dds_writer__s3tc_lwjgl2_delegate') - testCompile project(':dds_writer__rgtc_lwjgl2_delegate') - testCompile project(':dds_writer__lwjgl2_blockcompression_delegate') + compile project(':dds_writer__cli') + compile project(':dds_writer__s3tc_lwjgl2_delegate') + compile project(':dds_writer__rgtc_lwjgl2_delegate') + compile project(':dds_writer__lwjgl2_blockcompression_delegate') - testCompile "${jme_group}:jme3-core:${jme_version}" - testCompile "${jme_group}:jme3-desktop:${jme_version}" + compile "${jme_group}:jme3-core:${jme_version}" + compile "${jme_group}:jme3-desktop:${jme_version}" testCompile 'junit:junit:4.12' diff --git a/Tests/src/test/java/tests/InteractiveCLI.java b/Tests/src/test/java/tests/InteractiveCLI.java index 0f59874..05f4923 100644 --- a/Tests/src/test/java/tests/InteractiveCLI.java +++ b/Tests/src/test/java/tests/InteractiveCLI.java @@ -1,8 +1,13 @@ package tests; import ddswriter.cli.CLI109; +import ddswriter.delegates.lwjgl2_s3tc.S3tcCLI109Module; public class InteractiveCLI{ public static void main(String[] args) throws Exception { - CLI109.main(new String[]{"--debug","--use_lwjgl","--interactive"}); + // S3tcCLI109Module.class.newInstance(); + CLI109.main(new String[]{"--debug","--interactive","--use-lwjgl"}); + // CLI109.main(new String[]{"--debug","--in","D:\\Assets\\AGEN\\thelab_map\\textures\\Ramp_BaseColorMap.png","--out","C:\\Users\\Win7rb\\AppData\\Local\\Temp\\test.dds","--use-opengl", + // "--format","S3TC_DXT1","--gen-mipmaps" + // }); } } diff --git a/build.gradle b/build.gradle index 00475b5..86946aa 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ allprojects { group="com.github.riccardobl.DDSWriter" + + version= project.hasProperty('in_version') ? project.getProperty('in_version') : '-SNAPSHOT' if (project.hasProperty("DEV_INSTALL")){ version="dev" @@ -17,6 +19,17 @@ allprojects { } +task buildBundle( type: Jar, dependsOn: subprojects.tasks["build"] ) { + baseName = project.name +'-bundle' + manifest { + attributes 'Main-Class': "ddswriter.cli.CLI109" + } + subprojects.each { subproject -> + from subproject.configurations.archives.allArtifacts.files.collect { + zipTree(it) + } + } +} subprojects { apply plugin: 'maven' diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..cadd9e5 --- /dev/null +++ b/build.sh @@ -0,0 +1,29 @@ +#!/bin/bash +./gradlew clean + +if [ "$1" = "travis" ]; +then + if [ "$TRAVIS_TAG" != "" ]; + then + args="-Pin_version=$TRAVIS_TAG" + else + args="-Pin_version=$TRAVIS_COMMIT" + fi +else + args=$@ +fi + +./gradlew build buildBundle $args +cd build/libs +cp -Rvf ../../res/* . +chmod +x *.sh +rm -Rvf dist +if [ "$LINUX" != "" ]; +then + ./make-linux-bundle.sh +fi +if [ "$WINDOWS" != "" ]; +then + ./make-windows-bundle.sh +fi +./make-generic-bundle.sh diff --git a/dds_writer/src/main/java/ddswriter/DDSDelegate.java b/dds_writer/src/main/java/ddswriter/DDSDelegate.java index 95a9878..624df20 100644 --- a/dds_writer/src/main/java/ddswriter/DDSDelegate.java +++ b/dds_writer/src/main/java/ddswriter/DDSDelegate.java @@ -31,5 +31,12 @@ and associated documentation files (the "Software"), to deal in the Software wit */ public interface DDSDelegate{ public void body(Texture tx,Map options, DDS_HEADER header,DDS_BODY body)throws Exception ; - public void header(Texture tx,Map options,DDS_HEADER header)throws Exception ; + + public void header(Texture tx, Map options, DDS_HEADER header) throws Exception; + + /** + * Since the same delegate can be used multiple times, this method is called after every succesful export and should + * reset the delegate to its original state. + */ + public void end(); } diff --git a/dds_writer/src/main/java/ddswriter/DDSSlicedDelegate.java b/dds_writer/src/main/java/ddswriter/DDSSlicedDelegate.java index 1f7b5ec..c6c962f 100644 --- a/dds_writer/src/main/java/ddswriter/DDSSlicedDelegate.java +++ b/dds_writer/src/main/java/ddswriter/DDSSlicedDelegate.java @@ -41,6 +41,11 @@ public void skip() { SKIP=true; } + @Override + public void end() { + SKIP=false; + } + public abstract void body(Texture tx, Texel ir, int mipmap, int slice, Map options, DDS_HEADER header, DDS_BODY body) throws Exception; public abstract void header(Texture tx, Texel ir, int mipmap, int slice, Map options, DDS_HEADER header) throws Exception; @@ -64,8 +69,8 @@ public void process_slice(Texture tx, Texel ir, int mipmap, int slice, Map options, DDS_HEADER header, DD int mipmaps=!tx.getImage().hasMipmaps()?1:tx.getImage().getMipMapSizes().length; // boolean is_header=body==null; - if(tx instanceof Texture2D){ for(int mipmap=0;mipmap options,Collection=ir.getWidth()||y>=ir.getHeight()||x<0||y<0){ LOGGER.warn("Invalid coordinates x{} y{} for image w{} h{}. Use padding color.",x,y,ir.getWidth(),ir.getHeight()); c=PADDINGPX_COLOR; }else{ - c=ir.getPixel(x,y).toVector4f(); + c=new Pixel(PixelFormat.FLOAT_NORMALIZED_RGBA,ir.getPixel(x,y).toVector4f()); } pixels[xl][yl]=c; } } - Texel tx=new Texel(PixelFormat.FLOAT_NORMALIZED_RGBA,pixels); + Texel tx=new Texel(pixels); tx.AREA=new Vector2f[]{from,to }; return tx; } - public static Texel fromTexel(PixelFormat dest_format, Texel tx, Vector2f from, Vector2f to) { - Vector4f pixels[][]=new Vector4f[(int)(to.x-from.x)][(int)(to.y-from.y)]; + public static Texel fromTexel(Texel tx, Vector2f from, Vector2f to) { + Pixel pixels[][]=new Pixel[(int)(to.x-from.x)][(int)(to.y-from.y)]; for(int y=(int)from.y;y=tx.getWidth()||y>=tx.getHeight()||x<0||y<0){ LOGGER.warn("Invalid coordinates x{} y{} for texel w{} h{}. Use padding color.",x,y,tx.getWidth(),tx.getHeight()); c=PADDINGPX_COLOR; }else{ - c=tx.get(dest_format,x,y); + c=tx.get(x,y); } pixels[xl][yl]=c; } } - Texel tnx=new Texel(PixelFormat.FLOAT_NORMALIZED_RGBA,pixels); + Texel tnx=new Texel(pixels); tnx.AREA=new Vector2f[]{from,to @@ -103,80 +102,41 @@ public static Texel fromTexel(PixelFormat dest_format, Texel tx, Vector2f from, return tnx; } - public Texel(PixelFormat format,int w,int h){ - this(format,new Vector4f[w][h]); + public Texel(int w,int h){ + this(new Pixel[w][h]); } - public Texel(PixelFormat format,Vector4f pixels[][]){ - this(format,pixels,new Vector2f[]{new Vector2f(0,0),// from + public Texel(Pixel pixels[][]){ + this(pixels,new Vector2f[]{new Vector2f(0,0),// from new Vector2f(pixels.length,pixels[0].length)//to }); } - public Texel(PixelFormat format,Vector4f pixels[][],Vector2f area[]){ + public Texel(Pixel pixels[][],Vector2f area[]){ PIXELS=pixels; - FORMAT=format; AREA=area; } - protected Vector4f convert(PixelFormat from, PixelFormat to, Vector4f c) { - if(from==to) return c.clone(); - if(from==PixelFormat.FLOAT_NORMALIZED_RGBA){ - switch(to){ - case INT_RGBA:{ - Vector4f out=c.clone(); - out.x=(int)(c.x*255f); - out.y=(int)(c.y*255f); - out.z=(int)(c.z*255f); - out.w=(int)(c.w*255f); - return out; - } - case PACKED_ARGB:{ - Vector4f out=convert(PixelFormat.FLOAT_NORMALIZED_RGBA,PixelFormat.INT_RGBA,c); - out=convert(PixelFormat.INT_RGBA,PixelFormat.PACKED_ARGB,out); - return out; - } - } - }else if(from==PixelFormat.INT_RGBA){ - switch(to){ - case FLOAT_NORMALIZED_RGBA:{ - Vector4f out=c.clone(); - out.x=(c.x/255f); - out.y=(c.y/255f); - out.z=(c.z/255f); - out.w=(c.w/255f); - return out; - } - case PACKED_ARGB:{ - Vector4f out=new Vector4f(); - int p=(int)c.w<<24|(int)c.x<<16|(int)c.y<<8|(int)c.z; - out.x=p; - return out; - } - } - } - return null; - } - public void convertFormat(PixelFormat format) { - for(int x=0;x=dst.getWidth()||y>=dst.getHeight()) continue; dst.setPixel(x,y,crgba); } diff --git a/dds_writer/src/main/java/ddswriter/TexelMipmapGenerator.java b/dds_writer/src/main/java/ddswriter/TexelMipmapGenerator.java index 7492d52..df1dedb 100644 --- a/dds_writer/src/main/java/ddswriter/TexelMipmapGenerator.java +++ b/dds_writer/src/main/java/ddswriter/TexelMipmapGenerator.java @@ -24,18 +24,17 @@ and associated documentation files (the "Software"), to deal in the Software wit import ddswriter.Texel.PixelFormat; public class TexelMipmapGenerator{ + private static Vector4f bottomLeft=new Vector4f(); + private static Vector4f bottomRight=new Vector4f(); + private static Vector4f topLeft=new Vector4f(); + private static Vector4f topRight=new Vector4f(); public static Texel scaleImage(Texel input, int outputWidth, int outputHeight) { - Texel output=new Texel(PixelFormat.FLOAT_NORMALIZED_RGBA,outputWidth,outputHeight); + Texel output=new Texel(outputWidth,outputHeight); float xRatio=((float)(input.getWidth()-1))/output.getWidth(); float yRatio=((float)(input.getHeight()-1))/output.getHeight(); - - Vector4f outputColor=new Vector4f(); - Vector4f bottomLeft=new Vector4f(); - Vector4f bottomRight=new Vector4f(); - Vector4f topLeft=new Vector4f(); - Vector4f topRight=new Vector4f(); + for(int y=0;y options, DDS_HEADER header) throws Exception { + String format=((String)options.get("format")); if(format==null){ @@ -104,10 +111,11 @@ public void body(Texture tx, Texel ir, int mipmap, int slice, Map int h=ir.getHeight(); for(int y=0;y genericHelp() { out.add("Options: \n"); out.add(" --in : Input file\n"); out.add(" --out : Output file\n"); - out.add(" --format: Output format. Default: ARGB8 (uncompressed)\n"); + out.add(" --inlist : Csv list of multiple input files\n"); + out.add(" --format: Output format. Default: ARGB8 (uncompressed). When --inlist is used, this params becomes a csv list.\n"); + out.add(" --multires <:100%,low:50%,lowest:50%,solid:8px>: Output multiple images "+ + "with given resolutions, the param is a csv list in which every resolution level is represent as SUFFIX:SIZE"+ + "where SUFFIX is a string that will be appended to the filename and can be empty, SIZE is a value that can be either percentage or pixels" + +"(the size of the previous level will be used to calculate the percentage). NOTE: Works only with 2d textures" + +" \n"); + out.add(" --interpolation-method : NEAREST, BILINEAR, BICUBIC (optional, default: BILINEAR) \n"); out.add(" --gen-mipmaps: Generate mipmaps\n"); + out.add(" --interactive: Open interactive console\n"); out.add(" --exit: Exit interactive console\n"); out.add(" --debug: Show debug informations\n"); out.add("Input formats:\n"); @@ -94,9 +110,32 @@ static int run(String[] _args) throws Exception { } } - + String interpolation=options.get("interpolation-method"); + if(interpolation==null) interpolation="bilinear"; String in=options.get("in"); + boolean in_as_list=false; + boolean out_as_list=false; + if(in==null){ + in=options.get("inlist"); + if(in!=null)in_as_list=true; + } String out=options.get("out"); + if(out==null){ + out=options.get("outlist"); + if(out!=null)out_as_list=true; + } + String _multires=options.get("multires"); + List multires=null; + if(_multires!=null){ + multires=new ArrayList(); + String vls[]=_multires.split(","); + for(String v:vls){ + String x[]=v.split(":"); + String prefix=x.length==1?"":x[0]; + String size=x[x.length-1]; + multires.add(new String[]{prefix,size}); + } + } ArrayList modules=new ArrayList (); @@ -120,55 +159,164 @@ static int run(String[] _args) throws Exception { Texture tx=null; - String ext=in.substring(in.lastIndexOf(".")+1); - - switch(ext){ - case "jpg": - case "jpeg": - case "bmp": - case "png":{ - AWTLoader loader=new AWTLoader(); - Image img=loader.load(ImageIO.read(new File(in)),false); - tx=new Texture2D(img); - break; + + List ins=new ArrayList(); + if(in_as_list){ + ins.addAll(Arrays.asList(in.split(","))); + }else{ + ins.add(in); + } + + ArrayList outs=new ArrayList(); + if(out_as_list){ + outs.addAll(Arrays.asList(out.split(","))); + + }else{ + outs.add(out); + } + + if(in_as_list&&out_as_list){ + if(ins.size()!=outs.size()){ + System.err.println("--inlist and --outlist must have the same number of values"); } - case "tga":{ - InputStream is=new BufferedInputStream(new FileInputStream(new File(in))); - Image img=TGALoader.load(is,false); - tx=new Texture2D(img); - is.close(); - break; + } + + String formats[]=options.containsKey("format")?options.get("format").split(","):null; + int i=0; + for(String xin:ins){ + String xout=outs.get(out_as_list?i:0); + String ext=xin.substring(xin.lastIndexOf(".")+1); + if(formats!=null) options.put("format",formats[i>=formats.length?formats.length-1:i]); + + switch(ext){ + case "jpg": + case "jpeg": + case "bmp": + case "png":{ + AWTLoader loader=new AWTLoader(); + Image img=loader.load(ImageIO.read(new File(xin)),false); + tx=new Texture2D(img); + break; + } + case "tga":{ + InputStream is=new BufferedInputStream(new FileInputStream(new File(xin))); + Image img=TGALoader.load(is,false); + tx=new Texture2D(img); + is.close(); + break; + } + case "dds":{ + InputStream is=new BufferedInputStream(new FileInputStream(new File(xin))); + tx=DDSLoaderI.load(is); + is.close(); + } } - case "dds":{ - InputStream is=new BufferedInputStream(new FileInputStream(new File(in))); - tx=DDSLoaderI.load(is); - is.close(); + + if(tx==null){ + System.err.println("Input format not supported: "+xin); + if(!in_as_list) return 1; + else continue; } - } - if(tx==null){ - System.err.println("Input format not supported: "+ext); - return 1; - } + if(multires!=null&&tx.getType()==Type.TwoDimensional){ + BufferedImage img=null; + try{ + img=ImageToAwt.convert(tx.getImage(), false, true, 0); + }catch(Exception e){ + System.err.println("Can't scale image "+xin+": "+e); + // e.printStackTrace(); + } + int size=tx.getImage().getWidth(); + for(String[] res:multires){ + String outres=xout; + File outf=new File(outres); + + if(outf.isDirectory()){ + File inf=new File(xin); + outf=new File(outf.getAbsolutePath(),inf.getName()+".dds"); + } - OutputStream fo=new BufferedOutputStream(new FileOutputStream(new File(out))); - DDSWriter.write(tx,options,delegates,fo); - fo.close(); + outres=outf.getAbsolutePath(); + int x=outres.lastIndexOf("."); + outres=outres.substring(0,x)+res[0]+outres.substring(x); + outf=new File(outres); + + OutputStream fo=new BufferedOutputStream(new FileOutputStream(outf)); + + if(res[1].endsWith("px")){ + size=Integer.parseInt(res[1].substring(0,res[1].length()-2)); + }else if(res[1].endsWith("%")){ + int pc=Integer.parseInt(res[1].substring(0,res[1].length()-1)); + size=size*pc/100; + }else{ + size=tx.getImage().getWidth(); + } + + Texture resizedtx; + if(img!=null&&size c) { String out=""; for(String s:c){ - out+=s; + out+=s; } return out; } + + + public static BufferedImage resizeTo(BufferedImage sourceImage, int width, int height,String interpolation) { + double scaleX = width / (double) sourceImage.getWidth(); + double scaleY = height / (double) sourceImage.getHeight(); + AffineTransform scaleTransform=AffineTransform.getScaleInstance(scaleX,scaleY); + int intr=AffineTransformOp.TYPE_BILINEAR; + if(interpolation.equalsIgnoreCase("nearest")){ + intr=AffineTransformOp.TYPE_NEAREST_NEIGHBOR; + }else if(interpolation.equalsIgnoreCase("bicubic")){ + intr=AffineTransformOp.TYPE_BICUBIC; + } + AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, intr); + + BufferedImage scaledImage=bilinearScaleOp.filter(sourceImage,new BufferedImage(width,height,sourceImage.getType())); + return scaledImage; + } + + public static void main(String[] _args) throws Exception { boolean interactive=false; for(int i=0;i<_args.length;i++){ diff --git a/dds_writer__cli/src/main/resources/log4j2.xml b/dds_writer__cli/src/main/resources/log4j2.xml new file mode 100644 index 0000000..57653ff --- /dev/null +++ b/dds_writer__cli/src/main/resources/log4j2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dds_writer__lwjgl2_blockcompression_delegate/src/main/java/ddswriter/delegates/lwjgl2/LWJGLBlockCompressionDelegate.java b/dds_writer__lwjgl2_blockcompression_delegate/src/main/java/ddswriter/delegates/lwjgl2/LWJGLBlockCompressionDelegate.java index d87f6d8..93a94dc 100644 --- a/dds_writer__lwjgl2_blockcompression_delegate/src/main/java/ddswriter/delegates/lwjgl2/LWJGLBlockCompressionDelegate.java +++ b/dds_writer__lwjgl2_blockcompression_delegate/src/main/java/ddswriter/delegates/lwjgl2/LWJGLBlockCompressionDelegate.java @@ -43,6 +43,7 @@ and associated documentation files (the "Software"), to deal in the Software wit import com.jme3.texture.Texture; import com.jme3.util.BufferUtils; +import ddswriter.Pixel; import ddswriter.Texel; import ddswriter.Texel.PixelFormat; import ddswriter.delegates.CommonBodyDelegate; @@ -79,16 +80,15 @@ public void lwjglBody(int gl_format, Texture tx, Texel ir, int mipmap, int slice int id=intBuf1.get(0); glBindTexture(GL_TEXTURE_2D,id); - - Vector4f pixels[][]=ir.getPixels(PixelFormat.FLOAT_NORMALIZED_RGBA); + Pixel pixels[][]=ir.getPixels(); FloatBuffer bbf=BufferUtils.createFloatBuffer(pixels.length*pixels[0].length*4); for(int y=0;y options, List help, ArrayList delegates) { + if(ADDED_TO_HELP)return; + int i=0; + for(String s:help){ + if(s.startsWith("Input formats")){ + break; + }else{ + i++; + } + } + help.add(i," --use-opengl: Enable hardware compression with opengl\n"); + ADDED_TO_HELP=true; + } public boolean startGL() { if(pbuffer!=null) return true; try{ + String extf=System.getProperty("nativePath"); + if(extf!=null)NativeLibraryLoader.setCustomExtractionFolder(extf); NativeLibraryLoader.loadNativeLibrary("lwjgl",true); + PixelFormat pixel_format = new PixelFormat(8,8,0); diff --git a/dds_writer__rgtc_lwjgl2_delegate/build.gradle b/dds_writer__rgtc_lwjgl2_delegate/build.gradle index 9eeedf7..12d157b 100644 --- a/dds_writer__rgtc_lwjgl2_delegate/build.gradle +++ b/dds_writer__rgtc_lwjgl2_delegate/build.gradle @@ -17,15 +17,15 @@ dependencies { } -task fatJar(type: Jar) { - manifest { - attributes 'Main-Class': "ddswriter.cli.CLI109" - } - baseName = project.name + '-fat' - from { - (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } - } - with jar -} +// task fatJar(type: Jar) { +// manifest { +// attributes 'Main-Class': "ddswriter.cli.CLI109" +// } +// baseName = project.name + '-fat' +// from { +// (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } +// } +// with jar +// } -jar.finalizedBy(fatJar) +// jar.finalizedBy(fatJar) diff --git a/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RGTC_LWJGL2CompressionDelegate.java b/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RGTC_LWJGL2CompressionDelegate.java index 96c10b5..9d46d12 100644 --- a/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RGTC_LWJGL2CompressionDelegate.java +++ b/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RGTC_LWJGL2CompressionDelegate.java @@ -54,10 +54,13 @@ private Format(String s,int blocksize,int gl,String... aliases){ } protected Format FORMAT; - + @Override + public void end() { + super.end(); + FORMAT=null; + } @Override public void header(Texture tx, Map options, DDS_HEADER header) throws Exception { - String format=((String)options.get("format")); if(format==null){ skip(); diff --git a/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RgtcCLI109Module.java b/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RgtcCLI109Module.java index 3215ad2..e883789 100644 --- a/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RgtcCLI109Module.java +++ b/dds_writer__rgtc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_rgtc/RgtcCLI109Module.java @@ -38,21 +38,16 @@ public RgtcCLI109Module(){ @Override public void load(Map options, List help, ArrayList delegates) { - if(!startGL()) return; - int i=0; - for(String s:help){ - if(s.startsWith("Input formats")){ - break; - }else{ - i++; - } - } - help.add(i," --use-lwjgl: Enable hardware compression with lwjgl\n"); - + super.load(options, help, delegates); String hwc=options.get("use_lwjgl"); - if(hwc==null)options.get("use-lwjgl"); + if(hwc==null)hwc=options.get("use-lwjgl"); + if(hwc==null)hwc=options.get("use-opengl"); + if(hwc==null||hwc.equals("false")) return; - i=0; + + if(!startGL()) return; + + int i=0; for(String s:help){ if(s.startsWith("Output formats")){ break; diff --git a/dds_writer__s3tc_lwjgl2_delegate/build.gradle b/dds_writer__s3tc_lwjgl2_delegate/build.gradle index 8a225f9..cc6e1f5 100644 --- a/dds_writer__s3tc_lwjgl2_delegate/build.gradle +++ b/dds_writer__s3tc_lwjgl2_delegate/build.gradle @@ -15,16 +15,16 @@ dependencies { } -task fatJar(type: Jar) { - manifest { - attributes 'Main-Class': "ddswriter.cli.CLI109" - } - baseName = project.name + '-fat' - from { - (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } - } - with jar -} +// task fatJar(type: Jar) { +// manifest { +// attributes 'Main-Class': "ddswriter.cli.CLI109" +// } +// baseName = project.name + '-fat' +// from { +// (configurations.runtime).collect { it.isDirectory() ? it : zipTree(it) } +// } +// with jar +// } -jar.finalizedBy(fatJar) +// jar.finalizedBy(fatJar) diff --git a/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3TC_LWJGL2CompressionDelegate.java b/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3TC_LWJGL2CompressionDelegate.java index 1020604..90479b8 100644 --- a/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3TC_LWJGL2CompressionDelegate.java +++ b/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3TC_LWJGL2CompressionDelegate.java @@ -57,7 +57,11 @@ private Format(String s,int blocksize,int gl,String... aliases){ } - + @Override + public void end() { + super.end(); + FORMAT=null; + } @Override public void header(Texture tx, Map options, DDS_HEADER header) throws Exception { diff --git a/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3tcCLI109Module.java b/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3tcCLI109Module.java index b7160f5..845b662 100644 --- a/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3tcCLI109Module.java +++ b/dds_writer__s3tc_lwjgl2_delegate/src/main/java/ddswriter/delegates/lwjgl2_s3tc/S3tcCLI109Module.java @@ -36,21 +36,18 @@ public S3tcCLI109Module(){ @Override public void load(Map options, List help, ArrayList delegates) { - if(!startGL()) return; - int i=0; - for(String s:help){ - if(s.startsWith("Input formats")){ - break; - }else{ - i++; - } - } - help.add(i," --use-lwjgl: Enable hardware compression with lwjgl\n"); + super.load(options, help, delegates); String hwc=options.get("use_lwjgl"); - if(hwc==null)options.get("use-lwjgl"); + if(hwc==null)hwc=options.get("use-lwjgl"); + if(hwc==null)hwc=options.get("use-opengl"); if(hwc==null||hwc.equals("false")) return; - i=0; + + if(!startGL()) return; + + + + int i=0; for(String s:help){ if(s.startsWith("Output formats")){ break; diff --git a/res/Launcher.c b/res/Launcher.c new file mode 100644 index 0000000..5684ee5 --- /dev/null +++ b/res/Launcher.c @@ -0,0 +1,263 @@ +#include +#include +#include + +// #ifndef SEP +// #define SEP "/" +// #endif +#if !defined(WINDOWS) && !defined(LINUX) +#define LINUX +#endif + +#ifdef WINDOWS +#include +#include "7z.h" +#include "7z_dll.h" +#include "WindowsLauncher.h" +#define MKDIR "mkdir" +#define SEP "\\" +#endif +#ifdef LINUX +#include +#include "LinuxLauncher.h" +#define MKDIR "mkdir -p" +#define SEP "/" +#endif + +#ifndef SHARED_ROOT +#include +#define _RND_CHARSET \ + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +void rand_str(char *dest, size_t length) { + while (length-- > 0) { + size_t index = (double)rand() / RAND_MAX * (sizeof _RND_CHARSET - 1); + *dest++ = _RND_CHARSET[index]; + } + *dest = '\0'; +} +#else +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +int fexists(const char *f) { + FILE *fp; + if (fp = fopen(f, "r")) { + fclose(fp); + return 1; + } + return 0; +} +#endif + +const char *getTempDir(){ + const char* d=getenv("TMPDIR"); + if(d==NULL){ + d = getenv("TMP"); + } + if(d==NULL){ + d = getenv("TEMP"); + } + if(d==NULL){ + d = getenv("TEMPDIR"); + } + #ifdef LINUX + if(d==NULL){ + d = "/tmp"; + } +#endif + return d; +} + +int main(int argc, char **argv) { + if (argc < 1) { + printf("Error! Launch this from a shell."); + return 1; + } +#ifndef SHARED_ROOT + srand(time(NULL)); +#endif + + char cmd[512]; + const char *tmp = getTempDir(); + if (tmp == NULL) { + printf("Error! Invalid tmp folder"); + return 1; + } +#ifdef DEBUG + printf("System temp folder %s\n", tmp); + printf("Args:\n"); + for (int i = 0; i < argc;i++){ + printf("%s\n", argv[i]); + } +#endif + + char root[64]; + +#ifndef SHARED_ROOT + char rand[6]; + rand_str(rand, 6); +#else + char *rand = TOSTRING(SHARED_ROOT); +#endif + + strcpy(root, tmp); + strcat(root, SEP); + strcat(root, rand); + strcat(root, SEP); + strcat(root, "\0"); + +#ifdef DEBUG + printf("Use temp folder %s\n", root); +#endif + strcpy(cmd, MKDIR); + strcat(cmd, " \""); + strcat(cmd, root); + strcat(cmd, "\"\0"); + +#ifdef DEBUG + printf("Cmd %s \n", cmd); +#endif + system(cmd); + + char Bundle_path[strlen(root) + 32]; +#ifdef WINDOWS + char __7z_exe_path[strlen(root) + 6]; + strcpy(__7z_exe_path, root); + strcat(__7z_exe_path, "7z.exe"); + + char __7z_dll_path[strlen(root) + 6]; + strcpy(__7z_dll_path, root); + strcat(__7z_dll_path, "7z.dll"); + + strcpy(Bundle_path, root); + strcat(Bundle_path, "windows-bundle.7z"); + strcat(Bundle_path, "\0"); + + char WindowsLauncher_bat_path[strlen(root) + 19]; + strcpy(WindowsLauncher_bat_path, root); + strcat(WindowsLauncher_bat_path, "WindowsLauncher.bat"); +#endif +#ifdef LINUX + strcpy(Bundle_path, root); + strcat(Bundle_path, "linux-bundle.tar.gz"); + strcat(Bundle_path, "\0"); + + char LinuxLauncher_sh_path[strlen(root) + 17]; + strcpy(LinuxLauncher_sh_path, root); + strcat(LinuxLauncher_sh_path, "LinuxLauncher.sh"); +#endif + +#ifdef DEBUG +#ifdef WINDOWS + printf("7z.exe %s\n", __7z_exe_path); + printf("7z.dll %s\n", __7z_dll_path); +#endif + printf("bundle.7z %s\n", Bundle_path); + printf("Launcher %s\n", argv[0]); +#endif + + FILE *out; + FILE *in; + +#ifdef WINDOWS +#ifdef SHARED_ROOT + if (!fexists(__7z_exe_path)) { +#endif + + out = fopen(__7z_exe_path, "wb"); + fwrite(__7z_exe, 1, __7z_exe_len, out); + fclose(out); + +#ifdef SHARED_ROOT + } +#endif + +#ifdef SHARED_ROOT + if (!fexists(__7z_dll_path)) { +#endif + out = fopen(__7z_dll_path, "wb"); + fwrite(__7z_dll, 1, __7z_dll_len, out); + fclose(out); +#ifdef SHARED_ROOT + } +#endif + +#endif + +#ifdef WINDOWS +#ifdef SHARED_ROOT + if (!fexists(WindowsLauncher_bat_path)) { +#endif + out = fopen(WindowsLauncher_bat_path, "wb"); + fwrite(WindowsLauncher_bat, 1, WindowsLauncher_bat_len, out); + fclose(out); +#ifdef SHARED_ROOT + } +#endif +#endif +#ifdef LINUX +#ifdef SHARED_ROOT + if (!fexists(LinuxLauncher_sh_path)) { +#endif + out = fopen(LinuxLauncher_sh_path, "wb"); + fwrite(LinuxLauncher_sh, 1, LinuxLauncher_sh_len, out); + fclose(out); +#ifdef SHARED_ROOT + } +#endif +#endif + +#ifdef SHARED_ROOT + if (!fexists(Bundle_path)) { +#endif + unsigned char chunk[1024 * 1024]; + out = fopen(Bundle_path, "wb"); + in = fopen(argv[0], "rb"); + while (!feof(in)) { + int read = fread(chunk, 1, 1, in); + fwrite(chunk, 1, read, out); + } + fclose(out); + fclose(in); +#ifdef SHARED_ROOT + } +#endif + +#ifdef LINUX + strcpy(cmd, "\"$(which chmod)\""); + strcat(cmd, " +x \""); + strcat(cmd, LinuxLauncher_sh_path); + strcat(cmd, "\"\0"); + + system(cmd); +#ifdef DEBUG + printf("Cmd %s \n", cmd); +#endif +#endif + + +#ifdef LINUX + argv[0] = LinuxLauncher_sh_path; + #ifdef DEBUG + printf("Exec Args:\n"); + for (int i = 0; i < argc;i++){ + printf("%s\n", argv[i]); + } +#endif + + execv(LinuxLauncher_sh_path, argv); +#endif +#ifdef WINDOWS + argv[0] = WindowsLauncher_bat_path; +#ifdef DEBUG + printf("Exec Args:\n"); + for (int i = 0; i < argc;i++){ + printf("%s\n", argv[i]); + } +#endif + spawnv(P_WAIT,WindowsLauncher_bat_path, argv); +#endif + + + + return 0; +} \ No newline at end of file diff --git a/res/LinuxLauncher.sh b/res/LinuxLauncher.sh new file mode 100644 index 0000000..2416b7e --- /dev/null +++ b/res/LinuxLauncher.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +ROOT="`dirname $0`" +if [ ! -f "$ROOT/READY" ]; +then + export ARCHIVE=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' "$ROOT/linux-bundle.tar.gz"` + tail -n+$ARCHIVE "$ROOT/linux-bundle.tar.gz" | tar --skip-old-files -xz -C $ROOT > /dev/null + echo "1">"$ROOT/READY" +fi +VM_ARGS="-XX:+AggressiveOpts -XX:+UseG1GC -XX:-UseGCOverheadLimit" +ARGS=$@ +if [ "$1" = "--vmArgs" ]; +then + VM_ARGS=$VM_ARGS $2 + ARGS=${@:3} +fi +"$ROOT/jre/bin/java" $VM_ARGS -DnativePath="$ROOT" -jar "$ROOT/ddswriter.jar" $ARGS diff --git a/res/WindowsLauncher.bat b/res/WindowsLauncher.bat new file mode 100644 index 0000000..5df369f --- /dev/null +++ b/res/WindowsLauncher.bat @@ -0,0 +1,13 @@ +@ECHO OFF +set ROOT=%~dp0 +set ROOT=%ROOT:\=\\% +IF NOT EXIST "%~dp0READY" ( + "%ROOT%7z.exe" x "%~dp0windows-bundle.7z" -o"%ROOT%" > NUL + @echo "1" > "%ROOT%READY" +) +set VM_ARGS=-XX:+AggressiveOpts -XX:+UseG1GC -XX:-UseGCOverheadLimit +set ARGS=%* +if [%1]==[--vmArgs] ( + set VM_ARGS=%VM_ARGS% %2 +) +"%ROOT%jre\\bin\\java" %VM_ARGS% -DnativePath="%ROOT%" -jar "%ROOT%ddswriter.jar" %ARGS% diff --git a/res/make-generic-bundle.sh b/res/make-generic-bundle.sh new file mode 100644 index 0000000..a9210bb --- /dev/null +++ b/res/make-generic-bundle.sh @@ -0,0 +1,6 @@ +#!/bin/bash +v="`ls ddswriter-bundle-*.jar`" +v=${v%.*} +v=${v##*-} +mkdir -p dist +cp ddswriter-bundle-*.jar dist/DDSWriter-$v.jar diff --git a/res/make-linux-bundle.sh b/res/make-linux-bundle.sh new file mode 100644 index 0000000..c59feb9 --- /dev/null +++ b/res/make-linux-bundle.sh @@ -0,0 +1,49 @@ +#!/bin/bash +if [ "$DEBUG" != "" ]; +then + export DEBUG="-DDEBUG" +fi +v="`ls ddswriter-bundle-*.jar`" +v=${v%.*} +v=${v##*-} +wget https://bitbucket.org/alexkasko/openjdk-unofficial-builds/downloads/openjdk-1.7.0-u80-unofficial-linux-amd64-image.zip -O lin.zip +hash="`sha256sum lin.zip | cut -d ' ' -f 1`" +if [ "$hash" != "b87beb73f07af5b89b35b8656439c70fb7f46afdaa36e4a9394ad854c3a0b23d" ]; +then + echo "Corrupted JRE" + exit 1 +fi +unzip lin.zip +mv openjdk-*-linux-*-image linux-bundle +rm -Rf linux-bundle/src.zip +rm -Rf linux-bundle/man +cp ddswriter-bundle-*.jar linux-bundle/ddswriter.jar +tar -czvf linux-bundle.tar.gz -C linux-bundle/ . +# cat LinuxLauncher.sh linux-bundle.tar.gz > DDSWriter-$v-linux32 +# mkdir -p dist +# mv DDSWriter-$v-linux32 dist/ +# rm lin.zip +# rm -Rvf linux-bundle +# rm linux-bundle.tar.gz + + +rm -Rf build-llauncher +mkdir build-llauncher +mkdir -p dist + +xxd -i LinuxLauncher.sh > build-llauncher/LinuxLauncher.h +cp linux-bundle.tar.gz build-llauncher/linux-bundle.tar.gz +cp Launcher.c build-llauncher/Launcher.c +cd build-llauncher/ +shared_root="DDSw-build-`date +%Y%m%d_%H%M%S`" +gcc Launcher.c -o Launcher.bin -DSHARED_ROOT=$shared_root -DLINUX $DEBUG +echo -e "\n__ARCHIVE_BELOW__" > sep.tmp +cat Launcher.bin sep.tmp linux-bundle.tar.gz > ../dist/DDSWriter-$v-linux64 +chmod +x ../dist/DDSWriter-$v-linux64 +rm sep.tmp +cd .. +# mv DDSWriter-$v-linux32 dist/ + +# rm lin.zip +# rm -Rvf windows-bundle +# rm windows-bundle.7z \ No newline at end of file diff --git a/res/make-windows-bundle.sh b/res/make-windows-bundle.sh new file mode 100644 index 0000000..4022353 --- /dev/null +++ b/res/make-windows-bundle.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# Win dependencies: +# choco install wget 7z +# wget http://www.labtestproject.com/files/sha256sum/sha256sum.exe -O /bin/sha256sum.exe +# (mingw) +if [ "$DEBUG" != "" ]; +then + export DEBUG="-DDEBUG" +fi +v="`ls ddswriter-bundle-*.jar`" +v=${v%.*} +v=${v##*-} +wget https://bitbucket.org/alexkasko/openjdk-unofficial-builds/downloads/openjdk-1.7.0-u80-unofficial-windows-amd64-image.zip -O win.zip +hash="`sha256sum win.zip | cut -d ' ' -f 1`" +if [ "$hash" != "1b835601f4ae689b9271040713b01d6bdd186c6a57bb4a7c47e1f7244d5ac928" ]; +then + echo "Corrupted JRE" + exit 1 +fi +unzip win.zip +mkdir windows-bundle +mv openjdk-*-windows-*-image windows-bundle/jre +rm -Rf windows-bundle/jre/src.zip +cp ddswriter-bundle-*.jar windows-bundle/ddswriter.jar + +wget "https://www.7-zip.org/a/7z1805.exe" -O 7z.exe +hash="`sha256sum 7z.exe | cut -d ' ' -f 1`" +if [ "$hash" != "647a9a621162cd7a5008934a08e23ff7c1135d6f1261689fd954aa17d50f9729" ]; +then + echo "Corrupted 7z" + exit 1 +fi +mkdir -p 7z +7z x 7z.exe -o7z +rm 7z.exe +cp 7z/7z.exe 7z.exe +cp 7z/7z.dll 7z.dll +cd windows-bundle +7z a -t7z ../windows-bundle.7z * +cd .. + +rm -Rf build-wlauncher +mkdir build-wlauncher +mkdir -p dist +xxd -i 7z.exe > build-wlauncher/7z.h +xxd -i 7z.dll > build-wlauncher/7z_dll.h +xxd -i WindowsLauncher.bat > build-wlauncher/WindowsLauncher.h +cp windows-bundle.7z build-wlauncher/windows-bundle.7z +cp Launcher.c build-wlauncher/Launcher.c +cd build-wlauncher/ +shared_root="DDSw-build-`date +%Y%m%d_%H%M%S`" + +if [[ "`uname -a`" == MINGW* ]]; +then + GCC="gcc" +else + GCC="i686-w64-mingw32-gcc" +fi + +"$GCC" Launcher.c -o WindowsLauncher.exe -DSHARED_ROOT=$shared_root -DWINDOWS $DEBUG +cat WindowsLauncher.exe windows-bundle.7z > ../dist/DDSWriter-$v-win64.exe +cd .. +# mv DDSWriter-$v-win32.exe dist/ +# rm -Rvf 7z +# rm 7z.exe +# rm 7z.dll +# rm win.z/ip +# rm -Rvf windows-bundle +# rm windows-bundle.7z