1a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard/*
2a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * Copyright 2010, The Android Open Source Project
3a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *
4a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * Redistribution and use in source and binary forms, with or without
5a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * modification, are permitted provided that the following conditions
6a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * are met:
7a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *  * Redistributions of source code must retain the above copyright
8a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *    notice, this list of conditions and the following disclaimer.
9a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *  * Redistributions in binary form must reproduce the above copyright
10a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *    notice, this list of conditions and the following disclaimer in the
11a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *    documentation and/or other materials provided with the distribution.
12a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard *
13a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard */
25a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
26d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik#define LOG_TAG "TilesManager"
27d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik#define LOG_NDEBUG 1
28d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik
29a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#include "config.h"
30a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#include "TilesManager.h"
31a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
32a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#if USE(ACCELERATED_COMPOSITING)
33a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
34d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik#include "AndroidLog.h"
35594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik#include "GLWebViewState.h"
36a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#include "SkCanvas.h"
37211482b53e73a386e2aabb0d3acb92e0e7ea22d4Nicolas Roard#include "SkDevice.h"
38a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#include "SkPaint.h"
39594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik#include "Tile.h"
40594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik#include "TileTexture.h"
41594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik#include "TransferQueue.h"
42594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik
437c554a61cb935660cdc86905d040c781b490150fTeng-Hui Zhu#include <android/native_window.h>
44f56ebc1167a793612f34175b5e33db5cef631457Derek Sollenberger#include <cutils/atomic.h>
45ddbf1e63de50066df17c19a621d17634acde2dfaAndy McFadden#include <gui/GLConsumer.h>
464533237f156ff61f2486d0e6d748eafa8ce4d3d3Mathias Agopian#include <gui/Surface.h>
47a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#include <wtf/CurrentTime.h>
48a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
494a59c354560ed255d45ad00dbdbed13f045c557eChris Craik// Important: We need at least twice as many textures as is needed to cover
504a59c354560ed255d45ad00dbdbed13f045c557eChris Craik// one viewport, otherwise the allocation may stall.
514a59c354560ed255d45ad00dbdbed13f045c557eChris Craik// We need n textures for one TiledPage, and another n textures for the
524a59c354560ed255d45ad00dbdbed13f045c557eChris Craik// second page used when scaling.
53ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu// In our case, we use 256*256 textures. Both base and layers can use up to
54ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu// MAX_TEXTURE_ALLOCATION textures, which is 224MB GPU memory in total.
55ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu// For low end graphics systems, we cut this upper limit to half.
56ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu// We've found the viewport dependent value m_currentTextureCount is a reasonable
57ebcd36bcdbefb452a0be4e9e452a054ffdff4763Teng-Hui Zhu// number to cap the layer tile texturs, it worked on both phones and tablets.
58ebcd36bcdbefb452a0be4e9e452a054ffdff4763Teng-Hui Zhu// TODO: after merge the pool of base tiles and layer tiles, we should revisit
59ebcd36bcdbefb452a0be4e9e452a054ffdff4763Teng-Hui Zhu// the logic of allocation management.
605ab250a6ffd49127ffe53059518204cfe5eea6f0Chris Craik#define MAX_TEXTURE_ALLOCATION ((10+TILE_PREFETCH_DISTANCE*2)*(7+TILE_PREFETCH_DISTANCE*2)*4)
615a18cae6b44f84a00cfdda598023a158a7310763Teng-Hui Zhu#define TILE_WIDTH 256
625a18cae6b44f84a00cfdda598023a158a7310763Teng-Hui Zhu#define TILE_HEIGHT 256
63a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
64211482b53e73a386e2aabb0d3acb92e0e7ea22d4Nicolas Roard#define BYTES_PER_PIXEL 4 // 8888 config
65211482b53e73a386e2aabb0d3acb92e0e7ea22d4Nicolas Roard
66c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures
67c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
68334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik// Eventually this should be dynamically be determined, and smart scheduling
69334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik// between the generators should be implemented
70334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik#define NUM_TEXTURES_GENERATORS 1
71334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
72a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roardnamespace WebCore {
73a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
74522c8aecb5c6a797ceb59e8eaa9ab44e3a5fda54Shimeng (Simon) Wangint TilesManager::getMaxTextureAllocation()
75522c8aecb5c6a797ceb59e8eaa9ab44e3a5fda54Shimeng (Simon) Wang{
76ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    if (m_maxTextureAllocation == -1) {
77ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        GLint glMaxTextureSize = 0;
78ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTextureSize);
79ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        GLUtils::checkGlError("TilesManager::getMaxTextureAllocation");
80ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        // Half of glMaxTextureSize can be used for base, the other half for layers.
81ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        m_maxTextureAllocation = std::min(MAX_TEXTURE_ALLOCATION, glMaxTextureSize / 2);
82ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        if (!m_highEndGfx)
83ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu            m_maxTextureAllocation = m_maxTextureAllocation / 2;
84ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    }
85ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    return m_maxTextureAllocation;
86522c8aecb5c6a797ceb59e8eaa9ab44e3a5fda54Shimeng (Simon) Wang}
87522c8aecb5c6a797ceb59e8eaa9ab44e3a5fda54Shimeng (Simon) Wang
88a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas RoardTilesManager::TilesManager()
8993bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik    : m_layerTexturesRemain(true)
90e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu    , m_highEndGfx(false)
91ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    , m_currentTextureCount(0)
92ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    , m_currentLayerTextureCount(0)
93ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    , m_maxTextureAllocation(-1)
94211482b53e73a386e2aabb0d3acb92e0e7ea22d4Nicolas Roard    , m_generatorReady(false)
9503d850006e8ce54945fe44c36ffaf074143184c5Teng-Hui Zhu    , m_showVisualIndicator(false)
96d2c2030045e0e26787ff8b9935d449e3be8a71ccJohn Reck    , m_invertedScreen(false)
978852b0905b1a50ca045eb4bd19b2589aad663b5cTeng-Hui Zhu    , m_useMinimalMemory(true)
98bac79a8ecce7b3aaf3bc4964957c9c59f163de38Chris Craik    , m_useDoubleBuffering(true)
99d8be9016b7fda67a91b4ee17b3b2e7ba692ee553Chris Craik    , m_contentUpdates(0)
100f7ad77dc2a981834d664fd24022c3dfade69c8aaChris Craik    , m_webkitContentUpdates(0)
101451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui Zhu    , m_queue(0)
102808dc42f1e6a574778bc9e8bd41beb7bd9aef06fChris Craik    , m_drawGLCount(1)
103c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    , m_lastTimeLayersUsed(0)
104c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    , m_hasLayerTextures(false)
1052ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    , m_eglContext(EGL_NO_CONTEXT)
106a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
107d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("TilesManager ctor");
1085ab250a6ffd49127ffe53059518204cfe5eea6f0Chris Craik    m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
1095ab250a6ffd49127ffe53059518204cfe5eea6f0Chris Craik    m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
1105ab250a6ffd49127ffe53059518204cfe5eea6f0Chris Craik    m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
1115ab250a6ffd49127ffe53059518204cfe5eea6f0Chris Craik    m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2);
112334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
113334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS];
114334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) {
115334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik        m_textureGenerators[i] = new TexturesGenerator(this);
116334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik        ALOGD("Starting TG #%d, %p", i, m_textureGenerators[i].get());
117334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik        m_textureGenerators[i]->run("TexturesGenerator");
118334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    }
119334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik}
120334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
121334c36c686871998bf6c4ac958dfe3b3d5a87033Chris CraikTilesManager::~TilesManager()
122334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik{
123334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    delete[] m_textureGenerators;
124a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
125a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
126334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
127ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhuvoid TilesManager::allocateTextures()
128a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
129ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    int nbTexturesToAllocate = m_currentTextureCount - m_textures.size();
130ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_currentTextureCount);
1317e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard    int nbTexturesAllocated = 0;
1327e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard    for (int i = 0; i < nbTexturesToAllocate; i++) {
133594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = new TileTexture(
134ec182c75fb35d955a9115fbaf516f648a48ed0e1Derek Sollenberger            tileWidth(), tileHeight());
1357e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard        // the atomic load ensures that the texture has been fully initialized
1367e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard        // before we pass a pointer for other threads to operate on
137594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* loadedTexture =
138594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik            reinterpret_cast<TileTexture*>(
1397e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
1407e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard        m_textures.append(loadedTexture);
1417e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard        nbTexturesAllocated++;
142a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    }
1433c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard
144ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    int nbLayersTexturesToAllocate = m_currentLayerTextureCount - m_tilesTextures.size();
145d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("%d layers tiles to allocate (%d textures planned)",
146ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu          nbLayersTexturesToAllocate, m_currentLayerTextureCount);
14782b16301ec89989ef436f317f2f23f57ed2e2660Nicolas Roard    int nbLayersTexturesAllocated = 0;
14882b16301ec89989ef436f317f2f23f57ed2e2660Nicolas Roard    for (int i = 0; i < nbLayersTexturesToAllocate; i++) {
149594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = new TileTexture(
150c51715092b8d3be1b51cce8bae61750cbcf342c4Chris Craik            tileWidth(), tileHeight());
1513c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard        // the atomic load ensures that the texture has been fully initialized
1523c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard        // before we pass a pointer for other threads to operate on
153594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* loadedTexture =
154594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik            reinterpret_cast<TileTexture*>(
1553c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
1563c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard        m_tilesTextures.append(loadedTexture);
15782b16301ec89989ef436f317f2f23f57ed2e2660Nicolas Roard        nbLayersTexturesAllocated++;
1583c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard    }
159d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)",
160d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik          nbTexturesAllocated, m_textures.size(),
161d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik          m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024,
162d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik          nbLayersTexturesAllocated, m_tilesTextures.size(),
163c51715092b8d3be1b51cce8bae61750cbcf342c4Chris Craik          m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024);
164a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
165a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
166a3a38731f4eeb01d2a42965b6c875d957999969dChris Craikvoid TilesManager::discardTextures(bool allTextures, bool glTextures)
1672986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik{
1682986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    const unsigned int max = m_textures.size();
1692986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik
1702986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    unsigned long long sparedDrawCount = ~0; // by default, spare no textures
1712986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    if (!allTextures) {
1722986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        // if we're not deallocating all textures, spare those with max drawcount
1732986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        sparedDrawCount = 0;
1742986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        for (unsigned int i = 0; i < max; i++) {
1752986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik            TextureOwner* owner = m_textures[i]->owner();
1762986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik            if (owner)
1772986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik                sparedDrawCount = std::max(sparedDrawCount, owner->drawCount());
1782986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        }
1792986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    }
180a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik    discardTexturesVector(sparedDrawCount, m_textures, glTextures);
181a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik    discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures);
182c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard}
1832986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik
1842ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhuvoid TilesManager::markAllGLTexturesZero()
1852ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu{
1862ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    for (unsigned int i = 0; i < m_textures.size(); i++)
1872ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        m_textures[i]->m_ownTextureId = 0;
1882ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    for (unsigned int i = 0; i < m_tilesTextures.size(); i++)
1892ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        m_tilesTextures[i]->m_ownTextureId = 0;
1902ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu}
1912ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu
192a3a38731f4eeb01d2a42965b6c875d957999969dChris Craikvoid TilesManager::discardTexturesVector(unsigned long long sparedDrawCount,
193594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik                                         WTF::Vector<TileTexture*>& textures,
194a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik                                         bool deallocateGLTextures)
195c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard{
196c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    const unsigned int max = textures.size();
1972986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    int dealloc = 0;
19850359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu    WTF::Vector<int> discardedIndex;
1992986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    for (unsigned int i = 0; i < max; i++) {
200c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        TextureOwner* owner = textures[i]->owner();
2012986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        if (!owner || owner->drawCount() < sparedDrawCount) {
202a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik            if (deallocateGLTextures) {
203a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik                // deallocate textures' gl memory
204a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik                textures[i]->discardGLTexture();
20550359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu                discardedIndex.append(i);
206a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik            } else if (owner) {
207a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik                // simply detach textures from owner
208594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik                static_cast<Tile*>(owner)->discardTextures();
209a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik            }
2102986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik            dealloc++;
2112986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik        }
2122986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik    }
21350359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu
21450359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu    bool base = textures == m_textures;
215594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik    // Clean up the vector of TileTextures and reset the max texture count.
21650359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu    if (discardedIndex.size()) {
21750359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu        android::Mutex::Autolock lock(m_texturesLock);
21850359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu        for (int i = discardedIndex.size() - 1; i >= 0; i--)
21950359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu            textures.remove(discardedIndex[i]);
22050359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu
22150359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu        int remainedTextureNumber = textures.size();
222ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        int* countPtr = base ? &m_currentTextureCount : &m_currentLayerTextureCount;
22350359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu        if (remainedTextureNumber < *countPtr) {
224ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu            ALOGV("reset currentTextureCount for %s tiles from %d to %d",
225d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                  base ? "base" : "layer", *countPtr, remainedTextureNumber);
22650359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu            *countPtr = remainedTextureNumber;
22750359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu        }
22850359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu
22950359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu    }
23050359a67e1503b5d416cae7e64d46e3f3389442aTeng-Hui Zhu
231d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("Discarded %d %s textures (out of %d %s tiles)",
232d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik          dealloc, (deallocateGLTextures ? "gl" : ""),
233d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik          max, base ? "base" : "layer");
2342986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik}
2352986d27084d881dbe6f9c3ae35430a5978b7e659Chris Craik
23654e75f0875a8376c1119b019431921bc58295b79Nicolas Roardvoid TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
23754e75f0875a8376c1119b019431921bc58295b79Nicolas Roard                                        int* nbLayerTextures, int* nbAllocatedLayerTextures)
23854e75f0875a8376c1119b019431921bc58295b79Nicolas Roard{
23954e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    *nbTextures = m_textures.size();
24054e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    for (unsigned int i = 0; i < m_textures.size(); i++) {
241594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = m_textures[i];
24254e75f0875a8376c1119b019431921bc58295b79Nicolas Roard        if (texture->m_ownTextureId)
24354e75f0875a8376c1119b019431921bc58295b79Nicolas Roard            *nbAllocatedTextures += 1;
24454e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    }
24554e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    *nbLayerTextures = m_tilesTextures.size();
24654e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    for (unsigned int i = 0; i < m_tilesTextures.size(); i++) {
247594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = m_tilesTextures[i];
24854e75f0875a8376c1119b019431921bc58295b79Nicolas Roard        if (texture->m_ownTextureId)
24954e75f0875a8376c1119b019431921bc58295b79Nicolas Roard            *nbAllocatedLayerTextures += 1;
25054e75f0875a8376c1119b019431921bc58295b79Nicolas Roard    }
25154e75f0875a8376c1119b019431921bc58295b79Nicolas Roard}
25254e75f0875a8376c1119b019431921bc58295b79Nicolas Roard
253bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craikvoid TilesManager::dirtyTexturesVector(WTF::Vector<TileTexture*>& textures)
254bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik{
255bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik    for (unsigned int i = 0; i < textures.size(); i++) {
256bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik        Tile* currentOwner = static_cast<Tile*>(textures[i]->owner());
257bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik        if (currentOwner)
258bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik            currentOwner->markAsDirty();
259bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik    }
260bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik}
261bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik
262bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craikvoid TilesManager::dirtyAllTiles()
263bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik{
264bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik    dirtyTexturesVector(m_textures);
265bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik    dirtyTexturesVector(m_tilesTextures);
266bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik}
267bd3f93b66934582acd0b6c70bcf60ca643b36eadChris Craik
268a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roardvoid TilesManager::printTextures()
269a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
270a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#ifdef DEBUG
271d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("++++++");
272a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    for (unsigned int i = 0; i < m_textures.size(); i++) {
273594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = m_textures[i];
274594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        Tile* o = 0;
275a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        if (texture->owner())
276594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik            o = (Tile*) texture->owner();
277a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        int x = -1;
278a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        int y = -1;
279a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        if (o) {
280a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard            x = o->x();
281a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard            y = o->y();
282a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        }
2837b4a179bde698a856bed54a680438a9db3ff0566Chris Craik        ALOGV("[%d] texture %x owner: %x (%d, %d) scale: %.2f",
2847b4a179bde698a856bed54a680438a9db3ff0566Chris Craik              i, texture, o, x, y, o ? o->scale() : 0);
285a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    }
286d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("------");
287a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#endif // DEBUG
288a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
289a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
290b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roardvoid TilesManager::gatherTextures()
291b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard{
292b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
293b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard    m_availableTextures = m_textures;
294b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard    m_availableTilesTextures = m_tilesTextures;
29593bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik    m_layerTexturesRemain = true;
296b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard}
297b7d8e1b710ce418ca1d8b7fc3612740757fd1aecNicolas Roard
298594c6b805969c2673c84d1d1d1a3556ce376ac7aChris CraikTileTexture* TilesManager::getAvailableTexture(Tile* owner)
299a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
300a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
301610686734abc1ecfc43ab4e02289ac713fe76f1fDerek Sollenberger
302594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik    WTF::Vector<TileTexture*>* availableTexturePool;
303e080317b90534632e8be18dc8d5e9a51554b444aChris Craik    if (owner->isLayerTile())
3048ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        availableTexturePool = &m_availableTilesTextures;
305e080317b90534632e8be18dc8d5e9a51554b444aChris Craik    else
3068ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        availableTexturePool = &m_availableTextures;
307e080317b90534632e8be18dc8d5e9a51554b444aChris Craik
308e080317b90534632e8be18dc8d5e9a51554b444aChris Craik    // Sanity check that the tile does not already own a texture
309e080317b90534632e8be18dc8d5e9a51554b444aChris Craik    if (owner->backTexture() && owner->backTexture()->owner() == owner) {
31086ceef033ca2c835916e3970c2ea7cfdba5856a3Chris Craik        int removeIndex = availableTexturePool->find(owner->backTexture());
31186ceef033ca2c835916e3970c2ea7cfdba5856a3Chris Craik
31286ceef033ca2c835916e3970c2ea7cfdba5856a3Chris Craik        // TODO: investigate why texture isn't found
31386ceef033ca2c835916e3970c2ea7cfdba5856a3Chris Craik        if (removeIndex >= 0)
31486ceef033ca2c835916e3970c2ea7cfdba5856a3Chris Craik            availableTexturePool->remove(removeIndex);
315e080317b90534632e8be18dc8d5e9a51554b444aChris Craik        return owner->backTexture();
3163c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard    }
3173c131605fca8e29a88fdc4923d86bdc3f40adb2bNicolas Roard
318610686734abc1ecfc43ab4e02289ac713fe76f1fDerek Sollenberger    // The heuristic for selecting a texture is as follows:
3196aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik    //  1. Skip textures currently being painted, they can't be painted while
3206aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik    //         busy anyway
3216aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik    //  2. If a tile isn't owned, break with that one
3226aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik    //  3. Don't let tiles acquire their front textures
323d8be9016b7fda67a91b4ee17b3b2e7ba692ee553Chris Craik    //  4. Otherwise, use the least recently prepared tile, but ignoring tiles
324ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik    //         drawn in the last frame to avoid flickering
32572a76070d36a51926c224d230f1503c46f30da60Chris Craik
326594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik    TileTexture* farthestTexture = 0;
327ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik    unsigned long long oldestDrawCount = getDrawGLCount() - 1;
3288ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik    const unsigned int max = availableTexturePool->size();
329a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    for (unsigned int i = 0; i < max; i++) {
330594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        TileTexture* texture = (*availableTexturePool)[i];
331594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        Tile* currentOwner = static_cast<Tile*>(texture->owner());
3328ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        if (!currentOwner) {
3336aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik            // unused texture! take it!
334a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard            farthestTexture = texture;
335a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard            break;
336a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        }
33772a76070d36a51926c224d230f1503c46f30da60Chris Craik
3386aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik        if (currentOwner == owner) {
3396aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik            // Don't let a tile acquire its own front texture, as the
3406aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik            // acquisition logic doesn't handle that
341808dc42f1e6a574778bc9e8bd41beb7bd9aef06fChris Craik            continue;
3426aa089bded6a1abbf8d61264588e1e3a32be31b3Chris Craik        }
343808dc42f1e6a574778bc9e8bd41beb7bd9aef06fChris Craik
3448ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        unsigned long long textureDrawCount = currentOwner->drawCount();
3458ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        if (oldestDrawCount > textureDrawCount) {
346a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard            farthestTexture = texture;
3478ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik            oldestDrawCount = textureDrawCount;
348a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        }
349a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    }
35072a76070d36a51926c224d230f1503c46f30da60Chris Craik
351ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik    if (farthestTexture) {
352594c6b805969c2673c84d1d1d1a3556ce376ac7aChris Craik        Tile* previousOwner = static_cast<Tile*>(farthestTexture->owner());
353ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik        if (farthestTexture->acquire(owner)) {
354ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik            if (previousOwner) {
355f6a40880028cf495025747229c627f42e25acc66Chris Craik                previousOwner->removeTexture(farthestTexture);
356f6a40880028cf495025747229c627f42e25acc66Chris Craik
357d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)",
358d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                      owner->isLayerTile() ? "LAYER" : "BASE",
359d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                      farthestTexture, previousOwner->x(), previousOwner->y(),
360d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                      owner->x(), owner->y(),
361d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik                      oldestDrawCount, getDrawGLCount());
362ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik            }
363ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik
364ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik            availableTexturePool->remove(availableTexturePool->find(farthestTexture));
365ab3df5899158b0bcb5c7bb6858d9717a22781ad3Chris Craik            return farthestTexture;
3668ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik        }
36793bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik    } else {
36893bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik        if (owner->isLayerTile()) {
36993bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik            // couldn't find a tile for a layer, layers shouldn't request redraw
37093bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik            // TODO: once we do layer prefetching, don't set this for those
37193bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik            // tiles
37293bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik            m_layerTexturesRemain = false;
37393bfc77abb66a95750b747cf5d782c31beadf7cfChris Craik        }
374a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    }
375610686734abc1ecfc43ab4e02289ac713fe76f1fDerek Sollenberger
376d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik    ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available",
377808dc42f1e6a574778bc9e8bd41beb7bd9aef06fChris Craik          owner->isLayerTile() ? "LAYER" : "BASE",
3788ad3ab0e47f0d5039e89c1873c178f538ec1b0dfChris Craik          owner, owner->x(), owner->y(), max);
379a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#ifdef DEBUG
380a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    printTextures();
381a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#endif // DEBUG
382a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    return 0;
383a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
384a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
385e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhuvoid TilesManager::setHighEndGfx(bool highEnd)
386e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu{
387e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu    m_highEndGfx = highEnd;
388e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu}
389e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu
390e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhubool TilesManager::highEndGfx()
391e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu{
392e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu    return m_highEndGfx;
393e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu}
394e1dfe84b38ed080c7bb7ac00fd9e3c6c590a147dTeng-Hui Zhu
395ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhuint TilesManager::currentTextureCount()
396a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
3977e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
398ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    return m_currentTextureCount;
3997e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard}
4007e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard
401ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhuint TilesManager::currentLayerTextureCount()
402c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard{
403c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
404ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    return m_currentLayerTextureCount;
405c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard}
406c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
407ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhuvoid TilesManager::setCurrentTextureCount(int newTextureCount)
4087e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard{
409ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    int maxTextureAllocation = getMaxTextureAllocation();
410ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    ALOGV("setCurrentTextureCount: %d (current: %d, max:%d)",
411ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu         newTextureCount, m_currentTextureCount, maxTextureAllocation);
412ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    if (m_currentTextureCount == maxTextureAllocation ||
413ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        newTextureCount <= m_currentTextureCount)
4147e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard        return;
4157e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard
4167e3773d591be20a4ddb1ef7df2709fd7655b7917Nicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
417ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    m_currentTextureCount = std::min(newTextureCount, maxTextureAllocation);
41840dbb7e9ff961829a7f4402ab8657c622ec2e9f6Nicolas Roard
419ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    allocateTextures();
420a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
421a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
422ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhuvoid TilesManager::setCurrentLayerTextureCount(int newTextureCount)
423c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard{
424ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    int maxTextureAllocation = getMaxTextureAllocation();
425ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    ALOGV("setCurrentLayerTextureCount: %d (current: %d, max:%d)",
426ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu         newTextureCount, m_currentLayerTextureCount, maxTextureAllocation);
427ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    if (!newTextureCount && m_hasLayerTextures) {
428c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed;
429c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) {
430c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard            unsigned long long sparedDrawCount = ~0; // by default, spare no textures
431a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik            bool deleteGLTextures = true;
432a3a38731f4eeb01d2a42965b6c875d957999969dChris Craik            discardTexturesVector(sparedDrawCount, m_tilesTextures, deleteGLTextures);
433c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard            m_hasLayerTextures = false;
434c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        }
435c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        return;
436c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    }
437c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    m_lastTimeLayersUsed = WTF::currentTime();
438ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    if (m_currentLayerTextureCount == maxTextureAllocation ||
439ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu        newTextureCount <= m_currentLayerTextureCount)
440c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard        return;
441c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
442c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    android::Mutex::Autolock lock(m_texturesLock);
443ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    m_currentLayerTextureCount = std::min(newTextureCount, maxTextureAllocation);
444c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
445ce0e4b6b423e45f5a1c2eeedd8a5eff9d24f666eTeng-Hui Zhu    allocateTextures();
446c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard    m_hasLayerTextures = true;
447c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard}
448c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
449451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui ZhuTransferQueue* TilesManager::transferQueue()
450451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui Zhu{
4517a09d1cde40c92dfd028e68ca2408478b9fe152bJohn Reck    // m_queue will be created on the UI thread, although it may
4527a09d1cde40c92dfd028e68ca2408478b9fe152bJohn Reck    // be accessed from the TexturesGenerator. However, that can only happen after
4537a09d1cde40c92dfd028e68ca2408478b9fe152bJohn Reck    // a previous transferQueue() call due to a prepare.
454451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui Zhu    if (!m_queue)
455a464817e995321cae99f09266e27d4fa322d9b31Chris Craik        m_queue = new TransferQueue(m_useMinimalMemory && !m_highEndGfx);
456451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui Zhu    return m_queue;
457451fcf2a39629f20f52ee6bb0294d217d8aa487fTeng-Hui Zhu}
458c4718e6733cb345bafc3a95a9e1c234047bfde7eNicolas Roard
4592ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu// When GL context changed or we get a low memory signal, we want to cleanup all
4602ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu// the GPU memory webview is using.
4612ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu// The recreation will be on the next incoming draw call at the drawGL of
4622ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu// GLWebViewState or the VideoLayerAndroid
4632ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhuvoid TilesManager::cleanupGLResources()
4642ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu{
4652ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    transferQueue()->cleanupGLResourcesAndQueue();
4662ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    shader()->cleanupGLResources();
4672ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    videoLayerManager()->cleanupGLResources();
4682ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    m_eglContext = EGL_NO_CONTEXT;
4692ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    GLUtils::checkGlError("TilesManager::cleanupGLResources");
4702ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu}
4712ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu
4722ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhuvoid TilesManager::updateTilesIfContextVerified()
4732ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu{
4746c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu    EGLContext ctx = eglGetCurrentContext();
4756c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu    GLUtils::checkEglError("contextChanged");
4766c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu    if (ctx != m_eglContext) {
4776c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu        if (m_eglContext != EGL_NO_CONTEXT) {
4786c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // A change in EGL context is an unexpected error, but we don't want to
4796c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // crash or ANR. Therefore, abandon the Surface Texture and GL resources;
4806c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // they'll be recreated later in setupDrawing. (We can't delete them
4816c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // since the context is gone)
4826c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            ALOGE("Unexpected : EGLContext changed! current %x , expected %x",
4836c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu                  ctx, m_eglContext);
4846c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            transferQueue()->resetQueue();
4856c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            shader()->forceNeedsInit();
4866c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            videoLayerManager()->forceNeedsInit();
4876c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            markAllGLTexturesZero();
4886c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu        } else {
4896c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // This is the first time we went into this new EGL context.
4906c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // We will have the GL resources to be re-inited and we can't update
4916c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            // dirty tiles yet.
4926c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu            ALOGD("new EGLContext from framework: %x ", ctx);
4936c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu        }
4942ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    } else {
4952ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        // Here before we draw, update the Tile which has updated content.
4962ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        // Inside this function, just do GPU blits from the transfer queue into
4972ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        // the Tiles' texture.
4982ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        transferQueue()->updateDirtyTiles();
4992ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        // Clean up GL textures for video layer.
5002ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu        videoLayerManager()->deleteUnusedTextures();
5012ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    }
5022ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu    m_eglContext = ctx;
5036c4c0302dd154e5090966c57bb4b6b216644fb01Teng-Hui Zhu    return;
5042ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu}
5052ac76fe4e18c3325c8b3bb8f9435fdc7b96c0acaTeng-Hui Zhu
506334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craikvoid TilesManager::removeOperationsForFilter(OperationFilter* filter)
507334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik{
508334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++)
509334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik        m_textureGenerators[i]->removeOperationsForFilter(filter);
510334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    delete filter;
511334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik}
512334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
513334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craikbool TilesManager::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
514334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik{
515334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) {
516334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik        if (m_textureGenerators[i]->tryUpdateOperationWithPainter(tile, painter))
517334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik            return true;
518334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    }
519334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    return false;
520334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik}
521334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
522334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craikvoid TilesManager::scheduleOperation(QueuedOperation* operation)
523334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik{
524334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    // TODO: painter awareness, store prefer awareness, store preferred thread into painter
525334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    m_scheduleThread = (m_scheduleThread + 1) % NUM_TEXTURES_GENERATORS;
526334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik    m_textureGenerators[m_scheduleThread]->scheduleOperation(operation);
527334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik}
528334c36c686871998bf6c4ac958dfe3b3d5a87033Chris Craik
529e859a34171f2a36877d95197d118d962078f8aa0John Reckint TilesManager::tileWidth()
530a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
531ffc715a2e6382fe9e331557c35fafc426507b8f5Derek Sollenberger    return TILE_WIDTH;
532ffc715a2e6382fe9e331557c35fafc426507b8f5Derek Sollenberger}
533ffc715a2e6382fe9e331557c35fafc426507b8f5Derek Sollenberger
534e859a34171f2a36877d95197d118d962078f8aa0John Reckint TilesManager::tileHeight()
535ffc715a2e6382fe9e331557c35fafc426507b8f5Derek Sollenberger{
536ffc715a2e6382fe9e331557c35fafc426507b8f5Derek Sollenberger    return TILE_HEIGHT;
537a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
538a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
539a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas RoardTilesManager* TilesManager::instance()
540a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard{
541a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    if (!gInstance) {
542a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard        gInstance = new TilesManager();
543d487c56b47c747d3e331ee1892e4c0473363afd2Chris Craik        ALOGV("instance(), new gInstance is %x", gInstance);
544a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    }
545a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard    return gInstance;
546a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard}
547a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
548a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas RoardTilesManager* TilesManager::gInstance = 0;
549a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
550a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard} // namespace WebCore
551a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard
552a5ffb7c279df240a07658953e1bd5df6d0480cb6Nicolas Roard#endif // USE(ACCELERATED_COMPOSITING)
553