Browse Source

Merge pull request #4660 from sebavan/master

Remove GL calls from texture tools
David Catuhe 7 years ago
parent
commit
e966418fc6

+ 50 - 13
src/Engine/babylon.engine.ts

@@ -4119,7 +4119,7 @@
                         var ktx = new KhronosTextureContainer(data, 1);
 
                         this._prepareWebGLTexture(texture, scene, ktx.pixelWidth, ktx.pixelHeight, invertY, false, true, () => {
-                            ktx.uploadLevels(this._gl, !noMipmap);
+                            ktx.uploadLevels(texture, !noMipmap);
                             return false;
                         }, samplingMode);
                     };
@@ -4130,7 +4130,7 @@
                         var header = TGATools.GetTGAHeader(data);
 
                         this._prepareWebGLTexture(texture, scene, header.width, header.height, invertY, noMipmap, false, () => {
-                            TGATools.UploadContent(this._gl, data);
+                            TGATools.UploadContent(texture, data);
                             return false;
                         }, samplingMode);
                     };
@@ -4141,7 +4141,7 @@
 
                         var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap && ((info.width >> (info.mipmapCount - 1)) === 1);
                         this._prepareWebGLTexture(texture, scene, info.width, info.height, invertY, !loadMipmap, info.isFourCC, () => {
-                            DDSTools.UploadDDSLevels(this, this._gl, data, info, loadMipmap, 1);
+                            DDSTools.UploadDDSLevels(this, texture, data, info, loadMipmap, 1);
                             return false;
                         }, samplingMode);
                     };
@@ -4385,6 +4385,11 @@
             }
         }
 
+        /** @hidden */
+        public _getUnpackAlignement(): number {
+            return this._gl.getParameter(this._gl.UNPACK_ALIGNMENT);
+        }
+
         /**
          * Creates a dynamic texture
          * @param width defines the width of the texture
@@ -5205,17 +5210,49 @@
         }
 
         /** @hidden */
