Error with Image on Xiaomi devices
blackcand opened this issue · comments
blackcand commented
_bug report
Every time I minimizing the application, I get the error of image always loss. It's just failing with xiaomi devices
with the following code:
// @flow
import * as React from "react";
import { Shaders, Node, GLSL, LinearCopy, Uniform } from "gl-react";
const shaders = Shaders.create({
contain: {
vert: GLSL`
attribute vec2 _p;
varying vec2 uv;
uniform float tR;
uniform vec2 res;
float r;
void main() {
r = res.x / res.y;
gl_Position = vec4(_p, 0.0, 1.0);
uv = .5 + .5 * _p * vec2(max(r / tR, 1.), max(tR / r, 1.));
}
`,
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D t;
uniform float alpha;
void main() {
vec4 c = texture2D(t, uv);
gl_FragColor =
step(0.0, uv.x) *
step(0.0, uv.y) *
step(uv.x, 1.0) *
step(uv.y, 1.0) *
c * sqrt(alpha);
}
`,
},
free: {
vert: GLSL`
attribute vec2 _p;
varying vec2 uv;
uniform float zoom;
uniform vec2 center;
uniform float tR;
uniform vec2 res;
float r;
vec2 invert(vec2 p) {
return vec2(p.x, 1.0 - p.y);
}
void main() {
r = res.x / res.y;
gl_Position = vec4(_p, 0.0, 1.0);
// crop with zoom & center in a cover mode. preserving image ratio
float maxR = max(r, tR);
vec2 zoomedCanvasSize = vec2(
(r / maxR) * zoom,
(tR / maxR) * zoom
);
vec4 crop = vec4(
center.x - zoomedCanvasSize.x / 2.,
center.y - zoomedCanvasSize.y / 2.,
zoomedCanvasSize.x,
zoomedCanvasSize.y
);
// apply the crop rectangle
uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
}
`,
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D t;
uniform float alpha;
void main() {
vec4 c = texture2D(t, uv);
gl_FragColor =
step(0.0, uv.x) *
step(0.0, uv.y) *
step(uv.x, 1.0) *
step(uv.y, 1.0) *
c * sqrt(alpha);
}
`,
},
cover: {
// NB the cover vertex code can probably be simplified. good enough for now.
vert: GLSL`
attribute vec2 _p;
varying vec2 uv;
uniform float zoom;
uniform vec2 center;
uniform float tR;
uniform vec2 res;
float r;
vec2 invert(vec2 p) {
return vec2(p.x, 1.0 - p.y);
}
void main() {
r = res.x / res.y;
gl_Position = vec4(_p, 0.0, 1.0);
// crop with zoom & center in a cover mode. preserving image ratio
float maxR = max(r, tR);
vec2 zoomedCanvasSize = vec2(
(r / maxR) * zoom,
(tR / maxR) * zoom
);
vec4 crop = vec4(
center.x - zoomedCanvasSize.x / 2.,
center.y - zoomedCanvasSize.y / 2.,
zoomedCanvasSize.x,
zoomedCanvasSize.y
);
// clamp to not escape the edges
float w = crop[2], h = crop[3];
float ratio = w / h;
if (w > 1.) {
w = 1.;
h = w / ratio;
}
if (h > 1.) {
h = 1.;
w = h * ratio;
}
crop = vec4(
max(0., min(crop.x, 1. - w)),
max(0., min(crop.y, 1. - h)),
w,
h
);
// apply the crop rectangle
uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
}
`,
frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D t;
uniform float alpha;
void main() {
vec4 c = texture2D(t, uv);
gl_FragColor = c * sqrt(alpha);
}
`,
},
});
type ImageProps =
| {
source: { uri: string },
center?: [number, number],
zoom?: number,
alpha?: number,
onDraw?: () => mixed,
resizeMode: "cover" | "free",
}
| {
source: { uri: string },
center?: [number, number],
zoom?: number,
alpha?: number,
onDraw?: () => mixed,
resizeMode: "contain",
}
| {
source: { uri: string },
center?: [number, number],
zoom?: number,
alpha?: number,
onDraw?: () => mixed,
resizeMode: "stretch",
};
export default class Image extends React.PureComponent<ImageProps> {
_isMounted = false;
static defaultProps = { resizeMode: "cover", center: [0.5, 0.5], zoom: 1, alpha: 1 };
state = { isAlready: false };
componentDidMount() {
this._isMounted = true;
setTimeout(() => {
// fix first draw is black screen ~1s
if (this._isMounted) {
this.setState({ isAlready: true });
}
}, 100);
}
componentWillUnmount() {
this._isMounted = false;
}
render(): React.Node {
let { source, resizeMode, center, zoom, alpha, onDraw, ...rest } = this.props;
if (!this.state.isAlready) {
onDraw = undefined;
}
if (resizeMode === "cover" || resizeMode === "free") {
return (
<Node
shader={resizeMode === "cover" ? shaders.cover : shaders.free}
uniforms={{
t: source,
tR: Uniform.textureSizeRatio(source),
res: Uniform.Resolution,
center,
zoom,
alpha,
}}
{...{ onDraw }}
{...rest}
/>
);
}
if (resizeMode === "contain") {
return (
<Node
shader={shaders.contain}
uniforms={{
t: source,
tR: Uniform.textureSizeRatio(source),
res: Uniform.Resolution,
alpha,
}}
{...{ onDraw }}
{...rest}
/>
);
}
// fallback on stretch, most basic thing
return <LinearCopy {...rest}>{source}</LinearCopy>;
}
}
library version
"gl-react": "^3.17.2",
"gl-react-expo": "^3.17.2",
"react-native-view-shot": "^3.1.2",
"react-native": "~0.61.5",
I don't find any solution for this. Any ideas?