mirror of
https://github.com/openstf/stf
synced 2025-10-05 10:39:25 +02:00
Add performance test for Canvas Render.
This commit is contained in:
parent
df3a29d94c
commit
9eb5c74639
9 changed files with 263 additions and 50 deletions
199
res/app/components/stf/screen/fast-image-render/index.js
Normal file
199
res/app/components/stf/screen/fast-image-render/index.js
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
// See http://jsperf.com/fastest-canvas-drawing/2
|
||||||
|
// See http://jsperf.com/canvas-drawimage-vs-putimagedata/3
|
||||||
|
// See http://jsperf.com/canvas-drawimage-vs-webgl-drawarrays
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: add ability to resize
|
||||||
|
function FastImageLoader(url, size) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function CanvasRender(canvasElement, options) {
|
||||||
|
var checkForCanvasElement = function checkForCanvasElement() {
|
||||||
|
if (!canvasElement) {
|
||||||
|
throw new Error('Needs a canvas element')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.displayWidth = canvasElement.offsetWidth
|
||||||
|
this.displayHeight = canvasElement.offsetHeight
|
||||||
|
|
||||||
|
if (!this.displayWidth || !this.displayHeight) {
|
||||||
|
throw new Error('Unable to get display size canvas must have dimensions')
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
this.options = options
|
||||||
|
this.context = canvasElement.getContext('2d')
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasRender.prototype.resize = function (width, height) {
|
||||||
|
this.displayWidth = width
|
||||||
|
this.displayHeight = height
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasRender.prototype.draw = function (image) {
|
||||||
|
this.context.drawImage(image, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasRender.prototype.clear = function () {
|
||||||
|
this.context.clearRect(0, 0, this.displayWidth, this.displayHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function WebGLRender(canvasElement, options) {
|
||||||
|
var checkForCanvasElement = function checkForCanvasElement() {
|
||||||
|
if (!canvasElement) {
|
||||||
|
throw new Error('Needs a canvas element')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.displayWidth = canvasElement.offsetWidth
|
||||||
|
this.displayHeight = canvasElement.offsetHeight
|
||||||
|
|
||||||
|
if (!this.displayWidth || !this.displayHeight) {
|
||||||
|
throw new Error('Unable to get display size canvas must have dimensions')
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
this.options = {
|
||||||
|
// alpha: this.transparent,
|
||||||
|
// antialias: !!antialias,
|
||||||
|
// premultipliedAlpha: !!transparent,
|
||||||
|
// stencil: true
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.ctx = canvasElement.getContext('experimental-webgl', this.options)
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
this.ctx = canvasElement.getContext('webgl', this.options)
|
||||||
|
} catch (e2) {
|
||||||
|
// fail, not able to get a context
|
||||||
|
throw new Error('This browser does not support webGL. Try using the canvas renderer' + this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.contextLost = false
|
||||||
|
|
||||||
|
// gl.useProgram(this.shaderManager.defaultShader.program)
|
||||||
|
|
||||||
|
//this.ctx.disable(this.ctx.DEPTH_TEST)
|
||||||
|
//this.ctx.disable(this.ctx.CULL_FACE)
|
||||||
|
|
||||||
|
this.setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLRender.prototype.setup = function () {
|
||||||
|
// create shaders
|
||||||
|
var vertexShaderSrc =
|
||||||
|
'attribute vec2 aVertex;' +
|
||||||
|
'attribute vec2 aUV;' +
|
||||||
|
'varying vec2 vTex;' +
|
||||||
|
'void main(void) {' +
|
||||||
|
' gl_Position = vec4(aVertex, 0.0, 1.0);' +
|
||||||
|
' vTex = aUV;' +
|
||||||
|
'}';
|
||||||
|
|
||||||
|
var fragmentShaderSrc =
|
||||||
|
'precision highp float;' +
|
||||||
|
'varying vec2 vTex;' +
|
||||||
|
'uniform sampler2D sampler0;' +
|
||||||
|
'void main(void){' +
|
||||||
|
' gl_FragColor = texture2D(sampler0, vTex);' +
|
||||||
|
'}';
|
||||||
|
|
||||||
|
var vertShaderObj = this.ctx.createShader(this.ctx.VERTEX_SHADER)
|
||||||
|
var fragShaderObj = this.ctx.createShader(this.ctx.FRAGMENT_SHADER)
|
||||||
|
this.ctx.shaderSource(vertShaderObj, vertexShaderSrc)
|
||||||
|
this.ctx.shaderSource(fragShaderObj, fragmentShaderSrc)
|
||||||
|
this.ctx.compileShader(vertShaderObj)
|
||||||
|
this.ctx.compileShader(fragShaderObj)
|
||||||
|
|
||||||
|
var progObj = this.ctx.createProgram()
|
||||||
|
this.ctx.attachShader(progObj, vertShaderObj)
|
||||||
|
this.ctx.attachShader(progObj, fragShaderObj)
|
||||||
|
|
||||||
|
this.ctx.linkProgram(progObj)
|
||||||
|
this.ctx.useProgram(progObj)
|
||||||
|
|
||||||
|
var width = this.displayWidth
|
||||||
|
var height = this.displayHeight
|
||||||
|
|
||||||
|
this.ctx.viewport(0, 0, width, height)
|
||||||
|
|
||||||
|
this.vertexBuff = this.ctx.createBuffer()
|
||||||
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vertexBuff)
|
||||||
|
this.ctx.bufferData(
|
||||||
|
this.ctx.ARRAY_BUFFER,
|
||||||
|
new Float32Array([-1 / 8, 1 / 6, -1 / 8, -1 / 6, 1 / 8, -1 / 6, 1 / 8, 1 / 6]),
|
||||||
|
this.ctx.STATIC_DRAW)
|
||||||
|
|
||||||
|
this.texBuff = this.ctx.createBuffer()
|
||||||
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.texBuff)
|
||||||
|
this.ctx.bufferData(
|
||||||
|
this.ctx.ARRAY_BUFFER,
|
||||||
|
new Float32Array([0, 1, 0, 0, 1, 0, 1, 1]),
|
||||||
|
this.ctx.STATIC_DRAW)
|
||||||
|
|
||||||
|
this.vloc = this.ctx.getAttribLocation(progObj, 'aVertex')
|
||||||
|
this.tloc = this.ctx.getAttribLocation(progObj, 'aUV')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLRender.prototype.resize = function (width, height) {
|
||||||
|
this.displayWidth = width
|
||||||
|
this.displayHeight = height
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLRender.prototype.draw = function (image) {
|
||||||
|
tex = this.ctx.createTexture()
|
||||||
|
this.ctx.bindTexture(this.ctx.TEXTURE_2D, tex)
|
||||||
|
this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_MIN_FILTER, this.ctx.NEAREST)
|
||||||
|
this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_MAG_FILTER, this.ctx.NEAREST)
|
||||||
|
// this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_MIN_FILTER, this.ctx.LINEAR);
|
||||||
|
|
||||||
|
// this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_WRAP_S, this.ctx.CLAMP_TO_EDGE);
|
||||||
|
// this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_WRAP_T, this.ctx.CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
this.ctx.generateMipmap(this.ctx.TEXTURE_2D)
|
||||||
|
this.ctx.texImage2D(this.ctx.TEXTURE_2D, 0, this.ctx.RGBA, this.ctx.RGBA, this.ctx.UNSIGNED_BYTE, image)
|
||||||
|
|
||||||
|
this.ctx.enableVertexAttribArray(this.vloc)
|
||||||
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vertexBuff)
|
||||||
|
this.ctx.vertexAttribPointer(this.vloc, 2, this.ctx.FLOAT, false, 0, 0)
|
||||||
|
|
||||||
|
this.ctx.enableVertexAttribArray(this.tloc)
|
||||||
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.texBuff)
|
||||||
|
this.ctx.bindTexture(this.ctx.TEXTURE_2D, tex)
|
||||||
|
this.ctx.vertexAttribPointer(this.tloc, 2, this.ctx.FLOAT, false, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLRender.prototype.clear = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function FastImageRender(canvasElement, options) {
|
||||||
|
this.options = options || {}
|
||||||
|
if (this.options.render === 'webgl') {
|
||||||
|
this.render = new WebGLRender(canvasElement, options)
|
||||||
|
} else {
|
||||||
|
this.render = new CanvasRender(canvasElement, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FastImageRender.prototype.resize = function (width, height) {
|
||||||
|
this.render.resize(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
FastImageRender.prototype.draw = function (image) {
|
||||||
|
this.render.draw(image)
|
||||||
|
}
|
||||||
|
|
||||||
|
FastImageRender.prototype.clear = function () {
|
||||||
|
this.render.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Non CommonJS world
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
module.exports = FastImageRender
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Fast Image Render Test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Fast Image Render Test</h2>
|
||||||
|
|
||||||
|
<h3>Frame number</h3>
|
||||||
|
<div id="frame-number"></div>
|
||||||
|
|
||||||
|
<canvas width="643px" height="1149px"></canvas>
|
||||||
|
<!--<canvas width="642px" height="1146px"></canvas>-->
|
||||||
|
|
||||||
|
<script src="../index.js"></script>
|
||||||
|
<script src="performance_test.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,44 @@
|
||||||
|
var canvasElement = document.querySelector('canvas')
|
||||||
|
var frameNumberElement = document.querySelector('#frame-number')
|
||||||
|
|
||||||
|
var loader = new Image()
|
||||||
|
var width = 300
|
||||||
|
var height = 300
|
||||||
|
|
||||||
|
var frames = {
|
||||||
|
total: 100,
|
||||||
|
current: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function loadScreen() {
|
||||||
|
// loader.src = 'http://placehold.it/' + width + 'x' + height + '?' + Date.now()
|
||||||
|
// loader.src = 'http://lorempixel.com/' + width + '/' + height + '/abstract/Frame-' + frames.current + '/?' + Date.now()
|
||||||
|
console.time('load')
|
||||||
|
loader.src = 'screen.jpg?' + Date.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadScreen()
|
||||||
|
|
||||||
|
var imageRender = new FastImageRender(canvasElement, {render: 'canvas'})
|
||||||
|
|
||||||
|
|
||||||
|
loader.onload = function () {
|
||||||
|
console.timeEnd('load')
|
||||||
|
console.time('draw')
|
||||||
|
imageRender.draw(this)
|
||||||
|
console.timeEnd('draw')
|
||||||
|
|
||||||
|
frameNumberElement.innerHTML = frames.current
|
||||||
|
|
||||||
|
if (frames.current++ < frames.total) {
|
||||||
|
loadScreen()
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.onerror = function (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
BIN
res/app/components/stf/screen/fast-image-render/test/screen.jpg
Normal file
BIN
res/app/components/stf/screen/fast-image-render/test/screen.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
BIN
res/app/components/stf/screen/fast-image-render/test/screen.png
Normal file
BIN
res/app/components/stf/screen/fast-image-render/test/screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 577 KiB |
|
@ -1,16 +0,0 @@
|
||||||
function CanvasRender(options, canvasElement) {
|
|
||||||
this.options = options
|
|
||||||
this.context = canvasElement.getContext('2d')
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasRender.prototype.draw = function (image) {
|
|
||||||
this.context.drawImage(image, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasRender.prototype.clear = function () {
|
|
||||||
var width = 300
|
|
||||||
var height = 300
|
|
||||||
ctx.clearRect(0, 0, width, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = CanvasRender
|
|
|
@ -1,18 +0,0 @@
|
||||||
var canvasRender = require('./canvas')
|
|
||||||
var webGLRender = require('./webgl')
|
|
||||||
var canvasElement;
|
|
||||||
|
|
||||||
function ImageRender(options) {
|
|
||||||
this.options = options
|
|
||||||
this.render = new canvasRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageRender.prototype.draw = function (image) {
|
|
||||||
this.render.draw(image)
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageRender.prototype.clear = function () {
|
|
||||||
this.render.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ImageRender
|
|
|
@ -1,15 +0,0 @@
|
||||||
// Based on http://jsperf.com/canvas-drawimage-vs-webgl-drawarrays
|
|
||||||
|
|
||||||
function WebGLRender(options) {
|
|
||||||
this.options = options
|
|
||||||
}
|
|
||||||
|
|
||||||
WebGLRender.prototype.draw = function (image) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
WebGLRender.prototype.clear = function () {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = WebGLRender
|
|
|
@ -1,4 +1,4 @@
|
||||||
var imageRender = require('./image-render')
|
var imageRender = require('./fast-image-render')
|
||||||
|
|
||||||
module.exports = function DeviceScreenDirective($document, ScalingService, $rootScope) {
|
module.exports = function DeviceScreenDirective($document, ScalingService, $rootScope) {
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue