Forum Discussion
10 Replies
- TheEndlessChannel SurferTake a look at this thread from last week: viewtopic.php?f=34&t=30944
One of the biggest factors I've found is the size of the image being drawn in a single layer. There's a surprising speed difference between drawing an image that is 600 pixels high vs. an image that's 598 pixels high, so I've found in many cases, you get better refresh rates if you break larger images into multiple layers. kbenson also had some interesting suggestions for using multiple canvases. - kbensonVisitorYeah, we've had really good results so far with multiple canvas items, and calling show on them in order. Here's a few tips:
1) Every time you create a new roImageCanvas object, the other ones will need to redraw everything the next time you call show() on them, so pre-initialize as many as you think you'll need.
2) Once you've got a canvas set up with all the images you want displayed on it, called show(), and given it time to actually do all the compositing, subsequent calls to show() without changing the canvas are quick compared to adding new images and calling how. To the degree that it only takes 15-50 ms (manual sleep!) to call show on a previously shown image canvas.
So, if you have an animation that isn't too complex, you could conceivably create a set of canvas objects, one for each frame, and after calling show on them all initially, you could call show on them in order later for a quick animation.
P.S. If you don't sleep manually between canvas item show() calls, the display order gets all messed up. You could conceivably make use of this to make sure a splash screen is displayed while doing the initial show() on all the objects so they display fast later in the animation. - renojimCommunity Streaming ExpertThanks guys. It looks like I have some experimenting to do. I had read that thread, but I didn't look at it too closely. At the time I didn't see the point of multiple canvasses when you could have multiple layers, but I'll have to try it for myself.
Thanks again!
-JT - kbensonVisitor
"renojim" wrote:
At the time I didn't see the point of multiple canvasses when you could have multiple layers, but I'll have to try it for myself.
Yeah, it's a dirty hack to get around poor performance with multiple items on a canvas. It would be great if Roku could improve canvas performance, but I'm not sure how feasible that is with the hardware and the canvas's current main purpose. Hopefully there's some optimizations they can make to greatly speed up adding layers with lots of images already on the canvas. I could live with the ~100ms update time if it was somewhat constant, and didn't turn into 4000ms when lots of images were already present on that canvas.
P.S. I just realized I haven't tested whether there's a difference in delays with multiple images if they are overlapping or not. I guess I know what I'll be testing tonight... - TheEndlessChannel Surfer
"kbenson" wrote:
P.S. I just realized I haven't tested whether there's a difference in delays with multiple images if they are overlapping or not. I guess I know what I'll be testing tonight...
I've actually done some testing with this myself, and found the difference to be negligible. I'm curious to see if you get the same results. I suspect you will, based on my other testing.
One test in particular that reveals a lot about how the canvas works, you may be interested in trying...
Draw a full screen image in one go and time it. Then draw the same image in three sections (to the same layer) with the appropriately different TargetRects and SourceRects, so you're essentially drawing the exact same data, from the exact same file, to the screen. I was surprised at the results. - kbensonVisitor
"TheEndless" wrote:
One test in particular that reveals a lot about how the canvas works, you may be interested in trying...
Draw a full screen image in one go and time it. Then draw the same image in three sections (to the same layer) with the appropriately different TargetRects and SourceRects, so you're essentially drawing the exact same data, from the exact same file, to the screen. I was surprised at the results.
I haven't tested yet, but are you scaling? We've found that if you can get away with smaller source images, it's much quicker.
Also, if you haven't already, take a two pixel PNG with different colors for each pixel, and scale that up. You get interpolation between the color differences. Easy, super small way to do color gradients. - TheEndlessChannel Surfer
"kbenson" wrote:
"TheEndless" wrote:
One test in particular that reveals a lot about how the canvas works, you may be interested in trying...
Draw a full screen image in one go and time it. Then draw the same image in three sections (to the same layer) with the appropriately different TargetRects and SourceRects, so you're essentially drawing the exact same data, from the exact same file, to the screen. I was surprised at the results.
I haven't tested yet, but are you scaling? We've found that if you can get away with smaller source images, it's much quicker.
Also, if you haven't already, take a two pixel PNG with different colors for each pixel, and scale that up. You get interpolation between the color differences. Easy, super small way to do color gradients.
I'm not scaling, but I get the same performance result whether I paint the full image three times (squashed vertically), or I paint different SourceRects of the image. I mentioned in another post that the cutoff seems to be around 598 pixels. I got significantly different paint times painting the image at 598 pixels high than I did at 599 pixels. Very strange...
In the end, I just cut my background image into 3 separate images, and paint them each on the "background" layer. I get the same visual results as having a single image, with much better performance. I haven't actually tested to see if cutting them down further will make a difference, because I basically needed a refresh under a second for updates to my onscreen timer, but I'd be willing to bet that it does.
The gradient thing is awesome! I might just use that! - renojimCommunity Streaming Expert
"kbenson" wrote:
Are you using multiple canvas objects? From what I remember, I haven't had any problems with this on a single canvas, but multiple canvas items require you to call .show() on the back ones first (with a small delay between them), otherwise the back canvas can't refresh and wipe out any drawing that happened on top of it.
I copied this from greubel's thead since I didn't want to hijack it.
I tried this for an animation, but calling .show() on the back one causes a sort of flashing as the object I'm trying to move across the screen disappears completely during the small delay and then reappears when I call .show() on its canvas. Is this as good as I can expect, or am I missing something? Also, it looks like the box isn't too happy about me calling show() on two different canvases 100 times a second - when I press Home it takes a few seconds for the main screen to appear.
I did lots of experimenting last night, but I wasn't real happy with anything I tried and several things I tried had really strange results. The best compromise I found was to have a background canvas and another canvas where the animation takes place. Then when I want to move the object across the screen, I redraw it in the background color at its old position and at the same time draw it at its new position. This only works because my animation is really simple, my background is mostly empty, and the few places where the moving image crosses over something on the background I can handle pretty easily. It mostly works, but there are still strange things happening on these canvasses. If I don't put enough of a delay in the loop it looks like some updates get discarded leaving artifacts on the screen. Pressing a button on the remote sometimes has the same effect.
That gradient idea sounds pretty cool. I'm going to have to use that someplace. Thanks for sharing!
-JT - renojimCommunity Streaming ExpertI've discovered another problem with the multiple canvas approach. It looks like when the box comes out of screensaver only the topmost canvas gets redrawn. Has anyone else seen this?
-JT - kbensonVisitorSo, there's a few tricks to getting multiple canvases to work right when they overlap.
First, you don't want to be altering multiple canvases in the visual stack. That is, if you have two or three canvas objects that overlap, you only want to be changing layers on the "top" one. That's because adding to a canvas and calling show() incurs the normal delay of re-compositing that canvas. If there's lots of images, or very large images, it may take a bit to update, and it's hard to determine how long. The call to .show on any canvas items "above" it need to happen after it finishes. Calling show() on a canvas item that has NOT been changed is quite quick though, somewhere between 11 and 40 ms.
Second, you need to call show() on all canvas objects that overlap, in order, on each update to the topmost canvas in that stack. As long as the lower canvas objects aren't changing, this shouldn't be too much of a problem, as caling show() on them is quite speedy.
So, it's dirty, it's a hack, it's painful to do, but if you do it right, in some circumstances you can get a fairly static update time out of canvas operations, which can't be (currently) said for a single canvas.