We tried it on an iPad Air and this sample ran ok, however in our real app it still ran slowly if we tried to transition the filter values on a button press.
I say our real app, in actual fact it’s also a prototype app which is basically the sample posted above with button presses + transitions enabled. Still no enterFrame listeners or anything like that, just transition + perform with delay calls on the touch began/ended phases:
local minX = display.screenOriginX local minY = display.screenOriginY local maxX = display.viewableContentWidth + -1\* display.screenOriginX local maxY = display.viewableContentHeight + -1\* display.screenOriginY local \_W = maxX - minX local \_H = maxY - minY local centerX = display.contentCenterX local centerY = display.contentCenterY local allowBlurFilter = true local enableTouch = true local rectW, rectH = \_W \* 0.4, \_W \* 0.2 --make a background local bg = display.newRect(minX + \_W \* 0.5, minY + \_H \* 0.5, \_W, \_H) bg:setFillColor( 1, 1, 0.8 ) --draw a large image on screen local img = display.newImageRect("images/coronaicon.png", \_W, \_W) img.x, img.y = centerX, minY + (\_W \* 0.5) local function filterTransition(obj, alpha, blur, sigma, time, ease, xScale, yScale ) if obj.\_colorTransition ~= nil then timer.cancel(obj.\_colorTransition) obj.\_colorTransition = nil end if obj.\_valueTransition ~= nil then transition.cancel(obj.\_valueTransition) obj.\_valueTransition = nil end obj.\_valueTransition = transition.to(obj, {time = time, xScale = xScale, yScale = yScale, \_a=alpha, \_hb=blur, \_hs=sigma, \_vb=blur, \_vs=sigma, transition = ease}) local f = function() if obj then if obj.\_hb then --count = count + 1 obj.alpha = obj.\_a obj.fill.effect.horizontal.blurSize = obj.\_hb obj.fill.effect.horizontal.sigma = obj.\_hs obj.fill.effect.vertical.blurSize = obj.\_vb obj.fill.effect.vertical.sigma = obj.\_vs end end end obj.\_colorTransition = timer.performWithDelay(5, f, math.ceil(time/5)) end local function cancelTransitions(obj, shadow) if obj and obj.trans then transition.cancel(obj) obj.trans = nil end if shadow then if shadow.\_colorTransition then timer.cancel( shadow.\_colorTransition ) end if shadow.\_valueTransition then transition.cancel( shadow.\_valueTransition ) end end end --draw 4 rects, with blurred drop shadow for i = 1, 4 do local x, y = 0, 0 if i \<= 2 then x = centerX - rectW \* 0.6 else x = centerX + rectW \* 0.6 end y = maxY - 300 - ((2-i) % 2) \* (rectH \* 1.5) --create a shadow and insert it into a snapshot which is twice as large, so there is room for blurring local shadowRect = display.newRect( 0, 0, rectW, rectH ) shadowRect:setFillColor( 0 ) local shadow = display.newSnapshot( rectW \* 2, rectH \* 2 ) shadow.x = 10 shadow.y = 10 shadow.alpha = 0.5 shadow.group:insert(shadowRect) if allowBlurFilter then shadow.fill.effect = "filter.blurGaussian" shadow.fill.effect.horizontal.blurSize = 4 shadow.fill.effect.horizontal.sigma = 128 shadow.fill.effect.vertical.blurSize = 4 shadow.fill.effect.vertical.sigma = 128 shadow:invalidate() end --used in the transition function above if shadow.fill.effect then shadow.\_a = shadow.alpha shadow.\_hb = shadow.fill.effect.horizontal.blurSize shadow.\_hs = shadow.fill.effect.horizontal.sigma shadow.\_vb = shadow.fill.effect.vertical.blurSize shadow.\_vs = shadow.fill.effect.vertical.sigma end --create the button local button = display.newRect( 0, 0, rectW, rectH) button:setFillColor( 0.04, 0.25, 0.55 ) --add some text to it local buttonText = display.newText({ text = "Button "..i, x = button.x, y = button.y, width = button.width, height = 0, font = native.systemFont, align = "center", fontSize = 90, }) --insert into a group local group = display.newGroup( ) group.x, group.y = x, y group:insert(shadow) group:insert(button) group:insert(buttonText) local function onTouch(e) if e.phase == "began" then display.getCurrentStage():setFocus(button) cancelTransitions(group, shadow) group.trans = transition.to(group, {xScale = 1.1, yScale = 1.1, time = transitionTimeUp, transition = easing.outElastic, onComplete = function() cancelTransitions(group, shadow) end }) filterTransition(shadow, 0.7, 32, 64, 800, easing.outElastic, 1.1, 1.1) elseif e.phase == "ended" or e.phase == "cancelled" then display.getCurrentStage():setFocus(nil) cancelTransitions(group, shadow) group.trans = transition.to(group, {xScale = 1, yScale = 1, time = transitionTimeDown, transition = easing.outBack, onComplete = function() cancelTransitions(group, shadow) end}) filterTransition(shadow, 0.5, 4, 128, 400, easing.outBack, 1, 1) end return true end if enableTouch then button:addEventListener( "touch", onTouch ) end end ---[[--draw frame rate on screen local fps = require("memory\_and\_FPS") local performance = fps.PerformanceOutput.new() performance.group.x, performance.group.y = centerX, minY --]]
(I’ve also updated the repo on bitbucket if you’d rather grab it from there)
So on the iPad 3 just using the filter kills the framerate, on the iPad Air it’s fine until you try to perform any re-rendering of the filter, and then the frame rate takes a hit again. It’s not as bad, but given that this is a super basic sample and running on a reasonably recent device it’s still a bit concerning.
I’ve taken a screenshot on the iPad Air that shows the hit the frame rate takes when press one of the buttons:

It was a bit hard to capture it at the exact time, but you can see on the graph that it drops from 55-60ish down to under 25fps, and then back up again when you release the button.
On a related note, you can see that even when the frame rate is high, it seems to be jumping constantly between 60 and 30. We’ve always seen this happening in all of our apps and never been sure why. I’m aware it could be the fps tracker itself that’s causing it, but wondered if there was anything else that could be causing it or if anyone else had seen similar fps rates?