BackingStore.cpp 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300
  1. /*
  2. * Copyright (C) 2009, 2010, 2011, 2012, 2013 Research In Motion Limited. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "config.h"
  19. #include "BackingStore.h"
  20. #include "BackingStoreClient.h"
  21. #include "BackingStoreTile.h"
  22. #include "BackingStoreVisualizationViewportAccessor.h"
  23. #include "BackingStore_p.h"
  24. #include "FatFingers.h"
  25. #include "Frame.h"
  26. #include "FrameView.h"
  27. #include "GraphicsContext.h"
  28. #include "InspectorController.h"
  29. #include "InspectorInstrumentation.h"
  30. #include "Page.h"
  31. #include "SurfacePool.h"
  32. #include "WebPage.h"
  33. #include "WebPageClient.h"
  34. #include "WebPageCompositorClient.h"
  35. #include "WebPageCompositor_p.h"
  36. #include "WebPage_p.h"
  37. #include "WebSettings.h"
  38. #include <BlackBerryPlatformExecutableMessage.h>
  39. #include <BlackBerryPlatformGraphics.h>
  40. #include <BlackBerryPlatformGraphicsContext.h>
  41. #include <BlackBerryPlatformIntRectRegion.h>
  42. #include <BlackBerryPlatformLog.h>
  43. #include <BlackBerryPlatformMessage.h>
  44. #include <BlackBerryPlatformMessageClient.h>
  45. #include <BlackBerryPlatformPerformanceMonitor.h>
  46. #include <BlackBerryPlatformScreen.h>
  47. #include <BlackBerryPlatformSettings.h>
  48. #include <BlackBerryPlatformViewportAccessor.h>
  49. #include <BlackBerryPlatformWindow.h>
  50. #include <graphics/AffineTransform.h>
  51. #include <wtf/CurrentTime.h>
  52. #include <wtf/MathExtras.h>
  53. #include <wtf/NotFound.h>
  54. #define SUPPRESS_NON_VISIBLE_REGULAR_RENDER_JOBS 0
  55. #define ENABLE_SCROLLBARS 1
  56. #define ENABLE_REPAINTONSCROLL 1
  57. #define DEBUG_BACKINGSTORE 0
  58. #define DEBUG_WEBCORE_REQUESTS 0
  59. #define DEBUG_VISUALIZE 0
  60. #define DEBUG_TILEMATRIX 0
  61. using namespace WebCore;
  62. using namespace std;
  63. using BlackBerry::Platform::Graphics::Window;
  64. using BlackBerry::Platform::IntRect;
  65. using BlackBerry::Platform::IntPoint;
  66. using BlackBerry::Platform::IntSize;
  67. namespace BlackBerry {
  68. namespace WebKit {
  69. WebPage* BackingStorePrivate::s_currentBackingStoreOwner = 0;
  70. typedef std::pair<int, int> Divisor;
  71. typedef Vector<Divisor> DivisorList;
  72. // FIXME: Cache this and/or use a smarter algorithm.
  73. static DivisorList divisors(unsigned n)
  74. {
  75. DivisorList divisors;
  76. for (unsigned i = 1; i <= n; ++i)
  77. if (!(n % i))
  78. divisors.append(std::make_pair(i, n / i));
  79. return divisors;
  80. }
  81. Platform::IntRect BackingStoreGeometry::backingStoreRect() const
  82. {
  83. return Platform::IntRect(backingStoreOffset(), backingStoreSize());
  84. }
  85. Platform::IntSize BackingStoreGeometry::backingStoreSize() const
  86. {
  87. return Platform::IntSize(numberOfTilesWide() * BackingStorePrivate::tileWidth(), numberOfTilesHigh() * BackingStorePrivate::tileHeight());
  88. }
  89. bool BackingStoreGeometry::isTileCorrespondingToBuffer(TileIndex index, TileBuffer* tileBuffer) const
  90. {
  91. return tileBuffer
  92. && scale() == tileBuffer->lastRenderScale()
  93. && originOfTile(index) == tileBuffer->lastRenderOrigin();
  94. }
  95. BackingStorePrivate::BackingStorePrivate()
  96. : m_suspendScreenUpdateCounterWebKitThread(0)
  97. , m_suspendBackingStoreUpdates(0)
  98. , m_suspendGeometryUpdates(0)
  99. , m_resumeOperation(BackingStore::None)
  100. , m_suspendScreenUpdatesWebKitThread(true)
  101. , m_suspendScreenUpdatesUserInterfaceThread(true)
  102. , m_suspendRenderJobs(false)
  103. , m_suspendRegularRenderJobs(false)
  104. , m_tileMatrixContainsUsefulContent(false)
  105. , m_tileMatrixNeedsUpdate(false)
  106. , m_isScrollingOrZooming(false)
  107. , m_webPage(0)
  108. , m_client(0)
  109. , m_renderQueue(adoptPtr(new RenderQueue(this)))
  110. , m_hasBlitJobs(false)
  111. , m_webPageBackgroundColor(WebCore::Color::white)
  112. {
  113. m_frontState = reinterpret_cast<unsigned>(new BackingStoreGeometry);
  114. }
  115. BackingStorePrivate::~BackingStorePrivate()
  116. {
  117. BackingStoreGeometry* front = reinterpret_cast<BackingStoreGeometry*>(m_frontState);
  118. delete front;
  119. m_frontState = 0;
  120. }
  121. void BackingStorePrivate::instrumentBeginFrame()
  122. {
  123. #if ENABLE(INSPECTOR)
  124. WebPagePrivate::core(m_webPage)->inspectorController()->didBeginFrame();
  125. #endif
  126. }
  127. void BackingStorePrivate::instrumentCancelFrame()
  128. {
  129. #if ENABLE(INSPECTOR)
  130. WebPagePrivate::core(m_webPage)->inspectorController()->didCancelFrame();
  131. #endif
  132. }
  133. bool BackingStorePrivate::isOpenGLCompositing() const
  134. {
  135. if (Window* window = m_webPage->client()->window())
  136. return window->windowUsage() == Window::GLES2Usage;
  137. // If there's no window, OpenGL rendering is currently the only option.
  138. return true;
  139. }
  140. void BackingStorePrivate::suspendBackingStoreUpdates()
  141. {
  142. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  143. if (m_suspendBackingStoreUpdates) {
  144. BBLOG(Platform::LogLevelInfo,
  145. "Backingstore already suspended, increasing suspend counter.");
  146. }
  147. ++m_suspendBackingStoreUpdates;
  148. }
  149. void BackingStorePrivate::suspendGeometryUpdates()
  150. {
  151. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  152. if (m_suspendGeometryUpdates) {
  153. BBLOG(Platform::LogLevelInfo,
  154. "Backingstore geometry already suspended, increasing suspend counter.");
  155. }
  156. ++m_suspendGeometryUpdates;
  157. }
  158. void BackingStorePrivate::suspendScreenUpdates()
  159. {
  160. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  161. if (m_suspendScreenUpdateCounterWebKitThread) {
  162. BBLOG(Platform::LogLevelInfo,
  163. "Screen already suspended, increasing suspend counter.");
  164. }
  165. // Make sure the user interface thread gets the message before we proceed
  166. // because blitVisibleContents() can be called from the user interface
  167. // thread and it must honor this flag.
  168. ++m_suspendScreenUpdateCounterWebKitThread;
  169. updateSuspendScreenUpdateState();
  170. }
  171. void BackingStorePrivate::resumeBackingStoreUpdates()
  172. {
  173. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  174. ASSERT(m_suspendBackingStoreUpdates >= 1);
  175. if (m_suspendBackingStoreUpdates < 1) {
  176. Platform::logAlways(Platform::LogLevelCritical,
  177. "Call mismatch: Backingstore hasn't been suspended, therefore won't resume!");
  178. return;
  179. }
  180. // Set a flag indicating that we're about to resume backingstore updates and
  181. // the tile matrix should be updated as a consequence by the first render
  182. // job that happens after this resumption of backingstore updates.
  183. if (m_suspendBackingStoreUpdates == 1)
  184. setTileMatrixNeedsUpdate();
  185. --m_suspendBackingStoreUpdates;
  186. dispatchRenderJob();
  187. }
  188. void BackingStorePrivate::resumeGeometryUpdates()
  189. {
  190. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  191. ASSERT(m_suspendGeometryUpdates >= 1);
  192. if (m_suspendGeometryUpdates < 1) {
  193. Platform::logAlways(Platform::LogLevelCritical,
  194. "Call mismatch: Backingstore geometry hasn't been suspended, therefore won't resume!");
  195. return;
  196. }
  197. // Set a flag indicating that we're about to resume geometry updates and
  198. // the tile matrix should be updated as a consequence by the first render
  199. // job that happens after this resumption of geometry updates.
  200. if (m_suspendGeometryUpdates == 1)
  201. setTileMatrixNeedsUpdate();
  202. --m_suspendGeometryUpdates;
  203. dispatchRenderJob();
  204. }
  205. void BackingStorePrivate::resumeScreenUpdates(BackingStore::ResumeUpdateOperation op)
  206. {
  207. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  208. ASSERT(m_suspendScreenUpdateCounterWebKitThread);
  209. if (!m_suspendScreenUpdateCounterWebKitThread) {
  210. Platform::logAlways(Platform::LogLevelCritical,
  211. "Call mismatch: Screen hasn't been suspended, therefore won't resume!");
  212. return;
  213. }
  214. // Out of all nested resume calls, resume with the maximum-impact operation.
  215. if (op == BackingStore::RenderAndBlit
  216. || (m_resumeOperation == BackingStore::None && op == BackingStore::Blit))
  217. m_resumeOperation = op;
  218. if (m_suspendScreenUpdateCounterWebKitThread >= 2) { // we're still suspended
  219. BBLOG(Platform::LogLevelInfo,
  220. "Screen and backingstore still suspended, decreasing suspend counter.");
  221. --m_suspendScreenUpdateCounterWebKitThread;
  222. return;
  223. }
  224. op = m_resumeOperation;
  225. m_resumeOperation = BackingStore::None;
  226. #if USE(ACCELERATED_COMPOSITING)
  227. if (op != BackingStore::None) {
  228. if (isOpenGLCompositing() && !isActive()) {
  229. m_webPage->d->setCompositorDrawsRootLayer(true);
  230. m_webPage->d->setNeedsOneShotDrawingSynchronization();
  231. --m_suspendScreenUpdateCounterWebKitThread;
  232. updateSuspendScreenUpdateState();
  233. return;
  234. }
  235. m_webPage->d->setNeedsOneShotDrawingSynchronization();
  236. }
  237. #endif
  238. // Render visible contents if necessary.
  239. if (op == BackingStore::RenderAndBlit) {
  240. updateTileMatrixIfNeeded();
  241. TileIndexList visibleTiles = visibleTileIndexes(frontState());
  242. TileIndexList renderedTiles = render(visibleTiles);
  243. if (renderedTiles.size() != visibleTiles.size()) {
  244. // Add unrendered leftover tiles to the render queue.
  245. for (unsigned i = 0; i < visibleTiles.size(); ++i) {
  246. if (!renderedTiles.contains(visibleTiles[i])) {
  247. Platform::IntRect tileRect(frontState()->originOfTile(visibleTiles[i]), tileSize());
  248. m_renderQueue->addToQueue(RenderQueue::VisibleZoom, tileRect);
  249. }
  250. }
  251. }
  252. }
  253. // Make sure the user interface thread gets the message before we proceed
  254. // because blitVisibleContents() can be called from the user interface
  255. // thread and it must honor this flag.
  256. --m_suspendScreenUpdateCounterWebKitThread;
  257. updateSuspendScreenUpdateState();
  258. if (op == BackingStore::None)
  259. return;
  260. #if USE(ACCELERATED_COMPOSITING)
  261. // It needs layout and render before committing root layer if we set OSDS
  262. if (m_webPage->d->needsOneShotDrawingSynchronization())
  263. m_webPage->d->updateLayoutAndStyleIfNeededRecursive();
  264. // This will also blit since we set the OSDS flag above.
  265. m_webPage->d->commitRootLayerIfNeeded();
  266. #else
  267. // Do some blitting if necessary.
  268. if (op == BackingStore::Blit || op == BackingStore::RenderAndBlit)
  269. blitVisibleContents();
  270. #endif
  271. }
  272. void BackingStorePrivate::updateSuspendScreenUpdateState(bool* hasSyncedToUserInterfaceThread)
  273. {
  274. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  275. bool isBackingStoreUsable = isActive() && m_tileMatrixContainsUsefulContent
  276. && (m_suspendBackingStoreUpdates || !m_renderQueue->hasCurrentVisibleZoomJob()); // Backingstore is not usable while we're waiting for an ("atomic") zoom job to finish.
  277. bool shouldSuspend = m_suspendScreenUpdateCounterWebKitThread
  278. || !buffer()
  279. || !m_webPage->isVisible()
  280. || (!isBackingStoreUsable && !m_webPage->d->compositorDrawsRootLayer());
  281. if (m_suspendScreenUpdatesWebKitThread == shouldSuspend) {
  282. if (hasSyncedToUserInterfaceThread)
  283. *hasSyncedToUserInterfaceThread = false;
  284. return;
  285. }
  286. m_suspendScreenUpdatesWebKitThread = shouldSuspend;
  287. // FIXME: If we change the backingstore to dispatch geometries, this
  288. // assignment should be moved to a dispatched setter function instead.
  289. m_suspendScreenUpdatesUserInterfaceThread = shouldSuspend;
  290. BlackBerry::Platform::userInterfaceThreadMessageClient()->syncToCurrentMessage();
  291. if (hasSyncedToUserInterfaceThread)
  292. *hasSyncedToUserInterfaceThread = true;
  293. }
  294. void BackingStorePrivate::repaint(const Platform::IntRect& windowRect, bool contentChanged, bool immediate)
  295. {
  296. // If immediate is true, then we're being asked to perform synchronously.
  297. // NOTE: WebCore::ScrollView will call this method with immediate:true and contentChanged:false.
  298. // This is a special case introduced specifically for the Apple's windows port and can be safely ignored I believe.
  299. // Now this method will be called from WebPagePrivate::repaint().
  300. if (contentChanged && !windowRect.isEmpty()) {
  301. // This windowRect is in document coordinates relative to the viewport,
  302. // but we need it in pixel contents coordinates.
  303. const Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  304. Platform::IntRect rect = viewportAccessor->roundToPixelFromDocumentContents(viewportAccessor->documentContentsFromViewport(windowRect));
  305. rect.intersect(viewportAccessor->pixelContentsRect());
  306. if (rect.isEmpty())
  307. return;
  308. #if DEBUG_WEBCORE_REQUESTS
  309. Platform::logAlways(Platform::LogLevelCritical,
  310. "BackingStorePrivate::repaint rect=%s contentChanged=%s immediate=%s",
  311. rect.toString().c_str(),
  312. contentChanged ? "true" : "false",
  313. immediate ? "true" : "false");
  314. #endif
  315. if (immediate)
  316. renderAndBlitImmediately(rect);
  317. else
  318. m_renderQueue->addToQueue(RenderQueue::RegularRender, rect);
  319. }
  320. }
  321. void BackingStorePrivate::slowScroll(const Platform::IntSize& delta, const Platform::IntRect& windowRect, bool immediate)
  322. {
  323. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  324. #if DEBUG_BACKINGSTORE
  325. // Start the time measurement...
  326. double time = WTF::currentTime();
  327. #endif
  328. scrollingStartedHelper(delta);
  329. // This windowRect is in document coordinates relative to the viewport,
  330. // but we need it in pixel contents coordinates.
  331. const Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  332. const Platform::IntRect rect = viewportAccessor->roundToPixelFromDocumentContents(viewportAccessor->documentContentsFromViewport(windowRect));
  333. if (immediate)
  334. renderAndBlitImmediately(rect);
  335. else {
  336. m_renderQueue->addToQueue(RenderQueue::VisibleScroll, rect);
  337. // We only blit here if the client did not generate the scroll as the
  338. // client supports blitting asynchronously during scroll operations.
  339. if (!m_client->isClientGeneratedScroll())
  340. blitVisibleContents();
  341. }
  342. #if DEBUG_BACKINGSTORE
  343. // Stop the time measurement.
  344. double elapsed = WTF::currentTime() - time;
  345. Platform::logAlways(Platform::LogLevelCritical, "BackingStorePrivate::slowScroll elapsed=%f", elapsed);
  346. #endif
  347. }
  348. void BackingStorePrivate::scroll(const Platform::IntSize& delta, const Platform::IntRect&, const Platform::IntRect&)
  349. {
  350. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  351. #if DEBUG_BACKINGSTORE
  352. // Start the time measurement...
  353. double time = WTF::currentTime();
  354. #endif
  355. scrollingStartedHelper(delta);
  356. // We only blit here if the client did not generate the scroll as the client
  357. // now supports blitting asynchronously during scroll operations.
  358. if (!m_client->isClientGeneratedScroll())
  359. blitVisibleContents();
  360. #if DEBUG_BACKINGSTORE
  361. // Stop the time measurement.
  362. double elapsed = WTF::currentTime() - time;
  363. Platform::logAlways(Platform::LogLevelCritical, "BackingStorePrivate::scroll dx=%d, dy=%d elapsed=%f", delta.width(), delta.height(), elapsed);
  364. #endif
  365. }
  366. void BackingStorePrivate::scrollingStartedHelper(const Platform::IntSize& delta)
  367. {
  368. // Notify the render queue so that it can shuffle accordingly.
  369. m_renderQueue->updateSortDirection(delta.width(), delta.height());
  370. m_renderQueue->visibleContentChanged(visibleContentsRect());
  371. // Scroll the actual backingstore.
  372. scrollBackingStore(delta.width(), delta.height());
  373. // Add any newly visible tiles that have not been previously rendered to the queue
  374. // and check if the tile was previously rendered by regular render job.
  375. updateTilesForScrollOrNotRenderedRegion();
  376. }
  377. bool BackingStorePrivate::shouldSuppressNonVisibleRegularRenderJobs() const
  378. {
  379. #if SUPPRESS_NON_VISIBLE_REGULAR_RENDER_JOBS
  380. return true;
  381. #else
  382. // Always suppress when loading as this drastically decreases page loading
  383. // time...
  384. return m_client->isLoading();
  385. #endif
  386. }
  387. bool BackingStorePrivate::shouldPerformRenderJobs() const
  388. {
  389. return isActive() && !m_suspendRenderJobs && !m_suspendBackingStoreUpdates && !m_renderQueue->isEmpty(!m_suspendRegularRenderJobs);
  390. }
  391. bool BackingStorePrivate::shouldPerformRegularRenderJobs() const
  392. {
  393. return shouldPerformRenderJobs() && !m_suspendRegularRenderJobs;
  394. }
  395. static const BlackBerry::Platform::Message::Type RenderJobMessageType = BlackBerry::Platform::Message::generateUniqueMessageType();
  396. class RenderJobMessage : public BlackBerry::Platform::ExecutableMessage {
  397. public:
  398. RenderJobMessage(BlackBerry::Platform::MessageDelegate* delegate)
  399. : BlackBerry::Platform::ExecutableMessage(delegate, BlackBerry::Platform::ExecutableMessage::UniqueCoalescing, RenderJobMessageType)
  400. { }
  401. };
  402. void BackingStorePrivate::dispatchRenderJob()
  403. {
  404. BlackBerry::Platform::MessageDelegate* messageDelegate = BlackBerry::Platform::createMethodDelegate(&BackingStorePrivate::renderJob, this);
  405. BlackBerry::Platform::webKitThreadMessageClient()->dispatchMessage(new RenderJobMessage(messageDelegate));
  406. }
  407. void BackingStorePrivate::renderJob()
  408. {
  409. if (!shouldPerformRenderJobs())
  410. return;
  411. instrumentBeginFrame();
  412. #if DEBUG_BACKINGSTORE
  413. Platform::logAlways(Platform::LogLevelCritical, "BackingStorePrivate::renderJob");
  414. #endif
  415. m_renderQueue->render(!m_suspendRegularRenderJobs);
  416. if (shouldPerformRenderJobs())
  417. dispatchRenderJob();
  418. }
  419. Platform::IntSize BackingStorePrivate::expandedContentsSize() const
  420. {
  421. const Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  422. return m_client->transformedViewportSize().expandedTo(viewportAccessor->pixelContentsSize());
  423. }
  424. Platform::IntRect BackingStorePrivate::expandedContentsRect() const
  425. {
  426. return Platform::IntRect(Platform::IntPoint(0, 0), expandedContentsSize());
  427. }
  428. Platform::IntRect BackingStorePrivate::visibleContentsRect() const
  429. {
  430. const Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  431. Platform::IntRect rect = viewportAccessor->pixelViewportRect();
  432. rect.intersect(viewportAccessor->pixelContentsRect());
  433. return rect;
  434. }
  435. void BackingStorePrivate::setBackingStoreRect(const Platform::IntRect& backingStoreRect, double scale)
  436. {
  437. if (!m_webPage->isVisible())
  438. return;
  439. if (!isActive()) {
  440. m_webPage->d->setShouldResetTilesWhenShown(true);
  441. return;
  442. }
  443. if (m_suspendBackingStoreUpdates || m_suspendGeometryUpdates)
  444. return;
  445. Platform::IntRect oldBackingStoreRect = frontState()->backingStoreRect();
  446. double currentScale = frontState()->scale();
  447. if (backingStoreRect == oldBackingStoreRect && scale == currentScale)
  448. return;
  449. #if DEBUG_TILEMATRIX
  450. Platform::logAlways(Platform::LogLevelCritical,
  451. "BackingStorePrivate::setBackingStoreRect changed from %s to %s",
  452. oldBackingStoreRect.toString().c_str(),
  453. backingStoreRect.toString().c_str());
  454. #endif
  455. BackingStoreGeometry* oldGeometry = frontState();
  456. TileMap oldTileMap = oldGeometry->tileMap();
  457. TileIndexList indexesToFill = indexesForBackingStoreRect(backingStoreRect);
  458. ASSERT(static_cast<int>(indexesToFill.size()) == oldTileMap.size());
  459. m_renderQueue->clear(oldBackingStoreRect, RenderQueue::DontClearRegularRenderJobs);
  460. m_renderQueue->backingStoreRectChanging(oldBackingStoreRect, backingStoreRect);
  461. TileMap newTileMap;
  462. TileMap leftOverTiles;
  463. // Iterate through our current tile map and add tiles that are rendered with
  464. // our new backing store rect.
  465. TileMap::const_iterator tileMapEnd = oldTileMap.end();
  466. for (TileMap::const_iterator it = oldTileMap.begin(); it != tileMapEnd; ++it) {
  467. TileIndex oldIndex = it->key;
  468. TileBuffer* oldTileBuffer = it->value;
  469. // If the new backing store rect contains this origin, then insert the tile there
  470. // and mark it as no longer shifted. Note: Platform::IntRect::contains checks for a 1x1 rect
  471. // below and to the right of the origin so it is correct usage here.
  472. if (oldTileBuffer && backingStoreRect.contains(oldTileBuffer->lastRenderOrigin())) {
  473. TileIndex newIndex = indexOfTile(oldTileBuffer->lastRenderOrigin(), backingStoreRect);
  474. size_t i = indexesToFill.find(newIndex);
  475. ASSERT(i != WTF::notFound);
  476. indexesToFill.remove(i);
  477. newTileMap.add(newIndex, oldTileBuffer);
  478. } else {
  479. // Store this tile and index so we can add it to the remaining left over spots...
  480. leftOverTiles.add(oldIndex, oldTileBuffer);
  481. }
  482. }
  483. ASSERT(static_cast<int>(indexesToFill.size()) == leftOverTiles.size());
  484. size_t i = 0;
  485. TileMap::const_iterator leftOverEnd = leftOverTiles.end();
  486. for (TileMap::const_iterator it = leftOverTiles.begin(); it != leftOverEnd; ++it) {
  487. TileBuffer* oldTileBuffer = it->value;
  488. if (i >= indexesToFill.size()) {
  489. ASSERT_NOT_REACHED();
  490. break;
  491. }
  492. TileIndex newIndex = indexesToFill.at(i);
  493. newTileMap.add(newIndex, oldTileBuffer);
  494. ++i;
  495. }
  496. // Checks to make sure we haven't lost any tiles.
  497. ASSERT(oldTileMap.size() == newTileMap.size());
  498. BackingStoreGeometry* newGeometry = new BackingStoreGeometry;
  499. newGeometry->setScale(scale);
  500. newGeometry->setNumberOfTilesWide(backingStoreRect.width() / tileWidth());
  501. newGeometry->setNumberOfTilesHigh(backingStoreRect.height() / tileHeight());
  502. newGeometry->setBackingStoreOffset(backingStoreRect.location());
  503. newGeometry->setTileMap(newTileMap);
  504. adoptAsFrontState(newGeometry); // swap into UI thread
  505. // Mark tiles as needing update.
  506. updateTilesAfterBackingStoreRectChange();
  507. }
  508. void BackingStorePrivate::updateTilesAfterBackingStoreRectChange()
  509. {
  510. BackingStoreGeometry* geometry = frontState();
  511. TileMap currentMap = geometry->tileMap();
  512. TileMap::const_iterator end = currentMap.end();
  513. for (TileMap::const_iterator it = currentMap.begin(); it != end; ++it) {
  514. TileIndex index = it->key;
  515. TileBuffer* tileBuffer = it->value;
  516. Platform::IntPoint tileOrigin = geometry->originOfTile(index);
  517. // The rect in transformed contents coordinates.
  518. Platform::IntRect rect(tileOrigin, tileSize());
  519. if (geometry->isTileCorrespondingToBuffer(index, tileBuffer)) {
  520. if (m_renderQueue->regularRenderJobsPreviouslyAttemptedButNotRendered(rect)) {
  521. // If the render queue previously tried to render this tile, but the
  522. // tile wasn't visible at the time we can't simply restore the tile
  523. // since the content is now invalid as far as WebKit is concerned.
  524. // Instead, we clear that part of the tile if it is visible and then
  525. // put the tile in the render queue again.
  526. // Intersect the tile with the not rendered region to get the areas
  527. // of the tile that we need to clear.
  528. Platform::IntRectRegion tileNotRenderedRegion = Platform::IntRectRegion::intersectRegions(m_renderQueue->regularRenderJobsNotRenderedRegion(), rect);
  529. clearAndUpdateTileOfNotRenderedRegion(index, tileBuffer, tileNotRenderedRegion, geometry);
  530. #if DEBUG_BACKINGSTORE
  531. Platform::logAlways(Platform::LogLevelCritical,
  532. "BackingStorePrivate::updateTilesAfterBackingStoreRectChange did clear tile %s",
  533. tileNotRenderedRegion.extents().toString().c_str());
  534. #endif
  535. } else {
  536. if (!tileBuffer || (!tileBuffer->isRendered(tileVisibleContentsRect(index, geometry), geometry->scale())
  537. && !isCurrentVisibleJob(index, geometry)))
  538. updateTile(tileOrigin, false /*immediate*/);
  539. }
  540. } else if (rect.intersects(expandedContentsRect()))
  541. updateTile(tileOrigin, false /*immediate*/);
  542. }
  543. }
  544. TileIndexList BackingStorePrivate::indexesForBackingStoreRect(const Platform::IntRect& backingStoreRect) const
  545. {
  546. TileIndexList indexes;
  547. int numberOfTilesWide = backingStoreRect.width() / tileWidth();
  548. int numberOfTilesHigh = backingStoreRect.height() / tileHeight();
  549. for (int y = 0; y < numberOfTilesHigh; ++y) {
  550. for (int x = 0; x < numberOfTilesWide; ++x) {
  551. TileIndex index(x, y);
  552. indexes.append(index);
  553. }
  554. }
  555. return indexes;
  556. }
  557. TileIndex BackingStorePrivate::indexOfTile(const Platform::IntPoint& origin, const Platform::IntRect& backingStoreRect) const
  558. {
  559. int offsetX = origin.x() - backingStoreRect.x();
  560. int offsetY = origin.y() - backingStoreRect.y();
  561. if (offsetX)
  562. offsetX = offsetX / tileWidth();
  563. if (offsetY)
  564. offsetY = offsetY / tileHeight();
  565. return TileIndex(offsetX, offsetY);
  566. }
  567. void BackingStorePrivate::clearAndUpdateTileOfNotRenderedRegion(const TileIndex&, TileBuffer* tileBuffer,
  568. const Platform::IntRectRegion& tileNotRenderedRegion,
  569. BackingStoreGeometry*,
  570. bool update)
  571. {
  572. if (tileNotRenderedRegion.isEmpty())
  573. return;
  574. // Clear the render queue of this region.
  575. m_renderQueue->clear(tileNotRenderedRegion, RenderQueue::ClearAnyJobs);
  576. if (update) {
  577. // Add it again as a regular render job.
  578. m_renderQueue->addToQueue(RenderQueue::RegularRender, tileNotRenderedRegion);
  579. }
  580. if (!tileBuffer)
  581. return;
  582. // If the region in question is already marked as not rendered, return early
  583. if (Platform::IntRectRegion::intersectRegions(tileBuffer->renderedRegion(), tileNotRenderedRegion).isEmpty())
  584. return;
  585. // Clear the tile of this region. The back buffer region is invalid anyway, but the front
  586. // buffer must not be manipulated without synchronization with the compositing thread, or
  587. // we have a race.
  588. // Instead of using the customary sequence of copy-back, modify and swap, we send a synchronous
  589. // message to the compositing thread to avoid the copy-back step and save memory bandwidth.
  590. // The trade-off is that the WebKit thread might wait a little longer for the compositing thread
  591. // than it would from a waitForCurrentMessage() call.
  592. ASSERT(Platform::webKitThreadMessageClient()->isCurrentThread());
  593. if (!Platform::webKitThreadMessageClient()->isCurrentThread())
  594. return;
  595. Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
  596. Platform::createMethodCallMessage(&BackingStorePrivate::clearRenderedRegion,
  597. this, tileBuffer, tileNotRenderedRegion));
  598. }
  599. void BackingStorePrivate::clearRenderedRegion(TileBuffer* tileBuffer, const Platform::IntRectRegion& region)
  600. {
  601. ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
  602. if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread())
  603. return;
  604. if (!tileBuffer)
  605. return;
  606. tileBuffer->clearRenderedRegion(region);
  607. }
  608. bool BackingStorePrivate::isCurrentVisibleJob(const TileIndex& index, BackingStoreGeometry* geometry) const
  609. {
  610. return m_renderQueue->isCurrentVisibleZoomJob(index)
  611. || m_renderQueue->isCurrentVisibleScrollJob(index)
  612. || m_renderQueue->isCurrentVisibleZoomJobCompleted(index)
  613. || m_renderQueue->isCurrentVisibleScrollJobCompleted(index)
  614. || m_renderQueue->isCurrentRegularRenderJob(index, geometry);
  615. }
  616. Platform::IntRect BackingStorePrivate::nonOverscrolled(const Platform::IntRect& viewportRect, const Platform::IntRect& contentsRect)
  617. {
  618. const Platform::IntPoint maximumReasonableViewportLocation(
  619. contentsRect.right() - viewportRect.width(),
  620. contentsRect.bottom() - viewportRect.height());
  621. const Platform::IntPoint minimumRectLocation(
  622. std::max(0, std::min(maximumReasonableViewportLocation.x(), viewportRect.x())),
  623. std::max(0, std::min(maximumReasonableViewportLocation.y(), viewportRect.y())));
  624. return Platform::IntRect(minimumRectLocation, viewportRect.size());
  625. }
  626. Platform::IntRect BackingStorePrivate::enclosingTileRect(const Platform::IntRect& pixelContentsRect)
  627. {
  628. Platform::IntPoint location(
  629. tileWidth() * (pixelContentsRect.x() / tileWidth()),
  630. tileHeight() * (pixelContentsRect.y() / tileHeight()));
  631. return Platform::IntRect(location, Platform::IntSize(
  632. tileWidth() * ((pixelContentsRect.right() - location.x() - 1) / tileWidth() + 1),
  633. tileHeight() * ((pixelContentsRect.bottom() - location.y() - 1) / tileHeight() + 1)));
  634. }
  635. Platform::IntRect BackingStorePrivate::desiredBackingStoreRect(const Platform::IntRect& pixelViewportRect, const Platform::IntRect& maximumReasonableRect, int deltaX, int deltaY)
  636. {
  637. const int scrollDeltaCutoff = 30;
  638. const float multiplierDownAtStandstill = 2.0f;
  639. Platform::IntRect desiredRect = pixelViewportRect;
  640. desiredRect.inflate(tileWidth() / 2, tileHeight() / 2);
  641. desiredRect.intersect(maximumReasonableRect);
  642. // Get a picture of the scrolling momentum, limited to between -1.0 and 1.0 on both x and y axes.
  643. const float expandX = std::max(-scrollDeltaCutoff, std::min(scrollDeltaCutoff, -deltaX)) / static_cast<float>(scrollDeltaCutoff);
  644. const float expandY = std::max(-scrollDeltaCutoff, std::min(scrollDeltaCutoff, -deltaY)) / static_cast<float>(scrollDeltaCutoff);
  645. const float momentum = std::max(expandX, expandY);
  646. // If no scrolling occurs, use the viewport ratio as default proportion.
  647. // At maximum momentum (1.0), disregard the viewport ratio completely (multiply by 1.0).
  648. // In between, interpolate.
  649. const float viewportRatio = pixelViewportRect.isEmpty() ? 1.0f : (pixelViewportRect.width() / static_cast<float>(pixelViewportRect.height()));
  650. const float viewportRatioMultiplier = viewportRatio + momentum * (1.0f - viewportRatio);
  651. // In the same manner, we prioritize the "down" direction if no other
  652. // momentum overpowers it, because the user will most likely scroll
  653. // in that direction.
  654. const float multiplierDown = multiplierDownAtStandstill + momentum * (1.0f - multiplierDownAtStandstill);
  655. // The stronger the momentum is of one axis, the lesser importance will be
  656. // placed on the other one. Also, if the rectangle already covers the whole
  657. // width or height then we don't have to increase it on that axis.
  658. float importanceX = desiredRect.width() == maximumReasonableRect.width() ? 0.0f : (1.0f - fabs(expandY));
  659. float importanceY = desiredRect.height() == maximumReasonableRect.height() ? 0.0f : (1.0f - fabs(expandX));
  660. if (importanceX <= FLT_EPSILON && importanceY <= FLT_EPSILON) {
  661. importanceX = 1.0f;
  662. importanceY = 1.0f;
  663. }
  664. importanceX *= viewportRatioMultiplier;
  665. // We use axis importance to calculate the ratio between x and y axes.
  666. // If the importance of one axis is 0 and the other is positive, one multiplier will be 0 and the other will be 1.
  667. const float multiplierX = importanceY ? (importanceX / importanceY) : 1.0f;
  668. const float multiplierY = importanceX ? (importanceY / importanceX) : 1.0f;
  669. // Try to assign proportional values for extending the desired
  670. // backingstore rect into the four directions. It doesn't matter how big
  671. // these values are as long as they're proportional and >= 0. Rationale:
  672. // * Allocate more tile space for the axis that is being scrolled.
  673. // * Allocate almost all space of one axis if scrolling in one direction hits the cutoff value, leave the rest for the opposite direction.
  674. float expandRight = (0.5f + (0.4f * expandX)) * multiplierX;
  675. float expandLeft = (0.5f + (-0.4f * expandX)) * multiplierX;
  676. float expandDown = (0.5f + (0.4f * expandY)) * multiplierY * multiplierDown;
  677. float expandUp = (0.5f + (-0.4f * expandY)) * multiplierY;
  678. // Calculate how many pixels we have left to spare and how many of these
  679. // we ideally want to allocate in any given direction.
  680. int remainingNumberOfTilePixels =
  681. SurfacePool::globalSurfacePool()->numberOfBackingStoreFrontBuffers() * tileWidth() * tileHeight()
  682. - desiredRect.area();
  683. while (expandRight > FLT_EPSILON || expandLeft > FLT_EPSILON || expandDown > FLT_EPSILON || expandUp > FLT_EPSILON) {
  684. int previousRemainingNumberOfTilePixels = remainingNumberOfTilePixels;
  685. // Excursion into mathematical formulas to be solved.
  686. // We now have proportional factors for how much far the ideal
  687. // tile geometry rect extends into each direction, what we need is to find
  688. // a constant "c" that translates these factors into actual pixel values.
  689. //
  690. // pxRight == c * expandRight
  691. // pxLeft == c * expandLeft
  692. // pxDown == c * expandDown
  693. // pxUp == c * expandUp
  694. //
  695. // remainingNumberOfTilePixels ==
  696. // pxUp * (pxLeft + initialWidth + pxRight)
  697. // + pxDown * (pxLeft + initialWidth + pxRight)
  698. // + initialHeight * (pxLeft + pxRight)
  699. //
  700. // Wolfram Alpha: solve p = c * u * (c * l + w + c * r) + c * d * (c * l + w + c * r) + h * (c * l + c * r) for c
  701. // leads to the following resolution (discounting the negative one):
  702. // (d+u)(l+r) != 0 and c = (sqrt((d w + h l + h r + u w)^2 + 4 p (d l + d r + l u + r u)) - d w - h l - h r - u w) / (2 (d+u) (l+r))
  703. //
  704. // [multiplierX == 0]: remainingNumberOfTilePixels == initialWidth * (pxUp + pxDown)
  705. // solve p = w * c * (u + d) for c => w (d+u) != 0 and c = p / (w (d+u))
  706. // [multiplierY == 0]: remainingNumberOfTilePixels == initialHeight * (pxLeft + pxRight)
  707. // solve p = h * c * (l + r) for c => h (l+r) != 0 and c = p / (h (l+r))
  708. const int p = remainingNumberOfTilePixels;
  709. const int w = desiredRect.width();
  710. const int h = desiredRect.height();
  711. const float r = expandRight;
  712. const float l = expandLeft;
  713. const float d = expandDown;
  714. const float u = expandUp;
  715. int pxLeft = 0;
  716. int pxRight = 0;
  717. int pxDown = 0;
  718. int pxUp = 0;
  719. if (l + r <= FLT_EPSILON) { // multiplierX == 0
  720. ASSERT(d + u > FLT_EPSILON);
  721. const float c = p / (w * (d + u));
  722. pxDown = static_cast<int>(c * expandDown);
  723. pxUp = static_cast<int>(c * expandUp);
  724. } else if (u + d <= FLT_EPSILON) { // multiplierY == 0
  725. ASSERT(l + r > FLT_EPSILON);
  726. const float c = p / (h * (l + r));
  727. pxLeft = static_cast<int>(c * expandLeft);
  728. pxRight = static_cast<int>(c * expandRight);
  729. } else {
  730. const float c = (sqrt(pow(w * (d + u) + h * (l + r), 2.0) + 4.0f * p * (d + u) * (l + r)) - w * (d + u) - h * (l + r)) / (2.0f * (d + u) * (l + r));
  731. pxRight = static_cast<int>(c * expandRight);
  732. pxLeft = static_cast<int>(c * expandLeft);
  733. pxDown = static_cast<int>(c * expandDown);
  734. pxUp = static_cast<int>(c * expandUp);
  735. }
  736. desiredRect.setX(desiredRect.x() - pxLeft);
  737. desiredRect.setWidth(desiredRect.width() + pxLeft + pxRight);
  738. desiredRect.setY(desiredRect.y() - pxUp);
  739. desiredRect.setHeight(desiredRect.height() + pxUp + pxDown);
  740. // If we have enough pixels left for another loop, ignore directions
  741. // that can't reasonably expand any further.
  742. if (desiredRect.right() >= maximumReasonableRect.right())
  743. expandRight = 0.0f;
  744. if (desiredRect.x() >= maximumReasonableRect.x())
  745. expandLeft = 0.0f;
  746. if (desiredRect.bottom() >= maximumReasonableRect.bottom())
  747. expandDown = 0.0f;
  748. if (desiredRect.y() >= maximumReasonableRect.y())
  749. expandUp = 0.0f;
  750. desiredRect.intersect(maximumReasonableRect);
  751. remainingNumberOfTilePixels =
  752. SurfacePool::globalSurfacePool()->numberOfBackingStoreFrontBuffers() * tileWidth() * tileHeight()
  753. - desiredRect.area();
  754. // If we don't have enough pixels left to expand the rectangle anymore,
  755. // just leave it and stick with the current one.
  756. if (previousRemainingNumberOfTilePixels == remainingNumberOfTilePixels)
  757. break;
  758. }
  759. return desiredRect;
  760. }
  761. void BackingStorePrivate::mergeDesiredBackingStoreRect(const Platform::IntRect& desiredRect, const Platform::IntRect& pixelViewportForDesiredRect)
  762. {
  763. double currentScale = m_webPage->d->currentScale();
  764. if (m_desiredBackingStoreRect.isEmpty() || m_desiredBackingStoreRectScale != currentScale)
  765. m_desiredBackingStoreRect = desiredRect;
  766. else {
  767. // Average out sudden spikes in scrolling deltas by taking half of the
  768. // previous desired rect's shape.
  769. Platform::IntRect previousRectAtCurrentLocation = m_desiredBackingStoreRect;
  770. previousRectAtCurrentLocation.move(
  771. -m_desiredBackingStoreRectViewportLocation.x() + pixelViewportForDesiredRect.x(),
  772. -m_desiredBackingStoreRectViewportLocation.y() + pixelViewportForDesiredRect.y());
  773. // Round up because we're more likely to scroll down and right, in general.
  774. Platform::IntPoint location(
  775. (desiredRect.x() + previousRectAtCurrentLocation.x() + 1) / 2,
  776. (desiredRect.y() + previousRectAtCurrentLocation.y() + 1) / 2);
  777. Platform::IntPoint bottomRight(
  778. (desiredRect.right() + previousRectAtCurrentLocation.right() + 1) / 2,
  779. (desiredRect.bottom() + previousRectAtCurrentLocation.bottom() + 1) / 2);
  780. m_desiredBackingStoreRect = Platform::IntRect(location,
  781. Platform::IntSize(bottomRight.x() - location.x(), bottomRight.y() - location.y()));
  782. }
  783. m_desiredBackingStoreRectScale = currentScale;
  784. m_desiredBackingStoreRectViewportLocation = pixelViewportForDesiredRect.location();
  785. }
  786. Platform::IntRect BackingStorePrivate::largestTileRectForDesiredRect(const Platform::IntRect& minimumRect, const Platform::IntRect& desiredRect)
  787. {
  788. // Store a static list of possible divisors.
  789. SurfacePool* surfacePool = SurfacePool::globalSurfacePool();
  790. ASSERT(!surfacePool->isEmpty());
  791. static DivisorList divisorList = divisors(surfacePool->numberOfBackingStoreFrontBuffers());
  792. const Platform::IntRect minimumTileRect = enclosingTileRect(minimumRect);
  793. const Divisor minimumTileRectDivisor(minimumTileRect.width() / tileWidth(), minimumTileRect.height() / tileHeight());
  794. Divisor bestRectDivisor;
  795. bool bestRectContainsMinimumRect = false;
  796. int bestRectArea = 0;
  797. int bestRectDistanceFromMinimumRect = 0;
  798. Platform::IntRect bestBackingStoreRect;
  799. for (size_t i = 0; i < divisorList.size(); ++i) {
  800. Divisor divisor = divisorList[i];
  801. int remainingTilesX = std::max(0, divisor.first - minimumTileRectDivisor.first);
  802. int remainingTilesY = std::max(0, divisor.second - minimumTileRectDivisor.second);
  803. Platform::IntSize divisorBackingStoreRectSize(divisor.first * tileWidth(), divisor.second * tileHeight());
  804. for (int dy = 0; dy <= remainingTilesY; ++dy) {
  805. for (int dx = 0; dx <= remainingTilesX; ++dx) {
  806. const Platform::IntRect possibleBackingStoreRect(
  807. Platform::IntPoint(minimumTileRect.x() - dx * tileWidth(), minimumTileRect.y() - dy * tileHeight()),
  808. divisorBackingStoreRectSize);
  809. Platform::IntRect relevantRect = possibleBackingStoreRect;
  810. relevantRect.intersect(desiredRect);
  811. int area = relevantRect.area();
  812. bool betterThanPreviousRect = false;
  813. bool containsMinimumRect = possibleBackingStoreRect.contains(minimumRect);
  814. int distanceFromMinimumRect = bestRectDistanceFromMinimumRect - 1;
  815. // Pick the best divisor based on the following criteria, in order of importance:
  816. // 1. Completely contains minimumTileRect.
  817. // 2. Covers the largest area within desiredRect.
  818. // 3. The closest border is farthest from the corresponding border of minimumRect.
  819. // 4. Random preference of rectangles in the following directions, in order: down, right, left, up.
  820. if (!bestRectArea) // bestBackingStoreRect is uninitialized
  821. betterThanPreviousRect = true;
  822. if (!bestRectContainsMinimumRect && containsMinimumRect)
  823. betterThanPreviousRect = true;
  824. if (bestRectContainsMinimumRect && area > bestRectArea)
  825. betterThanPreviousRect = true;
  826. if (bestRectContainsMinimumRect && area == bestRectArea) {
  827. // Left/up distance.
  828. distanceFromMinimumRect = std::min(
  829. minimumRect.x() - possibleBackingStoreRect.x(),
  830. minimumRect.y() - possibleBackingStoreRect.y());
  831. // Right/down distance.
  832. distanceFromMinimumRect = std::min(distanceFromMinimumRect, std::min(
  833. possibleBackingStoreRect.right() - minimumRect.right(),
  834. possibleBackingStoreRect.bottom() - minimumRect.bottom()));
  835. if (distanceFromMinimumRect > bestRectDistanceFromMinimumRect)
  836. betterThanPreviousRect = true;
  837. }
  838. if (bestRectContainsMinimumRect && area == bestRectArea && distanceFromMinimumRect == bestRectDistanceFromMinimumRect) {
  839. if (possibleBackingStoreRect.y() > bestBackingStoreRect.y())
  840. betterThanPreviousRect = true;
  841. else if (possibleBackingStoreRect.y() == bestBackingStoreRect.y() && possibleBackingStoreRect.x() > bestBackingStoreRect.x())
  842. betterThanPreviousRect = true;
  843. }
  844. #if DEBUG_TILEMATRIX
  845. Platform::logAlways(Platform::LogLevelCritical,
  846. "Desired rect %s: Potential rect %s (%dx%d) is %s than previous best rect %s (%dx%d). Area: %d vs. %d. Distance: %d vs. %d.",
  847. desiredRect.toString().c_str(),
  848. possibleBackingStoreRect.toString().c_str(),
  849. divisor.first, divisor.second,
  850. betterThanPreviousRect ? "better" : "worse",
  851. bestBackingStoreRect.toString().c_str(),
  852. bestRectDivisor.first, bestRectDivisor.second,
  853. area, bestRectArea,
  854. distanceFromMinimumRect, bestRectDistanceFromMinimumRect);
  855. #endif
  856. if (betterThanPreviousRect) {
  857. bestRectDivisor = divisor;
  858. bestRectContainsMinimumRect = containsMinimumRect;
  859. bestRectArea = area;
  860. bestRectDistanceFromMinimumRect = distanceFromMinimumRect;
  861. bestBackingStoreRect = possibleBackingStoreRect;
  862. }
  863. }
  864. }
  865. }
  866. return bestBackingStoreRect;
  867. }
  868. void BackingStorePrivate::scrollBackingStore(int deltaX, int deltaY)
  869. {
  870. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  871. if (!m_webPage->isVisible())
  872. return;
  873. if (!isActive()) {
  874. m_webPage->d->setShouldResetTilesWhenShown(true);
  875. return;
  876. }
  877. Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  878. Platform::IntRect pixelContentsRect = expandedContentsRect();
  879. Platform::IntRect nonOverscrolledPixelViewportRect = nonOverscrolled(viewportAccessor->pixelViewportRect(), pixelContentsRect);
  880. // Expand the minimal rect so that it includes the whole set of tiles covering that area.
  881. const Platform::IntRect maximumReasonableRect = enclosingTileRect(pixelContentsRect);
  882. Platform::IntRect desiredRect = desiredBackingStoreRect(nonOverscrolledPixelViewportRect, maximumReasonableRect, deltaX, deltaY);
  883. mergeDesiredBackingStoreRect(desiredRect, nonOverscrolledPixelViewportRect);
  884. const Platform::IntRect backingStoreRect = largestTileRectForDesiredRect(nonOverscrolledPixelViewportRect, m_desiredBackingStoreRect);
  885. #if DEBUG_TILEMATRIX
  886. Platform::logAlways(Platform::LogLevelCritical,
  887. "BackingStorePrivate::scrollBackingStore nonOverscrolledPixelViewportRect=%s, desiredRect=%s, pixelContentsRect=%s, maximumReasonableRect=%s, backingStoreRect=%s",
  888. nonOverscrolledPixelViewportRect.toString().c_str(),
  889. m_desiredBackingStoreRect.toString().c_str(),
  890. pixelContentsRect.toString().c_str(),
  891. maximumReasonableRect.toString().c_str(),
  892. backingStoreRect.toString().c_str());
  893. #endif
  894. ASSERT(!backingStoreRect.isEmpty());
  895. setBackingStoreRect(backingStoreRect, m_desiredBackingStoreRectScale);
  896. }
  897. TileIndexList BackingStorePrivate::render(const TileIndexList& tileIndexList)
  898. {
  899. if (!m_webPage->isVisible())
  900. return TileIndexList();
  901. requestLayoutIfNeeded();
  902. // If no tiles available for us to draw to, someone else has to render the root layer.
  903. if (!isActive())
  904. return TileIndexList();
  905. #if DEBUG_BACKINGSTORE
  906. Platform::logAlways(Platform::LogLevelInfo,
  907. "BackingStorePrivate::render %d tiles, m_suspendBackingStoreUpdates = %s",
  908. tileIndexList.size(),
  909. m_suspendBackingStoreUpdates ? "true" : "false");
  910. #endif
  911. ASSERT(!m_tileMatrixNeedsUpdate);
  912. if (tileIndexList.isEmpty())
  913. return tileIndexList;
  914. Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  915. BackingStoreGeometry* geometry = frontState();
  916. TileMap oldTileMap = geometry->tileMap();
  917. double currentScale = geometry->scale();
  918. BackingStoreGeometry* newGeometry = new BackingStoreGeometry;
  919. newGeometry->setScale(geometry->scale());
  920. newGeometry->setNumberOfTilesWide(geometry->numberOfTilesWide());
  921. newGeometry->setNumberOfTilesHigh(geometry->numberOfTilesHigh());
  922. newGeometry->setBackingStoreOffset(geometry->backingStoreOffset());
  923. TileMap newTileMap(oldTileMap); // copy a new, writable version
  924. TileIndexList renderedTiles;
  925. for (size_t i = 0; i < tileIndexList.size(); ++i) {
  926. if (!SurfacePool::globalSurfacePool()->numberOfAvailableBackBuffers()) {
  927. newGeometry->setTileMap(newTileMap);
  928. adoptAsFrontState(newGeometry); // this should get us at least one more.
  929. // newGeometry is now the front state and shouldn't be messed with.
  930. // Let's create a new one. (The old one will be automatically
  931. // destroyed by adoptAsFrontState() on being swapped out again.)
  932. geometry = frontState();
  933. newGeometry = new BackingStoreGeometry;
  934. newGeometry->setScale(geometry->scale());
  935. newGeometry->setNumberOfTilesWide(geometry->numberOfTilesWide());
  936. newGeometry->setNumberOfTilesHigh(geometry->numberOfTilesHigh());
  937. newGeometry->setBackingStoreOffset(geometry->backingStoreOffset());
  938. }
  939. TileIndex index = tileIndexList[i];
  940. Platform::IntPoint tileOrigin = newGeometry->originOfTile(index);
  941. Platform::IntRect dirtyRect(tileOrigin, tileSize());
  942. // Paint default background if contents rect is empty.
  943. if (!expandedContentsRect().isEmpty()) {
  944. // Otherwise we should clip the contents size and render the content.
  945. dirtyRect.intersect(expandedContentsRect());
  946. // We probably have extra tiles since the contents size is so small.
  947. // Save some cycles here...
  948. if (dirtyRect.isEmpty()) {
  949. #if DEBUG_BACKINGSTORE
  950. Platform::logAlways(Platform::LogLevelInfo,
  951. "BackingStorePrivate::render skipping tile at %s, it's outside the expanded contents rect of %s",
  952. newGeometry->originOfTile(index).toString().c_str(),
  953. expandedContentsRect().toString().c_str());
  954. #endif
  955. continue;
  956. }
  957. }
  958. TileBuffer* backBuffer = SurfacePool::globalSurfacePool()->takeBackBuffer();
  959. ASSERT(backBuffer);
  960. backBuffer->paintBackground();
  961. backBuffer->setLastRenderScale(currentScale);
  962. backBuffer->setLastRenderOrigin(tileOrigin);
  963. backBuffer->clearRenderedRegion();
  964. BlackBerry::Platform::Graphics::Buffer* nativeBuffer = backBuffer->nativeBuffer();
  965. BlackBerry::Platform::Graphics::setBufferOpaqueHint(nativeBuffer, !Color(m_webPage->settings()->backgroundColor()).hasAlpha());
  966. // TODO: This code is only needed for EGLImage code path, but preferrably BackingStore
  967. // should not know that, and the synchronization should be in BlackBerry::Platform::Graphics
  968. // if possible.
  969. if (isOpenGLCompositing())
  970. SurfacePool::globalSurfacePool()->waitForBuffer(backBuffer);
  971. const Platform::FloatPoint documentDirtyRectOrigin = viewportAccessor->toDocumentContents(dirtyRect.location(), currentScale);
  972. const Platform::IntRect dstRect(dirtyRect.location() - tileOrigin, dirtyRect.size());
  973. if (!renderContents(nativeBuffer, dstRect, currentScale, documentDirtyRectOrigin, RenderRootLayer))
  974. continue;
  975. // Add the newly rendered region to the tile so it can keep track for blits.
  976. backBuffer->addRenderedRegion(dirtyRect);
  977. renderedTiles.append(index);
  978. newTileMap.set(index, backBuffer);
  979. }
  980. // Let the render queue know that the tile contents are up to date now.
  981. m_renderQueue->clear(renderedTiles, frontState(), RenderQueue::DontClearCompletedJobs);
  982. // If we couldn't render all requested jobs, suspend blitting until we do.
  983. updateSuspendScreenUpdateState();
  984. newGeometry->setTileMap(newTileMap);
  985. adoptAsFrontState(newGeometry);
  986. #if DEBUG_BACKINGSTORE
  987. Platform::logAlways(Platform::LogLevelInfo,
  988. "BackingStorePrivate::render done rendering %d tiles.",
  989. renderedTiles.size());
  990. #endif
  991. return renderedTiles;
  992. }
  993. void BackingStorePrivate::requestLayoutIfNeeded() const
  994. {
  995. m_webPage->d->updateLayoutAndStyleIfNeededRecursive();
  996. }
  997. void BackingStorePrivate::renderAndBlitVisibleContentsImmediately()
  998. {
  999. renderAndBlitImmediately(visibleContentsRect());
  1000. }
  1001. void BackingStorePrivate::renderAndBlitImmediately(const Platform::IntRect& rect)
  1002. {
  1003. updateTileMatrixIfNeeded();
  1004. m_renderQueue->addToQueue(RenderQueue::VisibleZoom, rect);
  1005. renderJob();
  1006. }
  1007. void BackingStorePrivate::blitVisibleContents(bool force)
  1008. {
  1009. if (!BlackBerry::Platform::userInterfaceThreadMessageClient()->isCurrentThread()) {
  1010. BlackBerry::Platform::userInterfaceThreadMessageClient()->dispatchMessage(
  1011. BlackBerry::Platform::createMethodCallMessage(
  1012. &BackingStorePrivate::blitVisibleContents, this, force));
  1013. return;
  1014. }
  1015. if (m_suspendScreenUpdatesUserInterfaceThread) {
  1016. // Avoid client going into busy loop while blit is impossible.
  1017. if (force)
  1018. m_hasBlitJobs = false;
  1019. return;
  1020. }
  1021. if (!force) {
  1022. #if USE(ACCELERATED_COMPOSITING)
  1023. // If there's a WebPageCompositorClient, let it schedule the blit.
  1024. if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor()) {
  1025. if (WebPageCompositorClient* client = compositor->client()) {
  1026. client->invalidate(0);
  1027. return;
  1028. }
  1029. }
  1030. #endif
  1031. m_hasBlitJobs = true;
  1032. return;
  1033. }
  1034. m_hasBlitJobs = false;
  1035. Platform::ViewportAccessor* viewportAccessor = m_webPage->client()->userInterfaceViewportAccessor();
  1036. if (!viewportAccessor)
  1037. return;
  1038. const Platform::IntRect dstRect = viewportAccessor->destinationSurfaceRect();
  1039. if (dstRect.isEmpty())
  1040. return;
  1041. BlackBerry::Platform::PerformanceMonitor::instance()->reportFrameRenderBegin();
  1042. const Platform::IntRect pixelViewportRect = viewportAccessor->pixelViewportRect();
  1043. const Platform::FloatRect documentViewportRect = viewportAccessor->documentFromPixelContents(pixelViewportRect);
  1044. Platform::IntRect pixelSrcRect = pixelViewportRect;
  1045. Platform::FloatRect documentSrcRect = documentViewportRect;
  1046. #if DEBUG_VISUALIZE
  1047. // Substitute a srcRect that consists of the whole backingstore geometry
  1048. // instead of the normal viewport so we can visualize the entire
  1049. // backingstore and what it is doing when we scroll and zoom!
  1050. Platform::ViewportAccessor* debugViewportAccessor = new BackingStoreVisualizationViewportAccessor(viewportAccessor, this);
  1051. if (isActive()) {
  1052. viewportAccessor = debugViewportAccessor;
  1053. documentSrcRect = debugViewportAccessor->documentViewportRect();
  1054. pixelSrcRect = debugViewportAccessor->pixelViewportRect();
  1055. }
  1056. #endif
  1057. #if DEBUG_BACKINGSTORE
  1058. Platform::logAlways(Platform::LogLevelCritical,
  1059. "BackingStorePrivate::blitVisibleContents(): dstRect=%s, documentSrcRect=%s, scale=%f",
  1060. dstRect.toString().c_str(), documentSrcRect.toString().c_str(), viewportAccessor->scale());
  1061. #endif
  1062. BlackBerry::Platform::Graphics::Buffer* dstBuffer = buffer();
  1063. ASSERT(dstBuffer);
  1064. if (dstBuffer) {
  1065. // On the GPU, clearing is free and allows for optimizations,
  1066. // so we always want to do this first for the whole surface.
  1067. BlackBerry::Platform::Graphics::clearBuffer(dstBuffer,
  1068. m_webPageBackgroundColor.red(), m_webPageBackgroundColor.green(),
  1069. m_webPageBackgroundColor.blue(), m_webPageBackgroundColor.alpha());
  1070. } else
  1071. Platform::logAlways(Platform::LogLevelWarn, "Empty window buffer, can't blit contents.");
  1072. // Now go about actually compositing the contents.
  1073. Vector<TileBuffer*> blittedTiles;
  1074. if (isActive() && !m_webPage->d->compositorDrawsRootLayer()) {
  1075. BackingStoreGeometry* geometry = frontState();
  1076. TileMap currentMap = geometry->tileMap();
  1077. double currentScale = geometry->scale();
  1078. const Platform::IntRect transformedContentsRect = currentScale == viewportAccessor->scale()
  1079. ? viewportAccessor->pixelContentsRect()
  1080. : viewportAccessor->roundFromDocumentContents(viewportAccessor->documentContentsRect(), currentScale);
  1081. // For blitting backingstore tiles, we need the srcRect to be specified
  1082. // in backingstore tile pixel coordinates. If our viewport accessor is
  1083. // at a different scale, we calculate those coordinates by ourselves.
  1084. const Platform::IntRect transformedSrcRect = currentScale == viewportAccessor->scale()
  1085. ? pixelSrcRect
  1086. : viewportAccessor->roundFromDocumentContents(documentSrcRect, currentScale);
  1087. Platform::IntRect clippedTransformedSrcRect = transformedSrcRect;
  1088. const Platform::IntPoint origin = transformedSrcRect.location();
  1089. // FIXME: This should not explicitly depend on WebCore::.
  1090. TransformationMatrix transformation;
  1091. if (!transformedSrcRect.isEmpty())
  1092. transformation = TransformationMatrix::rectToRect(FloatRect(FloatPoint(0.0, 0.0), WebCore::IntSize(transformedSrcRect.size())), WebCore::IntRect(dstRect));
  1093. Platform::Graphics::PlatformGraphicsContext* destinationContext = lockBufferDrawable(dstBuffer);
  1094. if (!destinationContext)
  1095. Platform::logAlways(Platform::LogLevelWarn, "Could not lock drawable for the destination buffer, not drawing checkerboard.");
  1096. else {
  1097. // For public builds, keep page background color (as filled by
  1098. // clearBuffer() above) to convey the impression of less checkerboard.
  1099. if (!BlackBerry::Platform::Settings::isPublicBuild()) {
  1100. // For developer builds, keep the checkerboard to get it fixed better.
  1101. Platform::Graphics::AffineTransform srcTransform;
  1102. srcTransform.scale(transformation.a());
  1103. destinationContext->addPredefinedPattern(
  1104. viewportAccessor->pixelViewportFromContents(viewportAccessor->pixelContentsRect()),
  1105. Platform::Graphics::Checkerboard, srcTransform);
  1106. }
  1107. releaseBufferDrawable(dstBuffer);
  1108. }
  1109. // Get the list of tile rects that makeup the content.
  1110. TileRectList tileRectList = mapFromPixelContentsToTiles(clippedTransformedSrcRect, geometry);
  1111. for (size_t i = 0; i < tileRectList.size(); ++i) {
  1112. TileRect tileRect = tileRectList[i];
  1113. TileIndex index = tileRect.first;
  1114. Platform::IntRect dirtyRect = tileRect.second;
  1115. // Don't clip to contents if it is empty so we can still paint default background.
  1116. if (!transformedContentsRect.isEmpty()) {
  1117. // Otherwise we should clip the contents size and blit.
  1118. dirtyRect.intersect(transformedContentsRect);
  1119. }
  1120. // Save some cycles here...
  1121. if (dirtyRect.isEmpty())
  1122. continue;
  1123. // Now, this dirty rect is in transformed coordinates relative to the
  1124. // transformed contents, but ultimately it needs to be transformed
  1125. // coordinates relative to the viewport.
  1126. dirtyRect.move(-origin.x(), -origin.y());
  1127. TileBuffer* tileBuffer = currentMap.get(index);
  1128. if (geometry->isTileCorrespondingToBuffer(index, tileBuffer)) {
  1129. // Intersect the rendered region.
  1130. Platform::IntRectRegion renderedRegion = tileBuffer->renderedRegion();
  1131. std::vector<Platform::IntRect> dirtyRenderedRects = renderedRegion.rects();
  1132. for (size_t j = 0; j < dirtyRenderedRects.size(); ++j) {
  1133. const Platform::IntRect& dirtyRenderedRect = intersection(tileRect.second, dirtyRenderedRects.at(j));
  1134. if (dirtyRenderedRect.isEmpty())
  1135. continue;
  1136. // Blit the rendered parts.
  1137. blitTileRect(tileBuffer, dirtyRenderedRect, origin, transformation, geometry);
  1138. }
  1139. blittedTiles.append(tileBuffer);
  1140. }
  1141. }
  1142. }
  1143. // TODO: This code is only needed for EGLImage code path, but preferrably BackingStore
  1144. // should not know that, and the synchronization should be in BlackBerry::Platform::Graphics
  1145. // if possible.
  1146. if (isOpenGLCompositing())
  1147. SurfacePool::globalSurfacePool()->notifyBuffersComposited(blittedTiles);
  1148. #if USE(ACCELERATED_COMPOSITING)
  1149. if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
  1150. compositor->drawLayers(dstRect, documentSrcRect);
  1151. #endif
  1152. // Overlay an overscroll pattern (or color) for areas outside of the page contents.
  1153. const Platform::IntRect pixelContentsRect = viewportAccessor->pixelContentsRect();
  1154. Platform::IntRectRegion overScrollRegion = Platform::IntRectRegion::subtractRegions(
  1155. dstRect, viewportAccessor->pixelViewportFromContents(pixelContentsRect));
  1156. if (!overScrollRegion.isEmpty()) {
  1157. Platform::Graphics::PlatformGraphicsContext* destinationContext = lockBufferDrawable(dstBuffer);
  1158. if (!destinationContext)
  1159. Platform::logAlways(Platform::LogLevelWarn, "Could not lock drawable for the destination buffer, not drawing overscroll.");
  1160. else {
  1161. std::vector<Platform::IntRect> overScrollRects = overScrollRegion.rects();
  1162. for (size_t i = 0; i < overScrollRects.size(); ++i) {
  1163. const Platform::IntRect& overScrollRect = overScrollRects.at(i);
  1164. if (m_webPage->settings()->isEnableDefaultOverScrollBackground()) {
  1165. Platform::Graphics::AffineTransform srcTransform;
  1166. srcTransform.translate(-overScrollRect.x(), -overScrollRect.y());
  1167. destinationContext->addPredefinedPattern(overScrollRect, Platform::Graphics::Overscroll, srcTransform);
  1168. } else {
  1169. destinationContext->setFillColor(m_webPage->settings()->overScrollColor());
  1170. destinationContext->addFillRect(overScrollRect);
  1171. }
  1172. }
  1173. releaseBufferDrawable(dstBuffer);
  1174. }
  1175. }
  1176. #if DEBUG_VISUALIZE
  1177. if (debugViewportAccessor) {
  1178. Platform::Graphics::PlatformGraphicsContext* destinationContext = lockBufferDrawable(dstBuffer);
  1179. if (!destinationContext)
  1180. Platform::logAlways(Platform::LogLevelWarn, "Could not lock drawable for the destination buffer, not drawing viewport debug rects.");
  1181. else {
  1182. destinationContext->save();
  1183. Platform::FloatRect wkViewport = debugViewportAccessor->roundToPixelFromDocumentContents(Platform::IntRect(m_client->visibleContentsRect()));
  1184. Platform::FloatRect uiViewport = debugViewportAccessor->roundToPixelFromDocumentContents(documentViewportRect);
  1185. wkViewport.move(-pixelSrcRect.x(), -pixelSrcRect.y());
  1186. uiViewport.move(-pixelSrcRect.x(), -pixelSrcRect.y());
  1187. // Shrink by half a pixel to make pixel-perfect stroke rectangles.
  1188. wkViewport.inflate(-0.5, -0.5);
  1189. uiViewport.inflate(-0.5, -0.5);
  1190. // Draw a blue rect for the webkit thread viewport.
  1191. destinationContext->setStrokeColor(0xff0000ff);
  1192. destinationContext->addStrokeRect(wkViewport, 1.0);
  1193. // Draw a red rect for the ui thread viewport.
  1194. destinationContext->setStrokeColor(0x0000ffff);
  1195. destinationContext->addStrokeRect(uiViewport, 1.0);
  1196. destinationContext->restore();
  1197. releaseBufferDrawable(dstBuffer);
  1198. }
  1199. delete debugViewportAccessor;
  1200. }
  1201. #endif
  1202. m_webPage->client()->postToSurface(dstRect);
  1203. BlackBerry::Platform::PerformanceMonitor::instance()->reportFrameRenderEnd(true /*didRender*/);
  1204. }
  1205. #if USE(ACCELERATED_COMPOSITING)
  1206. void BackingStorePrivate::compositeContents(WebCore::LayerRenderer* layerRenderer, const WebCore::TransformationMatrix& transform, const WebCore::FloatRect& documentContents, bool contentsOpaque)
  1207. {
  1208. Platform::ViewportAccessor* viewportAccessor = m_webPage->client()->userInterfaceViewportAccessor();
  1209. if (!viewportAccessor)
  1210. return;
  1211. Platform::IntRect pixelContents = viewportAccessor->roundToPixelFromDocumentContents(documentContents);
  1212. pixelContents.intersect(viewportAccessor->pixelContentsRect());
  1213. if (pixelContents.isEmpty())
  1214. return;
  1215. if (!isActive())
  1216. return;
  1217. if (m_webPage->d->compositorDrawsRootLayer())
  1218. return;
  1219. BackingStoreGeometry* geometry = frontState();
  1220. TileMap currentMap = geometry->tileMap();
  1221. Vector<TileBuffer*> compositedTiles;
  1222. Platform::IntRectRegion pixelContentsRegion = pixelContents;
  1223. Platform::IntRectRegion backingStoreRegion = geometry->backingStoreRect();
  1224. Platform::IntRectRegion clearRegion = Platform::IntRectRegion::subtractRegions(pixelContentsRegion, backingStoreRegion);
  1225. // Clear those parts that are not covered by the backingStoreRect.
  1226. Color clearColor(Color::white);
  1227. std::vector<Platform::IntRect> clearRects = clearRegion.rects();
  1228. for (size_t i = 0; i < clearRects.size(); ++i)
  1229. layerRenderer->drawColor(transform, viewportAccessor->documentFromPixelContents(clearRects.at(i)), clearColor);
  1230. // Get the list of tile rects that makeup the content.
  1231. TileRectList tileRectList = mapFromPixelContentsToTiles(pixelContents, geometry);
  1232. for (size_t i = 0; i < tileRectList.size(); ++i) {
  1233. TileRect tileRect = tileRectList[i];
  1234. TileIndex index = tileRect.first;
  1235. Platform::IntRect dirtyRect = tileRect.second;
  1236. TileBuffer* tileBuffer = currentMap.get(index);
  1237. if (!tileBuffer || !geometry->isTileCorrespondingToBuffer(index, tileBuffer))
  1238. layerRenderer->drawColor(transform, viewportAccessor->documentFromPixelContents(dirtyRect), clearColor);
  1239. else {
  1240. Platform::IntPoint tileOrigin = tileBuffer->lastRenderOrigin();
  1241. Platform::FloatRect tileDocumentContentsRect = viewportAccessor->documentFromPixelContents(tileBuffer->pixelContentsRect());
  1242. layerRenderer->compositeBuffer(transform, tileDocumentContentsRect, tileBuffer->nativeBuffer(), contentsOpaque, 1.0f);
  1243. compositedTiles.append(tileBuffer);
  1244. // Intersect the rendered region and clear unrendered parts.
  1245. Platform::IntRectRegion notRenderedRegion = Platform::IntRectRegion::subtractRegions(dirtyRect, tileBuffer->renderedRegion());
  1246. std::vector<Platform::IntRect> notRenderedRects = notRenderedRegion.rects();
  1247. for (size_t i = 0; i < notRenderedRects.size(); ++i) {
  1248. Platform::IntRect tileSurfaceRect = notRenderedRects.at(i);
  1249. tileSurfaceRect.move(-tileOrigin.x(), -tileOrigin.y());
  1250. layerRenderer->drawColor(transform, viewportAccessor->documentFromPixelContents(tileSurfaceRect), clearColor);
  1251. }
  1252. }
  1253. }
  1254. SurfacePool::globalSurfacePool()->notifyBuffersComposited(compositedTiles);
  1255. }
  1256. #endif
  1257. Platform::IntRect BackingStorePrivate::blitTileRect(TileBuffer* tileBuffer,
  1258. const Platform::IntRect& tilePixelContentsRect,
  1259. const Platform::IntPoint& origin,
  1260. const WebCore::TransformationMatrix& matrix,
  1261. BackingStoreGeometry*)
  1262. {
  1263. if (!m_webPage->isVisible() || !isActive() || !tileBuffer)
  1264. return Platform::IntRect();
  1265. Platform::IntRect srcRect = tilePixelContentsRect;
  1266. Platform::IntPoint tileOrigin = tileBuffer->lastRenderOrigin();
  1267. srcRect.move(-tileOrigin.x(), -tileOrigin.y());
  1268. // Now, this dirty rect is in transformed coordinates relative to the
  1269. // transformed contents, but ultimately it needs to be transformed
  1270. // coordinates relative to the viewport.
  1271. Platform::IntRect dstRect = tilePixelContentsRect;
  1272. dstRect.move(-origin.x(), -origin.y());
  1273. dstRect = matrix.mapRect(dstRect);
  1274. if (!matrix.isIdentity()) {
  1275. // Because of rounding it is possible that dstRect could be off-by-one larger
  1276. // than the surface size of the dst buffer. We prevent this here, by clamping
  1277. // it to ensure that can't happen.
  1278. dstRect.intersect(Platform::IntRect(Platform::IntPoint(0, 0), surfaceSize()));
  1279. }
  1280. ASSERT(!dstRect.isEmpty());
  1281. ASSERT(!srcRect.isEmpty());
  1282. if (dstRect.isEmpty() || srcRect.isEmpty())
  1283. return Platform::IntRect();
  1284. blitToWindow(dstRect, tileBuffer->nativeBuffer(), srcRect, BlackBerry::Platform::Graphics::SourceCopy, 255);
  1285. return dstRect;
  1286. }
  1287. bool BackingStorePrivate::isTileVisible(const TileIndex& index, BackingStoreGeometry* geometry) const
  1288. {
  1289. return isTileVisible(geometry->originOfTile(index));
  1290. }
  1291. bool BackingStorePrivate::isTileVisible(const Platform::IntPoint& origin) const
  1292. {
  1293. return Platform::IntRect(origin, tileSize()).intersects(visibleContentsRect());
  1294. }
  1295. TileIndexList BackingStorePrivate::visibleTileIndexes(BackingStoreGeometry* geometry) const
  1296. {
  1297. TileMap tileMap = geometry->tileMap();
  1298. TileIndexList visibleTiles;
  1299. TileMap::const_iterator end = tileMap.end();
  1300. for (TileMap::const_iterator it = tileMap.begin(); it != end; ++it) {
  1301. Platform::IntRect tilePixelContentsRect(geometry->originOfTile(it->key), tileSize());
  1302. if (tilePixelContentsRect.intersects(visibleContentsRect()))
  1303. visibleTiles.append(it->key);
  1304. }
  1305. return visibleTiles;
  1306. }
  1307. Platform::IntRect BackingStorePrivate::tileVisibleContentsRect(const TileIndex& index, BackingStoreGeometry* geometry) const
  1308. {
  1309. if (!isTileVisible(index, geometry))
  1310. return Platform::IntRect();
  1311. return tileContentsRect(index, visibleContentsRect(), geometry);
  1312. }
  1313. Platform::IntRect BackingStorePrivate::tileContentsRect(const TileIndex& index, const Platform::IntRect& pixelContentsRect, BackingStoreGeometry* state) const
  1314. {
  1315. TileRectList tileRectList = mapFromPixelContentsToTiles(pixelContentsRect, state);
  1316. for (size_t i = 0; i < tileRectList.size(); ++i) {
  1317. TileRect tileRect = tileRectList[i];
  1318. if (index == tileRect.first)
  1319. return tileRect.second;
  1320. }
  1321. return Platform::IntRect();
  1322. }
  1323. void BackingStorePrivate::resetRenderQueue()
  1324. {
  1325. m_renderQueue->reset();
  1326. }
  1327. void BackingStorePrivate::resetTiles()
  1328. {
  1329. BackingStoreGeometry* geometry = frontState();
  1330. m_renderQueue->clear(geometry->backingStoreRect(), RenderQueue::ClearAnyJobs);
  1331. BackingStoreGeometry* newGeometry = new BackingStoreGeometry;
  1332. newGeometry->setScale(geometry->scale());
  1333. newGeometry->setNumberOfTilesWide(geometry->numberOfTilesWide());
  1334. newGeometry->setNumberOfTilesHigh(geometry->numberOfTilesHigh());
  1335. newGeometry->setBackingStoreOffset(geometry->backingStoreOffset());
  1336. TileMap currentMap = geometry->tileMap();
  1337. TileMap newTileMap;
  1338. TileMap::const_iterator end = currentMap.end();
  1339. for (TileMap::const_iterator it = currentMap.begin(); it != end; ++it)
  1340. newTileMap.add(it->key, 0); // clear all buffer info from the tile
  1341. newGeometry->setTileMap(newTileMap);
  1342. adoptAsFrontState(newGeometry); // swap into UI thread
  1343. }
  1344. void BackingStorePrivate::updateTiles(bool updateVisible, bool immediate)
  1345. {
  1346. if (!isActive())
  1347. return;
  1348. BackingStoreGeometry* geometry = frontState();
  1349. TileMap currentMap = geometry->tileMap();
  1350. TileMap::const_iterator end = currentMap.end();
  1351. for (TileMap::const_iterator it = currentMap.begin(); it != end; ++it) {
  1352. bool isVisible = isTileVisible(it->key, geometry);
  1353. if (!updateVisible && isVisible)
  1354. continue;
  1355. updateTile(geometry->originOfTile(it->key), immediate);
  1356. }
  1357. }
  1358. void BackingStorePrivate::updateTilesForScrollOrNotRenderedRegion(bool checkLoading)
  1359. {
  1360. // This method looks at all the tiles and if they are visible, but not completely
  1361. // rendered or we are loading, then it updates them. For all tiles, visible and
  1362. // non-visible, if a previous attempt was made to render them during a regular
  1363. // render job, but they were not visible at the time, then update them and if
  1364. // they are currently visible, reset them.
  1365. BackingStoreGeometry* geometry = frontState();
  1366. TileMap currentMap = geometry->tileMap();
  1367. bool isLoading = m_client->loadState() == WebPagePrivate::Committed;
  1368. bool updateNonVisibleTiles = !checkLoading || !isLoading;
  1369. TileMap::const_iterator end = currentMap.end();
  1370. for (TileMap::const_iterator it = currentMap.begin(); it != end; ++it) {
  1371. TileIndex index = it->key;
  1372. TileBuffer* tileBuffer = it->value;
  1373. bool isVisible = isTileVisible(index, geometry);
  1374. Platform::IntPoint tileOrigin = geometry->originOfTile(index);
  1375. // The rect in transformed contents coordinates.
  1376. Platform::IntRect rect(tileOrigin, tileSize());
  1377. if (geometry->isTileCorrespondingToBuffer(index, tileBuffer)
  1378. && m_renderQueue->regularRenderJobsPreviouslyAttemptedButNotRendered(rect)) {
  1379. // If the render queue previously tried to render this tile, but the
  1380. // tile wasn't visible at the time we can't simply restore the tile
  1381. // since the content is now invalid as far as WebKit is concerned.
  1382. // Instead, we clear that part of the tile if it is visible and then
  1383. // put the tile in the render queue again.
  1384. if (isVisible) {
  1385. // Intersect the tile with the not rendered region to get the areas
  1386. // of the tile that we need to clear.
  1387. Platform::IntRectRegion tileNotRenderedRegion = Platform::IntRectRegion::intersectRegions(m_renderQueue->regularRenderJobsNotRenderedRegion(), rect);
  1388. clearAndUpdateTileOfNotRenderedRegion(index, tileBuffer, tileNotRenderedRegion, geometry, false /*update*/);
  1389. #if DEBUG_BACKINGSTORE
  1390. Platform::logAlways(Platform::LogLevelCritical,
  1391. "BackingStorePrivate::updateTilesForScroll did clear tile %s",
  1392. tileNotRenderedRegion.extents().toString().c_str());
  1393. #endif
  1394. }
  1395. updateTile(tileOrigin, false /*immediate*/);
  1396. } else if ((isVisible || updateNonVisibleTiles)
  1397. && (!tileBuffer || !tileBuffer->isRendered(tileVisibleContentsRect(index, geometry), geometry->scale()))
  1398. && !isCurrentVisibleJob(index, geometry))
  1399. updateTile(tileOrigin, false /*immediate*/);
  1400. }
  1401. }
  1402. void BackingStorePrivate::updateTile(const Platform::IntPoint& origin, bool immediate)
  1403. {
  1404. if (!isActive())
  1405. return;
  1406. Platform::IntRect updateRect = Platform::IntRect(origin, tileSize());
  1407. if (immediate)
  1408. renderAndBlitImmediately(updateRect);
  1409. else {
  1410. RenderQueue::JobType jobType = isTileVisible(origin) ? RenderQueue::VisibleScroll : RenderQueue::NonVisibleScroll;
  1411. m_renderQueue->addToQueue(jobType, updateRect);
  1412. }
  1413. }
  1414. BackingStorePrivate::TileRectList BackingStorePrivate::mapFromPixelContentsToTiles(const Platform::IntRect& rect, BackingStoreGeometry* geometry) const
  1415. {
  1416. TileMap tileMap = geometry->tileMap();
  1417. TileRectList tileRectList;
  1418. TileMap::const_iterator end = tileMap.end();
  1419. for (TileMap::const_iterator it = tileMap.begin(); it != end; ++it) {
  1420. TileIndex index = it->key;
  1421. // Need to map the rect to tile coordinates.
  1422. Platform::IntRect r = rect;
  1423. // Do we intersect the current tile or no?
  1424. r.intersect(Platform::IntRect(geometry->originOfTile(index), tileSize()));
  1425. if (r.isEmpty())
  1426. continue;
  1427. // If we do append to list and Voila!
  1428. TileRect tileRect;
  1429. tileRect.first = index;
  1430. tileRect.second = r;
  1431. tileRectList.append(tileRect);
  1432. }
  1433. return tileRectList;
  1434. }
  1435. void BackingStorePrivate::updateTileMatrixIfNeeded()
  1436. {
  1437. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  1438. if (!m_tileMatrixNeedsUpdate)
  1439. return;
  1440. m_tileMatrixNeedsUpdate = false;
  1441. // This will update the tile matrix.
  1442. scrollBackingStore(0, 0);
  1443. }
  1444. void BackingStorePrivate::contentsSizeChanged(const Platform::IntSize&)
  1445. {
  1446. setTileMatrixNeedsUpdate();
  1447. updateTileMatrixIfNeeded();
  1448. }
  1449. void BackingStorePrivate::scrollChanged(const Platform::IntPoint&)
  1450. {
  1451. // FIXME: Need to do anything here?
  1452. }
  1453. void BackingStorePrivate::transformChanged()
  1454. {
  1455. if (!m_webPage->isVisible())
  1456. return;
  1457. m_renderQueue->reset();
  1458. if (!isActive()) {
  1459. m_webPage->d->setShouldResetTilesWhenShown(true);
  1460. return;
  1461. }
  1462. resetTiles();
  1463. }
  1464. void BackingStorePrivate::orientationChanged()
  1465. {
  1466. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  1467. setTileMatrixNeedsUpdate();
  1468. updateTileMatrixIfNeeded();
  1469. }
  1470. void BackingStorePrivate::actualVisibleSizeChanged(const Platform::IntSize&)
  1471. {
  1472. }
  1473. void BackingStorePrivate::createSurfaces()
  1474. {
  1475. BackingStoreGeometry* geometry = frontState();
  1476. TileMap initialMap = geometry->tileMap();
  1477. ASSERT(initialMap.isEmpty());
  1478. if (m_webPage->isVisible()) {
  1479. // This method is only to be called as part of setting up a new web page instance and
  1480. // before said instance is made visible so as to ensure a consistent definition of web
  1481. // page visibility. That is, a web page is said to be visible when explicitly made visible.
  1482. ASSERT_NOT_REACHED();
  1483. return;
  1484. }
  1485. // Initialize (initially, probably suspend) screen updates based on various
  1486. // conditions, including whether or not we have a drawing target buffer.
  1487. updateSuspendScreenUpdateState();
  1488. SurfacePool* surfacePool = SurfacePool::globalSurfacePool();
  1489. surfacePool->initialize(tileSize());
  1490. if (surfacePool->isEmpty()) // Settings specify 0 tiles / no backing store.
  1491. return;
  1492. // Pick a random divisor to initialize the tile map.
  1493. DivisorList divisorList = divisors(surfacePool->numberOfBackingStoreFrontBuffers());
  1494. const Divisor divisor = divisorList[0];
  1495. int numberOfTilesWide = divisor.first;
  1496. int numberOfTilesHigh = divisor.second;
  1497. TileMap newTileMap;
  1498. for (int y = 0; y < numberOfTilesHigh; ++y) {
  1499. for (int x = 0; x < numberOfTilesWide; ++x) {
  1500. TileIndex index(x, y);
  1501. newTileMap.add(index, 0); // no buffers initially assigned.
  1502. }
  1503. }
  1504. // Set the initial state of the backingstore geometry.
  1505. BackingStoreGeometry* newGeometry = new BackingStoreGeometry;
  1506. newGeometry->setScale(m_webPage->d->currentScale());
  1507. newGeometry->setNumberOfTilesWide(divisor.first);
  1508. newGeometry->setNumberOfTilesHigh(divisor.second);
  1509. newGeometry->setTileMap(newTileMap);
  1510. adoptAsFrontState(newGeometry); // swap into UI thread
  1511. }
  1512. Platform::IntPoint BackingStoreGeometry::originOfTile(const TileIndex& index) const
  1513. {
  1514. return Platform::IntPoint(backingStoreRect().x() + (index.i() * BackingStorePrivate::tileWidth()),
  1515. backingStoreRect().y() + (index.j() * BackingStorePrivate::tileHeight()));
  1516. }
  1517. int BackingStorePrivate::tileWidth()
  1518. {
  1519. return tileSize().width();
  1520. }
  1521. int BackingStorePrivate::tileHeight()
  1522. {
  1523. return tileSize().height();
  1524. }
  1525. Platform::IntSize BackingStorePrivate::tileSize()
  1526. {
  1527. static Platform::IntSize tileSize = Platform::Settings::instance()->tileSize();
  1528. return tileSize;
  1529. }
  1530. bool BackingStorePrivate::renderContents(BlackBerry::Platform::Graphics::Buffer* targetBuffer, const Platform::IntRect& dstRect, double scale, const Platform::FloatPoint& documentRenderOrigin, LayersToRender layersToRender) const
  1531. {
  1532. #if DEBUG_BACKINGSTORE
  1533. Platform::logAlways(Platform::LogLevelCritical,
  1534. "BackingStorePrivate::renderContents targetBuffer=0x%p dstRect=%s scale=%f documentRenderOrigin=%s",
  1535. targetBuffer, dstRect.toString().c_str(), scale, documentRenderOrigin.toString().c_str());
  1536. #endif
  1537. // It is up to callers of this method to perform layout themselves!
  1538. ASSERT(!m_webPage->d->mainFrame()->view()->needsLayout());
  1539. ASSERT(targetBuffer);
  1540. Platform::ViewportAccessor* viewportAccessor = m_webPage->webkitThreadViewportAccessor();
  1541. WebCore::FloatRect renderedFloatRect(documentRenderOrigin, viewportAccessor->toDocumentContents(dstRect.size(), scale));
  1542. WebCore::IntRect contentsRect(WebCore::IntPoint::zero(), m_client->contentsSize());
  1543. Color backgroundColor(m_webPage->settings()->backgroundColor());
  1544. if (contentsRect.isEmpty()
  1545. || backgroundColor.hasAlpha()
  1546. || !WebCore::FloatRect(contentsRect).contains(renderedFloatRect)) {
  1547. // Clear the area if it's not fully covered by (opaque) contents.
  1548. BlackBerry::Platform::Graphics::clearBuffer(targetBuffer, dstRect,
  1549. backgroundColor.red(), backgroundColor.green(),
  1550. backgroundColor.blue(), backgroundColor.alpha());
  1551. }
  1552. if (contentsRect.isEmpty())
  1553. return true;
  1554. Platform::Graphics::Drawable* bufferDrawable = Platform::Graphics::lockBufferDrawable(targetBuffer);
  1555. Platform::Graphics::Buffer* drawingBuffer = 0;
  1556. if (bufferDrawable)
  1557. drawingBuffer = targetBuffer;
  1558. else {
  1559. BBLOG(Platform::LogLevelWarn, "Using temporary buffer to paint contents, look into avoiding this.");
  1560. drawingBuffer = Platform::Graphics::createBuffer(dstRect.size(), Platform::Graphics::BackedWhenNecessary);
  1561. if (!drawingBuffer) {
  1562. Platform::logAlways(Platform::LogLevelWarn, "Could not create temporary buffer, expect bad things to happen.");
  1563. return false;
  1564. }
  1565. bufferDrawable = Platform::Graphics::lockBufferDrawable(drawingBuffer);
  1566. if (!bufferDrawable) {
  1567. Platform::logAlways(Platform::LogLevelWarn, "Could not lock temporary buffer drawable, expect bad things to happen.");
  1568. Platform::Graphics::destroyBuffer(drawingBuffer);
  1569. return false;
  1570. }
  1571. }
  1572. PlatformGraphicsContext* platformGraphicsContext = SurfacePool::globalSurfacePool()->createPlatformGraphicsContext(bufferDrawable);
  1573. ASSERT(platformGraphicsContext);
  1574. {
  1575. GraphicsContext graphicsContext(platformGraphicsContext);
  1576. // Clip the output to the destination pixels.
  1577. graphicsContext.save();
  1578. graphicsContext.clip(dstRect);
  1579. // Translate context according to offset.
  1580. if (targetBuffer == drawingBuffer)
  1581. graphicsContext.translate(-dstRect.x(), -dstRect.y());
  1582. // Add our transformation matrix as the global transform.
  1583. graphicsContext.scale(WebCore::FloatSize(scale, scale));
  1584. graphicsContext.translate(-documentRenderOrigin.x(), -documentRenderOrigin.y());
  1585. // Make sure the rectangle for the rendered rectangle is within the
  1586. // bounds of the page.
  1587. WebCore::IntRect renderedRect = enclosingIntRect(renderedFloatRect);
  1588. renderedRect.intersect(contentsRect);
  1589. // Take care of possible left overflow on RTL page.
  1590. if (int leftOverFlow = m_client->frame()->view()->minimumScrollPosition().x()) {
  1591. renderedRect.move(leftOverFlow, 0);
  1592. graphicsContext.translate(-leftOverFlow, 0);
  1593. }
  1594. // Let WebCore render the page contents into the drawing surface.
  1595. if (layersToRender == RenderRootLayer)
  1596. m_client->frame()->view()->paintContents(&graphicsContext, renderedRect);
  1597. else
  1598. m_client->frame()->view()->paintContentsForSnapshot(&graphicsContext, renderedRect, FrameView::ExcludeSelection, FrameView::DocumentCoordinates);
  1599. graphicsContext.restore();
  1600. }
  1601. SurfacePool::globalSurfacePool()->destroyPlatformGraphicsContext(platformGraphicsContext);
  1602. Platform::Graphics::releaseBufferDrawable(drawingBuffer);
  1603. if (targetBuffer != drawingBuffer) {
  1604. // If we couldn't directly draw to the buffer, copy from the drawing surface.
  1605. const Platform::IntRect srcRect(Platform::IntPoint::zero(), dstRect.size());
  1606. Platform::Graphics::blitToBuffer(targetBuffer, dstRect, drawingBuffer, srcRect);
  1607. Platform::Graphics::destroyBuffer(drawingBuffer);
  1608. }
  1609. return true;
  1610. }
  1611. #if DEBUG_FAT_FINGERS
  1612. static void drawDebugRect(BlackBerry::Platform::Graphics::Buffer* dstBuffer, const Platform::IntRect& dstRect, const Platform::IntRect& srcRect, unsigned char red, unsigned char green, unsigned char blue)
  1613. {
  1614. Platform::IntRect drawRect(srcRect);
  1615. drawRect.intersect(dstRect);
  1616. if (!drawRect.isEmpty())
  1617. BlackBerry::Platform::Graphics::clearBuffer(dstBuffer, drawRect, red, green, blue, 128);
  1618. }
  1619. #endif
  1620. void BackingStorePrivate::blitToWindow(const Platform::IntRect& dstRect,
  1621. const Platform::Graphics::Buffer* srcBuffer,
  1622. const Platform::IntRect& srcRect,
  1623. Platform::Graphics::BlendMode blendMode,
  1624. unsigned char globalAlpha)
  1625. {
  1626. ASSERT(BlackBerry::Platform::userInterfaceThreadMessageClient()->isCurrentThread());
  1627. BlackBerry::Platform::Graphics::Buffer* dstBuffer = buffer();
  1628. ASSERT(dstBuffer);
  1629. ASSERT(srcBuffer);
  1630. if (!dstBuffer)
  1631. Platform::logAlways(Platform::LogLevelWarn, "Empty window buffer, couldn't blitToWindow");
  1632. BlackBerry::Platform::Graphics::blitToBuffer(dstBuffer, dstRect, srcBuffer, srcRect, blendMode, globalAlpha);
  1633. #if DEBUG_FAT_FINGERS
  1634. drawDebugRect(dstBuffer, dstRect, FatFingers::m_debugFatFingerRect, 210, 210, 250);
  1635. drawDebugRect(dstBuffer, dstRect, Platform::IntRect(FatFingers::m_debugFatFingerClickPosition, Platform::IntSize(3, 3)), 0, 0, 0);
  1636. drawDebugRect(dstBuffer, dstRect, Platform::IntRect(FatFingers::m_debugFatFingerAdjustedPosition, Platform::IntSize(5, 5)), 100, 100, 100);
  1637. #endif
  1638. }
  1639. WebCore::Color BackingStorePrivate::webPageBackgroundColorUserInterfaceThread() const
  1640. {
  1641. ASSERT(BlackBerry::Platform::userInterfaceThreadMessageClient()->isCurrentThread());
  1642. return m_webPageBackgroundColor;
  1643. }
  1644. void BackingStorePrivate::setWebPageBackgroundColor(const WebCore::Color& color)
  1645. {
  1646. if (!BlackBerry::Platform::userInterfaceThreadMessageClient()->isCurrentThread()) {
  1647. typedef void (BlackBerry::WebKit::BackingStorePrivate::*FunctionType)(const WebCore::Color&);
  1648. BlackBerry::Platform::userInterfaceThreadMessageClient()->dispatchMessage(
  1649. BlackBerry::Platform::createMethodCallMessage<FunctionType, BackingStorePrivate, WebCore::Color>(
  1650. &BackingStorePrivate::setWebPageBackgroundColor, this, color));
  1651. return;
  1652. }
  1653. m_webPageBackgroundColor = color;
  1654. }
  1655. bool BackingStorePrivate::isScrollingOrZooming() const
  1656. {
  1657. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  1658. return m_isScrollingOrZooming;
  1659. }
  1660. void BackingStorePrivate::setScrollingOrZooming(bool scrollingOrZooming, bool shouldBlit)
  1661. {
  1662. ASSERT(BlackBerry::Platform::webKitThreadMessageClient()->isCurrentThread());
  1663. if (m_isScrollingOrZooming == scrollingOrZooming)
  1664. return;
  1665. m_isScrollingOrZooming = scrollingOrZooming;
  1666. #if !ENABLE_REPAINTONSCROLL
  1667. m_suspendRenderJobs = scrollingOrZooming; // Suspend the rendering of everything.
  1668. #endif
  1669. if (!m_webPage->settings()->shouldRenderAnimationsOnScrollOrZoom())
  1670. m_suspendRegularRenderJobs = scrollingOrZooming; // Suspend the rendering of animations.
  1671. m_webPage->d->m_mainFrame->view()->setConstrainsScrollingToContentEdge(!scrollingOrZooming);
  1672. // Clear this flag since we don't care if the render queue is under pressure
  1673. // or not since we are scrolling and it is more important to not lag than
  1674. // it is to ensure animations achieve better framerates!
  1675. if (scrollingOrZooming)
  1676. m_renderQueue->setCurrentRegularRenderJobBatchUnderPressure(false);
  1677. #if ENABLE_SCROLLBARS
  1678. else if (shouldBlit)
  1679. blitVisibleContents();
  1680. #endif
  1681. if (!scrollingOrZooming && shouldPerformRegularRenderJobs())
  1682. dispatchRenderJob();
  1683. }
  1684. BackingStoreGeometry* BackingStorePrivate::frontState() const
  1685. {
  1686. return reinterpret_cast<BackingStoreGeometry*>(m_frontState);
  1687. }
  1688. void BackingStorePrivate::adoptAsFrontState(BackingStoreGeometry* newFrontState)
  1689. {
  1690. bool hasValidBuffers = false;
  1691. // Remember the buffers we'll use in the new front state for comparison.
  1692. WTF::Vector<TileBuffer*> newTileBuffers;
  1693. TileMap newTileMap = newFrontState->tileMap();
  1694. TileMap::const_iterator end = newTileMap.end();
  1695. for (TileMap::const_iterator it = newTileMap.begin(); it != end; ++it) {
  1696. if (it->value) {
  1697. hasValidBuffers = true;
  1698. newTileBuffers.append(it->value);
  1699. }
  1700. }
  1701. if (!hasValidBuffers) {
  1702. m_tileMatrixContainsUsefulContent = false;
  1703. updateSuspendScreenUpdateState();
  1704. }
  1705. unsigned newFront = reinterpret_cast<unsigned>(newFrontState);
  1706. BackingStoreGeometry* oldFrontState = frontState();
  1707. // Atomic change.
  1708. _smp_xchg(&m_frontState, newFront);
  1709. bool hasSynced = false;
  1710. if (hasValidBuffers) {
  1711. m_tileMatrixContainsUsefulContent = true;
  1712. updateSuspendScreenUpdateState(&hasSynced);
  1713. }
  1714. if (!hasSynced) {
  1715. // Wait until the user interface thread won't access the old front state anymore.
  1716. BlackBerry::Platform::userInterfaceThreadMessageClient()->syncToCurrentMessage();
  1717. }
  1718. // Reclaim unused old tile buffers as back buffers.
  1719. TileMap oldTileMap = oldFrontState->tileMap();
  1720. end = oldTileMap.end();
  1721. for (TileMap::const_iterator it = oldTileMap.begin(); it != end; ++it) {
  1722. TileBuffer* tileBuffer = it->value;
  1723. if (tileBuffer && !newTileBuffers.contains(tileBuffer))
  1724. SurfacePool::globalSurfacePool()->addBackBuffer(tileBuffer);
  1725. }
  1726. delete oldFrontState;
  1727. }
  1728. // static
  1729. void BackingStorePrivate::setCurrentBackingStoreOwner(WebPage* webPage)
  1730. {
  1731. // Let the previously active backingstore release its tile buffers so
  1732. // the new one (e.g. another tab) can use the buffers to render contents.
  1733. if (BackingStorePrivate::s_currentBackingStoreOwner && BackingStorePrivate::s_currentBackingStoreOwner != webPage)
  1734. BackingStorePrivate::s_currentBackingStoreOwner->d->m_backingStore->d->resetTiles();
  1735. BackingStorePrivate::s_currentBackingStoreOwner = webPage;
  1736. if (webPage)
  1737. webPage->backingStore()->d->updateSuspendScreenUpdateState(); // depends on isActive()
  1738. }
  1739. bool BackingStorePrivate::isActive() const
  1740. {
  1741. return BackingStorePrivate::s_currentBackingStoreOwner == m_webPage && SurfacePool::globalSurfacePool()->isActive();
  1742. }
  1743. void BackingStorePrivate::didRenderContent(const Platform::IntRectRegion& renderedRegion)
  1744. {
  1745. #if USE(ACCELERATED_COMPOSITING)
  1746. if (m_webPage->d->needsOneShotDrawingSynchronization())
  1747. m_webPage->d->commitRootLayerIfNeeded();
  1748. else
  1749. #endif
  1750. {
  1751. if (isScrollingOrZooming())
  1752. return; // don't drag down framerates by double-blitting.
  1753. blitVisibleContents();
  1754. }
  1755. // Don't issue content rendered calls when all we rendered was filler
  1756. // background color before the page is committed.
  1757. if (!m_client->contentsSize().isEmpty()) {
  1758. std::vector<Platform::IntRect> renderedRects = renderedRegion.rects();
  1759. for (size_t i = 0; i < renderedRects.size(); ++i)
  1760. m_webPage->client()->notifyPixelContentRendered(renderedRects[i]);
  1761. }
  1762. }
  1763. BackingStore::BackingStore(WebPage* webPage, BackingStoreClient* client)
  1764. : d(new BackingStorePrivate)
  1765. {
  1766. d->m_webPage = webPage;
  1767. d->m_client = client;
  1768. }
  1769. BackingStore::~BackingStore()
  1770. {
  1771. deleteGuardedObject(d);
  1772. d = 0;
  1773. }
  1774. void BackingStore::createSurface()
  1775. {
  1776. static bool initialized = false;
  1777. if (!initialized) {
  1778. BlackBerry::Platform::Graphics::initialize();
  1779. initialized = true;
  1780. }
  1781. // Triggers creation of surfaces in backingstore.
  1782. d->createSurfaces();
  1783. // Focusing the WebPage triggers a repaint, so while we want it to be
  1784. // focused initially this has to happen after creation of the surface.
  1785. d->m_webPage->setFocused(true);
  1786. }
  1787. void BackingStore::suspendBackingStoreUpdates()
  1788. {
  1789. d->suspendBackingStoreUpdates();
  1790. }
  1791. void BackingStore::resumeBackingStoreUpdates()
  1792. {
  1793. d->resumeBackingStoreUpdates();
  1794. }
  1795. void BackingStore::suspendGeometryUpdates()
  1796. {
  1797. d->suspendGeometryUpdates();
  1798. }
  1799. void BackingStore::resumeGeometryUpdates()
  1800. {
  1801. d->resumeGeometryUpdates();
  1802. }
  1803. void BackingStore::suspendScreenUpdates()
  1804. {
  1805. d->suspendScreenUpdates();
  1806. }
  1807. void BackingStore::resumeScreenUpdates(ResumeUpdateOperation op)
  1808. {
  1809. d->resumeScreenUpdates(op);
  1810. }
  1811. bool BackingStore::isScrollingOrZooming() const
  1812. {
  1813. return d->isScrollingOrZooming();
  1814. }
  1815. void BackingStore::setScrollingOrZooming(bool scrollingOrZooming)
  1816. {
  1817. d->setScrollingOrZooming(scrollingOrZooming);
  1818. }
  1819. void BackingStore::blitVisibleContents()
  1820. {
  1821. d->blitVisibleContents(false /*force*/);
  1822. }
  1823. void BackingStore::repaint(int x, int y, int width, int height, bool contentChanged, bool immediate)
  1824. {
  1825. d->repaint(Platform::IntRect(x, y, width, height), contentChanged, immediate);
  1826. }
  1827. void BackingStore::acquireBackingStoreMemory()
  1828. {
  1829. SurfacePool::globalSurfacePool()->createBuffers();
  1830. }
  1831. void BackingStore::releaseOwnedBackingStoreMemory()
  1832. {
  1833. if (BackingStorePrivate::s_currentBackingStoreOwner == d->m_webPage) {
  1834. // Call resetTiles() (hopefully) after suspendScreenUpdates()
  1835. // so we will not cause checkerboard to be shown before suspending.
  1836. // This causes the tiles in use to be given back to the SurfacePool.
  1837. d->resetTiles();
  1838. SurfacePool::globalSurfacePool()->releaseBuffers();
  1839. }
  1840. }
  1841. bool BackingStore::hasBlitJobs() const
  1842. {
  1843. #if USE(ACCELERATED_COMPOSITING)
  1844. // If there's a WebPageCompositorClient, let it schedule the blit.
  1845. WebPageCompositorPrivate* compositor = d->m_webPage->d->compositor();
  1846. if (compositor && compositor->client())
  1847. return false;
  1848. #endif
  1849. // Normally, this would be called from the compositing thread,
  1850. // and the flag is set on the compositing thread, so no need for
  1851. // synchronization.
  1852. return d->m_hasBlitJobs;
  1853. }
  1854. void BackingStore::blitOnIdle()
  1855. {
  1856. #if USE(ACCELERATED_COMPOSITING)
  1857. // If there's a WebPageCompositorClient, let it schedule the blit.
  1858. WebPageCompositorPrivate* compositor = d->m_webPage->d->compositor();
  1859. if (compositor && compositor->client())
  1860. return;
  1861. #endif
  1862. d->blitVisibleContents(true /*force*/);
  1863. }
  1864. Platform::IntSize BackingStorePrivate::surfaceSize() const
  1865. {
  1866. if (Window* window = m_webPage->client()->window())
  1867. return window->surfaceSize();
  1868. #if USE(ACCELERATED_COMPOSITING)
  1869. if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
  1870. return compositor->context()->surfaceSize();
  1871. #endif
  1872. return Platform::IntSize();
  1873. }
  1874. Platform::Graphics::Buffer* BackingStorePrivate::buffer() const
  1875. {
  1876. if (Window* window = m_webPage->client()->window())
  1877. return window->buffer();
  1878. #if USE(ACCELERATED_COMPOSITING)
  1879. if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor())
  1880. return compositor->context() ? compositor->context()->buffer() : 0;
  1881. #endif
  1882. return 0;
  1883. }
  1884. bool BackingStore::drawContents(Platform::Graphics::Buffer* buffer, const Platform::IntRect& dstRect, double scale, const Platform::FloatPoint& documentScrollPosition)
  1885. {
  1886. if (!buffer || dstRect.isEmpty())
  1887. return false;
  1888. d->requestLayoutIfNeeded();
  1889. return d->renderContents(buffer, dstRect, scale, documentScrollPosition, BackingStorePrivate::RenderAllLayers);
  1890. }
  1891. }
  1892. }