Exemplo n.º 1
0
// Note: this need to be called within th lock.
// Only called by updateDirtyBaseTiles() for now
void TransferQueue::cleanupTransportQueue()
{
    int index = getNextTransferQueueIndex();

    for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) {
        if (m_transferQueue[index].status == pendingDiscard) {
            // No matter what the current upload type is, as long as there has
            // been a Surf Tex enqueue operation, this updateTexImage need to
            // be called to keep things in sync.
            if (m_transferQueue[index].uploadType == GpuUpload) {
                status_t result = m_sharedSurfaceTexture->updateTexImage();
                if (result != OK)
                    XLOGC("unexpected error: updateTexImage return %d", result);
            }

            // since tiles in the queue may be from another webview, remove
            // their textures so that they will be repainted / retransferred
            BaseTile* tile = m_transferQueue[index].savedBaseTilePtr;
            BaseTileTexture* texture = m_transferQueue[index].savedBaseTileTexturePtr;
            if (tile && texture && texture->owner() == tile) {
                // since tile destruction removes textures on the UI thread, the
                // texture->owner ptr guarantees the tile is valid
                tile->discardBackTexture();
                XLOG("transfer queue discarded tile %p, removed texture", tile);
            }

            m_transferQueue[index].savedBaseTilePtr = 0;
            m_transferQueue[index].savedBaseTileTexturePtr = 0;
            m_transferQueue[index].status = emptyItem;
        }
        index = (index + 1) % ST_BUFFER_NUMBER;
    }
}
bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale)
{
    if (!m_glWebViewState)
        return false;

    if (!m_invalRegion.isEmpty() && !m_prepare)
        return false;

    if (m_scale != scale)
        return false;

    int swaps = 0;
    bool fullSwap = true;
    for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
        for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
            BaseTile* t = getBaseTile(x, y);
            if (!t || !t->isTileReady())
                fullSwap = false;
        }
    }

    // swap every tile on page (even if off screen)
    for (int j = 0; j < m_baseTileSize; j++) {
        BaseTile& tile = m_baseTiles[j];
        if (tile.swapTexturesIfNeeded())
            swaps++;
    }

    XLOG("%p greedy swapped %d textures, returning true", this, swaps);
    return fullSwap;
}
Exemplo n.º 3
0
std::shared_ptr<Terrain> TerrainGenerator::generate() const
{
    if (!levelForElement)
        levelForElement = initElementTerrainLevels();

    std::shared_ptr<Terrain> terrain = std::make_shared<Terrain>(m_settings);

    assert(PxGetPhysics().getNbScenes() == 1);
    PxScene * pxScene;
    PxGetPhysics().getScenes(&pxScene, 1);

    // The tileID determines the position of the current tile in the grid of tiles.
    // Tiles get shifted by -(numTilesPerAxis + 1)/2 so that we have the Tile(0,0,0) in the origin.
    
    int maxxID = m_settings.tilesX - int((m_settings.tilesX + 1) * 0.5);
    int minxID = maxxID - m_settings.tilesX + 1;
    int maxzID = m_settings.tilesZ - int((m_settings.tilesZ + 1) * 0.5);
    int minzID = maxzID - m_settings.tilesZ + 1;

    terrain->minTileXID = minxID;
    terrain->minTileZID = minzID;

    for (int xID = minxID; xID <= maxxID; ++xID)
    for (int zID = minzID; zID <= maxzID; ++zID)
    {
        TileID tileIDBase(TerrainLevel::BaseLevel, xID, zID);

        std::initializer_list<std::string> baseElements = { "bedrock", "sand", "grassland" };

        /** create terrain object and pass terrain data */
        BaseTile * baseTile = new BaseTile(*terrain, tileIDBase, baseElements);

        // create the terrain using diamond square algorithm
        diamondSquare(*baseTile);
        // and apply the elements to the landscape
        applyElementsByHeight(*baseTile);

        /** same thing for the liquid level, just that we do not add a terrain type texture */
        TileID tileIDLiquid(TerrainLevel::WaterLevel, xID, zID);
        LiquidTile * liquidTile = new LiquidTile(*terrain, tileIDLiquid);

        /** Create physx objects: an actor with its transformed shapes
          * move tile according to its id, and by one half tile size, so the center of Tile(0,0,0) is in the origin */
        PxTransform pxTerrainTransform = PxTransform(PxVec3(m_settings.tileBorderLength() * (xID - 0.5f), 0.0f, m_settings.tileBorderLength() * (zID - 0.5f)));
        PxRigidStatic * actor = PxGetPhysics().createRigidStatic(pxTerrainTransform);
        terrain->m_pxActors.emplace(tileIDBase, actor);

        baseTile->createPxObjects(*actor);
        liquidTile->createPxObjects(*actor);

        pxScene->addActor(*actor);

        TileID temperatureID(TerrainLevel::TemperatureLevel, xID, zID);
        // the tile registers itself in the terrain
        new TemperatureTile(*terrain, temperatureID, *baseTile, *liquidTile);
    }

    return terrain;
}
Exemplo n.º 4
0
void TerrainGenerator::applyElementsByHeight(BaseTile & tile) const
{
    uint8_t sand = tile.elementIndex("sand");
    uint8_t grassland = tile.elementIndex("grassland");
    uint8_t bedrock = tile.elementIndex("bedrock");

    float sandMaxHeight = 2.5f;     // under water + shore
    float grasslandMaxHeight = m_settings.maxHeight * 0.2f;

    for (unsigned int row = 0; row < tile.samplesPerAxis - 1; ++row) {
        const unsigned int rowOffset = row * tile.samplesPerAxis;
        for (unsigned int column = 0; column < tile.samplesPerAxis - 1; ++column) {
            const unsigned int index = rowOffset + column;

            float height = 0.25f * (
                tile.valueAt(index)
                + tile.valueAt(row + 1, column)
                + tile.valueAt(row, column + 1)
                + tile.valueAt(row + 1, column + 1));
            if (height < sandMaxHeight) {
                tile.setElement(index, sand);
                continue;
            }
            if (height < grasslandMaxHeight) {
                tile.setElement(index, grassland);
                continue;
            }
            tile.setElement(index, bedrock);
        }
    }
}
Exemplo n.º 5
0
void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
                                          int x, int y, const SkBitmap& bitmap)
{
    if (!tryUpdateQueueWithBitmap(renderInfo, x, y, bitmap)) {
        // failed placing bitmap in queue, discard tile's texture so it will be
        // re-enqueued (and repainted)
        BaseTile* tile = renderInfo->baseTile;
        if (tile)
            tile->backTextureTransferFail();
    }
}
Exemplo n.º 6
0
    static shared_ptr<PixelCache> create(BaseTile &tile, uint radius) {

        auto center = tile.getCenter();
        Area boundingBox(center - vec2(radius, radius), center + vec2(radius, radius));

        shared_ptr<PixelCache> output = make_shared<PixelCache>();
        
        for (float x = boundingBox.getX1(); x < boundingBox.getX2(); x++) {
            for (float y = boundingBox.getY1(); y < boundingBox.getY2(); y++) {
                if (tile.contains(vec2(x, y))) {
                    output->mInsidePositions.push_back(ivec2(x, y));
                }
            }
        }
        
        output->mBoundingBox = boundingBox;
        
        return output;
    }
