Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
dev42
Level 7

is <bitmap>.finish() no longer necessary?

Going thru old posts and the SDK there is mention of issuing <bitmap>.finish() before drawing it to the screen.

I naturally forgot and then put it in afterword. Smiley Wink

Instead of guaranteeing no tearing, it did the opposite. A lot of flicker!

I'm on a Roku 2 3100X, SW ver 5.5 * build 410

So, if doing double buffering and drawing to a bitmap and then drawing that bitmap to the screen is done, is <bitmap>.finish() necessary? And if so, how to make it work?

Also, is this behavior consistent with other Rokus?

peace & 42
0 Kudos
11 Replies
TheEndless
Level 7

Re: is <bitmap>.finish() no longer necessary?

You should always call .finish() after drawing to a bitmap. What you're seeing is probably the same issue discussed here, which only happens on the previous generation Roku 2 XD/XS and the Streaming Stick: viewtopic.php?f=34&t=54513&p=438720#p438720
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
dev42
Level 7

Re: is <bitmap>.finish() no longer necessary?

"TheEndless" wrote:
You should always call .finish() after drawing to a bitmap.

I'm confused. If I call bitmap.finish() I get the tearing. If I don't call bitmap.finish() I don't get tearing, but you're saying this is the opposite of what should happen?
Furthermore, this has to do with my Roku 2 XS?
Library "v30/bslDefender.brs"
function Main()
? "bitmap tear v2"

screen = CreateObject("roScreen", True, 1280, 720)
msgport = CreateObject("roMessagePort")
screen.SetPort(msgport)

bitmap = CreateObject("roBitmap", { Width: 1280, Height: 720, AlphaEnable: True })
doFinish = True
codes = bslUniversalControlEventCodes()

? "Press 'B' to toggle bitmap.finish() on/off | Any other key to exit."
? "Calling bitmap.finish() = " ; doFinish

While True
msg = msgport.getmessage() ' poll for a button press
' returns IMMEDIATELY
if msg <> invalid and type(msg)="roUniversalControlEvent" then
b% = msg.GetInt()
if b% = codes.BUTTON_B_RELEASED then
doFinish = NOT doFinish
? "Calling bitmap.finish() = " ; doFinish
else if b% <> codes.BUTTON_B_PRESSED then
exit while
end if
end if
' Initiate drawing the the back buffer by clearing it.
screen.Clear(0)
' Create a bitmap in memory. We're not going to use it for anything.
' I believe the allocation of memory is what causes the flicker/tear.
' Comment this line out, replace it with a roBitmap created from a local path, or just move it above the Clear() and the flicker goes away.
' bitmap = CreateObject("roBitmap", { Width: 100, Height: 100, AlphaEnable: False }) 'Height and Width don't matter here
' Draw a red rect over the screen to make the issue more apparent
bitmap.DrawRect(0, 0, 1280, 720, &HFF0000FF)
if doFinish then
bitmap.finish()
end if
screen.DrawObject(0,0,bitmap)
screen.SwapBuffers()
End While
screen = Invalid
end function
B toggles bitmap.finish() on/off. Any other key exits.

peace & 42

ps - complete accident that there's 42 lines of code there.
[Edit2: added "screen = Invalid" else the main Roku menu disappears after exiting the app.]

Edit: the code above is a tweaked version of code The Endless posted in another thread. Link is above.
0 Kudos
TheEndless
Level 7

Re: is <bitmap>.finish() no longer necessary?

You should move the bitmap.DrawRect() and bitmap.Finish() code before the screen.Clear(). Any manipulation of bitmaps after you've initiated the screen update can cause the tearing.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
dev42
Level 7

Re: is <bitmap>.finish() no longer necessary?

Thanks. That worked.

Still, more Q's though. Will this work on all Roku's?