-        public _uploadDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, format: number, type: number, data: ArrayBufferView) {
-            this._gl.texImage2D(target, lod, internalFormat, width, height, 0, format, type, data);
+        public _uploadCompressedDataToTextureDirectly(texture: InternalTexture, internalFormat: number, width: number, height: number, data: ArrayBufferView, faceIndex: number = 0, lod: number = 0) {
+            var gl = this._gl;
+
+            var target = gl.TEXTURE_2D;
+            if (texture.isCube) {
+                target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
+            }
+
+            this._gl.compressedTexImage2D(target, lod, internalFormat, width, height, 0, <DataView>data);
         }
 
         /** @hidden */
-        public _uploadCompressedDataToTexture(target: number, lod: number, internalFormat: number, width: number, height: number, data: ArrayBufferView) {
-            this._gl.compressedTexImage2D(target, lod, internalFormat, width, height, 0, <DataView>data);
+        public _uploadDataToTextureDirectly(texture: InternalTexture, width: number, height: number, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0): void {
+            var gl = this._gl;
+
+            var textureType = this._getWebGLTextureType(texture.type);
+            var format = this._getInternalFormat(texture.format);
+            var internalFormat = this._getRGBABufferInternalSizedFormat(texture.type, format);
+
+            this._unpackFlipY(texture.invertY);
+
+            var target = gl.TEXTURE_2D;
+            if (texture.isCube) {
+                target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
+            }
+
+            gl.texImage2D(target, lod, internalFormat, width, height, 0, format, textureType, imageData);
+        }
+
+        /** @hidden */
+        public _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0): void {
+            var gl = this._gl;
+            var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
+
+            this._bindTextureDirectly(bindTarget, texture, true);
+
+            this._uploadDataToTextureDirectly(texture, texture.width, texture.height, imageData, faceIndex, lod);
+
+            this._bindTextureDirectly(bindTarget, null, true);
         }
 
         /** @hidden */
-        public _uploadImageToTexture(texture: InternalTexture, faceIndex: number, lod: number, image: HTMLImageElement) {
+        public _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex: number = 0, lod: number = 0) {
             var gl = this._gl;
 
             var textureType = this._getWebGLTextureType(texture.type);
@@ -5229,7 +5266,7 @@
 
             var target = gl.TEXTURE_2D;
             if (texture.isCube) {
-                var target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
+                target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex;
             }
 
             gl.texImage2D(target, lod, internalFormat, format, textureType, image);
@@ -5392,7 +5429,7 @@
                         var data: any = loadData.data;
                         this._unpackFlipY(info.isCompressed);
 
-                        DDSTools.UploadDDSLevels(this, this._gl, data, info, true, 6, mipmapIndex);
+                        DDSTools.UploadDDSLevels(this, texture, data, info, true, 6, mipmapIndex);
                     }
                     else {
                         Tools.Warn("DDS is the only prefiltered cube map supported so far.")
@@ -5485,7 +5522,7 @@
                     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
                     this._unpackFlipY(true);
 
-                    ktx.uploadLevels(this._gl, !noMipmap);
+                    ktx.uploadLevels(texture, !noMipmap);
 
                     this.setCubeMapTextureParams(gl, loadMipmap);
 
@@ -5532,7 +5569,7 @@
                                 this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
                                 this._unpackFlipY(info.isCompressed);
 
-                                DDSTools.UploadDDSLevels(this, this._gl, data, info, loadMipmap, 6, -1, index);
+                                DDSTools.UploadDDSLevels(this, texture, data, info, loadMipmap, 6, -1, index);
 
                                 if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                                     gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
@@ -5567,7 +5604,7 @@
                             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
                             this._unpackFlipY(info.isCompressed);
 
-                            DDSTools.UploadDDSLevels(this, this._gl, data, info, loadMipmap, 6);
+                            DDSTools.UploadDDSLevels(this, texture, data, info, loadMipmap, 6);
 
                             if (!noMipmap && !info.isFourCC && info.mipmapCount === 1) {
                                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);

+ 25 - 0
src/Engine/babylon.nullEngine.ts

@@ -410,6 +410,15 @@
             return 0;
         }
 
+        /** @hidden */
+        public _getUnpackAlignement(): number {
+            return 1;
+        }
+
+        /** @hidden */
+        public _unpackFlipY(value: boolean) {
+        }
+
         public updateDynamicIndexBuffer(indexBuffer: WebGLBuffer, indices: IndicesArray, offset: number = 0): void {
         }
 
@@ -457,5 +466,21 @@
 
         public hideLoadingUI(): void {
         }
+
+        /** @hidden */
+        public _uploadCompressedDataToTextureDirectly(texture: InternalTexture, internalFormat: number, width: number, height: number, data: ArrayBufferView, faceIndex: number = 0, lod: number = 0) {
+        }
+
+        /** @hidden */
+        public _uploadDataToTextureDirectly(texture: InternalTexture, width: number, height: number, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0): void {
+        }
+
+        /** @hidden */
+        public _uploadArrayBufferViewToTexture(texture: InternalTexture, imageData: ArrayBufferView, faceIndex: number = 0, lod: number = 0): void {
+        }
+
+        /** @hidden */
+        public _uploadImageToTexture(texture: InternalTexture, image: HTMLImageElement, faceIndex: number = 0, lod: number = 0) {
+        }
     }
 }

+ 16 - 13
src/Tools/babylon.dds.ts

@@ -373,7 +373,11 @@
             return byteArray;
         }
 
