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

查看:116
本文介绍了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视图中的动画冻结时UIScrollView被拖到iPhone上

推荐答案

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 早先创建如下:

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天全站免登陆