[ed.(OP) Other Q's deleted because OP was being too stubborn and trying to hold on to doing things the way they appeared to be working even-though it was plainly pointed out that it might not continue to work.]

I'm still in the early stages of my app dev and I'm still trying to figure out the look & feel of my app. This was the first off-screen assembled bitmap I was drawing to the roScreen. Up until this point I was using a lot of DrawText( ). I've tried to separate the logic from the drawing functions and that shouldn't change, but if I am to switch over to a more ( off-screen ) bitmap heavy version, I'm most likely going to have to make a change to my main loop... but maybe not as drastic a change as I think.

Although, the alternative is to just draw all bitmaps directly to the roScreen themselves... tsk tsk tsk decisions. decisions.

Off topic, I had to add a "screen = Invalid" after the while loop or the main Roku menu disappears. ( viewtopic.php?f=34&t=75635 )

	End While
screen = Invalid
end function


peace & 42
0 Kudos
TheEndless
Level 7

Re: is <bitmap>.finish() no longer necessary?

"dev42" wrote:
Still, more Q's though. Will this work on all Roku's?

Yes, there's no reason it wouldn't. All you're doing is making sure to not monkey with the video/graphics memory after you initiate drawing to the screen. Once you start drawing to the screen (clearing it in your example above) flicker is inevitable on the Roku 2 XD&XS and the Roku Streaming Stick if you do anything that requires modifying the video/graphics memory. It's annoying as hell, and only came about when the new home screen update was released (firmware 5.0), but it's the way it is for now. I'd hope, since the current generation streaming stick also exhibits the issue (i.e., it's not only on retired hardware), that they'd make a serious effort to fix it, but I'm not holding my breath. It's caused me MANY a headache... I'd recommend anyone developing with the 2D API make sure they test on either the Streaming Stick or a previous gen Roku 2 to avoid a significant amount of work to clean it up later on down the road...
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
dev42
Level 7

Re: is <bitmap>.finish() no longer necessary?

So, instead of drawing to roScreen all over my code, I could draw to an off-screen bitmap ("bgBitmap") and then in my "main" event loop:
  • <roScreen>.clear(0)
  • <roScreen>.drawObject(bgBitmap)
  • <roScreen>.swapBuffers()

yes?

[Edit: oooh oooh oooh! and I wouldn't even need to do the clear!!! If I'm not drawing the bitmap with alpha, yess?]

You've mentioned before this wouldn't be optimal speed-wise, but unless it is a huge performance hit, I willing to make that trade off.

Also, how exactly are references to objects counted ... If I'm in a function and the debugger and it's saying that my <roScreen> object has a refcnt=5 that means I've passed through 5 "nested" functions to get there? or something else?

The follow-up Q is *drum-roll* should I be setting every reference to the <roScreen> to Invalid after I'm done with it? ... and before exiting each function?

If that's too off topic, lemme bring it back... if I do make this switch and draw to the off-screen bitmap instead... will that automatically lower my refcnt or will it just transfer to the bitmap instead of the roScreen?

peace & 42
0 Kudos
TheEndless
Level 7

Re: is <bitmap>.finish() no longer necessary?

"dev42" wrote:
So, instead of drawing to roScreen all over my code, I could draw to an off-screen bitmap ("bgBitmap") and then in my "main" event loop:
<roScreen>.clear(0)
<roScreen>.drawObject(bgBitmap)
<roScreen>.swapBuffers()
yes?

No. I mean, you could do that, but that's overkill. What seems to cause the issue is manipulating non-roScreen memory (creating a bitmap, writing to a bitmap, disposing a bitmap, etc.) after you've initiated the screen update, but before you've called SwapBuffers. You can still draw all of your graphics directly to the roScreen, you just need to make sure they are ready to go before you do so.
"dev42" wrote:
Also, how exactly are references to objects counted ... If I'm in a function and the debugger and it's saying that my <roScreen> object has a refcnt=5 that means I've passed through 5 "nested" functions to get there? or something else?

That, I'm not sure, but I'd bet EnTerr has an idea.
"dev42" wrote:
The follow-up Q is *drum-roll* should I be setting every reference to the <roScreen> to Invalid after I'm done with it? ... and before exiting each function?

I wouldn't think so. You only want to set your roScreen reference to invalid when you're ready to close it.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
RokuMarkn
Level 7

Re: is <bitmap>.finish() no longer necessary?

The ref count is the number of variables referring to the object. It's set to 1 when you do CreateObject, and it get incremented every time a new variable is set to refer to that object, and decremented every time any such variable is modified or destroyed.

In answer to another one of your questions, all local variables are destroyed when the containing function exits. There is no need to set a variable to invalid unless it's going to remain in scope.

Also, I've updated section 4.3 of the Brightscript Language Reference to explain a bit more about references and such. I'd appreciate any feedback if it isn't clear.

--Mark
0 Kudos
Komag
Level 9

Re: is <bitmap>.finish() no longer necessary?

The updated 4.3 helps me understand it better, thanks.

I understand the basic idea is to save memory, right? If I set up an empty nested array such as [ [], [] ] (an array with two arrays within), and assign 100 variables to all equal it:
X = [ [], [] ]
aa = X
ab = X
ac = X
ad = X
ae = X
etc.

All those 100 variables only reference the ONE [ [], [] ] instead making 100 new copies of nested arrays that all eat up memory.

Later on when I want to fill information into ae, if I just say
ae[1] = ["red","blue"]
that will change the nested array for ALL the 100 variables! ac will now be [ ["red","blue"], [] ]

But I've found that if I use Append(), it creates a new nested array just for ae with the new values:
ae[1].Append(["red","blue])
now only ae will be [ ["red","blue"], [] ]
ac will still be [ [], [] ]
0 Kudos