-        public static UploadDDSLevels(engine: Engine, gl: WebGLRenderingContext, arrayBuffer: any, info: DDSInfo, loadMipmaps: boolean, faces: number, lodIndex = -1, currentFace?: number) {
+        /**
+         * Uploads DDS Levels to ta Babylon Texture.
+         * @hidden
+         */
+        public static UploadDDSLevels(engine: Engine, texture: InternalTexture, arrayBuffer: any, info: DDSInfo, loadMipmaps: boolean, faces: number, lodIndex = -1, currentFace?: number) {
             var sphericalPolynomialFaces: Nullable<Array<ArrayBufferView>> = null;
             if (info.sphericalPolynomial) {
                 sphericalPolynomialFaces = new Array<ArrayBufferView>();
@@ -384,7 +388,6 @@
             var fourCC: number, width: number, height: number, dataLength: number = 0, dataOffset: number;
             var byteArray: Uint8Array, mipmapCount: number, mip: number;
             let internalFormat = 0;
-            let format = 0;
             let blockBytes = 1;
 
             if (header[off_magic] !== DDS_MAGIC) {
@@ -461,7 +464,6 @@
             let aOffset = DDSTools._ExtractLongWordOrder(header[off_AMask]);
 
             if (computeFormats) {
-                format = engine._getWebGLTextureType(info.textureType);
                 internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
             }
 
@@ -471,8 +473,6 @@
             }
 
             for (var face = 0; face < faces; face++) {
-                var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face + (currentFace ? currentFace : 0));
-
                 width = header[off_width];
                 height = header[off_height];
 
@@ -481,6 +481,7 @@
                         // In case of fixed LOD, if the lod has just been uploaded, early exit.
                         const i = (lodIndex === -1) ? mip : 0;
 
+                        texture.format = Engine.TEXTUREFORMAT_RGBA;
                         if (!info.isCompressed && info.isFourCC) {
                             dataLength = width * height * 4;
                             var floatArray: Nullable<ArrayBufferView> = null;
@@ -500,7 +501,6 @@
                                 }
 
                                 info.textureType = Engine.TEXTURETYPE_UNSIGNED_INT;
-                                format = engine._getWebGLTextureType(info.textureType);
                                 internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
                             }
                             else {
@@ -516,7 +516,6 @@
                                     }
 
                                     info.textureType = Engine.TEXTURETYPE_FLOAT;
-                                    format = engine._getWebGLTextureType(info.textureType);
                                     internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
                                 } else { // 64
                                     floatArray = DDSTools._GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
@@ -527,30 +526,34 @@
                             }
 
                             if (floatArray) {
-                                engine._uploadDataToTexture(sampler, i, internalFormat, width, height, gl.RGBA, format, floatArray);
+                                texture.type = info.textureType;
+                                engine._uploadDataToTextureDirectly(texture, width, height, floatArray, face, i);
                             }
                         } else if (info.isRGB) {
+                            texture.format = Engine.TEXTUREFORMAT_RGB;
                             if (bpp === 24) {
                                 dataLength = width * height * 3;
                                 byteArray = DDSTools._GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset);
-                                engine._uploadDataToTexture(sampler, i, gl.RGB, width, height, gl.RGB, gl.UNSIGNED_BYTE, byteArray);
+                                engine._uploadDataToTextureDirectly(texture, width, height, byteArray, face, i);
                             } else { // 32
                                 dataLength = width * height * 4;
                                 byteArray = DDSTools._GetRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset, aOffset);
-                                engine._uploadDataToTexture(sampler, i, gl.RGBA, width, height, gl.RGBA, gl.UNSIGNED_BYTE, byteArray);
+                                engine._uploadDataToTextureDirectly(texture, width, height, byteArray, face, i);
                             }
                         } else if (info.isLuminance) {
-                            var unpackAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);
+                            var unpackAlignment = engine._getUnpackAlignement();
                             var unpaddedRowSize = width;
                             var paddedRowSize = Math.floor((width + unpackAlignment - 1) / unpackAlignment) * unpackAlignment;
                             dataLength = paddedRowSize * (height - 1) + unpaddedRowSize;
 
                             byteArray = DDSTools._GetLuminanceArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
-                            engine._uploadDataToTexture(sampler, i, gl.LUMINANCE, width, height, gl.LUMINANCE, gl.UNSIGNED_BYTE, byteArray);
+                            texture.format = Engine.TEXTUREFORMAT_LUMINANCE;
+                            texture.type = Engine.TEXTURETYPE_UNSIGNED_INT;
+                            engine._uploadDataToTextureDirectly(texture, width, height, byteArray, face, i);
                         } else {
                             dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
                             byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
-                            engine._uploadCompressedDataToTexture(sampler, i, internalFormat, width, height, byteArray);
+                            engine._uploadCompressedDataToTextureDirectly(texture, internalFormat, width, height, byteArray, face, i);
                         }
                     }
                     dataOffset += bpp ? (width * height * (bpp / 8)) : dataLength;

