不在 Android OpenGL 上绘图时快速屏幕闪烁 [英] Fast Screen Flicker while NOT drawing on Android OpenGL

查看:23
本文介绍了不在 Android OpenGL 上绘图时快速屏幕闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想节省电池续航时间.我的应用程序有时只需要绘制.所以我在 onDraw 方法中将这段代码添加到我的 Renderer 中:

I wanted to save battery life time. My app only needs to be drawn sometimes. So I added this code to my Renderer in the onDraw method:

boolean dirty = true;

public void onDrawFrame(GL10 arg0) {
    if (!dirty) return;
    dirty = false;

    ..... draw images ....
}

所以我的应用只有在我需要的时候才会被绘制.但是发生的情况是,如果我不在每一帧上绘制我的应用程序,它会非常快地闪烁.看起来它会每 2. 帧左右绘制一次,而在所有其他帧中只会绘制一个黑屏.

So my app only gets drawn when I want it. But what happens is that if I dont draw my app on every frame it flickers really fast. It looks like it will be drawn every 2. frame or so and in all the other frames only a black screen will be drawn.

我知道我可以将渲染模式设置为 RENDERMODE_WHEN_DIRTY.但我不想创建另一个线程来检查它是否脏.

I know that i could set the render mode to RENDERMODE_WHEN_DIRTY. But I dont want to create another thread to check if its dirty or not.

我的问题是它为什么会闪烁?在进行检查之前,我不会调用任何方法或 GLES20 调用:if (!dirty) return; 并且我确信 booleandirty 不会改变并且始终为 false,除非第一帧.

My question is why does it flicker? i dont call any methods or GLES20 calls before i do my check: if (!dirty) return; and i am sure that the boolean dirty doesnt change and is always false except for the first frame.

我将代码更改为:

int dirty = 0;

public void onDrawFrame(GL10 arg0) {
    if (dirty > 1) return;
    dirty++;

    ..... draw images ....
}

这会停止闪烁!看起来你必须至少画 2 次,这样你就不会让这个奇怪的屏幕闪烁.无论如何,我现在将尝试使用更干净的方式并创建一个调用 requestRender() 的线程,当我想绘制某些东西并将我的渲染模式设置为 RENDERMODE_WHEN_DIRTY

This stops the flickering! Looks like you have to draw atleast 2 times so you dont have this wierd screen flickering. Anyways I will now try to use the more clean way and create a thread that calls requestRender() when i want to draw something and set my render mode to RENDERMODE_WHEN_DIRTY

推荐答案

当调用 onDrawFrame() 时,再决定不想画一个框架已经太迟了.无论您在该方法中绘制什么,都会呈现出来.如果您不绘制任何内容,则将呈现渲染目标中发生的任何事情.无法保证那是什么.它可能是较旧的框架,也可能是随机垃圾.

When onDrawFrame() is called, it's too late to decide that you don't want to draw a frame. Whatever you draw in that method will be presented. If you don't draw anything, whatever happened to be in the render target will be presented. There's no guarantee about what that is. It could be an older frame, or random garbage.

您发现渲染帧至少两次的解决方法可能适用于您当前的系统,但我不会指望它在任何地方都能正常工作.它还会浪费电池电量.当您跳过实际渲染时,仍会显示帧.

The workaround you found of rendering the frame at least twice may work for your current system, but I wouldn't count on it working everywhere. It will also waste battery power. While you skip the actual rendering, the frames will still be presented.

最好的解决方案实际上是您使用 RENDERMODE_WHEN_DIRTY,并在您真正需要更新时触发更新.我不确定你为什么需要一个额外的线程.在您的程序逻辑中的某个时刻,您将更改需要重绘的数据/状态.发生这种情况时,您可以直接调用 requestRender(),而不是设置必须由另一个线程检查的标志.

The best solution is really that you use RENDERMODE_WHEN_DIRTY, and trigger updates when you actually need them. I'm not sure why you would need an extra thread for that. At some point in your program logic, you will change data/state that requires a redraw. You can directly call requestRender() when that happens, instead of setting a flag that has to be checked by another thread.

另一种选择是您调用:

eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);

在设置上下文/表面时.这要求在 eglSwapBuffers() 之后保留缓冲区内容.但是,它有一个很大的警告:并非所有设备都支持此功能.您可以测试它是否支持:

while setting up the context/surface. This requests that the buffer content is preserved after eglSwapBuffers(). It comes with a big caveat, though: This is not supported on all devices. You can test if it's supported with:

EGLint surfType = 0;
eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfType);
if (surfType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) {
    // supported!
}

您也可以在选择配置时请求此功能.作为传递给 eglChooseConfig() 的属性的一部分,添加:

You can also request this functionality as part of choosing the config. As part of the attributes passed to eglChooseConfig(), add:

...
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
...

但同样,所有设备都不支持.因此,仅当您针对特定设备时,它才是一个真正的选择,或者如果它不受支持,则具有功能回​​退.

But again, this is not supported on all devices. So it's only really an option if you're targeting specific devices, or have a functional fallback if it's not supported.

这篇关于不在 Android OpenGL 上绘图时快速屏幕闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