Issue with masked objects inside masked objects! Only some of the devices affected!

Hi,

We’ve acquired a new tester, and she has LG P880 (Optimus 4x HD) with Android 4.0.2. Device has tegra3.

We’ve tested our game on devices with same resolution and found no issues, but this is the first when we test on tegra 3.

We use masks to describe resistances of enemies in our game, and on her devices, the stars are sometimes covered with bars [check the screenshots].

This does not happen all the time.

It is possible that she will leave her phone on this scene, the phone will suspend, resume and graphics will be fine. Then, the phone will suspend again and the glitch will reappear.

I’m not sure what’s wrong, this looks to be connected to masks, but we use them in other places as well and they seem fine [also, they work fine on other devices with same resolution].

Anyone else seen similar behavior?

Current release was built using 2013.1143.

EDIT:

I was able to finally nail it.

The problem is with masked sprites which are placed inside other masked objects [scroll view widget in this case].

You can see few devices on the pictures:

iPad 3rd gen - works fine

Galaxy Tab 2 10.1 - works fine

Galaxy S2 - works fine

LG P880 - works terrible - sometimes you can’t see stars at all, sometimes they are covered with colored bars

Galaxy S4 - no stars at all

I’m attaching pictures as well as sample code.

I’ve double checked my masks, two of them had similar names, and one of them had height not dividable by 4.

I’ve changed the height from 22 to 24 and reuploaded to google play for my alpha testers.

I should have an answer today if this was the case.

There’s something more though.

I forgot to mention, that the stars are in a scrollview, which is masked as well (when there are more than 4 enemy types the list is scrollable).

Maybe this is why this is happening?

Unfortunately that was not the issue.

Even after changing the height of my mask [which worked just fine on other devices anyway] there was no change on the LG P880 with Tegra 3 processor.

I would love to hear a thought or two on this subject.

You are most likely running into a graphics hardware limitation.  There is a maximum number of textures (known as max texture units) that can be applied to the same polygon, and if you exceed that maximum, then you’ll run into graphics glitches with the hardware.  This is a hardcode maximum set by the graphics hardware manufacturer and the cheaper/weaker graphics hardware will support less texture units than others.  Worst case is a maximum of 2 units.  It’ll never be below 2.  Each image, mask, and text count as one texture.  So, for example, if you have a text object with 2 masks on top of it, then that counts as 3 texture units.

In Corona, you can fetch the hardware’s max texture units by calling the system.getInfo(“maxTextureUnits”) function.

   http://docs.coronalabs.com/daily/api/library/system/getInfo.html#maxtextureunits

Unfortunately, there are a lot of Android devices still being made with low-end graphics hardware.  So, if you want to support as many devices as you can, then I suggest that you never exceed 2 texture units.  This means never applying a mask on top of a mask.  Either that or call the above function and render your scene differently for low-end devices.

Hi Joshua,

Thanks for sharing this info.

I like the part where you call Galaxy S4 and P880 as inferior to Galaxy S2 and Tab 2 10.1 :slight_smile:

It means it’s not only the build quality that degrades with each S line :wink:

Now seriously.

You are correct with the texture units, I took these two screenshots right now, and as you’ve said, the error comes from the device with 2 texture units.

However… don’t you think it’s weird that my over 2 years old S2 has more of them than current S4?

I would expect there’s a bug somewhere…

I’ll try to create similar test using native open gl later today and share some shots, but I doubt this is a hardware limitation.

It’s definitely a graphics hardware limitation.  Even the newest devices can come with low-end graphics hardware.  It just means that the manufacturer has cut costs by using cheaper graphics hardware.  Unfortunately it’s normal.  You see this all the time with PCs too.  Cheap PCs tend to have lower-end hardware than the more expensive PCs.

Also, not all Samsung S4s are the same.  The S4 is more of a brand (just like the SIII and SII), meaning that there are several different variations of S4s that have very different internal hardware.  Some S4s will have a max texture unit of 2 and some will have a much higher maximum.  It’s just how it is.

Note tha this is also why we went out of our way to add an API for fetching the max texture units of the graphics hardware.

Joshua,

I know where you are coming from, I hope you understand why I’m being stubborn about this.

I will shut up about this until I can find some more info.

I still haven’t had time to write something native, but Joshua, if you could, explain to me how is it possible that on LG P880 with tegra 3, this issue is intermittent?

It sometimes happens and sometimes not. It’s possible that you will enter the scene, there will be no issue, you will suspend and resume and the issue will be there. Same thing the other way.

Why do you think this would happen?

If you are exceeding the graphics hardware’s max texture units, then you will run into buggy/undefined behavior with its OpenGL driver.  The point is to never exceed that maximum.

Have you tried commenting out that 2nd mask and testing that?

That should solve this problem… unless you are running into a second issue which may be confusing things.

I had problems with masks inside tableviews / in groups holding tableviews on android as well.

I had 2 tableviews onscreen and wanted to move them around, but not hang off the screen on odd size devices so I put a third mask on the screen group and bam – the masking stopped working properly on some android devices.

