CADisplayLink OpenGL 渲染中断 UIScrollView 行为 [英] CADisplayLink OpenGL rendering breaks UIScrollView behaviour

查看:11
本文介绍了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)

Promised links to similar questions: UIScrollView broken and halts scrolling with OpenGL rendering (related CADisplayLink, NSRunLoop)

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

推荐答案

CADisplayLink 触发的主线程上的缓慢更新可能是破坏 UIScrollView 滚动行为的原因.为 CADisplayLink 使用 NSRunLoopCommonModes 时,您的 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天全站免登陆