|
@@ -2,19 +2,41 @@ package hxd.res;
|
|
|
|
|
|
class Texture extends Resource {
|
|
|
|
|
|
+ static var TMP = {
|
|
|
+ var b = haxe.io.Bytes.alloc(4);
|
|
|
+ b.set(0, 0xFF);
|
|
|
+ b.set(1, 0x80);
|
|
|
+ b.set(2, 0x80);
|
|
|
+ b.set(3, 0xFF);
|
|
|
+ b;
|
|
|
+ }
|
|
|
+
|
|
|
+ var needResize : Bool;
|
|
|
var tex : h3d.mat.Texture;
|
|
|
- var size : { width : Int, height : Int };
|
|
|
+ var inf : { width : Int, height : Int, isPNG : Bool };
|
|
|
|
|
|
public function getSize() : { width : Int, height : Int } {
|
|
|
- if( size != null )
|
|
|
- return size;
|
|
|
+ if( inf != null )
|
|
|
+ return inf;
|
|
|
var f = new FileInput(entry);
|
|
|
- var width = 0, height = 0;
|
|
|
+ var width = 0, height = 0, isPNG = false;
|
|
|
switch( f.readUInt16() ) {
|
|
|
case 0xD8FF: // JPG
|
|
|
f.bigEndian = true;
|
|
|
- throw "TODO";
|
|
|
+ while( true ) {
|
|
|
+ switch( f.readUInt16() ) {
|
|
|
+ case 0xFFC2, 0xFFC0:
|
|
|
+ var len = f.readUInt16();
|
|
|
+ var prec = f.readByte();
|
|
|
+ height = f.readUInt16();
|
|
|
+ width = f.readUInt16();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ f.skip(f.readUInt16() - 2);
|
|
|
+ }
|
|
|
+ }
|
|
|
case 0x5089: // PNG
|
|
|
+ isPNG = true;
|
|
|
var TMP = hxd.impl.Tmp.getBytes(256);
|
|
|
f.bigEndian = true;
|
|
|
f.readBytes(TMP, 0, 6);
|
|
@@ -35,55 +57,101 @@ class Texture extends Resource {
|
|
|
}
|
|
|
hxd.impl.Tmp.saveBytes(TMP);
|
|
|
default:
|
|
|
- throw "Unsupported file format " + entry.name;
|
|
|
+ throw "Unsupported texture format " + entry.path;
|
|
|
}
|
|
|
f.close();
|
|
|
- size = { width : width, height : height };
|
|
|
- return size;
|
|
|
+ inf = { width : width, height : height, isPNG : isPNG };
|
|
|
+ return inf;
|
|
|
}
|
|
|
|
|
|
function loadTexture() {
|
|
|
var tw = tex.width, th = tex.height;
|
|
|
- var w = size.width, h = size.height;
|
|
|
+ var w = inf.width, h = inf.height;
|
|
|
var isSquare = w == tw && h == th;
|
|
|
- entry.loadBitmap(function(bmp) {
|
|
|
- if( isSquare )
|
|
|
- tex.uploadBitmap(bmp);
|
|
|
- else {
|
|
|
- var out = hxd.impl.Tmp.getBytes(tw * th * 4);
|
|
|
- var bmp = bmp.getBytes();
|
|
|
- var p = 0, b = 0;
|
|
|
- for( y in 0...h ) {
|
|
|
- for( x in 0...w * 4 )
|
|
|
- out.set(p++, bmp.get(b++));
|
|
|
- for( i in 0...(tw - w) * 4 )
|
|
|
- out.set(p++, 0);
|
|
|
+ if( inf.isPNG ) {
|
|
|
+ function load() {
|
|
|
+ if( needResize ) {
|
|
|
+ tex.resize(tw, th);
|
|
|
+ needResize = false;
|
|
|
+ }
|
|
|
+ // immediately loading the PNG is faster than going through loadBitmap
|
|
|
+ var png = new format.png.Reader(new haxe.io.BytesInput(entry.getBytes()));
|
|
|
+ png.checkCRC = false;
|
|
|
+ var bytes = hxd.impl.Tmp.getBytes(tw * th * 4);
|
|
|
+ format.png.Tools.extract32(png.read(), bytes);
|
|
|
+ if( !isSquare ) {
|
|
|
+ throw "TODO";
|
|
|
}
|
|
|
- for( i in 0...(th - h) * tw )
|
|
|
- out.set(p++, 0);
|
|
|
- hxd.impl.Tmp.saveBytes(bmp);
|
|
|
- tex.uploadBytes(out);
|
|
|
- hxd.impl.Tmp.saveBytes(out);
|
|
|
+ tex.uploadBytes(bytes);
|
|
|
+ hxd.impl.Tmp.saveBytes(bytes);
|
|
|
+ trace(flash.Lib.getTimer());
|
|
|
}
|
|
|
- bmp.dispose();
|
|
|
- });
|
|
|
+ if( entry.isAvailable )
|
|
|
+ load();
|
|
|
+ else
|
|
|
+ entry.load(load);
|
|
|
+ } else {
|
|
|
+ // use native decoding
|
|
|
+ entry.loadBitmap(function(bmp) {
|
|
|
+ if( needResize ) {
|
|
|
+ tex.resize(tw, th);
|
|
|
+ needResize = false;
|
|
|
+ }
|
|
|
+ if( isSquare )
|
|
|
+ tex.uploadBitmap(bmp);
|
|
|
+ else {
|
|
|
+ var out = hxd.impl.Tmp.getBytes(tw * th * 4);
|
|
|
+ var bmp = bmp.getBytes();
|
|
|
+ var p = 0, b = 0;
|
|
|
+ for( y in 0...h ) {
|
|
|
+ for( x in 0...w * 4 )
|
|
|
+ out.set(p++, bmp.get(b++));
|
|
|
+ for( i in 0...(tw - w) * 4 )
|
|
|
+ out.set(p++, 0);
|
|
|
+ }
|
|
|
+ for( i in 0...(th - h) * tw )
|
|
|
+ out.set(p++, 0);
|
|
|
+ hxd.impl.Tmp.saveBytes(bmp);
|
|
|
+ tex.uploadBytes(out);
|
|
|
+ hxd.impl.Tmp.saveBytes(out);
|
|
|
+ }
|
|
|
+ bmp.dispose();
|
|
|
+ trace(flash.Lib.getTimer());
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public function toTexture( ?hasAlpha : Bool ) : h3d.mat.Texture {
|
|
|
+ public function toTexture() : h3d.mat.Texture {
|
|
|
if( tex != null && !tex.isDisposed() )
|
|
|
return tex;
|
|
|
if( tex != null ) {
|
|
|
tex.dispose();
|
|
|
tex = null;
|
|
|
}
|
|
|
- var size = getSize();
|
|
|
- var w = size.width, h = size.height;
|
|
|
+ getSize();
|
|
|
+ var w = inf.width, h = inf.height;
|
|
|
var tw = 1, th = 1;
|
|
|
while( tw < w ) tw <<= 1;
|
|
|
while( th < h ) th <<= 1;
|
|
|
- tex = h3d.Engine.getCurrent().mem.allocTexture(tw, th, false);
|
|
|
+
|
|
|
+ if( inf.isPNG && entry.isAvailable ) {
|
|
|
+ // direct upload
|
|
|
+ needResize = false;
|
|
|
+ tex = h3d.Engine.getCurrent().mem.allocTexture(tw, th, false);
|
|
|
+ } else {
|
|
|
+ // create a temp 1x1 texture while we're loading
|
|
|
+ needResize = true;
|
|
|
+ tex = h3d.Engine.getCurrent().mem.allocTexture(1, 1, false);
|
|
|
+ tex.uploadBytes(TMP);
|
|
|
+ @:privateAccess {
|
|
|
+ tex.width = tw;
|
|
|
+ tex.height = th;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
loadTexture();
|
|
|
tex.onContextLost = function() {
|
|
|
+ needResize = false;
|
|
|
loadTexture();
|
|
|
return true;
|
|
|
};
|