Exemplo n.º 7
0
// When bliting, if the item from the transfer queue is mismatching b/t the
// BaseTile and the content, then the item is considered as obsolete, and
// the content is discarded.
bool TransferQueue::checkObsolete(int index)
{
    BaseTile* baseTilePtr = m_transferQueue[index].savedBaseTilePtr;
    if (!baseTilePtr) {
        XLOG("Invalid savedBaseTilePtr , such that the tile is obsolete");
        return true;
    }

    BaseTileTexture* baseTileTexture = baseTilePtr->backTexture();
    if (!baseTileTexture) {
        XLOG("Invalid baseTileTexture , such that the tile is obsolete");
        return true;
    }

    const TextureTileInfo* tileInfo = &m_transferQueue[index].tileInfo;

    if (tileInfo->m_x != baseTilePtr->x()
        || tileInfo->m_y != baseTilePtr->y()
        || tileInfo->m_scale != baseTilePtr->scale()
        || tileInfo->m_painter != baseTilePtr->painter()) {
        XLOG("Mismatching x, y, scale or painter , such that the tile is obsolete");
        return true;
    }

    return false;
}
Exemplo n.º 8
0
void TilesManager::printTextures()
{
#ifdef DEBUG
    XLOG("++++++");
    for (unsigned int i = 0; i < m_textures.size(); i++) {
        BaseTileTexture* texture = m_textures[i];
        BaseTile* o = 0;
        if (texture->owner())
            o = (BaseTile*) texture->owner();
        int x = -1;
        int y = -1;
        if (o) {
            x = o->x();
            y = o->y();
        }
        XLOG("[%d] texture %x  busy: %d owner: %x (%d, %d) page: %x scale: %.2f",
               i, texture,
               texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0);
    }
    XLOG("------");
#endif // DEBUG
}
void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView)
{
    if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0))
        return;

    bool isReady = tile.isTileReady();
    int left = tile.x() * TilesManager::tileWidth();
    int top = tile.y() * TilesManager::tileWidth();
    int right = left + TilesManager::tileWidth();
    int bottom = top + TilesManager::tileWidth();

    if (inView) {
        if (isReady)
            m_goodTiles++;
        else
            m_badTiles++;
    }
    m_records.last().append(TileProfileRecord(
                                left, top, right, bottom,
                                scale, isReady, (int)tile.drawCount()));
    XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale);
}
void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds)
{
    for (int i = 0; i < tilesInRow; i++) {
        int x = firstTileX;

        // If we are goingLeft, we want to schedule the tiles starting from the
        // right (and to the left if not). This is because tiles are appended to
        // the list and the texture uploader goes through the set front to back.
        if (goingLeft)
            x += (tilesInRow - 1) - i;
        else
            x += i;

        BaseTile* currentTile = 0;
        BaseTile* availableTile = 0;
        for (int j = 0; j < m_baseTileSize; j++) {
            BaseTile& tile = m_baseTiles[j];
            if (tile.x() == x && tile.y() == y) {
                currentTile = &tile;
                break;
            }

            if (!availableTile || (tile.drawCount() < availableTile->drawCount()))
                availableTile = &tile;
        }

        if (!currentTile && availableTile) {
            XLOG("STEALING tile %d, %d (draw count %llu) for tile %d, %d",
                 availableTile->x(), availableTile->y(), availableTile->drawCount(), x, y);
            availableTile->discardTextures(); // don't wait for textures to be stolen
            currentTile = availableTile;
        }

        if (!currentTile) {
            XLOG("ERROR: No tile available for tile %d %d", x, y);
        }

        if (currentTile) {
            currentTile->setGLWebViewState(m_glWebViewState);
            currentTile->setPage(this);

            currentTile->setContents(this, x, y, m_scale);

            // TODO: move below (which is largely the same for layers / tiled
            // page) into prepare() function

            // ensure there is a texture associated with the tile and then check to
            // see if the texture is dirty and in need of repainting
            if (currentTile->isDirty() || !currentTile->frontTexture())
                currentTile->reserveTexture();
            if (currentTile->backTexture()
                    && currentTile->isDirty()
                    && !currentTile->isRepaintPending()) {
                PaintTileOperation *operation = new PaintTileOperation(currentTile);
                TilesManager::instance()->scheduleOperation(operation);
            }
        }
    }
}
Exemplo n.º 11
0
BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner)
{
    android::Mutex::Autolock lock(m_texturesLock);

    // Sanity check that the tile does not already own a texture
    if (owner->backTexture() && owner->backTexture()->owner() == owner) {
        XLOG("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x",
             owner->x(), owner->y(), owner, owner->backTexture());
        if (owner->isLayerTile())
            m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture()));
        else
            m_availableTextures.remove(m_availableTextures.find(owner->backTexture()));
        return owner->backTexture();
    }

    WTF::Vector<BaseTileTexture*>* availableTexturePool;
    if (owner->isLayerTile()) {
        availableTexturePool = &m_availableTilesTextures;
    } else {
        availableTexturePool = &m_availableTextures;
    }

    // The heuristic for selecting a texture is as follows:
    //  1. Skip textures currently being painted, they can't be painted while
    //         busy anyway
    //  2. If a tile isn't owned, break with that one
    //  3. Don't let tiles acquire their front textures
    //  4. If we find a tile in the same page with a different scale,
    //         it's old and not visible. Break with that one
    //  5. Otherwise, use the least recently prepared tile, but ignoring tiles
    //         drawn in the last frame to avoid flickering

    BaseTileTexture* farthestTexture = 0;
    unsigned long long oldestDrawCount = getDrawGLCount() - 1;
    const unsigned int max = availableTexturePool->size();
    for (unsigned int i = 0; i < max; i++) {
        BaseTileTexture* texture = (*availableTexturePool)[i];
        BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner());

        if (texture->busy()) {
            // don't bother, since the acquire() will likely fail
            continue;
        }

        if (!currentOwner) {
            // unused texture! take it!
            farthestTexture = texture;
            break;
        }

        if (currentOwner == owner) {
            // Don't let a tile acquire its own front texture, as the
            // acquisition logic doesn't handle that
            continue;
        }

        if (currentOwner->painter() == owner->painter() && texture->scale() != owner->scale()) {
            // if we render the back page with one scale, then another while
            // still zooming, we recycle the tiles with the old scale instead of
            // taking ones from the front page
            farthestTexture = texture;
            break;
        }

        unsigned long long textureDrawCount = currentOwner->drawCount();
        if (oldestDrawCount > textureDrawCount) {
            farthestTexture = texture;
            oldestDrawCount = textureDrawCount;
        }
    }

    if (farthestTexture) {
        BaseTile* previousOwner = static_cast<BaseTile*>(farthestTexture->owner());
        if (farthestTexture->acquire(owner)) {
            if (previousOwner) {
                previousOwner->removeTexture(farthestTexture);

                XLOG("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)",
                     owner->isLayerTile() ? "LAYER" : "BASE",
                     farthestTexture, previousOwner->x(), previousOwner->y(),
                     owner->x(), owner->y(),
                     oldestDrawCount, getDrawGLCount());
            }

            availableTexturePool->remove(availableTexturePool->find(farthestTexture));
            return farthestTexture;
        }
    } else {
        if (owner->isLayerTile()) {
            // couldn't find a tile for a layer, layers shouldn't request redraw
            // TODO: once we do layer prefetching, don't set this for those
            // tiles
            m_layerTexturesRemain = false;
        }
    }

    XLOG("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available",
          owner->isLayerTile() ? "LAYER" : "BASE",
          owner, owner->x(), owner->y(), max);
#ifdef DEBUG
    printTextures();
#endif // DEBUG
    return 0;
}