Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b025b9c8 authored by Romain Guy's avatar Romain Guy
Browse files

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
parent 857d7cf8
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -151,6 +151,12 @@ class GLES20Canvas extends Canvas {

    private native void nPrepare(int renderer);

    void onPostDraw() {
        nFinish(mRenderer);
    }
    
    private native void nFinish(int renderer);

    @Override
    public boolean acquireContext() {
        if (!mContextLocked) {
+14 −4
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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 },

+0 −2
Original line number Diff line number Diff line
@@ -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);

+15 −1
Original line number Diff line number Diff line
@@ -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);
Loading