+ 2 - 2
src/Tools/babylon.environmentTextureTools.ts

@@ -477,13 +477,13 @@ module BABYLON {
                                 });
                             }
                             else {
-                                engine._uploadImageToTexture(texture, face, i, image);
+                                engine._uploadImageToTexture(texture, image, face, i);
 
                                 // Upload the face to the none lod texture support
                                 if (generateNonLODTextures) {
                                     let lodTexture = lodTextures![i];
                                     if (lodTexture) {
-                                        engine._uploadImageToTexture(lodTexture._texture!, face, 0, image);
+                                        engine._uploadImageToTexture(lodTexture._texture!, image, face, 0);
                                     }
                                 }
                                 resolve();

+ 8 - 5
src/Tools/babylon.khronosTextureContainer.ts

@@ -102,12 +102,14 @@ module BABYLON {
         }
 
         /**
+         * Uploads KTX content to ta Babylon Texture.
          * It is assumed that the texture has already been created & is currently bound
+         * @hidden
          */
-        public uploadLevels(gl: WebGLRenderingContext, loadMipmaps: boolean): void {
+        public uploadLevels(texture: InternalTexture, loadMipmaps: boolean): void {
             switch (this.loadType) {
                 case KhronosTextureContainer.COMPRESSED_2D:
-                    this._upload2DCompressedLevels(gl, loadMipmaps);
+                    this._upload2DCompressedLevels(texture, loadMipmaps);
                     break;
 
                 case KhronosTextureContainer.TEX_2D:
@@ -116,7 +118,7 @@ module BABYLON {
             }
         }
 
-        private _upload2DCompressedLevels(gl: WebGLRenderingContext, loadMipmaps: boolean): void {
+        private _upload2DCompressedLevels(texture: InternalTexture, loadMipmaps: boolean): void {
             // initialize width & height for level 1
             var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
             var width = this.pixelWidth;
@@ -127,9 +129,10 @@ module BABYLON {
                 var imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0]; // size per face, since not supporting array cubemaps
                 dataOffset += 4;//image data starts from next multiple of 4 offset. Each face refers to same imagesize field above.
                 for (var face = 0; face < this.numberOfFaces; face++) {
-                    var sampler = this.numberOfFaces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
                     var byteArray = new Uint8Array(this.arrayBuffer, dataOffset, imageSize);
-                    gl.compressedTexImage2D(sampler, level, this.glInternalFormat, width, height, 0, byteArray);
+
+                    const engine = texture.getEngine();
+                    engine._uploadCompressedDataToTextureDirectly(texture, this.glInternalFormat, width, height, byteArray, face, level);
 
                     dataOffset += imageSize; // add size of the image for the next face/mipmap
                     dataOffset += 3 - ((imageSize + 3) % 4); // add padding for odd sized image

+ 7 - 3
src/Tools/babylon.tga.ts

@@ -43,7 +43,11 @@
             return header;
         }
 
-        public static UploadContent(gl: WebGLRenderingContext, data: Uint8Array): void {
+        /**
+         * Uploads TGA content to ta Babylon Texture.
+         * @hidden
+         */
+        public static UploadContent(texture: InternalTexture, data: Uint8Array): void {
             // Not enough data to contain header ?
             if (data.length < 19) {
                 Tools.Error("Unable to load TGA file - Not enough data to contain header");
@@ -191,8 +195,8 @@
             var func = '_getImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
             var imageData = (<any>TGATools)[func](header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end);
 
-            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, header.width, header.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
-
+            const engine = texture.getEngine();
+            engine._uploadArrayBufferViewToTexture(texture, imageData);
         }
 
         static _getImageData8bits(header: any, palettes: Uint8Array, pixel_data: Uint8Array, y_start: number, y_step: number, y_end: number, x_start: number, x_step: number, x_end: number): Uint8Array {