Skip to content
80 changes: 66 additions & 14 deletions h3d/impl/GlDriver.hx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class GlDriver extends Driver {
static var UID = 0;
public var gl : GL2;
public static var ALLOW_WEBGL2 = true;
public var textureSupport:hxd.PixelFormat;
#end

#if (hlsdl||usegl)
Expand Down Expand Up @@ -783,7 +784,10 @@ class GlDriver extends Driver {
case GL2.RED, GL2.R8, GL2.R16F, GL2.R32F: GL2.RED;
case GL2.RG, GL2.RG8, GL2.RG16F, GL2.RG32F: GL2.RG;
case GL2.RGB16F, GL2.RGB32F: GL.RGB;
case 0x83F1, 0x83F2, 0x83F3: GL.RGBA;
case hxd.PixelFormat.DXT_FORMAT.RGBA_DXT1,hxd.PixelFormat.DXT_FORMAT.RGBA_DXT3,
hxd.PixelFormat.DXT_FORMAT.RGBA_DXT5,hxd.PixelFormat.ASTC_FORMAT.RGBA_4x4,
hxd.PixelFormat.PVRTC_FORMAT.RGBA_4BPPV1: GL.RGBA;
case hxd.PixelFormat.PVRTC_FORMAT.RGB_4BPPV1, hxd.PixelFormat.ETC_FORMAT.RGB_ETC1: GL.RGB;
default: throw "Invalid format " + t.internalFmt;
}
}
Expand All @@ -795,6 +799,7 @@ class GlDriver extends Driver {
case SRGB, SRGB_ALPHA: hasFeature(SRGBTextures);
case R8, RG8, RGB8, R16F, RG16F, RGB16F, R32F, RG32F, RGB32F, RG11B10UF, RGB10A2: #if js glES >= 3 #else true #end;
case S3TC(n): n <= maxCompressedTexturesSupport;
case ASTC(_), ETC(_), PVRTC(_): #if js true #else false #end;
default: false;
}
}
Expand Down Expand Up @@ -856,12 +861,30 @@ class GlDriver extends Driver {
tt.internalFmt = GL2.R11F_G11F_B10F;
tt.pixelFmt = GL2.UNSIGNED_INT_10F_11F_11F_REV;
case S3TC(n) if( n <= maxCompressedTexturesSupport ):
if( t.width&3 != 0 || t.height&3 != 0 )
throw "Compressed texture "+t+" has size "+t.width+"x"+t.height+" - must be a multiple of 4";
checkMult4(t);
switch( n ) {
case 1: tt.internalFmt = 0x83F1; // COMPRESSED_RGBA_S3TC_DXT1_EXT
case 2: tt.internalFmt = 0x83F2; // COMPRESSED_RGBA_S3TC_DXT3_EXT
case 3: tt.internalFmt = 0x83F3; // COMPRESSED_RGBA_S3TC_DXT5_EXT
case 1: tt.internalFmt = hxd.PixelFormat.DXT_FORMAT.RGBA_DXT1;
case 2: tt.internalFmt = hxd.PixelFormat.DXT_FORMAT.RGBA_DXT3;
case 3: tt.internalFmt = hxd.PixelFormat.DXT_FORMAT.RGBA_DXT5;
default: throw "Unsupported texture format "+t.format;
}
case ASTC(n):
checkMult4(t);
switch( n ) {
case 10: tt.internalFmt = hxd.PixelFormat.ASTC_FORMAT.RGBA_4x4;
default: throw "Unsupported texture format "+t.format;
}
case ETC(n):
checkMult4(t);
switch( n ) {
case 0: tt.internalFmt = hxd.PixelFormat.ETC_FORMAT.RGB_ETC1;
default: throw "Unsupported texture format "+t.format;
}
case PVRTC(n):
checkMult4(t);
switch(n) {
case 8: tt.internalFmt = hxd.PixelFormat.PVRTC_FORMAT.RGB_4BPPV1;
case 9: tt.internalFmt = hxd.PixelFormat.PVRTC_FORMAT.RGBA_4BPPV1;
default: throw "Unsupported texture format "+t.format;
}
default:
Expand All @@ -885,15 +908,15 @@ class GlDriver extends Driver {

if( t.flags.has(Cube) ) {
for( i in 0...6 ) {
gl.texImage2D(CUBE_FACES[i], 0, tt.internalFmt, tt.width, tt.height, 0, getChannels(tt), tt.pixelFmt, null);
gl.texImage2D(CUBE_FACES[i], 0, tt.internalFmt, tt.width, tt.height, 0, getChannels(tt), tt.pixelFmt, null);
if( checkError() ) break;
}
} else if( t.flags.has(IsArray) ) {
gl.texImage3D(GL2.TEXTURE_2D_ARRAY, 0, tt.internalFmt, tt.width, tt.height, t.layerCount, 0, getChannels(tt), tt.pixelFmt, null);
checkError();
} else {
#if js
if( !t.format.match(S3TC(_)) )
if( !t.format.match(S3TC(_)) && !t.format.match(ETC(_)) && !t.format.match(ASTC(_)) && !t.format.match(PVRTC(_)))
#end
gl.texImage2D(bind, 0, tt.internalFmt, tt.width, tt.height, 0, getChannels(tt), tt.pixelFmt, null);
checkError();
Expand All @@ -908,6 +931,11 @@ class GlDriver extends Driver {
return tt;
}

inline function checkMult4(t) {
if( t.width&3 != 0 || t.height&3 != 0 )
throw "Compressed texture "+t+" has size "+t.width+"x"+t.height+" - must be a multiple of 4";
}

function restoreBind() {
var t = boundTextures[lastActiveIndex];
if( t == null )
Expand Down Expand Up @@ -1127,12 +1155,15 @@ class GlDriver extends Driver {
case RGBA32F, R32F, RG32F, RGB32F: new Float32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, bufLen>>2);
case RGBA16F, R16F, RG16F, RGB16F: new Uint16Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, bufLen>>1);
case RGB10A2, RG11B10UF: new Uint32Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, bufLen>>2);
case ETC(_), PVRTC(_): new Uint8Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset);
default: new Uint8Array(@:privateAccess pixels.bytes.b.buffer, pixels.offset, bufLen);
}
if( t.format.match(S3TC(_)) )
gl.compressedTexImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, buffer);
else
gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, buffer);
switch (t.format) {
case S3TC(_), ASTC(_), PVRTC(_), ETC(_):
gl.compressedTexImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, buffer);
default:
gl.texImage2D(face, mipLevel, t.t.internalFmt, pixels.width, pixels.height, 0, getChannels(t.t), t.t.pixelFmt, buffer);
}
#else
throw "Not implemented";
#end
Expand Down Expand Up @@ -1526,12 +1557,33 @@ class GlDriver extends Driver {
}

