diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp new file mode 100644 index 0000000..f884e52 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp @@ -0,0 +1,182 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "TexturesGenerator" +#define LOG_NDEBUG 1 + +#include "config.h" +#include "TexturesGenerator.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "AndroidLog.h" +#include "GLUtils.h" +#include "PaintTileOperation.h" +#include "TilesManager.h" +#include "TransferQueue.h" + +namespace WebCore { + +void TexturesGenerator::scheduleOperation(QueuedOperation* operation) +{ + { + android::Mutex::Autolock lock(mRequestedOperationsLock); + mRequestedOperations.append(operation); + } + mRequestedOperationsCond.signal(); +} + +void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) +{ + if (!filter) + return; + + android::Mutex::Autolock lock(mRequestedOperationsLock); + for (unsigned int i = 0; i < mRequestedOperations.size();) { + QueuedOperation* operation = mRequestedOperations[i]; + if (filter->check(operation)) { + mRequestedOperations.remove(i); + delete operation; + } else { + i++; + } + } + + if (waitForRunning && m_currentOperation) { + QueuedOperation* operation = m_currentOperation; + + if (operation && filter->check(operation)) { + m_waitForCompletion = true; + // The reason we are signaling the transferQueue is : + // TransferQueue may be waiting a slot to work on, but now UI + // thread is waiting for Tex Gen thread to finish first before the + // UI thread can free a slot for the transferQueue. + // Therefore, it could be a deadlock. + // The solution is use this as a flag to tell Tex Gen thread that + // UI thread is waiting now, Tex Gen thread should not wait for the + // queue any more. + m_tilesManager->transferQueue()->interruptTransferQueue(true); + } + + delete filter; + + // At this point, it means that we are currently executing an operation that + // we want to be removed -- we should wait until it is done, so that + // when we return our caller can be sure that there is no more operations + // in the queue matching the given filter. + while (m_waitForCompletion) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + } else { + delete filter; + } +} + +status_t TexturesGenerator::readyToRun() +{ + ALOGV("Thread ready to run"); + return NO_ERROR; +} + +// Must be called from within a lock! +QueuedOperation* TexturesGenerator::popNext() +{ + // Priority can change between when it was added and now + // Hence why the entire queue is rescanned + QueuedOperation* current = mRequestedOperations.last(); + int currentPriority = current->priority(); + if (currentPriority < 0) { + mRequestedOperations.removeLast(); + return current; + } + int currentIndex = mRequestedOperations.size() - 1; + // Scan from the back to make removing faster (less items to copy) + for (int i = mRequestedOperations.size() - 2; i >= 0; i--) { + QueuedOperation *next = mRequestedOperations[i]; + int nextPriority = next->priority(); + if (nextPriority < 0) { + // Found a very high priority item, go ahead and just handle it now + mRequestedOperations.remove(i); + return next; + } + // pick items preferrably by priority, or if equal, by order of + // insertion (as we add items at the back of the queue) + if (nextPriority <= currentPriority) { + current = next; + currentPriority = nextPriority; + currentIndex = i; + } + } + mRequestedOperations.remove(currentIndex); + return current; +} + +bool TexturesGenerator::threadLoop() +{ + // Check if we have any pending operations. + mRequestedOperationsLock.lock(); + while (!mRequestedOperations.size()) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + + ALOGV("threadLoop, got signal"); + mRequestedOperationsLock.unlock(); + + m_currentOperation = 0; + bool stop = false; + while (!stop) { + mRequestedOperationsLock.lock(); + ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size()); + if (mRequestedOperations.size()) + m_currentOperation = popNext(); + mRequestedOperationsLock.unlock(); + + if (m_currentOperation) { + ALOGV("threadLoop, painting the request with priority %d", + m_currentOperation->priority()); + m_currentOperation->run(); + } + + QueuedOperation* oldOperation = m_currentOperation; + mRequestedOperationsLock.lock(); + if (m_currentOperation) + m_currentOperation = 0; + if (!mRequestedOperations.size()) + stop = true; + if (m_waitForCompletion) { + m_waitForCompletion = false; + m_tilesManager->transferQueue()->interruptTransferQueue(false); + mRequestedOperationsCond.signal(); + } + mRequestedOperationsLock.unlock(); + if (oldOperation) + delete oldOperation; // delete outside lock + } + ALOGV("threadLoop empty"); + + return true; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) |