Reputation: 311
In my app I use a GLSurfaceView to display a 2-dimensional background image which changes depending on the content displayed. The image is used as texture rendered on a simple rectangle with the same aspect ratio as the phone's screen. When the background changes, it renders an alpha-blend transition effect. If the device does not support Open GL ES 2.0, a static image is used instead. (Additional info: the image/texture is not a square and is not the size of a power of 2)
Some customers have reported that the background turns white on some devices (e.g. LG E455), making the app unusable, because the text displayed on top is white as well. I've been looking for a solution to the problem, but could not find anything.
Because I am providing the app for free without ads (I think ads do not fit the app) and I do not receive external funding, it is not an option for me to buy the device in question (LG E455) - as it is an old device - for the sole purpose of debugging this one issue.
I am using the following code to load the textures:
int getTexture(GL10 gl, int index) {
if (BackgroundRenderer.this.textures[index] == 0) {
gl.glGenTextures(1, BackgroundRenderer.this.textures, index);
gl.glBindTexture(GL10.GL_TEXTURE_2D, BackgroundRenderer.this.textures[index]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
Bitmap bitmap = ResourceStore.getBackgroundBitmap(index);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
return BackgroundRenderer.this.textures[index];
}
Version check and initialization:
private static boolean supportsOpenGLES2(Context context) {
ActivityManager activityManager = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo configurationInfo =
activityManager.getDeviceConfigurationInfo();
return configurationInfo.reqGlEsVersion >= 0x20000;
}
public BackgroundManager(Context context, ViewPager eventSource) {
this.context = context;
supportsRendering = BackgroundManager.supportsOpenGLES2(context);
eventSource.setTag(id.TAG_BACKGROUND_MANAGER, this);
if (this.supportsRendering) {
this.backgroundSurfaceView = new GLSurfaceView(context);
this.backgroundSurfaceView.setFocusable(false);
this.backgroundSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
eventSource.addOnPageChangeListener(BackgroundManager.getRenderer());
this.backgroundSurfaceView.setRenderer(BackgroundManager.getRenderer());
this.backgroundSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
} else {
this.backgroundStillView = new View(context);
}
}
If you need more code, please tell me.
I have thought about some possible solutions:
a) fix the problem (don't know how...)
b) disable the fancy effects in case the device does not support it, but here the question is, how can I detect if rendering would work in advance? The device passes my Open GL 2.0 version check.
c) move to a different rendering solution instead of OpenGL, as I have the feeling it is overkill for my purpose. Any suggestions?
Note: The solution proposed in Android 'white box' textures OpenGL ES 1.0 on some devices does not apply, because I use a different API and the device does support the extension as per http://specdevice.com/showspec.php?id=02c2-cba8-ffff-ffffebe99653 (although I am not sure if the information is correct/credible)
Thank you for your suggestions!
Upvotes: 0
Views: 917
Reputation: 16761
The problem here is that some devices do not support non-power-of-two textures. This is why some devices just show a white texture.
To solve this, it's best to always use a power-of-two bitmap when generating the texture.
Power-of-two bitmaps are bitmaps who's width / height are a power of two (256, 512, 1024, etc). As things stand at the moment, you're loading your bitmap via ResourceStore, and I doubt this tool creates a PO2 bitmap.
To overcome this issue, follow these steps:
Here's a code example:
public void getTexture(GL10 gl, int index) {
if (BackgroundRenderer.this.textures[index] == 0) {
//calls to gl.glGenTextures, gl.glBindTexture etc
Bitmap originalBitmap = ResourceStore.getBackgroundBitmap(index);
int po2W = 1;
int po2H = 1;
while (po2W < originalBitmap.getWidth())
po2W *= 2;
while (po2H < originalBitmap.getHeight())
po2H *= 2;
Bitmap po2Bitmap = Bitmap.createBitmap(po2W, po2H, Config.ARGB_8888);
Canvas canvas = new Canvas(po2Bitmap);
canvas.drawBitmap(originalBitmap, 0, 0, myPaint);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, po2Bitmap, 0);
// these ratios need to be used for setting the texture coordinates!
mWidthRatio = (float)orignalBitmap.getWidth() / (float)po2Bitmap.getWidth();
mHeightRatio = (float)orignalBitmap.getHeight() / (float)po2Bitmap.getHeight();
}
return BackgroundRenderer.this.textures[index];
}
Now, you will need to redefine the texture coordinates:
float textureData[] = {
0, 0, // top left
0, mHeightRatio, // bottom left
mWidthRatio, mHeightRatio, // bottom right
mWidthRatio, 0 // top right
};
Now you should be good to go.
Let me know if there's any problem.
Upvotes: 3