#if js
public function checkTextureSupport():hxd.PixelFormat {
var astcSupported = gl.getExtension('WEBGL_compressed_texture_astc') != null;
var dxtSupported = gl.getExtension('WEBGL_compressed_texture_s3tc') != null;
var pvrtcSupported = gl.getExtension('WEBGL_compressed_texture_pvrtc') != null
|| gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc') != null;
var etcSupported = gl.getExtension('WEBGL_compressed_texture_etc1') != null;
return if(astcSupported) {
hxd.PixelFormat.ASTC();
} else if(dxtSupported){
hxd.PixelFormat.S3TC();
} else if(pvrtcSupported){
hxd.PixelFormat.PVRTC();
} else if(etcSupported){
hxd.PixelFormat.ETC();
} else {
null;
}
}
var features : Map<Feature,Bool> = new Map();
function makeFeatures() {
for( f in Type.allEnums(Feature) )
features.set(f,checkFeature(f));
if( gl.getExtension("WEBGL_compressed_texture_s3tc") != null )
maxCompressedTexturesSupport = 3;
textureSupport = checkTextureSupport();
maxCompressedTexturesSupport = switch (textureSupport) {
case hxd.PixelFormat.S3TC(_), hxd.PixelFormat.ASTC(_), hxd.PixelFormat.ETC(_), hxd.PixelFormat.PVRTC(_): 3;
default: 0;
}
}
function checkFeature( f : Feature ) {
return switch( f ) {
Expand Down
26 changes: 24 additions & 2 deletions hxd/PixelFormat.hx
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,27 @@ enum PixelFormat {
SRGB_ALPHA;
RGB10A2;
RG11B10UF; // unsigned float
S3TC( v : Int );
}
ASTC( ?v : Int );
ETC( ?v : Int );
S3TC( ?v : Int );
PVRTC( ?v : Int);
}

enum abstract ASTC_FORMAT(Int) from Int to Int {
final RGBA_4x4 = 0x93B0;
}

enum abstract DXT_FORMAT(Int) from Int to Int {
final RGBA_DXT1 = 0x83F1;
final RGBA_DXT3 = 0x83F2;
final RGBA_DXT5 = 0x83F3;
}

enum abstract ETC_FORMAT(Int) from Int to Int {
final RGB_ETC1 = 0x8D64;
}

enum abstract PVRTC_FORMAT(Int) from Int to Int {
final RGB_4BPPV1 = 0x8C00;
final RGBA_4BPPV1 = 0x8C02;
}
6 changes: 5 additions & 1 deletion hxd/Pixels.hx
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ class Pixels {
}

case [S3TC(a),S3TC(b)] if( a == b ):
case [ASTC(a),ASTC(b)] if( a == b ):
case [ETC(a),ETC(b)] if( a == b ):
case [PVRTC(a),PVRTC(b)] if( a == b ):
// nothing

#if (hl && hl_ver >= "1.10")
Expand Down Expand Up @@ -420,6 +423,7 @@ class Pixels {
case RGB32F: 12;
case RGB10A2: 4;
case RG11B10UF: 4;
case ASTC(n), ETC(n), PVRTC(n): 1;
case S3TC(n):
if( n == 1 || n == 4 )
return width >> 1;
Expand Down Expand Up @@ -455,7 +459,7 @@ class Pixels {
channel.toInt() * 4;
case RGB10A2, RG11B10UF:
throw "Bit packed format";
case S3TC(_):
case S3TC(_), ASTC(_), ETC(_), PVRTC(_):
throw "Not supported";
}
}
Expand Down
4 changes: 2 additions & 2 deletions hxd/net/BinaryLoader.hx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class BinaryLoader {
throw msg;
}

public function load() {
public function load(raw = false) {
#if flash
loader = new flash.net.URLLoader();
loader.dataFormat = flash.net.URLLoaderDataFormat.BINARY;
Expand All @@ -43,7 +43,7 @@ class BinaryLoader {
onError(xhr.statusText);
return;
}
onLoaded(haxe.io.Bytes.ofData(xhr.response));
onLoaded(raw ? xhr.response : haxe.io.Bytes.ofData(xhr.response));
}

xhr.onprogress = function(e) {
Expand Down
Loading