community icon indicating copy to clipboard operation
community copied to clipboard

Texture size too large causes invisible text

Open cropleyb opened this issue 11 years ago • 18 comments

I have a large amount of scrollable text which was in a single Label. This works fine on my development machine (OS X) because I have the screen resolution set quite low (my eyesight isn't great). On iOS, this text disappeared. The reason: The text required a texture size that was too large. The workaround was to create a GridLayout containing several Labels. This works fine, but IMO it shouldn't be necessary. Ideally, I'd like the texture to (transparently to the developer) create a composite texture. If that is too difficult then it should at least raise an exception so that the developer can figure out what is going on. Thanks, Bruce

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

cropleyb avatar Apr 27 '14 23:04 cropleyb

This is a general issue and not really specific to text. E.g. imagine trying to display an image larger than the maximum texture size.

In terms of solving it, I imagine it could be solved generically at the texture level, or specifically for text. It should be semi-straight forward to solve it for text when we only need to scroll vertically. But we'd need to make some kind of scrollable behavior which when combined with a widget and added to a scrollview, the scrollview would be able to use the scrollable behavior to scroll more efficiently and overcome the texture size limitation.

Specifically for text, we can compute the layout for all the text and only render 3 times the visible amount of text (i.e. 3 time the viewport height), then as the scrollview scrolls down by a full viewport, we shift the text rendered by a single viewport height. This should allow seamless scrolling while only requiring to render the minimum amount of text required at a time.

matham avatar Apr 28 '14 01:04 matham

Same issue http://stackoverflow.com/questions/32412903/blank-text-output-on-android-phone I use a Scrollview though. Any suggestions.

abhigenie92 avatar Sep 05 '15 12:09 abhigenie92

There is a way to understand when the texture size limit is reached?

melassa avatar Nov 01 '16 11:11 melassa

I have a Lable inside a ScrollView and I have the same issue. I'm running my Kivy app on a Raspberry Pi 3. Is there a way to know the limit. It seems to have a different limit everytime the app is running. Because I can see the view turns blank at different amount of text. Thank you :)

ghost avatar Jan 18 '17 22:01 ghost

I think generally if you reach the maximum size in your app, you should probably change your app to break up text in smaller labels.

The texture size I believe is fixed for a particular system.

matham avatar Jan 18 '17 23:01 matham

I divide my text but the problem is to know the limit for a particular android phone, tablet, version

melassa avatar Jan 20 '17 12:01 melassa

@melassa, the resolution of the display is guaranteed to work as texture size, if you need a safe limit without querying gl features.

dessant avatar Jan 20 '17 12:01 dessant

Ok.

melassa avatar Jan 20 '17 12:01 melassa

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Oct 07 '17 04:10 stale[bot]

I'm also running into this, would prefer not to have to code more to break it up, but will do for now I guess.

uxmatthew avatar Mar 04 '18 23:03 uxmatthew

This is something of a nasty problem, in my opinion. It's especially bad because it isn't even close to obvious that this can be an issue. I've spent the last few hours playing with size, texture_size, text_size and hints with very strange combinations of results. This is the first time I'm noticing that there is a maximum texture size and consequently a maximum text size on labels, and the first piece of code was actually fine otherwise. Label docs (and any other widgets that could conceivably be hit by this) should mention this.

chintal avatar Jul 10 '18 17:07 chintal

Unfortunately, this is one of the things that people new to kivy must wade through and hit once before they learn about it. I'll create a label for these kinds of issues so we can document it in a faq e.g. But yeah, the docs should mention it.

matham avatar Jul 10 '18 18:07 matham

@abhigenie92 the link is dead @melassa, @chintal

Notice in the console this (my max size):

[INFO ] [GL ] Texture max size <16384>

from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string('''
#:import T kivy.graphics.opengl.GL_MAX_TEXTURE_SIZE
#:import G kivy.graphics.opengl.glGetIntegerv
TextInput:
    multiline: False
    on_text:
        print(any([s >= G(T)[0] for lb in self._lines_labels for s in lb.size]))
'''))

Pretty much you shouldn't be worried about the texture height (unless you use a silly font size), therefore it might be shortened to this:

    print(any([lb.size[0] >= G(T)[0] for lb in self._lines_labels]))

which is a simple check whether your texture is displayed or not. I think the caveat is when e.g. the (separate or integrated) GPU's memory is full, then this check won't matter and the texture might not be displayed at all or it could just crash or smth (haven't encountered such case in Kivy, can't say what happens).

With this check or perhaps with an adjusted one with an index if the Texture you can detect which one is just full and either move the text to the next line/widget/texture yourself or only limit the widget in this way:

from kivy.base import runTouchApp
from kivy.uix.textinput import TextInput
from kivy.graphics.opengl import glGetIntegerv, GL_MAX_TEXTURE_SIZE


