• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #define LOG_TAG "TexturesGenerator"
27 #define LOG_NDEBUG 1
28 
29 #include "config.h"
30 #include "TexturesGenerator.h"
31 
32 #if USE(ACCELERATED_COMPOSITING)
33 
34 #include "AndroidLog.h"
35 #include "BaseRenderer.h"
36 #include "GLUtils.h"
37 #include "PaintTileOperation.h"
38 #include "TilesManager.h"
39 #include "TransferQueue.h"
40 
41 namespace WebCore {
42 
TexturesGenerator(TilesManager * instance)43 TexturesGenerator::TexturesGenerator(TilesManager* instance)
44   : Thread(false)
45   , m_tilesManager(instance)
46   , m_deferredMode(false)
47   , m_renderer(0)
48 {
49 }
50 
~TexturesGenerator()51 TexturesGenerator::~TexturesGenerator()
52 {
53     delete m_renderer;
54 }
55 
tryUpdateOperationWithPainter(Tile * tile,TilePainter * painter)56 bool TexturesGenerator::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
57 {
58     android::Mutex::Autolock lock(mRequestedOperationsLock);
59     if (!mRequestedOperationsHash.contains(tile))
60         return false;
61 
62     static_cast<PaintTileOperation*>(mRequestedOperationsHash.get(tile))->updatePainter(painter);
63     return true;
64 }
65 
scheduleOperation(QueuedOperation * operation)66 void TexturesGenerator::scheduleOperation(QueuedOperation* operation)
67 {
68     bool signal = false;
69     {
70         android::Mutex::Autolock lock(mRequestedOperationsLock);
71         mRequestedOperations.append(operation);
72         mRequestedOperationsHash.set(operation->uniquePtr(), operation);
73 
74         bool deferrable = operation->priority() >= gDeferPriorityCutoff;
75         m_deferredMode &= deferrable;
76 
77         // signal if we weren't in deferred mode, or if we can no longer defer
78         signal = !m_deferredMode || !deferrable;
79     }
80     if (signal)
81         mRequestedOperationsCond.signal();
82 }
83 
removeOperationsForFilter(OperationFilter * filter)84 void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
85 {
86     if (!filter)
87         return;
88 
89     android::Mutex::Autolock lock(mRequestedOperationsLock);
90     for (unsigned int i = 0; i < mRequestedOperations.size();) {
91         QueuedOperation* operation = mRequestedOperations[i];
92         if (filter->check(operation)) {
93             mRequestedOperations.remove(i);
94             mRequestedOperationsHash.remove(operation->uniquePtr());
95             delete operation;
96         } else {
97             i++;
98         }
99     }
100 }
101 
readyToRun()102 status_t TexturesGenerator::readyToRun()
103 {
104     m_renderer = BaseRenderer::createRenderer();
105     return NO_ERROR;
106 }
107 
108 // Must be called from within a lock!
popNext()109 QueuedOperation* TexturesGenerator::popNext()
110 {
111     // Priority can change between when it was added and now
112     // Hence why the entire queue is rescanned
113     QueuedOperation* current = mRequestedOperations.last();
114     int currentPriority = current->priority();
115     if (currentPriority < 0) {
116         mRequestedOperations.removeLast();
117         mRequestedOperationsHash.remove(current->uniquePtr());
118         return current;
119     }
120     int currentIndex = mRequestedOperations.size() - 1;
121     // Scan from the back to make removing faster (less items to copy)
122     for (int i = mRequestedOperations.size() - 2; i >= 0; i--) {
123         QueuedOperation *next = mRequestedOperations[i];
124         int nextPriority = next->priority();
125         if (nextPriority < 0) {
126             // Found a very high priority item, go ahead and just handle it now
127             mRequestedOperations.remove(i);
128             mRequestedOperationsHash.remove(next->uniquePtr());
129             return next;
130         }
131         // pick items preferrably by priority, or if equal, by order of
132         // insertion (as we add items at the back of the queue)
133         if (nextPriority <= currentPriority) {
134             current = next;
135             currentPriority = nextPriority;
136             currentIndex = i;
137         }
138     }
139 
140     if (!m_deferredMode && currentPriority >= gDeferPriorityCutoff) {
141         // finished with non-deferred rendering, enter deferred mode to wait
142         m_deferredMode = true;
143         return 0;
144     }
145 
146     mRequestedOperations.remove(currentIndex);
147     mRequestedOperationsHash.remove(current->uniquePtr());
148     return current;
149 }
150 
threadLoop()151 bool TexturesGenerator::threadLoop()
152 {
153     // Check if we have any pending operations.
154     mRequestedOperationsLock.lock();
155 
156     if (!m_deferredMode) {
157         // if we aren't currently deferring work, wait for new work to arrive
158         while (!mRequestedOperations.size())
159             mRequestedOperationsCond.wait(mRequestedOperationsLock);
160     } else {
161         // if we only have deferred work, wait for better work, or a timeout
162         mRequestedOperationsCond.waitRelative(mRequestedOperationsLock, gDeferNsecs);
163     }
164 
165     mRequestedOperationsLock.unlock();
166 
167     bool stop = false;
168     while (!stop) {
169         QueuedOperation* currentOperation = 0;
170 
171         mRequestedOperationsLock.lock();
172         ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size());
173 
174         if (mRequestedOperations.size())
175             currentOperation = popNext();
176         mRequestedOperationsLock.unlock();
177 
178         if (currentOperation) {
179             ALOGV("threadLoop, painting the request with priority %d",
180                   currentOperation->priority());
181             // swap out the renderer if necessary
182             BaseRenderer::swapRendererIfNeeded(m_renderer);
183             currentOperation->run(m_renderer);
184         }
185 
186         mRequestedOperationsLock.lock();
187         if (m_deferredMode && !currentOperation)
188             stop = true;
189         if (!mRequestedOperations.size()) {
190             m_deferredMode = false;
191             stop = true;
192         }
193         mRequestedOperationsLock.unlock();
194 
195         if (currentOperation)
196             delete currentOperation; // delete outside lock
197     }
198     ALOGV("threadLoop empty");
199 
200     return true;
201 }
202 
203 } // namespace WebCore
204 
205 #endif // USE(ACCELERATED_COMPOSITING)
206