-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Browser fixes #479
Browser fixes #479
Changes from 31 commits
beee719
5339bf4
291fab9
fc8c624
d8b91f5
0b87f34
9a7d9e5
0703765
16b7628
34d4b04
50afc01
462f27c
be3326d
d18b56a
1487bd6
127e0a0
85bef7d
23ba463
b6f8d25
9938a8e
54db288
202e395
c6abb2e
0aa1b01
d369dbf
ac33e4f
449b5b5
1da66e1
fc418cc
0a82ba4
6afda7c
ad1c6ac
1a33343
3199462
617ff84
87e2ebf
b458147
8addf24
7745514
0b31a64
71bba6c
67d4cdd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ module.exports = function wrapReadPixels ( | |
context, | ||
glAttributes, | ||
extensions) { | ||
var supportsFloat = extensions.oes_texture_float && isFloatSupported(gl) | ||
|
||
function readPixelsImpl (input) { | ||
var type | ||
if (framebufferState.next === null) { | ||
|
@@ -30,6 +32,10 @@ module.exports = function wrapReadPixels ( | |
check( | ||
type === GL_UNSIGNED_BYTE || type === GL_FLOAT, | ||
'Reading from a framebuffer is only allowed for the types \'uint8\' and \'float\'') | ||
|
||
if (type === GL_FLOAT) { | ||
check(supportsFloat, 'Reading \'float\' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float') | ||
} | ||
} else { | ||
check( | ||
type === GL_UNSIGNED_BYTE, | ||
|
@@ -128,3 +134,28 @@ module.exports = function wrapReadPixels ( | |
|
||
return readPixels | ||
} | ||
|
||
function isFloatSupported (gl) { | ||
var texture = gl.createTexture() | ||
gl.bindTexture(gl.TEXTURE_2D, texture) | ||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null) | ||
|
||
var fbo = gl.createFramebuffer() | ||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo) | ||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0) | ||
gl.bindTexture(gl.TEXTURE_2D, null) | ||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) return false | ||
|
||
gl.viewport(0, 0, 1, 1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That should not affect previous render/framebuffer, should that? At the moment of this call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, and apologies, but just curious? What does this really do? On platforms where it's not supported, does it currently fail silently? Throw an error? A warning? After this, what is the result? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This uses own regl ‘check’ function to throw an error if reading floats is not supported, as discussed in the adjacent PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apologies, but I forgot: does it already throw an error without regl itself detecting and throwing an error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
gl.clearColor(1.0, 0.0, 0.0, 1.0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if that can lose previous clear color, if there is any. That should not be an issue, since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check is run on startup, right? I think it'd be fine then as long as the state is refreshed/initialized afterwards. |
||
gl.clear(gl.COLOR_BUFFER_BIT) | ||
var pixels = new Float32Array(4) | ||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, pixels) | ||
|
||
if (gl.getError()) return false | ||
|
||
gl.deleteFramebuffer(fbo) | ||
gl.deleteTexture(texture) | ||
|
||
return pixels[0] === 1.0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -827,6 +827,7 @@ module.exports = function createTextureSet ( | |
var type = info.type | ||
var width = info.width | ||
var height = info.height | ||
var channels = info.channels | ||
|
||
setFlags(info) | ||
|
||
|
@@ -839,8 +840,16 @@ module.exports = function createTextureSet ( | |
gl.copyTexImage2D( | ||
target, miplevel, format, info.xOffset, info.yOffset, width, height, 0) | ||
} else { | ||
gl.texImage2D( | ||
target, miplevel, format, width, height, 0, format, type, data) | ||
var nullData = !data | ||
if (nullData) { | ||
data = pool.zero.allocType(type, width * height * channels) | ||
} | ||
|
||
gl.texImage2D(target, miplevel, format, width, height, 0, format, type, data) | ||
|
||
if (nullData && data) { | ||
pool.zero.freeType(data) | ||
} | ||
} | ||
} | ||
|
||
|
@@ -1324,17 +1333,27 @@ module.exports = function createTextureSet ( | |
reglTexture2D.height = texture.height = h | ||
|
||
tempBind(texture) | ||
|
||
var data | ||
var channels = texture.channels | ||
var type = texture.type | ||
|
||
for (var i = 0; texture.mipmask >> i; ++i) { | ||
var _w = w >> i | ||
var _h = h >> i | ||
if (!_w || !_h) break | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Firefox warns when |
||
data = pool.zero.allocType(type, _w * _h * channels) | ||
gl.texImage2D( | ||
GL_TEXTURE_2D, | ||
i, | ||
texture.format, | ||
w >> i, | ||
h >> i, | ||
_w, | ||
_h, | ||
0, | ||
texture.format, | ||
texture.type, | ||
null) | ||
data) | ||
if (data) pool.zero.freeType(data) | ||
} | ||
tempRestore() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,6 @@ var GL_INT = 5124 | |
var GL_UNSIGNED_INT = 5125 | ||
var GL_FLOAT = 5126 | ||
|
||
var bufferPool = loop(8, function () { | ||
return [] | ||
}) | ||
|
||
function nextPow16 (v) { | ||
for (var i = 16; i <= (1 << 28); i *= 16) { | ||
if (v <= i) { | ||
|
@@ -34,59 +30,70 @@ function log2 (v) { | |
return r | (v >> 1) | ||
} | ||
|
||
function alloc (n) { | ||
var sz = nextPow16(n) | ||
var bin = bufferPool[log2(sz) >> 2] | ||
if (bin.length > 0) { | ||
return bin.pop() | ||
function createPool () { | ||
var bufferPool = loop(8, function () { | ||
return [] | ||
}) | ||
|
||
function alloc (n) { | ||
var sz = nextPow16(n) | ||
var bin = bufferPool[log2(sz) >> 2] | ||
if (bin.length > 0) { | ||
return bin.pop() | ||
} | ||
return new ArrayBuffer(sz) | ||
} | ||
return new ArrayBuffer(sz) | ||
} | ||
|
||
function free (buf) { | ||
bufferPool[log2(buf.byteLength) >> 2].push(buf) | ||
} | ||
function free (buf) { | ||
bufferPool[log2(buf.byteLength) >> 2].push(buf) | ||
} | ||
|
||
function allocType (type, n) { | ||
var result = null | ||
switch (type) { | ||
case GL_BYTE: | ||
result = new Int8Array(alloc(n), 0, n) | ||
break | ||
case GL_UNSIGNED_BYTE: | ||
result = new Uint8Array(alloc(n), 0, n) | ||
break | ||
case GL_SHORT: | ||
result = new Int16Array(alloc(2 * n), 0, n) | ||
break | ||
case GL_UNSIGNED_SHORT: | ||
result = new Uint16Array(alloc(2 * n), 0, n) | ||
break | ||
case GL_INT: | ||
result = new Int32Array(alloc(4 * n), 0, n) | ||
break | ||
case GL_UNSIGNED_INT: | ||
result = new Uint32Array(alloc(4 * n), 0, n) | ||
break | ||
case GL_FLOAT: | ||
result = new Float32Array(alloc(4 * n), 0, n) | ||
break | ||
default: | ||
return null | ||
function allocType (type, n) { | ||
var result = null | ||
switch (type) { | ||
case GL_BYTE: | ||
result = new Int8Array(alloc(n), 0, n) | ||
break | ||
case GL_UNSIGNED_BYTE: | ||
result = new Uint8Array(alloc(n), 0, n) | ||
break | ||
case GL_SHORT: | ||
result = new Int16Array(alloc(2 * n), 0, n) | ||
break | ||
case GL_UNSIGNED_SHORT: | ||
result = new Uint16Array(alloc(2 * n), 0, n) | ||
break | ||
case GL_INT: | ||
result = new Int32Array(alloc(4 * n), 0, n) | ||
break | ||
case GL_UNSIGNED_INT: | ||
result = new Uint32Array(alloc(4 * n), 0, n) | ||
break | ||
case GL_FLOAT: | ||
result = new Float32Array(alloc(4 * n), 0, n) | ||
break | ||
default: | ||
return null | ||
} | ||
if (result.length !== n) { | ||
return result.subarray(0, n) | ||
} | ||
return result | ||
} | ||
if (result.length !== n) { | ||
return result.subarray(0, n) | ||
|
||
function freeType (array) { | ||
free(array.buffer) | ||
} | ||
return result | ||
} | ||
|
||
function freeType (array) { | ||
free(array.buffer) | ||
return { | ||
alloc: alloc, | ||
free: free, | ||
allocType: allocType, | ||
freeType: freeType | ||
} | ||
} | ||
|
||
module.exports = { | ||
alloc: alloc, | ||
free: free, | ||
allocType: allocType, | ||
freeType: freeType | ||
} | ||
module.exports = createPool() | ||
|
||
// zero pool for initial zero data | ||
module.exports.zero = createPool() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reserved for zero-data inits. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,4 +46,4 @@ function updateDOM () { | |
pendingRaf = null | ||
} | ||
|
||
require('../index') | ||
require('./index') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enables
ANGLE_instanced_arrays
for every regl call, which makes Firefox display warnings onloseContext
/restoreContext