Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe 7 years ago
parent
commit
8a78b72197

+ 1 - 1
Viewer/src/labs/texture.ts

@@ -241,7 +241,7 @@ export class TextureUtils {
 
                 let gl = (<any>(scene.getEngine()))._gl;
                 gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture);
-                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                scene.getEngine()._unpackFlipY(false);
                 if (face instanceof HTMLElement || face instanceof ImageData) {
                     gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, textureCube.internalFormat, textureCube.internalFormat, textureCube.type, <any>face);
                 } else {

+ 8 - 0
dist/preview release/what's new.md

@@ -40,6 +40,14 @@
 - AssetsManager tasks will only run when their state is INIT. It is now possible to remove a task from the assets manager ([RaananW](https://github.com/RaananW))
 - Added sprite isVisible field ([TrevorDev](https://github.com/TrevorDev))
 - EnvironmentHelper will recreate ground and skybox meshes if force-disposed ([RaananW](https://github.com/RaananW))
+- Added viewport caching mecanism in engine ([sebavan](http://www.github.com/sebavan))
+- Added unpackFlipY caching mecanism in engine ([sebavan](http://www.github.com/sebavan))
+- Added rebind optimization of video texture ([sebavan](http://www.github.com/sebavan))
+- Fix Background Material effect caching ([sebavan](http://www.github.com/sebavan))
+- Prevent texture ```getSize``` to generate garbage collection ([sebavan](http://www.github.com/sebavan))
+- Prevent ```lodGenerationScale``` and ```lodGenerationOffset``` to force rebind ([sebavan](http://www.github.com/sebavan))
+- Added poster property on VideoTexture ([sebavan](http://www.github.com/sebavan))
+- Added ```onUserActionRequestedObservable``` to workaround and detect autoplay video policy restriction on VideoTexture ([sebavan](http://www.github.com/sebavan))
 
 ### glTF Loader
 

+ 57 - 19
src/Engine/babylon.engine.ts

@@ -2174,6 +2174,24 @@
             }
         }
 
+        private _viewportCached = new BABYLON.Vector4(0, 0, 0, 0);
+        
+        /** @hidden */
+        public _viewport(x: number, y: number, width: number, height: number): void {
+            if (x !== this._viewportCached.x ||
+                y !== this._viewportCached.y ||
+                width !== this._viewportCached.z ||
+                height !== this._viewportCached.w)
+            {
+                this._viewportCached.x = x;
+                this._viewportCached.y = y;
+                this._viewportCached.z = width;
+                this._viewportCached.w = height;
+
+                this._gl.viewport(x, y, width, height);
+            }
+        }
+
         /**
          * Set the WebGL's viewport
          * @param viewport defines the viewport element to be used
@@ -2188,7 +2206,7 @@
 
             this._cachedViewport = viewport;
 
-            this._gl.viewport(x * width, y * height, width * viewport.width, height * viewport.height);
+            this._viewport(x * width, y * height, width * viewport.width, height * viewport.height);
         }
 
         /**
@@ -2203,7 +2221,7 @@
             let currentViewport = this._cachedViewport;
             this._cachedViewport = null;
 
-            this._gl.viewport(x, y, width, height);
+            this._viewport(x, y, width, height);
 
             return currentViewport;
         }
@@ -2465,7 +2483,7 @@
                     }
                 }
 
-                gl.viewport(0, 0, requiredWidth, requiredHeight);
+                this._viewport(0, 0, requiredWidth, requiredHeight);
             }
 
             this.wipeCaches();
@@ -4072,6 +4090,11 @@
                 return;
             }
             this._currentEffect = null;
+            this._unpackFlipYCached = null;
+            this._viewportCached.x = 0;
+            this._viewportCached.y = 0;
+            this._viewportCached.z = 0;
+            this._viewportCached.w = 0;
 
             if (bruteForce) {
                 this.resetTextureCache();
@@ -4385,7 +4408,7 @@
             var internalFormat = this._getInternalFormat(format);
             var textureType = this._getWebGLTextureType(type);
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
 
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
@@ -4464,6 +4487,15 @@
             return texture;
         }
 
+        private _unpackFlipYCached: Nullable<boolean> = null;
+        /** @hidden */
+        public _unpackFlipY(value: boolean) {
+            if (this._unpackFlipYCached !== value) {
+                this._unpackFlipYCached = value;
+                this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, value ? 1 : 0);
+            }
+        }
+
         /**
          * Creates a dynamic texture
          * @param width defines the width of the texture
@@ -4535,7 +4567,7 @@
             }
 
             this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
+            this._unpackFlipY(invertY);
             if (premulAlpha) {
                 this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
             }
@@ -4562,8 +4594,8 @@
                 return;
             }
 
-            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 0 : 1); // Video are upside down by default
+            var wasPreviouslyBound = this._bindTextureDirectly(this._gl.TEXTURE_2D, texture, true);
+            this._unpackFlipY(!invertY); // Video are upside down by default
 
             try {
                 // Testing video texture support
@@ -4603,7 +4635,9 @@
                     this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 }
 
-                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                if (!wasPreviouslyBound) {
+                    this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                }
                 //    this.resetTextureCache();
                 texture.isReady = true;
 
@@ -5302,7 +5336,7 @@
             var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
 
             this._bindTextureDirectly(bindTarget, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, texture.invertY ? 1 : 0);
+            this._unpackFlipY(texture.invertY);
 
             var target = gl.TEXTURE_2D;
             if (texture.isCube) {
@@ -5467,7 +5501,7 @@
                     if (loadData.isDDS) {
                         var info: DDSInfo = loadData.info;
                         var data: any = loadData.data;
-                        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                        this._unpackFlipY(info.isCompressed);
 
                         DDSTools.UploadDDSLevels(this, this._gl, data, info, true, 6, mipmapIndex);
                     }
@@ -5555,7 +5589,7 @@
                     var loadMipmap = ktx.numberOfMipmapLevels > 1 && !noMipmap;
 
                     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
+                    this._unpackFlipY(true);
 
                     ktx.uploadLevels(this._gl, !noMipmap);
 
@@ -5602,7 +5636,7 @@
                                 loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
 
                                 this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                                this._unpackFlipY(info.isCompressed);
 
                                 DDSTools.UploadDDSLevels(this, this._gl, data, info, loadMipmap, 6, -1, index);
 
@@ -5637,7 +5671,7 @@
                             var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
 
                             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, info.isCompressed ? 1 : 0);
+                            this._unpackFlipY(info.isCompressed);
 
                             DDSTools.UploadDDSLevels(this, this._gl, data, info, loadMipmap, 6);
 
@@ -5684,7 +5718,7 @@
                     ];
 
                     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    this._unpackFlipY(false);
 
                     let internalFormat = format ? this._getInternalFormat(format) : this._gl.RGBA;
                     for (var index = 0; index < faces.length; index++) {
@@ -5759,7 +5793,7 @@
             }
 
             this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
 
             if (texture.width % 4 !== 0) {
                 gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
@@ -5923,7 +5957,7 @@
                     }
 
                     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture, true);
-                    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                    this._unpackFlipY(false);
 
                     var mipData = mipmapGenerator(faceDataArrays);
                     for (var level = 0; level < mipData.length; level++) {
@@ -5976,7 +6010,7 @@
             var internalSizedFomat = this._getRGBABufferInternalSizedFormat(textureType, format);
 
             this._bindTextureDirectly(this._gl.TEXTURE_3D, texture, true);
-            this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
 
             if (!this._doNotHandleContextLost) {
                 texture._bufferView = data;
@@ -6101,7 +6135,7 @@
             }
 
             this._bindTextureDirectly(gl.TEXTURE_2D, texture, true);
-            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
+            this._unpackFlipY(invertY === undefined ? true : (invertY ? true : false));
 
             texture.baseWidth = width;
             texture.baseHeight = height;
@@ -6327,7 +6361,8 @@
         }
 
         /** @hidden */
-        protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false, force = false): void {
+        protected _bindTextureDirectly(target: number, texture: Nullable<InternalTexture>, forTextureDataUpdate = false, force = false): boolean {
+            var wasPreviouslyBound = false;
             if (forTextureDataUpdate && texture && texture._designatedSlot > -1) {
                 this._activeChannel = texture._designatedSlot;
             }
@@ -6359,12 +6394,15 @@
                     texture._designatedSlot = this._activeChannel;
                 }
             } else if (forTextureDataUpdate) {
+                wasPreviouslyBound = true;
                 this._activateCurrentTexture();
             }
 
             if (isTextureForRendering && !forTextureDataUpdate) {
                 this._bindSamplerUniformToChannel(texture!._initialSlot, this._activeChannel);
             }
+
+            return wasPreviouslyBound;
         }
 
         /** @hidden */

+ 3 - 1
src/Engine/babylon.nullEngine.ts

@@ -410,10 +410,12 @@
         public updateDynamicVertexBuffer(vertexBuffer: WebGLBuffer, vertices: FloatArray, byteOffset?: number, byteLength?: number): void {
         }
 
-        protected _bindTextureDirectly(target: number, texture: InternalTexture): void {
+        protected _bindTextureDirectly(target: number, texture: InternalTexture): boolean {
             if (this._boundTexturesCache[this._activeChannel] !== texture) {
                 this._boundTexturesCache[this._activeChannel] = texture;
+                return true;
             }
+            return false;
         }
 
         public _bindTexture(channel: number, texture: InternalTexture): void {

+ 1 - 1
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -1083,7 +1083,7 @@
 
             this._uniformBuffer.update();
 
-            this._afterBind(mesh);
+            this._afterBind(mesh, this._activeEffect);
         }
 
         /**

+ 13 - 6
src/Materials/Textures/babylon.baseTexture.ts

@@ -220,16 +220,23 @@
             return false;
         }
 
+        private _cachedSize: ISize = Size.Zero();
         public getSize(): ISize {
-            if (this._texture && this._texture.width) {
-                return new Size(this._texture.width, this._texture.height);
-            }
+            if (this._texture) {
+                if (this._texture.width) {
+                    this._cachedSize.width = this._texture.width;
+                    this._cachedSize.height = this._texture.height;
+                    return this._cachedSize;
+                }
 
-            if (this._texture && this._texture._size) {
-                return new Size(this._texture._size, this._texture._size);
+                if (this._texture._size) {
+                    this._cachedSize.width = this._texture._size;
+                    this._cachedSize.height = this._texture._size;
+                    return this._cachedSize;
+                }
             }
 
-            return Size.Zero();
+            return this._cachedSize;
         }
 
         public getBaseSize(): ISize {

+ 2 - 2
src/Materials/Textures/babylon.internalTexture.ts

@@ -188,9 +188,9 @@ module BABYLON {
         /** @hidden */
         public _sphericalPolynomial: Nullable<SphericalPolynomial>;
         /** @hidden */
-        public _lodGenerationScale: number;
+        public _lodGenerationScale: number = 0;
         /** @hidden */
-        public _lodGenerationOffset: number;
+        public _lodGenerationOffset: number = 0;
 
         // The following three fields helps sharing generated fixed LODs for texture filtering
         // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.

+ 2 - 2
src/Materials/Textures/babylon.texture.ts

@@ -429,8 +429,8 @@
         public dispose(): void {
             super.dispose();
 
-            if (this.onLoadObservable) {
-                this.onLoadObservable.clear();
+            if (this._onLoadObservable) {
+                this._onLoadObservable.clear();
                 this._onLoadObservable = null;
             }
 

+ 48 - 2
src/Materials/Textures/babylon.videoTexture.ts

@@ -17,6 +17,11 @@
          * Automatically updates internal texture from video at every frame in the render loop
          */
         autoUpdateTexture: boolean;
+
+        /**
+         * Image src displayed during the video loading or until the user interacts with the video.
+         */
+        poster?: string;
     }
 
     export class VideoTexture extends Texture {
@@ -30,6 +35,15 @@
          */
         public readonly video: HTMLVideoElement;
 
+        private _onUserActionRequestedObservable: Nullable<Observable<Texture>> = null;
+
+        public get onUserActionRequestedObservable(): Observable<Texture> {
+            if (!this._onUserActionRequestedObservable) {
+                this._onUserActionRequestedObservable = new Observable<Texture>();
+            }
+            return this._onUserActionRequestedObservable;
+        }
+
         private _generateMipMaps: boolean;
         private _engine: Engine;
         private _stillImageCaptured = false;
@@ -67,6 +81,9 @@
 
             this.name = name || this._getName(src);
             this.video = this._getVideo(src);
+            if (settings.poster) {
+                this.video.poster = settings.poster;
+            }
 
             if (settings.autoPlay !== undefined) {
                 this.video.autoplay = settings.autoPlay;
@@ -143,16 +160,39 @@
 
             if (!this.video.autoplay) {
                 let oldHandler = this.video.onplaying;
+                let error = false;
                 this.video.onplaying = () => {
                     this.video.onplaying = oldHandler;
                     this._texture!.isReady = true;
                     this._updateInternalTexture();
-                    this.video.pause();
+                    if (!error) {
+                        this.video.pause();
+                    }
                     if (this._onLoadObservable && this._onLoadObservable.hasObservers()) {
                         this.onLoadObservable.notifyObservers(this);
                     }
                 };
-                this.video.play();
+                var playing = this.video.play();
+                if (playing) {
+                    playing.then(() => {
+                        // Everything is good.
+                    })
+                    .catch(() => {
+                        error = true;
+                        // On Chrome for instance, new policies might prevent playing without user interaction.
+                        if (this._onUserActionRequestedObservable && this._onUserActionRequestedObservable.hasObservers()) {
+                            this._onUserActionRequestedObservable.notifyObservers(this);
+                        }
+                    });
+                }
+                else {
+                    this.video.onplaying = oldHandler;
+                    this._texture.isReady = true;
+                    this._updateInternalTexture();
+                    if (this._onLoadObservable && this._onLoadObservable.hasObservers()) {
+                        this.onLoadObservable.notifyObservers(this);
+                    }
+                }
             }
             else {
                 this._texture.isReady = true;
@@ -226,6 +266,12 @@
 
         public dispose(): void {
             super.dispose();
+            
+            if (this._onUserActionRequestedObservable) {
+                this._onUserActionRequestedObservable.clear();
+                this._onUserActionRequestedObservable = null;
+            }
+
             this.video.removeEventListener("canplay", this._createInternalTexture);
             this.video.removeEventListener("paused", this._updateInternalTexture);
             this.video.removeEventListener("seeked", this._updateInternalTexture);