Better error handling in the OpenGL renderer.
Add a glGetError() check on every frame Don't attempt to create textures larger than the maximum size allowed Change-Id: Iee4afae16089406dbe8bf10fc93b674f1271a0ca
This commit is contained in:
@ -148,9 +148,15 @@ class GLES20Canvas extends Canvas {
|
||||
void onPreDraw() {
|
||||
nPrepare(mRenderer);
|
||||
}
|
||||
|
||||
|
||||
private native void nPrepare(int renderer);
|
||||
|
||||
void onPostDraw() {
|
||||
nFinish(mRenderer);
|
||||
}
|
||||
|
||||
private native void nFinish(int renderer);
|
||||
|
||||
@Override
|
||||
public boolean acquireContext() {
|
||||
if (!mContextLocked) {
|
||||
|
@ -210,7 +210,7 @@ public abstract class HardwareRenderer {
|
||||
* is invoked and the requested flag is turned off. The error code is
|
||||
* also logged as a warning.
|
||||
*/
|
||||
void checkErrors() {
|
||||
void checkEglErrors() {
|
||||
if (isEnabled()) {
|
||||
int error = sEgl.eglGetError();
|
||||
if (error != EGL10.EGL_SUCCESS) {
|
||||
@ -221,7 +221,7 @@ public abstract class HardwareRenderer {
|
||||
// we'll try again if it was context lost
|
||||
setRequested(false);
|
||||
}
|
||||
Log.w(LOG_TAG, "OpenGL error: " + error);
|
||||
Log.w(LOG_TAG, "EGL error: " + Integer.toHexString(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,7 +348,7 @@ public abstract class HardwareRenderer {
|
||||
void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
|
||||
SurfaceHolder holder) {
|
||||
if (isRequested()) {
|
||||
checkErrors();
|
||||
checkEglErrors();
|
||||
super.initializeIfNeeded(width, height, attachInfo, holder);
|
||||
}
|
||||
}
|
||||
@ -386,6 +386,9 @@ public abstract class HardwareRenderer {
|
||||
void onPreDraw() {
|
||||
}
|
||||
|
||||
void onPostDraw() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the EGL configuration for this renderer. The default configuration
|
||||
* is RGBX, no depth, no stencil.
|
||||
@ -418,10 +421,12 @@ public abstract class HardwareRenderer {
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
onPostDraw();
|
||||
|
||||
attachInfo.mIgnoreDirtyState = false;
|
||||
|
||||
sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
|
||||
checkErrors();
|
||||
checkEglErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,6 +575,11 @@ public abstract class HardwareRenderer {
|
||||
mGlCanvas.onPreDraw();
|
||||
}
|
||||
|
||||
@Override
|
||||
void onPostDraw() {
|
||||
mGlCanvas.onPostDraw();
|
||||
}
|
||||
|
||||
static HardwareRenderer create(boolean translucent) {
|
||||
if (GLES20Canvas.isAvailable()) {
|
||||
return new Gl20Renderer(translucent);
|
||||
|
@ -84,6 +84,11 @@ static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas,
|
||||
renderer->prepare();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject canvas,
|
||||
OpenGLRenderer* renderer) {
|
||||
renderer->finish();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject canvas,
|
||||
OpenGLRenderer* renderer) {
|
||||
renderer->acquireContext();
|
||||
@ -384,6 +389,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer },
|
||||
{ "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport },
|
||||
{ "nPrepare", "(I)V", (void*) android_view_GLES20Canvas_prepare },
|
||||
{ "nFinish", "(I)V", (void*) android_view_GLES20Canvas_finish },
|
||||
{ "nAcquireContext", "(I)V", (void*) android_view_GLES20Canvas_acquireContext },
|
||||
{ "nReleaseContext", "(I)V", (void*) android_view_GLES20Canvas_releaseContext },
|
||||
|
||||
|
@ -110,11 +110,9 @@ Layer* LayerCache::get(LayerSize& size) {
|
||||
layer = new Layer;
|
||||
layer->blend = true;
|
||||
|
||||
// Generate the texture in which the FBO will draw
|
||||
glGenTextures(1, &layer->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, layer->texture);
|
||||
|
||||
// The FBO will not be scaled, so we can use lower quality filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
|
@ -124,6 +124,8 @@ OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) {
|
||||
if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
|
||||
LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
||||
}
|
||||
|
||||
OpenGLRenderer::~OpenGLRenderer() {
|
||||
@ -161,6 +163,15 @@ void OpenGLRenderer::prepare() {
|
||||
mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::finish() {
|
||||
#if DEBUG_OPENGL
|
||||
GLenum status = GL_NO_ERROR;
|
||||
while ((status = glGetError()) != GL_NO_ERROR) {
|
||||
LOGD("GL error from OpenGLRenderer: 0x%x", status);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLRenderer::acquireContext() {
|
||||
if (mCaches.currentProgram) {
|
||||
if (mCaches.currentProgram->isInUse()) {
|
||||
@ -342,7 +353,10 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
|
||||
|
||||
// Layers only make sense if they are in the framebuffer's bounds
|
||||
bounds.intersect(*mSnapshot->clipRect);
|
||||
if (bounds.isEmpty()) return false;
|
||||
if (bounds.isEmpty() || bounds.getWidth() > mMaxTextureSize ||
|
||||
bounds.getHeight() > mMaxTextureSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LayerSize size(bounds.getWidth(), bounds.getHeight());
|
||||
Layer* layer = mCaches.layerCache.get(size);
|
||||
|
@ -44,6 +44,13 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Defines
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Debug
|
||||
#define DEBUG_OPENGL 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Renderer
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -59,6 +66,7 @@ public:
|
||||
|
||||
void setViewport(int width, int height);
|
||||
void prepare();
|
||||
void finish();
|
||||
void acquireContext();
|
||||
void releaseContext();
|
||||
|
||||
@ -395,6 +403,8 @@ private:
|
||||
// List of rectangles to clear due to calls to saveLayer()
|
||||
Vector<Rect*> mLayers;
|
||||
|
||||
GLint mMaxTextureSize;
|
||||
|
||||
}; // class OpenGLRenderer
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
Reference in New Issue
Block a user