Android bug——google map切换黑屏问题

现象描述:
在使用google map的时候,当从地图界面切换到导航界面的时候,极大概率出现切换过程中黑屏的现象,通过查看log,发现当前出现的错误码也为在hwui中的0x506
分析:
launcher花屏的问题也是出现0x506,但是这个0x506的问题已经解决了,这次这个google map的错误码问题应该和花屏的问题不是同一个问题。接着也是通过在hwui中的LayerRenderer中打印log,发现这次错误是出现在创建fbo的时候出错即createLayer的时候:
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
    Caches& caches = Caches::getInstance();
    GLuint fbo = caches.fboCache.get();
    if (!fbo) {
        ALOGW("Could not obtain an FBO");
        return NULL;
    }

    caches.activeTexture(0);
    Layer* layer = caches.layerCache.get(width, height);
    if (!layer) {
        ALOGW("Could not obtain a layer");
        return NULL;
    }
    ……
    GLuint previousFbo;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);

    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
    layer->bindTexture();
	……
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            layer->getTexture(), 0);

    glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
    return layer;
}

通过打印发现当前绑定到fbo的纹理是无效的,也就是是一个空的纹理,只有id,其他都是没有的。接着通过打印当前的opengl trace,发现当创建fbo的时候,没有调用glBindTexture的操作,也就是说当前的纹理没有被绑定使用。通过代码发现没有被绑定的原因是,在Caches中对纹理绑定进行了优化,也就是如果上一次调用了glBindTexture,且纹理的id一致的话,下次就不需要重新调用glBindTexture,这样可以防止频繁的调用opengl的接口,减少不必要的开销。但是这样的话是不可能导致纹理id无效的,除非当前的纹理id已经被删除了,但是在 Caches维护的id没删除,导致下次进入的时候由于刚好生成了与这个id号一样的纹理,这样就会导致没调用glBindTexture,直接使用上次的纹理,但是上次的却是无效的。

同时通过打印发现出现异常的纹理target比较奇怪,也就是为GL_TEXTURE_EXTERNAL_OES这种类型,接着通过代码发现,也就只有当创建的layer对象为createTextureLayer的时候,才会使用到拓展纹理。接着查看TextureView,发现TextureView的纹理创建在GLConsumer,然而纹理id的创建等都是在hwui中,这样当TextureView的纹理释放的时候(destroySurface):
 private void destroySurface() {
        if (mLayer != null) {
            mSurface.detachFromGLContext();
            // SurfaceTexture owns the texture name and detachFromGLContext
            // should have deleted it
            mLayer.clearStorage();

            boolean shouldRelease = true;
            if (mListener != null) {
                shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
            }

            synchronized (mNativeWindowLock) {
                nDestroyNativeWindow();
            }

            mLayer.destroy();
            if (shouldRelease) mSurface.release();
            mSurface = null;
            mLayer = null;

            mHadSurface = true;
        }
    }
首先会先将GLConsumer的纹理内容删除,同时调用glDeleteTextures删除纹理id,接着将会调用clearStorage来调用hwui中的layer的clearTexture:
void Layer::clearTexture() {
    texture.id = 0;
}
这时这边只是将纹理的id置为0,并没有将Caches维护的id也置为0,这样下次进行纹理id申请的时候,将会申请到上次删除的id,当调用Caches::bindTexture的时候则将会出现已经绑定了,但是当前的纹理却未绑定,这样也就导致了在使用fbo的时候出现了异常。
修改方案:

当调用layer的clearTexture时,将Caches维护的纹理id也一起清空。

void Layer::clearTexture() {
    if (texture.id) {
        texture.clearTexture();
        texture.id = 0;
    }
}

void Caches::clearTexture(GLuint texture) {
    for (int i = 0; i < REQUIRED_TEXTURE_UNITS_COUNT; i++) {
        if (mBoundTextures[i] == texture) {
            mBoundTextures[i] = 0;
        }
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值