class My(TextInput):
    def insert_text(self, *args, **kwargs):
        textures = self._lines_labels
        assert len(textures) == 1
        # assuming singleline mode, no silly \n inserting, etc

        max_size = glGetIntegerv(GL_MAX_TEXTURE_SIZE)[0]
        if textures[0].width >= max_size:
            print('GL_MAX_TEXTURE_SIZE({}) exceeded!'.format(max_size))
            # don't insert any text
            return
        super(My, self).insert_text(*args, **kwargs)


runTouchApp(My(multiline=False))

Try inserting character by character or Copy&Paste long string. Obviously if the Texture's size is less than the max and you insert more than the difference, the text will be just a black box, but the behavior is upon you i.e. whether you insert by chunks or by characters.

KeyWeeUsr avatar Jul 10 '18 19:07 KeyWeeUsr

Just to mention that yep, I ran into this too. After an hour or so of playing with texture_size, etc I finally came across this thread. It'd be great if the user didn't have to worry about this, but in the meantime the docs (probably for Label) really should mention it somewhere.

charlesbaynham avatar Sep 18 '18 11:09 charlesbaynham

same problem :(

PremKolar avatar Sep 27 '20 17:09 PremKolar

Unfortunately, this problem still exists at the moment.

NikitaAkimov avatar Mar 22 '21 21:03 NikitaAkimov

I think perhaps the best solution is to raise an exception when this happens, rather than silently not work to make it obvious to the user what they need to fix.

The actual issue is not likely to be fixed because this a gl limitation, and in a performant app, it probably shouldn't create these giant textures at once anyway. So this is not something kivy should create workarounds for but leave it up to app dev to split their textures up. But we should make it clear somehow to the user when this happens.

A PR raising an error would be welcome to create a discussion around this.

matham avatar Mar 22 '21 22:03 matham

I am writing an epub reader and wanted to display a chapter in a label which is in a scrollview. Looks like I have to code what I would expect a UI framework to do for me.

Codingboy avatar Jun 15 '22 10:06 Codingboy

Still there 2.1.0. Can someone update the documentation to include this limitation please, I've just spent my friday afternoon trying to understand what I was doing wrong, and at the end it was just an undocumented behavior 🥲 Thank you!

OK, to all suffering the same issue, here is the workaround. First of all, there is also the error in the output "UNSUPPORTED (log once): POSSIBLE ISSUE: unit 0 GLD_TEXTURE_INDEX_2D is unloadable and bound to sampler type (Float) - using zero texture because texture unloadable", which indicates that the texture is too large to be loaded.

Now the actual workaround:

from kivy.graphics.opengl import glGetIntegerv, GL_MAX_TEXTURE_SIZE MAX_TEXTURE_SIZE = glGetIntegerv(GL_MAX_TEXTURE_SIZE)[0]

def adapt_text_size(self, instance, value): if value[0] >= MAX_TEXTURE_SIZE: instance.text_size[0] = MAX_TEXTURE_SIZE - 1 if value[1] >= MAX_TEXTURE_SIZE: instance.text_size[1] = MAX_TEXTURE_SIZE - 1 instance.canvas.ask_update()

and you need to bind it on any UI element (in my case MDLabel), which you suspect can grow too big.

label.bind(texture_size=self.adapt_text_size)

That's it!

IMPORTANT: it will just clip your text, preventing the "black rectangle" problem. The much more elegant solution would be to split the UI element in multiple parts and render them. But it's too much for my case. I hope that Kivy core development team can address this issue properly.

CoderCoderCoder avatar Aug 24 '23 19:08 CoderCoderCoder

If you have a use case which actually needs a large texture size, you can also stitch multiple smaller labels together into a layout and use that instead. An example of this is in https://github.com/ebs-universe/kivy_garden.ebs.marquee/blob/main/kivy_garden/ebs/marquee/simple.py , specifically the text setter. While this won't be usable as is for the general case, the same approach can be adapted for your use case.

Be careful when doing this, though. The implementation above is also pretty naive, and if you try to push too much text in, you will end up with proportionally increased memory use.

chintal avatar Aug 25 '23 08:08 chintal

Please do not use bountysource. Many devs have had trouble getting paid there. You can check out this lemmy community as an alternative https://lemmy.ml/c/bugbounties

For statements from devs who have been unable to cash out from bountysource see: https://github.com/bountysource/core/issues

makeasnek avatar Aug 25 '23 08:08 makeasnek

@makeasnek: Yes, BountySource is not recommended any more. It has been removed from our docs #8447.

However, it remains locked into the history of old issues, unless someone writes a bot to clear it out.

Julian-O avatar Nov 15 '23 04:11 Julian-O