#include "config.h"
#include "RenderQueue.h"
#include "BackingStore_p.h"
#include "WebPageClient.h"
#include "WebPage_p.h"
#define DEBUG_RENDER_QUEUE 0
#define DEBUG_RENDER_QUEUE_SORT 0
#if DEBUG_RENDER_QUEUE
#include <BlackBerryPlatformLog.h>
#include <wtf/CurrentTime.h>
#endif
namespace BlackBerry {
namespace WebKit {
template<SortDirection sortDirection>
static inline int compareRectOneDirection(const Platform::IntRect& r1, const Platform::IntRect& r2)
{
switch (sortDirection) {
case LeftToRight:
return r1.x() - r2.x();
case RightToLeft:
return r2.x() - r1.x();
case TopToBottom:
return r1.y() - r2.y();
case BottomToTop:
return r2.y() - r1.y();
default:
break;
}
ASSERT_NOT_REACHED();
return 0;
}
template<SortDirection primarySortDirection, SortDirection secondarySortDirection>
static bool rectIsLessThan(const Platform::IntRect& r1, const Platform::IntRect& r2)
{
int primaryResult = compareRectOneDirection<primarySortDirection>(r1, r2);
if (primaryResult || secondarySortDirection == primarySortDirection)
return primaryResult < 0;
return compareRectOneDirection<secondarySortDirection>(r1, r2) < 0;
}
typedef bool (*FuncRectLessThan)(const Platform::IntRect& r1, const Platform::IntRect& r2);
static FuncRectLessThan rectLessThanFunction(SortDirection primary, SortDirection secondary)
{
static FuncRectLessThan s_rectLessThanFunctions[NumSortDirections][NumSortDirections] = { { 0 } };
static bool s_initialized = false;
if (!s_initialized) {
#define ADD_COMPARE_FUNCTION(_primary, _secondary) \
s_rectLessThanFunctions[_primary][_secondary] = rectIsLessThan<_primary, _secondary>
ADD_COMPARE_FUNCTION(LeftToRight, LeftToRight);
ADD_COMPARE_FUNCTION(LeftToRight, RightToLeft);
ADD_COMPARE_FUNCTION(LeftToRight, TopToBottom);
ADD_COMPARE_FUNCTION(LeftToRight, BottomToTop);
ADD_COMPARE_FUNCTION(RightToLeft, LeftToRight);
ADD_COMPARE_FUNCTION(RightToLeft, RightToLeft);
ADD_COMPARE_FUNCTION(RightToLeft, TopToBottom);
ADD_COMPARE_FUNCTION(RightToLeft, BottomToTop);
ADD_COMPARE_FUNCTION(TopToBottom, LeftToRight);
ADD_COMPARE_FUNCTION(TopToBottom, RightToLeft);
ADD_COMPARE_FUNCTION(TopToBottom, TopToBottom);
ADD_COMPARE_FUNCTION(TopToBottom, BottomToTop);
ADD_COMPARE_FUNCTION(BottomToTop, LeftToRight);
ADD_COMPARE_FUNCTION(BottomToTop, RightToLeft);
ADD_COMPARE_FUNCTION(BottomToTop, TopToBottom);
ADD_COMPARE_FUNCTION(BottomToTop, BottomToTop);
#undef ADD_COMPARE_FUNCTION
s_initialized = true;
}
return s_rectLessThanFunctions[primary][secondary];
}
class RectLessThan {
public:
RectLessThan(SortDirection primarySortDirection, SortDirection secondarySortDirection)
: m_rectIsLessThan(rectLessThanFunction(primarySortDirection, secondarySortDirection))
{
}
bool operator()(const Platform::IntRect& r1, const Platform::IntRect& r2)
{
return m_rectIsLessThan(r1, r2);
}
private:
FuncRectLessThan m_rectIsLessThan;
};
class RenderRectLessThan {
public:
RenderRectLessThan(SortDirection primarySortDirection, SortDirection secondarySortDirection)
: m_rectIsLessThan(rectLessThanFunction(primarySortDirection, secondarySortDirection))
{
}
bool operator()(const RenderRect& r1, const RenderRect& r2)
{
return m_rectIsLessThan(r1.subRects()[0], r2.subRects()[0]);
}
private:
FuncRectLessThan m_rectIsLessThan;
};
RenderRect::RenderRect(const Platform::IntPoint& location, const Platform::IntSize& size, int splittingFactor)
: Platform::IntRect(location, size)
, m_splittingFactor(0)
, m_primarySortDirection(TopToBottom)
, m_secondarySortDirection(LeftToRight)
{
initialize(splittingFactor);
}
RenderRect::RenderRect(int x, int y, int width, int height, int splittingFactor)
: Platform::IntRect(x, y, width, height)
, m_splittingFactor(0)
, m_primarySortDirection(TopToBottom)
, m_secondarySortDirection(LeftToRight)
{
initialize(splittingFactor);
}
void RenderRect::initialize(int splittingFactor)
{
m_subRects.push_back(*this);
for (int i = 0; i < splittingFactor; ++i)
split();
quickSort();
}
static void splitRectInHalfAndAddToList(const Platform::IntRect& rect, bool vertical, IntRectList& renderRectList)
{
if (vertical) {
int width1 = static_cast<int>(ceilf(rect.width() / 2.0));
int width2 = static_cast<int>(floorf(rect.width() / 2.0));
renderRectList.push_back(Platform::IntRect(rect.x(), rect.y(), width1, rect.height()));
renderRectList.push_back(Platform::IntRect(rect.x() + width1, rect.y(), width2, rect.height()));
} else {
int height1 = static_cast<int>(ceilf(rect.height() / 2.0));
int height2 = static_cast<int>(floorf(rect.height() / 2.0));
renderRectList.push_back(Platform::IntRect(rect.x(), rect.y(), rect.width(), height1));
renderRectList.push_back(Platform::IntRect(rect.x(), rect.y() + height1, rect.width(), height2));
}
}
void RenderRect::split()
{
++m_splittingFactor;
bool vertical = !(m_splittingFactor % 2);
IntRectList subRects;
for (size_t i = 0; i < m_subRects.size(); ++i)
splitRectInHalfAndAddToList(m_subRects.at(i), vertical, subRects);
m_subRects.swap(subRects);
}
Platform::IntRect RenderRect::rectForRendering()
{
ASSERT(!m_subRects.empty());
Platform::IntRect rect = m_subRects[0];
m_subRects.erase(m_subRects.begin());
return rect;
}
void RenderRect::updateSortDirection(SortDirection primary, SortDirection secondary)
{
if (primary == m_primarySortDirection && secondary == m_secondarySortDirection)
return;
m_primarySortDirection = primary;
m_secondarySortDirection = secondary;
quickSort();
}
void RenderRect::quickSort()
{
std::sort(m_subRects.begin(), m_subRects.begin(), RectLessThan(m_primarySortDirection, m_secondarySortDirection));
}
RenderQueue::RenderQueue(BackingStorePrivate* parent)
: m_parent(parent)
, m_rectsAddedToRegularRenderJobsInCurrentCycle(false)
, m_currentRegularRenderJobsBatchUnderPressure(false)
, m_primarySortDirection(TopToBottom)
, m_secondarySortDirection(LeftToRight)
{
}
void RenderQueue::reset()
{
m_rectsAddedToRegularRenderJobsInCurrentCycle = false;
m_currentRegularRenderJobsBatchUnderPressure = false;
m_primarySortDirection = TopToBottom;
m_secondarySortDirection = LeftToRight;
m_visibleZoomJobs.clear();
m_visibleScrollJobs.clear();
m_visibleScrollJobsCompleted.clear();
m_nonVisibleScrollJobs.clear();
m_nonVisibleScrollJobsCompleted.clear();
m_regularRenderJobsRegion = Platform::IntRectRegion();
m_currentRegularRenderJobsBatch.clear();
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion();
m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion();
m_parent->stopRenderTimer();
ASSERT(isEmpty());
}
int RenderQueue::splittingFactor(const Platform::IntRect& rect) const
{
Platform::IntRect untransformedRect = m_parent->m_webPage->d->mapFromTransformed(rect);
double rectArea = untransformedRect.width() * untransformedRect.height();
Platform::IntSize defaultMaxLayoutSize = WebPagePrivate::defaultMaxLayoutSize();
double maxArea = defaultMaxLayoutSize.width() * defaultMaxLayoutSize.height();
const unsigned splitFactor = 1 << 0;
double renderRectArea = maxArea / splitFactor;
return ceil(log(rectArea / renderRectArea) / log(2.0));
}
RenderRect RenderQueue::convertToRenderRect(const Platform::IntRect& rect) const
{
return RenderRect(rect.location(), rect.size(), splittingFactor(rect));
}
bool RenderQueue::isEmpty(bool shouldPerformRegularRenderJobs) const
{
return m_visibleZoomJobs.empty() && m_visibleScrollJobs.empty()
&& (!shouldPerformRegularRenderJobs || m_currentRegularRenderJobsBatch.empty())
&& (!shouldPerformRegularRenderJobs || m_regularRenderJobsRegion.isEmpty())
&& m_nonVisibleScrollJobs.empty();
}
bool RenderQueue::hasCurrentRegularRenderJob() const
{
return !m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty();
}
bool RenderQueue::hasCurrentVisibleZoomJob() const
{
return !m_visibleZoomJobs.empty();
}
bool RenderQueue::hasCurrentVisibleScrollJob() const
{
return !m_visibleScrollJobs.empty();
}
bool RenderQueue::isCurrentVisibleScrollJob(const Platform::IntRect& rect) const
{
return std::find(m_visibleScrollJobs.begin(), m_visibleScrollJobs.end(), rect) != m_visibleScrollJobs.end();
}
bool RenderQueue::isCurrentVisibleScrollJobCompleted(const Platform::IntRect& rect) const
{
return std::find(m_visibleScrollJobsCompleted.begin(), m_visibleScrollJobsCompleted.end(), rect) != m_visibleScrollJobsCompleted.end();
}
bool RenderQueue::isCurrentRegularRenderJob(const Platform::IntRect& rect) const
{
return m_regularRenderJobsRegion.isRectInRegion(rect) == Platform::IntRectRegion::ContainedInRegion
|| m_currentRegularRenderJobsBatchRegion.isRectInRegion(rect) == Platform::IntRectRegion::ContainedInRegion;
}
bool RenderQueue::currentRegularRenderJobBatchUnderPressure() const
{
return m_currentRegularRenderJobsBatchUnderPressure;
}
void RenderQueue::setCurrentRegularRenderJobBatchUnderPressure(bool currentRegularRenderJobsBatchUnderPressure)
{
m_currentRegularRenderJobsBatchUnderPressure = currentRegularRenderJobsBatchUnderPressure;
}
void RenderQueue::eventQueueCycled()
{
if (m_rectsAddedToRegularRenderJobsInCurrentCycle && m_currentRegularRenderJobsBatchRegion.isEmpty())
m_currentRegularRenderJobsBatchUnderPressure = true;
m_rectsAddedToRegularRenderJobsInCurrentCycle = false;
}
void RenderQueue::addToQueue(JobType type, const IntRectList& rectList)
{
for (size_t i = 0; i < rectList.size(); ++i)
addToQueue(type, rectList.at(i));
}
void RenderQueue::addToQueue(JobType type, const Platform::IntRect& rect)
{
if (type == NonVisibleScroll && std::find(m_visibleScrollJobs.begin(), m_visibleScrollJobs.end(), rect) != m_visibleScrollJobs.end())
return;
switch (type) {
case VisibleZoom:
addToScrollZoomQueue(convertToRenderRect(rect), &m_visibleZoomJobs);
return;
case VisibleScroll:
addToScrollZoomQueue(convertToRenderRect(rect), &m_visibleScrollJobs);
return;
case RegularRender:
{
m_rectsAddedToRegularRenderJobsInCurrentCycle = true;
Platform::IntRectRegion::IntersectionState state = m_currentRegularRenderJobsBatchRegion.isRectInRegion(rect);
if (state == Platform::IntRectRegion::ContainedInRegion || state == Platform::IntRectRegion::PartiallyContainedInRegion) {
m_regularRenderJobsRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsRegion, m_currentRegularRenderJobsBatchRegion);
m_currentRegularRenderJobsBatch.clear();
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion();
m_currentRegularRenderJobsBatchUnderPressure = true;
}
addToRegularQueue(rect);
}
return;
case NonVisibleScroll:
addToScrollZoomQueue(convertToRenderRect(rect), &m_nonVisibleScrollJobs);
return;
}
ASSERT_NOT_REACHED();
}
void RenderQueue::addToRegularQueue(const Platform::IntRect& rect)
{
#if DEBUG_RENDER_QUEUE
if (m_regularRenderJobsRegion.isRectInRegion(rect) != Platform::IntRectRegion::ContainedInRegion) {
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::addToRegularQueue %d,%d %dx%d",
rect.x(), rect.y(), rect.width(), rect.height());
}
#endif
if (m_regularRenderJobsRegion.numRects() > 2)
m_regularRenderJobsRegion = Platform::unionOfRects(m_regularRenderJobsRegion.extents(), rect);
else
m_regularRenderJobsRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsRegion, rect);
if (!isEmpty())
m_parent->startRenderTimer(); }
void RenderQueue::addToScrollZoomQueue(const RenderRect& rect, RenderRectList* rectList)
{
if (std::find(rectList->begin(), rectList->end(), rect) != rectList->end())
return;
#if DEBUG_RENDER_QUEUE
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::addToScrollZoomQueue %d,%d %dx%d",
rect.x(), rect.y(), rect.width(), rect.height());
#endif
rectList->push_back(rect);
if (!isEmpty())
m_parent->startRenderTimer(); }
void RenderQueue::quickSort(RenderRectList* queue)
{
size_t length = queue->size();
if (!length)
return;
for (size_t i = 0; i < length; ++i)
queue->at(i).updateSortDirection(m_primarySortDirection, m_secondarySortDirection);
return std::sort(queue->begin(), queue->end(), RenderRectLessThan(m_primarySortDirection, m_secondarySortDirection));
}
void RenderQueue::updateSortDirection(int lastDeltaX, int lastDeltaY)
{
bool primaryIsHorizontal = abs(lastDeltaX) >= abs(lastDeltaY);
if (primaryIsHorizontal) {
m_primarySortDirection = lastDeltaX <= 0 ? LeftToRight : RightToLeft;
m_secondarySortDirection = lastDeltaY <= 0 ? TopToBottom : BottomToTop;
} else {
m_primarySortDirection = lastDeltaY <= 0 ? TopToBottom : BottomToTop;
m_secondarySortDirection = lastDeltaX <= 0 ? LeftToRight : RightToLeft;
}
}
void RenderQueue::visibleContentChanged(const Platform::IntRect& visibleContent)
{
if (m_visibleScrollJobs.empty() && m_nonVisibleScrollJobs.empty()) {
ASSERT(m_visibleScrollJobsCompleted.empty() && m_nonVisibleScrollJobsCompleted.empty());
return;
}
for (size_t i = 0; i < m_visibleScrollJobs.size(); ++i) {
RenderRect rect = m_visibleScrollJobs.at(i);
if (!rect.intersects(visibleContent)) {
m_visibleScrollJobs.erase(m_visibleScrollJobs.begin() + i);
addToScrollZoomQueue(rect, &m_nonVisibleScrollJobs);
--i;
}
}
for (size_t i = 0; i < m_visibleScrollJobsCompleted.size(); ++i) {
RenderRect rect = m_visibleScrollJobsCompleted.at(i);
if (!rect.intersects(visibleContent)) {
m_visibleScrollJobsCompleted.erase(m_visibleScrollJobsCompleted.begin() + i);
addToScrollZoomQueue(rect, &m_nonVisibleScrollJobsCompleted);
--i;
}
}
for (size_t i = 0; i < m_nonVisibleScrollJobs.size(); ++i) {
RenderRect rect = m_nonVisibleScrollJobs.at(i);
if (rect.intersects(visibleContent)) {
m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin() + i);
addToScrollZoomQueue(rect, &m_visibleScrollJobs);
--i;
}
}
for (size_t i = 0; i < m_nonVisibleScrollJobsCompleted.size(); ++i) {
RenderRect rect = m_nonVisibleScrollJobsCompleted.at(i);
if (rect.intersects(visibleContent)) {
m_nonVisibleScrollJobsCompleted.erase(m_nonVisibleScrollJobsCompleted.begin() + i);
addToScrollZoomQueue(rect, &m_visibleScrollJobsCompleted);
--i;
}
}
if (m_visibleScrollJobs.empty() && !m_visibleScrollJobsCompleted.empty())
visibleScrollJobsCompleted(false );
if (m_nonVisibleScrollJobs.empty() && !m_nonVisibleScrollJobsCompleted.empty())
nonVisibleScrollJobsCompleted();
ASSERT(!isEmpty());
}
void RenderQueue::clear(const Platform::IntRectRegion& region, bool clearRegularRenderJobs)
{
IntRectList rects = region.rects();
for (size_t i = 0; i < rects.size(); ++i)
clear(rects.at(i), clearRegularRenderJobs);
}
void RenderQueue::clear(const Platform::IntRect& rect, bool clearRegularRenderJobs)
{
if (m_visibleScrollJobs.empty() && m_nonVisibleScrollJobs.empty())
ASSERT(m_visibleScrollJobsCompleted.empty() && m_nonVisibleScrollJobsCompleted.empty());
for (size_t i = 0; i < m_visibleScrollJobs.size(); ++i) {
if (rect.contains(m_visibleScrollJobs.at(i))) {
m_visibleScrollJobs.erase(m_visibleScrollJobs.begin() + i);
--i;
}
}
for (size_t i = 0; i < m_visibleScrollJobsCompleted.size(); ++i) {
if (rect.contains(m_visibleScrollJobsCompleted.at(i))) {
m_visibleScrollJobsCompleted.erase(m_visibleScrollJobsCompleted.begin() + i);
--i;
}
}
for (size_t i = 0; i < m_nonVisibleScrollJobs.size(); ++i) {
if (rect.contains(m_nonVisibleScrollJobs.at(i))) {
m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin() + i);
--i;
}
}
for (size_t i = 0; i < m_nonVisibleScrollJobsCompleted.size(); ++i) {
if (rect.contains(m_nonVisibleScrollJobsCompleted.at(i))) {
m_nonVisibleScrollJobsCompleted.erase(m_nonVisibleScrollJobsCompleted.begin() + i);
--i;
}
}
if (clearRegularRenderJobs)
this->clearRegularRenderJobs(rect);
if (m_visibleScrollJobs.empty() && !m_visibleScrollJobsCompleted.empty())
visibleScrollJobsCompleted(false );
if (m_nonVisibleScrollJobs.empty() && !m_nonVisibleScrollJobsCompleted.empty())
nonVisibleScrollJobsCompleted();
if (isEmpty())
m_parent->stopRenderTimer();
}
void RenderQueue::clearRegularRenderJobs(const Platform::IntRect& rect)
{
for (size_t i = 0; i < m_currentRegularRenderJobsBatch.size(); ++i) {
if (rect.contains(m_currentRegularRenderJobsBatch.at(i))) {
m_currentRegularRenderJobsBatch.erase(m_currentRegularRenderJobsBatch.begin() + i);
--i;
}
}
m_regularRenderJobsRegion = Platform::IntRectRegion::subtractRegions(m_regularRenderJobsRegion, rect);
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, rect);
m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::subtractRegions(m_regularRenderJobsNotRenderedRegion, rect);
}
void RenderQueue::clearVisibleZoom()
{
m_visibleZoomJobs.clear();
if (isEmpty())
m_parent->stopRenderTimer();
}
bool RenderQueue::regularRenderJobsPreviouslyAttemptedButNotRendered(const Platform::IntRect& rect)
{
return m_regularRenderJobsNotRenderedRegion.isRectInRegion(rect) != Platform::IntRectRegion::NotInRegion;
}
void RenderQueue::render(bool shouldPerformRegularRenderJobs)
{
#if DEBUG_RENDER_QUEUE
double time = WTF::currentTime();
#endif
m_parent->requestLayoutIfNeeded();
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
if (elapsed)
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::render layout elapsed=%f", elapsed);
#endif
if (!m_visibleZoomJobs.empty())
renderVisibleZoomJob();
else if (!m_visibleScrollJobs.empty())
renderVisibleScrollJob();
else if (shouldPerformRegularRenderJobs && (!m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty())) {
if (currentRegularRenderJobBatchUnderPressure())
renderAllCurrentRegularRenderJobs();
else
renderRegularRenderJob();
} else if (!m_nonVisibleScrollJobs.empty())
renderNonVisibleScrollJob();
if (isEmpty())
m_parent->stopRenderTimer();
}
void RenderQueue::renderAllCurrentRegularRenderJobs()
{
#if DEBUG_RENDER_QUEUE
double time = WTF::currentTime();
#endif
m_parent->requestLayoutIfNeeded();
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
if (elapsed)
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs layout elapsed=%f", elapsed);
#endif
if (!hasCurrentRegularRenderJob())
return;
if (m_currentRegularRenderJobsBatchRegion.isEmpty()) {
m_currentRegularRenderJobsBatchRegion = m_regularRenderJobsRegion;
m_regularRenderJobsRegion = Platform::IntRectRegion();
}
Platform::IntRectRegion regionNotRendered;
if (m_parent->shouldSuppressNonVisibleRegularRenderJobs()) {
regionNotRendered = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, m_parent->visibleContentsRect());
m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsNotRenderedRegion, regionNotRendered);
#if DEBUG_RENDER_QUEUE
if (!regionNotRendered.isEmpty())
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs region not completely rendered!");
#endif
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::intersectRegions(m_currentRegularRenderJobsBatchRegion, m_parent->visibleContentsRect());
}
bool rendered = false;
if (!m_currentRegularRenderJobsBatchRegion.isEmpty()) {
std::vector<Platform::IntRect> rectList = m_currentRegularRenderJobsBatchRegion.rects();
for (size_t i = 0; i < rectList.size(); ++i)
rendered = m_parent->render(rectList.at(i)) ? true : rendered;
}
#if DEBUG_RENDER_QUEUE
elapsed = WTF::currentTime() - time;
Platform::IntRect extents = m_currentRegularRenderJobsBatchRegion.extents();
int numberOfRects = m_currentRegularRenderJobsBatchRegion.rects().size();
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs extents=(%d,%d %dx%d) numberOfRects=%d elapsed=%f",
extents.x(), extents.y(), extents.width(), extents.height(), numberOfRects, elapsed);
#endif
Platform::IntRect renderedRect = m_currentRegularRenderJobsBatchRegion.extents();
m_currentRegularRenderJobsBatch.clear();
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion();
m_currentRegularRenderJobsBatchUnderPressure = false;
if (rendered && !m_parent->isScrollingOrZooming()) {
if (!m_parent->shouldDirectRenderingToWindow())
m_parent->blitVisibleContents();
else
m_parent->invalidateWindow();
m_parent->m_webPage->client()->notifyContentRendered(renderedRect);
}
if (m_parent->shouldSuppressNonVisibleRegularRenderJobs() && !regionNotRendered.isEmpty())
m_parent->updateTilesForScrollOrNotRenderedRegion(false );
}
void RenderQueue::startRegularRenderJobBatchIfNeeded()
{
if (!m_currentRegularRenderJobsBatch.empty())
return;
IntRectList regularRenderJobs = m_regularRenderJobsRegion.rects();
m_currentRegularRenderJobsBatch = regularRenderJobs;
m_currentRegularRenderJobsBatchRegion = m_regularRenderJobsRegion;
m_regularRenderJobsRegion = Platform::IntRectRegion();
#if DEBUG_RENDER_QUEUE
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::startRegularRenderJobBatchIfNeeded batch size is %d!", m_currentRegularRenderJobsBatch.size());
#endif
}
void RenderQueue::renderVisibleZoomJob()
{
ASSERT(m_visibleZoomJobs.size() > 0);
#if DEBUG_RENDER_QUEUE
double time = WTF::currentTime();
#endif
RenderRect* rect = &m_visibleZoomJobs[0];
ASSERT(!rect->isCompleted());
Platform::IntRect subRect = rect->rectForRendering();
if (rect->isCompleted())
m_visibleZoomJobs.erase(m_visibleZoomJobs.begin());
m_parent->render(subRect);
clearRegularRenderJobs(subRect);
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleZoomJob rect=(%d,%d %dx%d) elapsed=%f",
subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed);
#endif
}
void RenderQueue::renderVisibleScrollJob()
{
ASSERT(!m_visibleScrollJobs.empty());
#if DEBUG_RENDER_QUEUE || DEBUG_RENDER_QUEUE_SORT
double time = WTF::currentTime();
#endif
quickSort(&m_visibleScrollJobs);
#if DEBUG_RENDER_QUEUE_SORT
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleScrollJob sort elapsed=%f", elapsed);
#endif
RenderRect rect = m_visibleScrollJobs[0];
m_visibleScrollJobs.erase(m_visibleScrollJobs.begin());
ASSERT(!rect.isCompleted());
Platform::IntRect subRect = rect.rectForRendering();
if (rect.isCompleted())
m_visibleScrollJobsCompleted.push_back(rect);
else
m_visibleScrollJobs.insert(m_visibleScrollJobs.begin(), rect);
m_parent->render(subRect);
clearRegularRenderJobs(subRect);
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleScrollJob rect=(%d,%d %dx%d) elapsed=%f",
subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed);
#endif
if (m_visibleScrollJobs.empty())
visibleScrollJobsCompleted(true );
}
void RenderQueue::renderRegularRenderJob()
{
#if DEBUG_RENDER_QUEUE
double time = WTF::currentTime();
#endif
ASSERT(!m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty());
startRegularRenderJobBatchIfNeeded();
Platform::IntRect rect = m_currentRegularRenderJobsBatch[0];
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, Platform::IntRectRegion(rect));
m_currentRegularRenderJobsBatch.erase(m_currentRegularRenderJobsBatch.begin());
Platform::IntRectRegion regionNotRendered;
if (m_parent->shouldSuppressNonVisibleRegularRenderJobs()) {
regionNotRendered = Platform::IntRectRegion::subtractRegions(rect, m_parent->visibleContentsRect());
m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsNotRenderedRegion, regionNotRendered);
#if DEBUG_RENDER_QUEUE
if (!regionNotRendered.isEmpty()) {
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderRegularRenderJob rect (%d,%d %dx%d) not completely rendered!",
rect.x(), rect.y(), rect.width(), rect.height());
}
#endif
rect.intersect(m_parent->visibleContentsRect());
}
if (!rect.isEmpty())
m_parent->render(rect);
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderRegularRenderJob rect=(%d,%d %dx%d) elapsed=%f",
rect.x(), rect.y(), rect.width(), rect.height(), elapsed);
#endif
if (m_currentRegularRenderJobsBatch.empty()) {
Platform::IntRect renderedRect = m_currentRegularRenderJobsBatchRegion.extents();
m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion();
m_currentRegularRenderJobsBatchUnderPressure = false;
if (!m_parent->isScrollingOrZooming()) {
if (!m_parent->shouldDirectRenderingToWindow())
m_parent->blitVisibleContents();
else
m_parent->invalidateWindow();
m_parent->m_webPage->client()->notifyContentRendered(renderedRect);
}
}
ASSERT(m_visibleScrollJobs.empty());
if (m_parent->shouldSuppressNonVisibleRegularRenderJobs() && !regionNotRendered.isEmpty())
m_parent->updateTilesForScrollOrNotRenderedRegion(false );
}
void RenderQueue::renderNonVisibleScrollJob()
{
ASSERT(!m_nonVisibleScrollJobs.empty());
#if DEBUG_RENDER_QUEUE || DEBUG_RENDER_QUEUE_SORT
double time = WTF::currentTime();
#endif
quickSort(&m_nonVisibleScrollJobs);
#if DEBUG_RENDER_QUEUE_SORT
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderNonVisibleScrollJob sort elapsed=%f", elapsed);
#endif
RenderRect rect = m_nonVisibleScrollJobs[0];
m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin());
ASSERT(!rect.isCompleted());
Platform::IntRect subRect = rect.rectForRendering();
if (rect.isCompleted())
m_nonVisibleScrollJobsCompleted.push_back(rect);
else
m_nonVisibleScrollJobs.insert(m_nonVisibleScrollJobs.begin(), rect);
m_parent->render(subRect);
clearRegularRenderJobs(subRect);
ASSERT(m_visibleScrollJobs.empty());
#if DEBUG_RENDER_QUEUE
double elapsed = WTF::currentTime() - time;
BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderNonVisibleScrollJob rect=(%d,%d %dx%d) elapsed=%f",
subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed);
#endif
if (m_nonVisibleScrollJobs.empty())
nonVisibleScrollJobsCompleted();
}
void RenderQueue::visibleScrollJobsCompleted(bool shouldBlit)
{
ASSERT(m_visibleScrollJobs.empty());
m_visibleScrollJobsCompleted.clear();
if (shouldBlit && !m_parent->isScrollingOrZooming()) {
if (!m_parent->shouldDirectRenderingToWindow())
m_parent->blitVisibleContents();
else
m_parent->invalidateWindow();
m_parent->m_webPage->client()->notifyContentRendered(m_parent->visibleContentsRect());
}
}
void RenderQueue::nonVisibleScrollJobsCompleted()
{
ASSERT(m_nonVisibleScrollJobs.empty());
m_nonVisibleScrollJobsCompleted.clear();
}
} }