Hello,
I'm an Android developer, our App applies real-time effects to the camera preview, using some fairly simple GLSL shaders.
We are getting some issues with devices that use the PowerVR SGX 540 (Galaxy S and Droid 3 among others).
The errors don't affect all variants of the devices equally, our Galaxy S works fine, but the ones from the American carriers don't: some effects don't show up, we have some error reporting features in the App, and the typical error we get is a GL_INVALID_OPERATION after either glDrawArrays or glGetUniformLocation (and the shader doesn't work)
We've tried all sorts of things with no luck: packing uniforms into vec4s, removing uniforms altogether, rearrange client code, etc...
My questions are:
- Do all devices use the same drivers? Different variants of the same phone seem to behave differently.
- Are there any known bugs with these devices? should I be avoiding any particular features?
As an example of our shaders, this is one that creates a cartoon effect:
precision mediump float;
varying vec4 v_yTexCoord;
varying vec4 v_effectTexCoord;
uniform sampler2D effectTexture;
uniform sampler2D effectTexture2;
uniform sampler2D yTexture;
uniform sampler2D uvTexture;
uniform vec4 pvalues;
uniform vec4 textureSize;
float yDecode(vec2 texCoord)
{
return 1.164 * ( texture2D(yTexture, texCoord).r - 0.0627 );
}
vec4 yuvDecode(vec2 texCoord)
{
vec4 y = 1.164 * ( texture2D(yTexture, texCoord) - 0.0627 );
vec4 uv = texture2D(uvTexture, texCoord) - 0.5;
return y + vec4( 1.596 * uv.r, - 0.813 * uv.r - 0.391 * uv.a, 2.018 * uv.a, 1.0);
}
float edgeDetection(vec2 texCoords)
{
vec2 xdisp = vec2(1.0/textureSize.x, 0.0);
vec2 ydisp = vec2(0.0, 1.0/textureSize.y);
//grab surrounding px colors
float tl = yDecode(texCoords - xdisp - ydisp);
float l = yDecode(texCoords - xdisp);
float bl = yDecode(texCoords - xdisp + ydisp);
float t = yDecode(texCoords - xdisp);
float b = yDecode(texCoords + ydisp);
float tr = yDecode(texCoords + xdisp - ydisp);
float r = yDecode(texCoords + xdisp);
float br = yDecode(texCoords + xdisp + ydisp);
float dX = -tl - 2.0*l - bl + tr + 2.0*r + br;
float dY = -tl - 2.0*t - tr + bl + 2.0*b + br;
//compute the magnitude
float grad = abs(dX) + abs(dY);
return clamp(grad*pvalues.z, 0.0, 1.0);
}
void main()
{
float grad = edgeDetection(v_yTexCoord.xy);
highp vec4 color = yuvDecode(v_yTexCoord.xy);
vec3 yuv;
yuv.r = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
yuv.g = (color.b-yuv.r)*0.565;
yuv.b = (color.r-yuv.r)*0.713;
float grayscale = yuv.r;
float chalk = floor((yuv.r * 5.0 ) + 0.5);
float howmuch = 48.0;
yuv.r = ceil((yuv.r * 256.0 / howmuch)-0.5);
yuv.r *= howmuch;
yuv.r /= 256.0;
vec3 colorC;
colorC.r = yuv.r + 1.403 * yuv.b;
colorC.g = yuv.r - 0.344 * yuv.g - 0.714 * yuv.b;
colorC.b = yuv.r + 1.770 * yuv.g;
grad = mix(grad, 0.5, grad);
color.rgb = vec3(1.0 - grad);
vec2 halfCoord = v_effectTexCoord.xy * 0.5;
vec2 topLeft = vec2(0.0, 0.0);
vec2 topRight = vec2(0.5, 0.0);
vec2 bottomLeft = vec2(0.0, 0.5);
vec2 bottomRight = vec2(0.5, 0.5);
if ( chalk < 1.0 )
{
color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + bottomRight ).rgb);
}
if ( (chalk >= 1.0 ) && (chalk < 2.0) )
{
color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + bottomLeft ).rgb);
}
if ( (chalk >= 2.0 ) && (chalk < 3.0) )
{
color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + topRight ).rgb);
}
if ( (chalk >= 3.0) )
{
color.rgb -= vec3(1.0 - texture2D( effectTexture, halfCoord.xy + topLeft ).rgb);
}
color.rgb = mix(colorC * vec3(229.0/255.0, 170.0/255.0, 110.0/255.0), color.rgb, 0.65);
// Contrast 2*(Src*t + 0.25 - 0.5*t)
color.xyz = ((color.rgb - 0.5) * max(pvalues.x, 0.0)) + 0.5;
// Brightness
color.xyz *= vec3(pvalues.y, pvalues.y, pvalues.y);
gl_FragColor = color;
}
madruga2011-09-09 21:19:23