mirror of
https://github.com/openseadragon/openseadragon.git
synced 2024-11-25 14:46:10 +03:00
Add functional test for problems with WebGL and fall back to canvas if needed
This commit is contained in:
parent
e1e0ec6b24
commit
fb374fc286
@ -3905,7 +3905,7 @@ function drawWorld( viewer ) {
|
|||||||
viewer.world.draw();
|
viewer.world.draw();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <em>- Needs documentation -</em>
|
* This event is raised any time the viewer has rendered a new frame.
|
||||||
*
|
*
|
||||||
* @event update-viewport
|
* @event update-viewport
|
||||||
* @memberof OpenSeadragon.Viewer
|
* @memberof OpenSeadragon.Viewer
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
(function( $ ){
|
(function( $ ){
|
||||||
|
|
||||||
const OpenSeadragon = $; // alias for JSDoc
|
const OpenSeadragon = $; // alias for JSDoc
|
||||||
|
let testing = false;
|
||||||
/**
|
/**
|
||||||
* @class OpenSeadragon.WebGLDrawer
|
* @class OpenSeadragon.WebGLDrawer
|
||||||
* @classdesc Default implementation of WebGLDrawer for an {@link OpenSeadragon.Viewer}. The WebGLDrawer
|
* @classdesc Default implementation of WebGLDrawer for an {@link OpenSeadragon.Viewer}. The WebGLDrawer
|
||||||
@ -110,7 +110,9 @@
|
|||||||
|
|
||||||
this.context = this._outputContext; // API required by tests
|
this.context = this._outputContext; // API required by tests
|
||||||
|
|
||||||
}
|
this._requiresCanvasDrawerFallback = false;
|
||||||
|
this._doRenderingTest();
|
||||||
|
}
|
||||||
|
|
||||||
// Public API required by all Drawer implementations
|
// Public API required by all Drawer implementations
|
||||||
/**
|
/**
|
||||||
@ -281,7 +283,7 @@
|
|||||||
//iterate over tiled images and draw each one using a two-pass rendering pipeline if needed
|
//iterate over tiled images and draw each one using a two-pass rendering pipeline if needed
|
||||||
tiledImages.forEach( (tiledImage, tiledImageIndex) => {
|
tiledImages.forEach( (tiledImage, tiledImageIndex) => {
|
||||||
|
|
||||||
if(tiledImage.isTainted()){
|
if(tiledImage.isTainted() || this._requiresCanvasDrawerFallback ){
|
||||||
// first, draw any data left in the rendering buffer onto the output canvas
|
// first, draw any data left in the rendering buffer onto the output canvas
|
||||||
if(renderingBufferHasImageData){
|
if(renderingBufferHasImageData){
|
||||||
this._outputContext.drawImage(this._renderingCanvas, 0, 0);
|
this._outputContext.drawImage(this._renderingCanvas, 0, 0);
|
||||||
@ -1325,6 +1327,79 @@
|
|||||||
return shaderProgram;
|
return shaderProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test webgl rendering in the current browser by drawing a small image
|
||||||
|
* in a new viewer. If all pixel data is 0, rendering failed, and fallback
|
||||||
|
* to the CanvasDrawer is required for all tiled images.
|
||||||
|
* @private
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
_doRenderingTest(){
|
||||||
|
// Avoid infinite call stack by only testing once
|
||||||
|
if( testing ){
|
||||||
|
this._isTestingViewer = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Set the testing flag to true until the test viewer has been created
|
||||||
|
testing = true;
|
||||||
|
|
||||||
|
// A dataUrl with non-zero pixels to use
|
||||||
|
const dataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAASgAwAEAAAAAQAAAAQAAAAANlaTAQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KGV7hBwAAAElJREFUCB1jZACCa5uWJr/78JHVhkNkNuPpmhy/b5+Z1/74/vPzr2/3y1junTr5QYf1NAsDI4Pg1ivin0E6GLbnMDhsTmHwArEBM20b4j0ge4MAAAAASUVORK5CYII=";
|
||||||
|
|
||||||
|
// Create a small element for the test viewer and append it to our viewer's element
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.setAttribute('id', 'osd_internal_test');
|
||||||
|
div.style.width = '4px';
|
||||||
|
div.style.height = '4px';
|
||||||
|
div.style.position = 'fixed';
|
||||||
|
div.style.top = 0;
|
||||||
|
div.style.left = 0;
|
||||||
|
this.viewer.element.appendChild( div );
|
||||||
|
|
||||||
|
// create the test viewer
|
||||||
|
const testViewer = $( { element: div, drawer: 'webgl', navigator: false } );
|
||||||
|
|
||||||
|
// reset testing flag to false so additional viewers can be tested
|
||||||
|
testing = false;
|
||||||
|
|
||||||
|
// Once a frame is drawn, check the pixel values in the output canvas
|
||||||
|
testViewer.addOnceHandler('update-viewport', () => {
|
||||||
|
const numNonZeroValues = testViewer.drawer._outputContext.getImageData(0, 0, 4, 4).data.filter( pixel => pixel > 0).length;
|
||||||
|
// If all values are zero, rendering failed. Set a flag and issue a warning.
|
||||||
|
this._requiresCanvasDrawerFallback = ( numNonZeroValues === 0);
|
||||||
|
if( this._requiresCanvasDrawerFallback ){
|
||||||
|
$.console.warn('A problem was detected with webgl rendering. Falling back to CanvasDrawer.');
|
||||||
|
|
||||||
|
// Raise an event so applications can handle this more gracefully if needed
|
||||||
|
/**
|
||||||
|
* This event is fired if a WebGLDrawer detects a problem with rendering and
|
||||||
|
* requires fallback to CanvasDrawer. This fallback happens automatically,
|
||||||
|
* but some applications may not desire this and would wish to explicitly handle
|
||||||
|
* the error in a different way, for example by removing and/or re-creating the viewer with
|
||||||
|
* different settings.
|
||||||
|
*
|
||||||
|
* @event webgl-error
|
||||||
|
* @memberof OpenSeadragon.Viewer
|
||||||
|
* @type {object}
|
||||||
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised the event.
|
||||||
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
||||||
|
*/
|
||||||
|
this.viewer.raiseEvent('webgl-error', { });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the test viewer
|
||||||
|
setTimeout( () => testViewer.destroy(), 0);
|
||||||
|
this.viewer.element.removeChild(div);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open the test image using the dataUrl from above
|
||||||
|
const testSource = {
|
||||||
|
url: dataUrl,
|
||||||
|
type: 'image'
|
||||||
|
};
|
||||||
|
testViewer.open( testSource );
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user