It states on the setMask() page ( http://docs.coronalabs.com/api/type/DisplayObject/setMask.html ) that “Some platforms (e.g. Android) may have a mask nesting limit”.

That may not be any consolation, but I still got the functionality I wanted to work on Android.

In my case it was 3 masks being processed overall that caused it to choke / screen to not render right (each tableview had it’s own, and the main displayGroup had one too). I found a way to cut it to 1 mask during the movement operation -, then the code switches it back to its standard masking when it is complete.

Don’t know if you can find a way to do that based on your use case,but like Joshua says, just comment out the setMask on some masks, and see if the others start working correctly for starters.

I’ve double checked my masks, two of them had similar names, and one of them had height not dividable by 4.

I’ve changed the height from 22 to 24 and reuploaded to google play for my alpha testers.

I should have an answer today if this was the case.

There’s something more though.

I forgot to mention, that the stars are in a scrollview, which is masked as well (when there are more than 4 enemy types the list is scrollable).

Maybe this is why this is happening?

Unfortunately that was not the issue.

Even after changing the height of my mask [which worked just fine on other devices anyway] there was no change on the LG P880 with Tegra 3 processor.

I would love to hear a thought or two on this subject.

You are most likely running into a graphics hardware limitation.  There is a maximum number of textures (known as max texture units) that can be applied to the same polygon, and if you exceed that maximum, then you’ll run into graphics glitches with the hardware.  This is a hardcode maximum set by the graphics hardware manufacturer and the cheaper/weaker graphics hardware will support less texture units than others.  Worst case is a maximum of 2 units.  It’ll never be below 2.  Each image, mask, and text count as one texture.  So, for example, if you have a text object with 2 masks on top of it, then that counts as 3 texture units.

In Corona, you can fetch the hardware’s max texture units by calling the system.getInfo(“maxTextureUnits”) function.

   http://docs.coronalabs.com/daily/api/library/system/getInfo.html#maxtextureunits

Unfortunately, there are a lot of Android devices still being made with low-end graphics hardware.  So, if you want to support as many devices as you can, then I suggest that you never exceed 2 texture units.  This means never applying a mask on top of a mask.  Either that or call the above function and render your scene differently for low-end devices.

Hi Joshua,

Thanks for sharing this info.

I like the part where you call Galaxy S4 and P880 as inferior to Galaxy S2 and Tab 2 10.1 :slight_smile:

It means it’s not only the build quality that degrades with each S line :wink:

Now seriously.

You are correct with the texture units, I took these two screenshots right now, and as you’ve said, the error comes from the device with 2 texture units.

However… don’t you think it’s weird that my over 2 years old S2 has more of them than current S4?

I would expect there’s a bug somewhere…

I’ll try to create similar test using native open gl later today and share some shots, but I doubt this is a hardware limitation.

It’s definitely a graphics hardware limitation.  Even the newest devices can come with low-end graphics hardware.  It just means that the manufacturer has cut costs by using cheaper graphics hardware.  Unfortunately it’s normal.  You see this all the time with PCs too.  Cheap PCs tend to have lower-end hardware than the more expensive PCs.

Also, not all Samsung S4s are the same.  The S4 is more of a brand (just like the SIII and SII), meaning that there are several different variations of S4s that have very different internal hardware.  Some S4s will have a max texture unit of 2 and some will have a much higher maximum.  It’s just how it is.

Note tha this is also why we went out of our way to add an API for fetching the max texture units of the graphics hardware.

Joshua,

I know where you are coming from, I hope you understand why I’m being stubborn about this.

I will shut up about this until I can find some more info.

I still haven’t had time to write something native, but Joshua, if you could, explain to me how is it possible that on LG P880 with tegra 3, this issue is intermittent?

It sometimes happens and sometimes not. It’s possible that you will enter the scene, there will be no issue, you will suspend and resume and the issue will be there. Same thing the other way.

Why do you think this would happen?

If you are exceeding the graphics hardware’s max texture units, then you will run into buggy/undefined behavior with its OpenGL driver.  The point is to never exceed that maximum.

Have you tried commenting out that 2nd mask and testing that?

That should solve this problem… unless you are running into a second issue which may be confusing things.

I had problems with masks inside tableviews / in groups holding tableviews on android as well.

I had 2 tableviews onscreen and wanted to move them around, but not hang off the screen on odd size devices so I put a third mask on the screen group and bam – the masking stopped working properly on some android devices.

It states on the setMask() page ( http://docs.coronalabs.com/api/type/DisplayObject/setMask.html ) that “Some platforms (e.g. Android) may have a mask nesting limit”.

That may not be any consolation, but I still got the functionality I wanted to work on Android.

In my case it was 3 masks being processed overall that caused it to choke / screen to not render right (each tableview had it’s own, and the main displayGroup had one too). I found a way to cut it to 1 mask during the movement operation -, then the code switches it back to its standard masking when it is complete.

Don’t know if you can find a way to do that based on your use case,but like Joshua says, just comment out the setMask on some masks, and see if the others start working correctly for starters.