Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Huge Tilemap with Flickable and GridLayout for Android deployment impossible?

Huge Tilemap with Flickable and GridLayout for Android deployment impossible?

Scheduled Pinned Locked Moved Mobile and Embedded
androidflickablegridlayout
5 Posts 2 Posters 3.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wumpus
    wrote on last edited by
    #1

    Hi everyone,

    I am trying to realize a large map application, which I want to deploy on Android 4.4 - 5.0. I have 233 png-files, which resulted from cutting a huge png (~18000 x 13000 px) file into 1024x1024 px tiles. As a QML Windows desktop application everything runs just fine, even when I am loading all tiles into a Flickable and GridLayout. In case of Android, however, when loading more than ~90 tiles (i.e. 5*18), the app crashes at startup. The error message reads like:

    W/Adreno-EGL(17217): <qeglDrvAPI_eglSwapBuffers:3602>: EGL_BAD_CONTEXT
    W/Qt (17217): (null):0 ((null)): QEGLPlatformContext::swapBuffers(): eglError: 12294, this: 0x9ee0efd0

    Here is the main code for reference:

    import QtQuick 2.3
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.2
    import QtPositioning 5.4
    import QtQuick.Layouts 1.1
    
    Rectangle {
        id: backgroundRect
        color: "lightblue"
    
        Flickable {
            id: flickable1
            boundsBehavior: Flickable.DragAndOvershootBounds
            anchors.fill: parent
            contentHeight: 12*1024+466
            contentWidth: 17*1024+192
            flickableDirection: Flickable.AutoFlickDirection
    
            GridLayout {
                id: bigGrid
                rowSpacing: 0
                columnSpacing: 0
                columns: 18
    
                Repeater {
                    model: tilesModel // This is created on c++ side as StringList containing the filenames
                    Image {
                        asynchronous: true
                        cache: false
                        source: modelData 
                    }
                }
            }
        }
    }
    

    To me it seems to be an OpenGL-on-Android-related problem. I tried using an ImageProvider on the c++ side, but got stuck there as well.

    Some specs: Qt5.4, QtCreator3.3.0, Android for armeabi-v7a (GCC 4.9, Qt 5.4.0), android-ndk-r10d, jdk1.8.0_25, Sony Experia Z1 (Lollipop)

    Any help/ideas appreciated

    1 Reply Last reply
    0
    • T Offline
      T Offline
      t3685
      wrote on last edited by t3685
      #2

      It looks like you're loading all the images at start of your application. Your Android device probably ran out of memory.

      You probably need to switch to an approach where you only load the pictures as needed

      W 1 Reply Last reply
      0
      • T t3685

        It looks like you're loading all the images at start of your application. Your Android device probably ran out of memory.

        You probably need to switch to an approach where you only load the pictures as needed

        W Offline
        W Offline
        wumpus
        wrote on last edited by
        #3

        @t3685 Thanks for the answer. You are right, of course.

        My problem is only that I have no clue how I could realize this "loading on demand" version. Of course, less than 3 tiles are visible at first and I can track the Flickable contentX and contentY properties from inside QML. I even managed to access these properties from the C++ side, but how do I stop loading all images at startup in the first place? Should I not set the source attribute of the Images in QML, perhaps? Then later I set the values from C++ side on demand?

        Actually, I hoped to be able to exploit the requestImage() function of my QImageProvider, but due to caching (and some undocumented "bug") this function is only called, when the source attribute changes to a non-cached string (even if the cache attriubte is set to false for the image). In effect, I can only do the coordinate checking once at startup for all the pictures, if I dont add a random number to the source-string with each frame.

        Well, I'd be glad if anyone could help here.

        Best,
        wumpus

        T 1 Reply Last reply
        0
        • W wumpus

          @t3685 Thanks for the answer. You are right, of course.

          My problem is only that I have no clue how I could realize this "loading on demand" version. Of course, less than 3 tiles are visible at first and I can track the Flickable contentX and contentY properties from inside QML. I even managed to access these properties from the C++ side, but how do I stop loading all images at startup in the first place? Should I not set the source attribute of the Images in QML, perhaps? Then later I set the values from C++ side on demand?

          Actually, I hoped to be able to exploit the requestImage() function of my QImageProvider, but due to caching (and some undocumented "bug") this function is only called, when the source attribute changes to a non-cached string (even if the cache attriubte is set to false for the image). In effect, I can only do the coordinate checking once at startup for all the pictures, if I dont add a random number to the source-string with each frame.

          Well, I'd be glad if anyone could help here.

          Best,
          wumpus

          T Offline
          T Offline
          t3685
          wrote on last edited by
          #4

          @wumpus

          Hi,

          The repeater you are using creates all the images immediately.
          Since you don't have a huge amount of tiles consider placing your images in loader elements. The loader element has a property called active which can be used to load or unload a qml component.
          You would then need to add logic to switch this property on or off when they need to shown or not.
          If the number of tiles increases you will have to think of other solutions.

          Ps, the default image provider is very efficient so I wouldn't mess too much if I were you :-)

          Good luck!

          W 1 Reply Last reply
          0
          • T t3685

            @wumpus

            Hi,

            The repeater you are using creates all the images immediately.
            Since you don't have a huge amount of tiles consider placing your images in loader elements. The loader element has a property called active which can be used to load or unload a qml component.
            You would then need to add logic to switch this property on or off when they need to shown or not.
            If the number of tiles increases you will have to think of other solutions.

            Ps, the default image provider is very efficient so I wouldn't mess too much if I were you :-)

            Good luck!

            W Offline
            W Offline
            wumpus
            wrote on last edited by
            #5

            @t3685

            Hi,
            yes, indeed. This was the problem.

            I solved ot now by creating an item, which contains a grid of "only" 36 (i.e. 6x6) elements inside the Flickable.

                    Item {
                        id: imageItem
                        GridLayout {
                            id: localGrid
                            columns: 6
                            rows: 6
                            rowSpacing: 0
                            columnSpacing: 0
                            Repeater {
                                model: tile1000model
                                Image {
                                    transformOrigin: Item.Left
                                    asynchronous: true
                                    sourceSize.height: 1024
                                    sourceSize.width: 1024
                                    source: modelData
                                }
                            }
                        }
                    }
            

            This grid is then dynamically moved over the Flickable-area, depending on the contentX and contentY changes:

            onContentXChanged: updateImages(contentX, contentY) 
            onContentYChanged: updateImages(contentX, contentY) 
            
            function updateImages(x, y) {
                var _x = Math.floor(x / 1024)
                var _y = Math.floor(y / 1024)
                if (_x < 0) {
                    _x = 0
                }
                if (_y < 0) {
                    _y = 0
                }
                var _x2 = _x
                var _y2 = _y
                if (_x >= 2) { // not at left border
                    _x2 -= 2
                }
                if (_y >= 2) { // not at top
                    _y2 -= 2
                }
                console.log("_x", _x, "prevX", prevX, "_y", _y, "prevY", prevY)
                if (Math.abs(prevX - _x) > 1 || Math.abs(prevY - _y) > 1) {
                    imageItem.y = _y2 * 1024
                    imageItem.x = _x2 * 1024
                    for (var i = 0; i < localGrid.children.length; ++i) {
                        var ix = i % 6 + _x2
                        var iy = Math.floor(i / 6) + _y2
                        if (localGrid.children[i].source)
                            localGrid.children[i].source = "qrc:/slices/tile1000_" + iy + "_" + ix + ".png"
                    }
                    prevX = _x
                    prevY = _y
                }
            }
            

            This works fine, but when scrolling from right to left, or from bottom to top, some flickering happens, because the loading takes too much time.

            Well, thank you for your help.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved