CADisplayLink OpenGL 渲染破坏了 UIScrollView 行为 [英] CADisplayLink OpenGL rendering breaks UIScrollView behaviour

查看:15
本文介绍了CADisplayLink OpenGL 渲染破坏了 UIScrollView 行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SO 上有一些类似的问题(链接在最后),但没有一个允许我解决我的问题,所以这里是:

There are a few similar questions out there on SO (links at end), but none of them has allowed me to fix my problem, so here goes:

我正在使用 OpenGL 渲染来制作用于游戏项目的图像平铺和缓存库,并且我想劫持 UIScrollView 的物理特性以允许用户浏览图像(因为它具有很好的反弹行为,不妨用它).所以我有一个 UIScrollView,我用它来获取我的纹理的渲染视图,但是有一个问题 - 在滚动视图上移动会阻止 CADisplayLink 在用户完成滚动之前触发(这看起来很糟糕).一个临时修复是使用 NSRunLoopCommonModes 而不是默认的运行模式,但不幸的是,这破坏了我正在测试的某些手机上滚动视图行为的某些方面(3GS 和模拟器似乎工作正常,而 iPhone4 和 3G't).

I'm using OpenGL rendering to make an image tiling and caching library for use in a game project, and I want to hijack the physics of the UIScrollView to allow the user to navigate around the images (since it has nice bounce behaviour, might as well use it). So I have a UIScrollView which I'm using to get the rendering view for my textures, but there's a problem - moving around on the scroll view prevents the CADisplayLink from firing until the user has finished scrolling (which looks horrible). One temporary fix has been to use NSRunLoopCommonModes instead of the default run mode, but unfortunately this breaks some aspects of scroll view behaviour on certain phones I'm testing on (the 3GS and simulator seem to work fine, while the iPhone4 and the 3G don't).

有谁知道我如何解决 CADisplayLink 和 UIScrollView 之间的这种冲突,或者知道如何修复在其他运行模式下工作的 UIScrollView?提前致谢:)

Does anyone know how I could get around this clash between the CADisplayLink and the UIScrollView, or know how to fix the UIScrollView working in other run modes? Thanks in advance :)

承诺的类似问题链接:UIScrollView 损坏并停止滚动 OpenGL 渲染(相关 CADisplayLink,NSRunLoop)

OpenGL ES 视图中的动画在 iPhone 上拖动 UIScrollView 时冻结

推荐答案

CADisplayLink 触发的主线程更新缓慢可能是这里破坏 UIScrollView 滚动行为的原因.将 NSRunLoopCommonModes 用于 CADisplayLink 时,您的 OpenGL ES 渲染可能需要足够长的时间才能使每一帧摆脱 UIScrollView 的计时.

It's possible that slow updates on the main thread triggered by the CADisplayLink are what's breaking UIScrollView's scrolling behavior here. Your OpenGL ES rendering might be taking long enough for each frame to throw off the timing of a UIScrollView when using NSRunLoopCommonModes for the CADisplayLink.

解决此问题的一种方法是使用 Grand Central Dispatch 串行队列在后台线程上执行 OpenGL ES 渲染操作.我在最近更新 Molecules(其源代码可在该链接中找到)中做到了这一点,并且在我的 CADisplayLink 上使用 NSRunLoopCommonModes 进行测试时,我没有看到与渲染同时出现在屏幕上的表格视图的本机滚动行为有任何中断.

One way around this is to perform your OpenGL ES rendering actions on a background thread by using a Grand Central Dispatch serial queue. I did this in my recent update to Molecules (source code for which can be found at that link), and in testing with using NSRunLoopCommonModes on my CADisplayLink, I don't see any interruption of the native scrolling behavior of a table view that's onscreen at the same time as the rendering.

为此,您可以创建一个 GCD 串行调度队列,并将其用于对特定 OpenGL ES 上下文的所有渲染更新,以避免同时写入上下文的两个操作.然后,在您的 CADisplayLink 回调中,您可以使用如下代码:

For this, you can create a GCD serial dispatch queue and use it for all of your rendering updates to a particular OpenGL ES context to avoid two actions writing to the context at the same time. Then, within your CADisplayLink callback you can use code like the following:

if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
    return;
}

dispatch_async(openGLESContextQueue, ^{

    [EAGLContext setCurrentContext:context];

    // Render here

    dispatch_semaphore_signal(frameRenderingSemaphore);
});

其中 frameRenderingSemaphore 是之前创建的,如下所示:

where frameRenderingSemaphore is created earlier as follows:

frameRenderingSemaphore = dispatch_semaphore_create(1);

如果一个新的帧渲染动作不在执行中,此代码只会将一个新的帧渲染动作添加到队列中.这样,CADisplayLink 可以连续触发,但如果一帧的处理时间超过 1/60 秒,它不会因挂起的渲染操作而使队列过载.

This code will only add a new frame rendering action onto the queue if one isn't in the middle of executing. That way, the CADisplayLink can fire continuously, but it won't overload the queue with pending rendering actions if a frame takes longer than 1/60th of a second to process.

再一次,我在我的 iPad 上尝试了这个,发现表格视图的滚动动作没有中断,只是因为 OpenGL ES 渲染消耗了 GPU 周期而稍微变慢了.

Again, I tried this on my iPad here and found no disruption to the scrolling action of a table view, just a little slowdown as the OpenGL ES rendering consumed GPU cycles.

这篇关于CADisplayLink OpenGL 渲染破坏了 UIScrollView 行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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