diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
22 files changed, 222 insertions, 380 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 7208380..524f986 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -247,7 +247,7 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, TiledPage::VisibleBounds); // Cancel pending paints for the foreground page - TilesManager::instance()->removePaintOperationsForPage(tiledPage); + TilesManager::instance()->removePaintOperationsForPage(tiledPage, false); } // If we fired a request, let's check if it's ready to use diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp index 8a1d2fa..dc983a6 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.cpp +++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp @@ -51,14 +51,9 @@ // Touch ring border width. This is doubled if the ring is not pressed #define RING_BORDER_WIDTH 1 -// Put a cap on the number of matches to draw. If the current page has more -// matches than this, only draw the focused match. This both prevents clutter -// on the page and keeps the performance happy -#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 GLExtras::GLExtras() - : m_ring(0) - , m_drawExtra(0) + : m_drawExtra(0) , m_viewport() { } @@ -150,30 +145,8 @@ void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder, } } -void GLExtras::drawCursorRings(const LayerAndroid* layer) -{ - int layerId = layer ? layer->uniqueId() : -1; - if (layerId != m_ring->layerId()) - return; - - SkRegion region; - for (size_t i = 0; i < m_ring->rings().size(); i++) { - IntRect rect = m_ring->rings().at(i); - if (i == 0) - region.setRect(rect); - else - region.op(rect, SkRegion::kUnion_Op); - } - drawRegion(region, m_ring->m_isPressed, !m_ring->m_isButton, - layer ? layer->drawTransform() : 0); -} - void GLExtras::drawGL(const LayerAndroid* layer) { - if (m_drawExtra) { - if (m_drawExtra == m_ring) - drawCursorRings(layer); - else - m_drawExtra->drawGL(this, layer); - } + if (m_drawExtra) + m_drawExtra->drawGL(this, layer); } diff --git a/Source/WebCore/platform/graphics/android/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h index 72ee41c..59a7c3c 100644 --- a/Source/WebCore/platform/graphics/android/GLExtras.h +++ b/Source/WebCore/platform/graphics/android/GLExtras.h @@ -31,10 +31,6 @@ #include "SkRect.h" #include "SkRegion.h" -namespace android { - class CursorRing; -} - namespace WebCore { class LayerAndroid; @@ -46,7 +42,6 @@ public: virtual ~GLExtras(); void drawGL(const LayerAndroid* layer); - void setCursorRingExtra(android::CursorRing* ring) { m_ring = ring; } void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; } void setViewport(const SkRect & viewport) { m_viewport = viewport; } @@ -55,9 +50,7 @@ public: private: void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat); - void drawCursorRings(const LayerAndroid* layer); - android::CursorRing* m_ring; android::DrawExtra* m_drawExtra; SkRect m_viewport; }; diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index 39d8755..3024d28 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -36,9 +36,6 @@ #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> -#include <cutils/log.h> -#include <wtf/text/CString.h> - #undef XLOGC #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) @@ -54,6 +51,11 @@ #endif // DEBUG +// We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every +// LOG_VOLUME_PER_CYCLE seconds. +#define LOG_CYCLE 30.0 +#define LOG_VOLUME_PER_CYCLE 20 + struct ANativeWindowBuffer; namespace WebCore { @@ -118,10 +120,35 @@ void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, flo // GL & EGL error checks ///////////////////////////////////////////////////////////////////////////////////////// -static void crashIfOOM(GLint errorCode) { +double GLUtils::m_previousLogTime = 0; +int GLUtils::m_currentLogCounter = 0; + +bool GLUtils::allowGLLog() +{ + if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) { + m_currentLogCounter++; + return true; + } + + // when we are in Log cycle and over the log limit, just return false + double currentTime = WTF::currentTime(); + double delta = currentTime - m_previousLogTime; + bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0); + if (inLogCycle) + return false; + + // When we are out of Log Cycle and over the log limit, we need to reset + // the counter and timer. + m_previousLogTime = currentTime; + m_currentLogCounter = 0; + return false; +} + +static void crashIfOOM(GLint errorCode) +{ const GLint OOM_ERROR_CODE = 0x505; if (errorCode == OOM_ERROR_CODE) { - XLOG("Fatal OOM detected."); + XLOGC("ERROR: Fatal OOM detected."); CRASH(); } } @@ -129,11 +156,17 @@ static void crashIfOOM(GLint errorCode) { void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) { if (returnVal != EGL_TRUE) { - XLOG("EGL ERROR - %s() returned %d\n", op, returnVal); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("EGL ERROR - %s() returned %d\n", op, returnVal); } for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { - XLOG("after %s() eglError (0x%x)\n", op, error); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("after %s() eglError (0x%x)\n", op, error); crashIfOOM(error); } } @@ -142,7 +175,10 @@ bool GLUtils::checkGlError(const char* op) { bool ret = false; for (GLint error = glGetError(); error; error = glGetError()) { - XLOG("GL ERROR - after %s() glError (0x%x)\n", op, error); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR - after %s() glError (0x%x)\n", op, error); crashIfOOM(error); ret = true; } @@ -153,7 +189,10 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) { bool ret = false; for (GLint error = glGetError(); error; error = glGetError()) { - XLOG("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error); crashIfOOM(error); ret = true; } @@ -163,7 +202,10 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) void GLUtils::checkSurfaceTextureError(const char* functionName, int status) { if (status != NO_ERROR) { - XLOG("ERROR at calling %s status is (%d)", functionName, status); +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("ERROR at calling %s status is (%d)", functionName, status); } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -315,7 +357,8 @@ void GLUtils::deleteTexture(GLuint* texture) *texture = 0; } -GLuint GLUtils::createSampleColorTexture(int r, int g, int b) { +GLuint GLUtils::createSampleColorTexture(int r, int g, int b) +{ GLuint texture; glGenTextures(1, &texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -501,7 +544,10 @@ void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GL 0, internalformat, type, bitmap.getPixels()); bitmap.unlockPixels(); if (GLUtils::checkGlError("glTexImage2D")) { - XLOG("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d," " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); } @@ -538,7 +584,10 @@ void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, } bitmap.unlockPixels(); if (GLUtils::checkGlError("glTexSubImage2D")) { - XLOG("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," +#ifndef DEBUG + if (allowGLLog()) +#endif + XLOGC("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); } diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index b198d35..e001aee 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -85,6 +85,9 @@ public: static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); + static bool allowGLLog(); + static double m_previousLogTime; + static int m_currentLogCounter; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index e0d48ee..76d7324 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -141,7 +141,7 @@ bool GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndica m_layersRenderingMode = kAllTextures; } if (layer) { - XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0)); + XLOG("new base layer %p, with child %p", layer, layer->getChild(0)); layer->setState(this); } bool queueFull = m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout); diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp index 9cfed60..0aa1ae6 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp @@ -26,6 +26,7 @@ #include "GraphicsContext.h" #include "AffineTransform.h" +#include "Font.h" #include "Gradient.h" #include "NotImplemented.h" #include "Path.h" @@ -1265,6 +1266,25 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, boo // FIXME: IMPLEMENT! } +void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to, bool isActive) +{ + if (paintingDisabled()) + return; + + IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to); + if (isActive) + fillRect(rect, backgroundColor, colorSpace); + else { + int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height(); + const int t = 3, t2 = t * 2; + + fillRect(IntRect(x, y, w, t), backgroundColor, colorSpace); + fillRect(IntRect(x, y+h-t, w, t), backgroundColor, colorSpace); + fillRect(IntRect(x, y+t, t, h-t2), backgroundColor, colorSpace); + fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor, colorSpace); + } +} + } // namespace WebCore /////////////////////////////////////////////////////////////////////////////// diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 79c02eb..83fb414 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -685,13 +685,16 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM // now apply it to our children + TransformationMatrix childMatrix; + childMatrix = localMatrix; + childMatrix.translate3d(m_offset.x(), m_offset.y(), 0); if (!m_childrenTransform.isIdentity()) { - localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); - localMatrix.multiply(m_childrenTransform); - localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); + childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); + childMatrix.multiply(m_childrenTransform); + childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f); } for (int i = 0; i < count; i++) - this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale); + this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(), opacity, scale); } void LayerAndroid::setContentsImage(SkBitmapRef* img) diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp index 59c1271..4925bd6 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -38,6 +38,9 @@ #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__) + #ifdef DEBUG #undef XLOG @@ -45,10 +48,10 @@ #else -#undef XLOGC -#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__) +#undef XLOG +#define XLOG(...) -#endif +#endif // DEBUG namespace WebCore { diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h index 25d234b..5434dbf 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/TextureOwner.h @@ -26,8 +26,6 @@ #ifndef TextureOwner_h #define TextureOwner_h -#include "SkRefCnt.h" - class SkCanvas; class Layer; @@ -37,7 +35,7 @@ class TiledPage; class BaseTileTexture; class GLWebViewState; -class TextureOwner : public SkRefCnt { +class TextureOwner { public: virtual ~TextureOwner() { } virtual bool removeTexture(BaseTileTexture* texture) = 0; diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp index d27631b..bccb99b 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -65,13 +65,18 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) removeOperationsForFilter(new PageFilter(page)); } -void TexturesGenerator::removePaintOperationsForPage(TiledPage* page) +void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) { - removeOperationsForFilter(new PagePaintFilter(page)); + removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); } void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) { + removeOperationsForFilter(filter, true); +} + +void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) +{ if (!filter) return; @@ -85,7 +90,34 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) i++; } } - delete filter; + + if (waitForRunning && m_currentOperation) { + QueuedOperation* operation = m_currentOperation; + + if (operation && filter->check(operation)) { + m_waitForCompletion = true; + // The reason we are signaling the transferQueue is : + // TransferQueue may be waiting a slot to work on, but now UI + // thread is waiting for Tex Gen thread to finish first before the + // UI thread can free a slot for the transferQueue. + // Therefore, it could be a deadlock. + // The solution is use this as a flag to tell Tex Gen thread that + // UI thread is waiting now, Tex Gen thread should not wait for the + // queue any more. + TilesManager::instance()->transferQueue()->interruptTransferQueue(true); + } + + delete filter; + + // At this point, it means that we are currently executing an operation that + // we want to be removed -- we should wait until it is done, so that + // when we return our caller can be sure that there is no more operations + // in the queue matching the given filter. + while (m_waitForCompletion) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + } else { + delete filter; + } } status_t TexturesGenerator::readyToRun() @@ -160,6 +192,7 @@ bool TexturesGenerator::threadLoop() stop = true; if (m_waitForCompletion) { m_waitForCompletion = false; + TilesManager::instance()->transferQueue()->interruptTransferQueue(false); mRequestedOperationsCond.signal(); } mRequestedOperationsLock.unlock(); diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h index c7924cc..2e3b6b4 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.h @@ -42,18 +42,16 @@ class LayerAndroid; class TexturesGenerator : public Thread { public: - TexturesGenerator() - : Thread(false) + TexturesGenerator() : Thread(false) , m_waitForCompletion(false) - , m_currentOperation(0) - {} - + , m_currentOperation(0) { } virtual ~TexturesGenerator() { } virtual status_t readyToRun(); void removeOperationsForPage(TiledPage* page); - void removePaintOperationsForPage(TiledPage* page); + void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); void removeOperationsForFilter(OperationFilter* filter); + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); void scheduleOperation(QueuedOperation* operation); diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 80d2c3f..7aac242 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -59,7 +59,8 @@ namespace WebCore { using namespace android; TiledPage::TiledPage(int id, GLWebViewState* state) - : m_baseTileSize(0) + : m_baseTiles(0) + , m_baseTileSize(0) , m_id(id) , m_scale(1) , m_invScale(1) @@ -69,11 +70,7 @@ TiledPage::TiledPage(int id, GLWebViewState* state) , m_isPrefetchPage(false) , m_willDraw(false) { - int maxTiles = TilesManager::getMaxTextureAllocation() + 1; - m_baseTiles = new BaseTile*[maxTiles]; - for (int i = 0; i < maxTiles; i++) - m_baseTiles[i] = new BaseTile(); - + m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; #ifdef DEBUG_COUNT ClassTracker::instance()->increment("TiledPage"); #endif @@ -97,14 +94,13 @@ void TiledPage::updateBaseTileSize() TiledPage::~TiledPage() { TilesManager* tilesManager = TilesManager::instance(); - // remove as many painting operations for this page as possible, to avoid - // unnecessary work. + // In order to delete the page we must ensure that none of its BaseTiles are + // currently painting or scheduled to be painted by the TextureGenerator tilesManager->removeOperationsForPage(this); - - int maxTiles = TilesManager::getMaxTextureAllocation() + 1; - for (int i = 0; i < maxTiles; i++) - SkSafeUnref(m_baseTiles[i]); - delete m_baseTiles; + // Discard the transfer queue after the removal operation to make sure + // no tiles for this page will be left in the transfer queue. + tilesManager->transferQueue()->setPendingDiscardWithLock(); + delete[] m_baseTiles; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledPage"); #endif @@ -114,9 +110,9 @@ BaseTile* TiledPage::getBaseTile(int x, int y) const { // TODO: replace loop over array with HashMap indexing for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - if (tile->x() == x && tile->y() == y) - return tile; + BaseTile& tile = m_baseTiles[j]; + if (tile.x() == x && tile.y() == y) + return &tile; } return 0; } @@ -124,8 +120,8 @@ BaseTile* TiledPage::getBaseTile(int x, int y) const void TiledPage::discardTextures() { for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - tile->discardTextures(); + BaseTile& tile = m_baseTiles[j]; + tile.discardTextures(); } return; } @@ -165,14 +161,14 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y BaseTile* currentTile = 0; BaseTile* availableTile = 0; for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - if (tile->x() == x && tile->y() == y) { - currentTile = tile; + BaseTile& tile = m_baseTiles[j]; + if (tile.x() == x && tile.y() == y) { + currentTile = &tile; break; } - if (!availableTile || (tile->drawCount() < availableTile->drawCount())) - availableTile = tile; + if (!availableTile || (tile.drawCount() < availableTile->drawCount())) + availableTile = &tile; } if (!currentTile && availableTile) { @@ -220,12 +216,12 @@ bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds) bool visibleTileIsDirty = false; for (int x = 0; x < m_baseTileSize; x++) { - BaseTile* tile = m_baseTiles[x]; + BaseTile& tile = m_baseTiles[x]; // if the tile is in the dirty region then we must invalidate it - if (m_invalRegion.contains(tile->x(), tile->y())) { - tile->markAsDirty(m_latestPictureInval, m_invalTilesRegion); - if (tileBounds.contains(tile->x(), tile->y())) + if (m_invalRegion.contains(tile.x(), tile.y())) { + tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); + if (tileBounds.contains(tile.x(), tile.y())) visibleTileIsDirty = true; } } @@ -305,9 +301,9 @@ bool TiledPage::hasMissingContent(const SkIRect& tileBounds) { int neededTiles = tileBounds.width() * tileBounds.height(); for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - if (tileBounds.contains(tile->x(), tile->y())) { - if (tile->frontTexture()) + BaseTile& tile = m_baseTiles[j]; + if (tileBounds.contains(tile.x(), tile.y())) { + if (tile.frontTexture()) neededTiles--; } } @@ -319,9 +315,9 @@ bool TiledPage::isReady(const SkIRect& tileBounds) int neededTiles = tileBounds.width() * tileBounds.height(); XLOG("tiled page %p needs %d ready tiles", this, neededTiles); for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - if (tileBounds.contains(tile->x(), tile->y())) { - if (tile->isTileReady()) + BaseTile& tile = m_baseTiles[j]; + if (tileBounds.contains(tile.x(), tile.y())) { + if (tile.isTileReady()) neededTiles--; } } @@ -352,12 +348,12 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale) // swap every tile on page (even if off screen) for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - if (tile->swapTexturesIfNeeded()) + BaseTile& tile = m_baseTiles[j]; + if (tile.swapTexturesIfNeeded()) swaps++; } - XLOG("%p greedy swapped %d textures, returning true", this, swaps); + XLOG("%p greedy swapped %d textures, returning %d", this, swaps, fullSwap); return fullSwap; } @@ -377,16 +373,16 @@ void TiledPage::drawGL() const float tileHeight = TilesManager::tileHeight() * m_invScale; for (int j = 0; j < m_baseTileSize; j++) { - BaseTile* tile = m_baseTiles[j]; - bool tileInView = m_tileBounds.contains(tile->x(), tile->y()); + BaseTile& tile = m_baseTiles[j]; + bool tileInView = m_tileBounds.contains(tile.x(), tile.y()); if (tileInView) { SkRect rect; - rect.fLeft = tile->x() * tileWidth; - rect.fTop = tile->y() * tileHeight; + rect.fLeft = tile.x() * tileWidth; + rect.fTop = tile.y() * tileHeight; rect.fRight = rect.fLeft + tileWidth; rect.fBottom = rect.fTop + tileHeight; - tile->draw(m_transparency, rect, m_scale); + tile.draw(m_transparency, rect, m_scale); } TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index d858cc2..791e1f6 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -105,10 +105,9 @@ private: BaseTile* getBaseTile(int x, int y) const; - // array of tile ptrs used to compose a page. The tiles are allocated in the + // array of tiles used to compose a page. The tiles are allocated in the // constructor to prevent them from potentially being allocated on the stack - BaseTile** m_baseTiles; - + BaseTile* m_baseTiles; // stores the number of tiles in the m_baseTiles array. This enables us to // quickly iterate over the array without have to check it's size int m_baseTileSize; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index 4b872a3..1e8b946 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -317,8 +317,9 @@ const TransformationMatrix* TiledTexture::transform() void TiledTexture::removeTiles() { - for (unsigned int i = 0; i < m_tiles.size(); i++) - SkSafeUnref(m_tiles[i]); + for (unsigned int i = 0; i < m_tiles.size(); i++) { + delete m_tiles[i]; + } m_tiles.clear(); } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index d3852d9..b670055 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -58,9 +58,9 @@ public: return gInstance != 0; } - void removeOperationsForFilter(OperationFilter* filter) + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false) { - m_pixmapsGenerationThread->removeOperationsForFilter(filter); + m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); } void removeOperationsForPage(TiledPage* page) @@ -68,9 +68,9 @@ public: m_pixmapsGenerationThread->removeOperationsForPage(page); } - void removePaintOperationsForPage(TiledPage* page) + void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) { - m_pixmapsGenerationThread->removePaintOperationsForPage(page); + m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); } void scheduleOperation(QueuedOperation* operation) diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp index d422904..0271ee3 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp @@ -103,14 +103,14 @@ void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float sc scale, true, (int)(timeDelta * 1000))); } -void TilesProfiler::nextTile(BaseTile* tile, float scale, bool inView) +void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; - bool isReady = tile->isTileReady(); - int left = tile->x() * TilesManager::tileWidth(); - int top = tile->y() * TilesManager::tileWidth(); + bool isReady = tile.isTileReady(); + int left = tile.x() * TilesManager::tileWidth(); + int top = tile.y() * TilesManager::tileWidth(); int right = left + TilesManager::tileWidth(); int bottom = top + TilesManager::tileWidth(); @@ -122,7 +122,7 @@ void TilesProfiler::nextTile(BaseTile* tile, float scale, bool inView) } m_records.last().append(TileProfileRecord( left, top, right, bottom, - scale, isReady, (int)tile->drawCount())); + scale, isReady, (int)tile.drawCount())); XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); } diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/TilesProfiler.h index 7a3fe59..286d350 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.h +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.h @@ -58,7 +58,7 @@ public: float stop(); void clear(); void nextFrame(int left, int top, int right, int bottom, float scale); - void nextTile(BaseTile* tile, float scale, bool inView); + void nextTile(BaseTile& tile, float scale, bool inView); void nextInval(const IntRect& rect, float scale); int numFrames() { return m_records.size(); diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 3c2ed1b..2d5be64 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -67,6 +67,7 @@ TransferQueue::TransferQueue(bool useMinimalMem) , m_fboID(0) , m_sharedSurfaceTextureId(0) , m_hasGLContext(true) + , m_interruptedByRemovingOp(false) , m_currentDisplay(EGL_NO_DISPLAY) , m_currentUploadType(DEFAULT_UPLOAD_TYPE) { @@ -245,8 +246,17 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, #endif } +void TransferQueue::interruptTransferQueue(bool interrupt) +{ + m_transferQueueItemLocks.lock(); + m_interruptedByRemovingOp = interrupt; + if (m_interruptedByRemovingOp) + m_transferQueueItemCond.signal(); + m_transferQueueItemLocks.unlock(); +} + // This function must be called inside the m_transferQueueItemLocks, for the -// wait and getHasGLContext(). +// wait, m_interruptedByRemovingOp and getHasGLContext(). // Only called by updateQueueWithBitmap() for now. bool TransferQueue::readyForUpdate() { @@ -254,8 +264,13 @@ bool TransferQueue::readyForUpdate() return false; // Don't use a while loop since when the WebView tear down, the emptyCount // will still be 0, and we bailed out b/c of GL context lost. - if (!m_emptyItemCount) + if (!m_emptyItemCount) { + if (m_interruptedByRemovingOp) + return false; m_transferQueueItemCond.wait(m_transferQueueItemLocks); + if (m_interruptedByRemovingOp) + return false; + } if (!getHasGLContext()) return false; @@ -315,8 +330,6 @@ void TransferQueue::setPendingDiscard() if (m_transferQueue[i].status == pendingBlit) m_transferQueue[i].status = pendingDiscard; - for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) - SkSafeUnref(m_pureColorTileQueue[i].savedBaseTilePtr); m_pureColorTileQueue.clear(); bool GLContextExisted = getHasGLContext(); @@ -345,7 +358,6 @@ void TransferQueue::updatePureColorTiles() // The queue should be clear instead of setting to different status. XLOG("Warning: Don't expect an emptyItem here."); } - SkSafeUnref(data->savedBaseTilePtr); } m_pureColorTileQueue.clear(); } @@ -386,11 +398,6 @@ void TransferQueue::updateDirtyBaseTiles() if (result != OK) XLOGC("unexpected error: updateTexImage return %d", result); } - - XLOG("removing tile %p from %p, update", - m_transferQueue[index].savedBaseTilePtr, - &m_transferQueue[index]); - SkSafeUnref(m_transferQueue[index].savedBaseTilePtr); m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { @@ -511,7 +518,7 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, ANativeWindow_unlockAndPost(m_ANW.get()); } - // b) After update the Surface Texture, now update the transfer queue info. + // b) After update the Surface Texture, now udpate the transfer queue info. addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); XLOG("Bitmap updated x, y %d %d, baseTile %p", @@ -536,19 +543,8 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, TextureUploadType type, TileTransferData* data) { - BaseTile* old = data->savedBaseTilePtr; - SkSafeRef(renderInfo->baseTile); - SkSafeUnref(data->savedBaseTilePtr); - data->savedBaseTileTexturePtr = renderInfo->baseTile->backTexture(); data->savedBaseTilePtr = renderInfo->baseTile; - XLOG("adding tile %p, %d by %d, refs %d, removed %p, dataPtr %p", - data->savedBaseTilePtr, - data->savedBaseTilePtr->x(), - data->savedBaseTilePtr->y(), - data->savedBaseTilePtr->getRefCnt(), - old, - data); data->status = pendingBlit; data->uploadType = type; @@ -642,10 +638,6 @@ void TransferQueue::cleanupPendingDiscard() XLOG("transfer queue discarded tile %p, removed texture", tile); } - XLOG("removing tile %p from %p, cleanup", - m_transferQueue[index].savedBaseTilePtr, - &m_transferQueue[index]); - SkSafeUnref(m_transferQueue[index].savedBaseTilePtr); m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].savedBaseTileTexturePtr = 0; m_transferQueue[index].status = emptyItem; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index 30dd0c6..5dd2e0a 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -129,6 +129,8 @@ public: // The lock will be done when returning true. bool readyForUpdate(); + void interruptTransferQueue(bool); + void lockQueue() { m_transferQueueItemLocks.lock(); } void unlockQueue() { m_transferQueueItemLocks.unlock(); } @@ -194,6 +196,8 @@ private: int m_emptyItemCount; + bool m_interruptedByRemovingOp; + // We are using wait/signal to handle our own queue sync. // First of all, if we don't have our own lock, then while WebView is // destroyed, the UI thread will wait for the Tex Gen to get out from diff --git a/Source/WebCore/platform/graphics/android/android_graphics.cpp b/Source/WebCore/platform/graphics/android/android_graphics.cpp deleted file mode 100644 index d76d581..0000000 --- a/Source/WebCore/platform/graphics/android/android_graphics.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "CachedPrefix.h" -#include "android_graphics.h" -#include "CachedRoot.h" -#include "IntRect.h" -#include "LayerAndroid.h" -#include "SkCanvas.h" -#include "SkCornerPathEffect.h" -#include "SkPath.h" -#include "SkRegion.h" -#include "WebViewCore.h" - -namespace android { - -#define RING_OUTSET 3 -#define RING_RADIUS 1 -#define RING_INNER_WIDTH 16 -#define RING_OUTER_WIDTH 16 - -static const RGBA32 ringFill = 0x666699FF; -static const RGBA32 ringPressedInner = 0x006699FF; -static const RGBA32 ringPressedOuter = 0x336699FF; -static const RGBA32 ringSelectedInner = 0xAA6699FF; -static const RGBA32 ringSelectedOuter = 0x336699FF; - - -CursorRing::CursorRing(WebViewCore* core) - : m_viewImpl(core) - , m_layerId(-1) -{ -} - -// The CSS values for the inner and outer widths may be specified as fractions -#define WIDTH_SCALE 0.0625f // 1/16, to offset the scale in CSSStyleSelector - -void CursorRing::drawLegacy(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) -{ - if (!m_lastBounds.isEmpty()) { - *inval = m_lastBounds; - m_lastBounds = IntRect(0, 0, 0, 0); - } -#if USE(ACCELERATED_COMPOSITING) - int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1; - int drawingLayerId = layer ? layer->uniqueId() : -1; - if (drawingLayerId != layerId) - return; -#endif - if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) { - DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)" - " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(), - m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height()); - return; - } - unsigned rectCount = m_rings.size(); - SkRegion rgn; - SkPath path; - for (unsigned i = 0; i < rectCount; i++) - { - SkRect r(m_rings[i]); - SkIRect ir; - - r.round(&ir); - ir.inset(-RING_OUTSET, -RING_OUTSET); - rgn.op(ir, SkRegion::kUnion_Op); - } - rgn.getBoundaryPath(&path); - - SkPaint paint; - paint.setAntiAlias(true); - paint.setPathEffect(new SkCornerPathEffect( - SkIntToScalar(RING_RADIUS)))->unref(); - SkColor outer; - SkColor inner; - if (m_isPressed) { - SkColor pressed; - pressed = ringFill; - paint.setColor(pressed); - canvas->drawPath(path, paint); - outer = ringPressedInner; - inner = ringPressedOuter; - } else { - outer = ringSelectedOuter; - inner = ringSelectedInner; - } - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(RING_OUTER_WIDTH * WIDTH_SCALE); - paint.setColor(outer); - canvas->drawPath(path, paint); - paint.setStrokeWidth(RING_INNER_WIDTH * WIDTH_SCALE); - paint.setColor(inner); - canvas->drawPath(path, paint); - SkRect localBounds, globalBounds; - localBounds = path.getBounds(); - float width = std::max(RING_INNER_WIDTH, RING_OUTER_WIDTH); - width *= WIDTH_SCALE; - localBounds.inset(-width, -width); - const SkMatrix& matrix = canvas->getTotalMatrix(); - matrix.mapRect(&globalBounds, localBounds); - SkIRect globalIBounds; - globalBounds.round(&globalIBounds); - m_lastBounds = globalIBounds; - inval->unite(m_lastBounds); -} - -void CursorRing::setIsButton(const CachedNode* node) -{ - m_isButton = false; -} - -bool CursorRing::setup() -{ - m_layerId = -1; - if (m_frame && m_root) { - const CachedLayer* cachedLayer = m_frame->layer(m_node); - if (cachedLayer) { - const WebCore::LayerAndroid* rootLayer = m_root->rootLayer(); - const LayerAndroid* aLayer = cachedLayer->layer(rootLayer); - if (aLayer) - m_layerId = aLayer->uniqueId(); - } - } - if (m_layerId == -1) - m_node->cursorRings(m_frame, &m_rings); - else - m_node->localCursorRings(m_frame, &m_rings); - - if (!m_rings.size()) { - DBG_NAV_LOG("!rings.size()"); - m_viewImpl->m_hasCursorBounds = false; - return false; - } - - setIsButton(m_node); - m_bounds = m_node->bounds(m_frame); - m_viewImpl->updateCursorBounds(m_root, m_frame, m_node); - - bool useHitBounds = m_node->useHitBounds(); - if (useHitBounds) - m_bounds = m_node->hitBounds(m_frame); - if (useHitBounds || m_node->useBounds()) { - m_rings.clear(); - m_rings.append(m_bounds); - } - m_absBounds = m_node->bounds(m_frame); - m_bounds.inflate(SkScalarCeil(RING_OUTER_WIDTH)); - m_absBounds.inflate(SkScalarCeil(RING_OUTER_WIDTH)); - if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus())) - return false; -#if DEBUG_NAV_UI - const WebCore::IntRect& ring = m_rings[0]; - DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) pressed=%s rings=%d" - " (%d, %d, %d, %d) isPlugin=%s", - m_node->index(), m_node->nodePointer(), - m_isPressed ? "true" : "false", - m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(), - m_node->isPlugin() ? "true" : "false"); -#endif - return true; -} - -} diff --git a/Source/WebCore/platform/graphics/android/android_graphics.h b/Source/WebCore/platform/graphics/android/android_graphics.h index 68207d7..7faa781 100644 --- a/Source/WebCore/platform/graphics/android/android_graphics.h +++ b/Source/WebCore/platform/graphics/android/android_graphics.h @@ -26,55 +26,17 @@ #ifndef android_graphics_DEFINED #define android_graphics_DEFINED -#include "DrawExtra.h" -#include "IntRect.h" -#include "SkTypes.h" -#include "wtf/Vector.h" - namespace WebCore { class GraphicsContext; - class GLExtras; } +class SkCanvas; -SkCanvas* android_gc2canvas(GraphicsContext* gc); - -namespace android { - -class CachedFrame; -class CachedNode; -class CachedRoot; -class WebViewCore; - -// Data and methods for cursor rings +// TODO: Move this somewhere else. The implementation for this is actually in +// GraphicsContextAndroid.cpp, but this is used by a handful of other files +SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc); // used to inflate node cache entry #define CURSOR_RING_HIT_TEST_RADIUS 5 -class CursorRing : public DrawExtra { -public: - CursorRing(WebViewCore* core); - virtual ~CursorRing() {} - virtual void drawLegacy(SkCanvas* , LayerAndroid* , IntRect* ); - void setIsButton(const CachedNode* ); - bool setup(); - WTF::Vector<IntRect>& rings() { return m_rings; } - int layerId() const { return m_layerId; } -private: - friend class WebView; - friend class WebCore::GLExtras; - WebViewCore* m_viewImpl; // copy for convenience - WTF::Vector<IntRect> m_rings; - IntRect m_bounds; - IntRect m_absBounds; - IntRect m_lastBounds; - const CachedRoot* m_root; - const CachedFrame* m_frame; - const CachedNode* m_node; - bool m_isButton; - bool m_isPressed; - int m_layerId; -}; - -} #endif |