Skip to content

Commit

Permalink
feat(gl-react): add Node#setDrawProps escape hatch
Browse files Browse the repository at this point in the history
fixes #109
  • Loading branch information
gre committed May 20, 2017
1 parent 5617f2b commit 7a1d314
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 40 deletions.
39 changes: 31 additions & 8 deletions packages/gl-react/src/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ const NodePropTypes = {
*/
export default class Node extends Component {
props: Props;
drawProps: Props = this.props;
context: SurfaceContext;
framebuffer: ?Framebuffer;
backbuffer: ?Framebuffer;
Expand Down Expand Up @@ -444,6 +445,10 @@ export default class Node extends Component {
}

componentWillReceiveProps(nextProps: Props, nextContext: *) {
this._syncNextDrawProps(nextProps, nextContext);
}

_syncNextDrawProps(nextProps: Props, nextContext: *) {
const nextWidthHeight = nodeWidthHeight(nextProps, nextContext);
if (this.framebuffer) {
this.framebuffer.syncSize(...nextWidthHeight);
Expand All @@ -453,9 +458,10 @@ export default class Node extends Component {
}
// FIXME should we do same for backbuffer?
invariant(
nextProps.backbuffering === this.props.backbuffering,
nextProps.backbuffering === this.drawProps.backbuffering,
"Node backbuffering prop must not changed. (not yet supported)"
);
this.drawProps = nextProps;
}

_resolveElement = (
Expand Down Expand Up @@ -509,7 +515,7 @@ export default class Node extends Component {
}

getGLShortName(): string {
const { shader } = this.props;
const { shader } = this.drawProps;
const shaderName = isShaderIdentifier(shader)
? // $FlowFixMe FIXME
Shaders.getShortName(shader)
Expand All @@ -518,7 +524,7 @@ export default class Node extends Component {
}
getGLName(): string {
const { shader } = this.props;
const { shader } = this.drawProps;
const shaderName = isShaderIdentifier(shader)
? // $FlowFixMe FIXME
Shaders.getName(shader)
Expand All @@ -527,7 +533,7 @@ export default class Node extends Component {
}
getGLSize(): [number, number] {
return nodeWidthHeight(this.props, this.context);
return nodeWidthHeight(this.drawProps, this.context);
}
getGLOutput(): WebGLTexture {
Expand All @@ -539,6 +545,23 @@ export default class Node extends Component {
return framebuffer.color;
}
/**
* Imperatively set the props with a partial subset of props to apply.
* This is an escape hatch to perform a redraw with different props without having to trigger a new React draw. Only use it when reaching a performance bottleneck.
* NB: at any time, render() needs to consistently render the same props you set in setDrawProps to avoid any potential blink (if a React draw would occur).
* @param {Props} patch a subset of props to apply on top of the previous draw props.
*/
setDrawProps(patch: Props) {
// $FlowFixMe
const nextProps: Props = {
...this.drawProps,
...patch,
};
this._syncNextDrawProps(nextProps, this.context);
this.redraw();
if (nextProps.sync) this.flush();
}
/**
* Capture the node pixels.
* Without parameters, it will capture the full rectangle,
Expand Down Expand Up @@ -620,15 +643,15 @@ export default class Node extends Component {
// when a FBO is not created, _draw() happens on the final Canvas (null fbo)
// NB we can just do this in WillMount because this context will not change.
invariant(
!this.props.backbuffering,
!this.drawProps.backbuffering,
"`backbuffering` is currently not supported for a Root Node. " +
"Try to wrap %s in a <LinearCopy> or <NearestCopy>.",
this.getGLName()
);
} else {
const fbo = createFBO(gl, width, height);
this.framebuffer = fbo;
if (this.props.backbuffering) {
if (this.drawProps.backbuffering) {
const fbo = createFBO(gl, width, height);
this.backbuffer = fbo;
}
Expand Down Expand Up @@ -760,7 +783,7 @@ export default class Node extends Component {
blendFunc,
clear,
onDraw,
} = this.props;
} = this.drawProps;
//~ PREPARE phase
Expand Down Expand Up @@ -821,7 +844,7 @@ export default class Node extends Component {
}
} else if (obj === Backbuffer) {
// maybe it's backbuffer?
if (!this.props.backbuffering) {
if (!this.drawProps.backbuffering) {
console.warn(
`${nodeName}, uniform ${uniformKeyName}: you must set \`backbuffering\` on Node when using Backbuffer`
);
Expand Down
70 changes: 70 additions & 0 deletions packages/tests/all.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,76 @@ test("renders a color uniform", () => {
inst.unmount();
});

test("use the imperative setDrawProps escape hatch", () => {
const shaders = Shaders.create({
clr: {
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform vec4 color;
void main() {
gl_FragColor = color;
}`,
},
white: {
frag: GLSL`
precision highp float;
varying vec2 uv;
void main() {
gl_FragColor = vec4(1.0);
}`,
},
});

let node;
const inst = create(
<Surface
width={1}
height={1}
webglContextAttributes={{ preserveDrawingBuffer: true }}
>
<Node
ref={ref => {
node = ref;
}}
shader={shaders.clr}
uniforms={{ color: [1, 0, 0, 1] }}
/>
</Surface>
);
const surface = inst.getInstance();
invariant(node, "nodeRef is set");
expectToBeCloseToColorArray(
surface.capture().data,
new Uint8Array([255, 0, 0, 255])
);
node.setDrawProps({
uniforms: {
color: [1, 1, 0, 1],
},
});
// check it's still lazy
expectToBeCloseToColorArray(
surface.capture().data,
new Uint8Array([255, 0, 0, 255])
);
surface.flush();
expectToBeCloseToColorArray(
surface.capture().data,
new Uint8Array([255, 255, 0, 255])
);
node.setDrawProps({
shader: shaders.white,
uniforms: {},
});
surface.flush();
expectToBeCloseToColorArray(
surface.capture().data,
new Uint8Array([255, 255, 255, 255])
);
inst.unmount();
});

test("composes color uniform with LinearCopy", () => {
const shaders = Shaders.create({
clr: {
Expand Down
64 changes: 32 additions & 32 deletions packages/tests/flow/snapshot.txt
Original file line number Diff line number Diff line change
@@ -1,83 +1,83 @@
../all.test.js:2416
../all.test.js:2486
v----
2416: <Node
2417: shader={shaders.helloTexture}
2418: uniformsOptions={{ t: { interpolation: "nope" } }}
2419: uniforms={{ t: <JustBlue blue={1} /> }}
2420: />
2486: <Node
2487: shader={shaders.helloTexture}
2488: uniformsOptions={{ t: { interpolation: "nope" } }}
2489: uniforms={{ t: <JustBlue blue={1} /> }}
2490: />
-^ props of React element `Node`
2418: uniformsOptions={{ t: { interpolation: "nope" } }}
2488: uniformsOptions={{ t: { interpolation: "nope" } }}
^^^^^^ string. This type is incompatible with
65: interpolation: Interpolation,
^^^^^^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:65

../all.test.js:2428
../all.test.js:2498
v----
2428: <Node
2429: shader={shaders.helloTexture}
2430: uniformsOptions={{ t: { wrap: "nope" } }}
2431: uniforms={{ t: <JustBlue blue={1} /> }}
2432: />
2498: <Node
2499: shader={shaders.helloTexture}
2500: uniformsOptions={{ t: { wrap: "nope" } }}
2501: uniforms={{ t: <JustBlue blue={1} /> }}
2502: />
-^ props of React element `Node`
2430: uniformsOptions={{ t: { wrap: "nope" } }}
2500: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: tuple type | WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Member 1:
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2430: uniformsOptions={{ t: { wrap: "nope" } }}
2500: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
Member 2:
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^ WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2430: uniformsOptions={{ t: { wrap: "nope" } }}
2500: uniformsOptions={{ t: { wrap: "nope" } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66

../all.test.js:2440
../all.test.js:2510
v----
2440: <Node
2441: shader={shaders.helloTexture}
2442: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2443: uniforms={{ t: <JustBlue blue={1} /> }}
2444: />
2510: <Node
2511: shader={shaders.helloTexture}
2512: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2513: uniforms={{ t: <JustBlue blue={1} /> }}
2514: />
-^ props of React element `Node`
2442: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2512: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^^^^^^^^^^^ array literal. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union: tuple type | WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Member 1:
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^^^^^^^^^^^^^ tuple type. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2442: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2512: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^ string. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66
Member 2:
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^ WrapMode. See: ../node_modules/gl-react/lib/Node.js.flow:66
Error:
2442: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
2512: uniformsOptions={{ t: { wrap: ["nope", "nope"] } }}
^^^^^^^^^^^^^^^^ array literal. This type is incompatible with
66: wrap: [WrapMode, WrapMode] | WrapMode,
^^^^^^^^ string enum. See: ../node_modules/gl-react/lib/Node.js.flow:66

../all.test.js:2452
../all.test.js:2522
v----
2452: <Node
2453: blendFunc="nope"
2454: shader={shaders.helloTexture}
2455: uniforms={{ t: <JustBlue blue={1} /> }}
2456: />
2522: <Node
2523: blendFunc="nope"
2524: shader={shaders.helloTexture}
2525: uniforms={{ t: <JustBlue blue={1} /> }}
2526: />
-^ props of React element `Node`
2453: blendFunc="nope"
2523: blendFunc="nope"
^^^^^^ string. Inexact type is incompatible with exact type
177: blendFunc: BlendFuncSrcDst,
^^^^^^^^^^^^^^^ exact type: object type. See: ../node_modules/gl-react/lib/Node.js.flow:177
Expand Down

0 comments on commit 7a1d314

Please sign in to comment.