diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2012-04-02 17:08:02 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-04-02 17:08:02 -0700 |
commit | 24667dd680e19d654262f570efeb697dfc87922c (patch) | |
tree | 78b045a2b5b9f5649136be7f2d3c091560a575e2 /Source | |
parent | 96027bf9f9621433909777b481964fdbd9258f85 (diff) | |
parent | afe34397d6d4655c908f0995e760772980722da3 (diff) | |
download | external_webkit-24667dd680e19d654262f570efeb697dfc87922c.zip external_webkit-24667dd680e19d654262f570efeb697dfc87922c.tar.gz external_webkit-24667dd680e19d654262f570efeb697dfc87922c.tar.bz2 |
Merge "Translucent background color support for webview"
Diffstat (limited to 'Source')
15 files changed, 150 insertions, 43 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 61b5f84..ddaf181 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -207,16 +207,16 @@ void BaseTile::setRepaintPending(bool pending) m_repaintPending = pending; } -void BaseTile::drawGL(float opacity, const SkRect& rect, float scale, +bool BaseTile::drawGL(float opacity, const SkRect& rect, float scale, const TransformationMatrix* transform) { if (m_x < 0 || m_y < 0 || m_scale != scale) - return; + return false; // No need to mutex protect reads of m_backTexture as it is only written to by // the consumer thread. if (!m_frontTexture) - return; + return false; // Early return if set to un-usable in purpose! m_atomicSync.lock(); @@ -224,9 +224,10 @@ void BaseTile::drawGL(float opacity, const SkRect& rect, float scale, m_atomicSync.unlock(); if (!isTexturePainted) - return; + return false; m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform); + return true; } bool BaseTile::isTileReady() diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h index 8bf681e..93ec287 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/BaseTile.h @@ -99,7 +99,8 @@ public: bool isTileReady(); - void drawGL(float opacity, const SkRect& rect, float scale, + // Return false when real draw didn't happen for any reason. + bool drawGL(float opacity, const SkRect& rect, float scale, const TransformationMatrix* transform); // the only thread-safe function called by the background thread diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index fb69deb..beb62db 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -644,19 +644,21 @@ void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationM matrix[12], matrix[13], matrix[14], matrix[15]); } -void GLUtils::drawBackground(const Color* backgroundColor) +void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor) { - if (TilesManager::instance()->invertedScreen()) { - float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + - ((float) backgroundColor->green() / 255.0) + - ((float) backgroundColor->blue() / 255.0)) / 3.0); - glClearColor(color, color, color, 1); - } else { - glClearColor((float)backgroundColor->red() / 255.0, - (float)backgroundColor->green() / 255.0, - (float)backgroundColor->blue() / 255.0, 1); + if (!backgroundColor->hasAlpha()) { + if (TilesManager::instance()->invertedScreen()) { + float color = 1.0 - ((((float) backgroundColor->red() / 255.0) + + ((float) backgroundColor->green() / 255.0) + + ((float) backgroundColor->blue() / 255.0)) / 3.0); + glClearColor(color, color, color, 1); + } else { + glClearColor((float)backgroundColor->red() / 255.0, + (float)backgroundColor->green() / 255.0, + (float)backgroundColor->blue() / 255.0, 1); + } + glClear(GL_COLOR_BUFFER_BIT); } - glClear(GL_COLOR_BUFFER_BIT); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 70ebbd6..f24ea0d 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -86,7 +86,7 @@ public: static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - static void drawBackground(const Color* backgroundColor); + static void clearBackgroundIfOpaque(const Color* backgroundColor); static bool allowGLLog(); static double m_previousLogTime; static int m_currentLogCounter; diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index b7458e8..a5080ca 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -156,10 +156,9 @@ void GLWebViewState::setViewport(const SkRect& viewport, float scale) m_isViewportScrolling = m_viewport != viewport && SkRect::Intersects(m_viewport, viewport); m_viewport = viewport; - ALOGV("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)", + ALOGV("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f )", m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, - m_viewport.width(), m_viewport.height(), scale, - zoomManager()->currentScale(), zoomManager()->futureScale()); + m_viewport.width(), m_viewport.height(), scale); } #ifdef MEASURES_PERF diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.cpp b/Source/WebCore/platform/graphics/android/LayerGroup.cpp index 2d6c1c4..7bdbd11 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.cpp +++ b/Source/WebCore/platform/graphics/android/LayerGroup.cpp @@ -163,6 +163,16 @@ IntRect LayerGroup::unclippedArea() return m_unclippedArea; } +bool LayerGroup::useAggressiveRendering() +{ + // When the background is translucent, 0 < alpha < 255, we had to turn off + // low res to avoid artifacts from double drawing. + // TODO: avoid double drawing for low res tiles. + return isBase() + && (!m_background.alpha() + || !m_background.hasAlpha()); +} + void LayerGroup::prepareGL(bool layerTilesDisabled) { bool tilesDisabled = layerTilesDisabled && !isBase(); @@ -209,9 +219,11 @@ bool LayerGroup::drawGL(bool layerTilesDisabled) if (m_dualTiledTexture && !tilesDisabled) { ALOGV("drawGL on LG %p with DTT %p", this, m_dualTiledTexture); + // TODO: why this visibleArea is different from visibleRect at zooming for base? IntRect drawArea = visibleArea(); askRedraw |= m_dualTiledTexture->drawGL(drawArea, opacity(), - drawTransform(), useAggressiveRendering()); + drawTransform(), useAggressiveRendering(), + background()); } // draw member layers (draws image textures, glextras) @@ -312,6 +324,13 @@ float LayerGroup::opacity() return 1.0; } +Color* LayerGroup::background() +{ + if (!isBase() || !m_background.isValid()) + return 0; + return &m_background; +} + const TransformationMatrix* LayerGroup::drawTransform() { // single layer groups query the layer's draw transform, while multi-layer diff --git a/Source/WebCore/platform/graphics/android/LayerGroup.h b/Source/WebCore/platform/graphics/android/LayerGroup.h index 22986e4..8e9608d 100644 --- a/Source/WebCore/platform/graphics/android/LayerGroup.h +++ b/Source/WebCore/platform/graphics/android/LayerGroup.h @@ -26,6 +26,7 @@ #ifndef LayerGroup_h #define LayerGroup_h +#include "Color.h" #include "IntRect.h" #include "TilePainter.h" #include "Vector.h" @@ -59,17 +60,20 @@ public: bool needsTexture() { return m_needsTexture; } bool hasText() { return m_hasText; } bool isBase(); + void setBackground(Color background) { m_background = background; } // TilePainter methods virtual bool paint(BaseTile* tile, SkCanvas* canvas); virtual float opacity(); + virtual Color* background(); + private: IntRect computePrepareArea(); IntRect visibleArea(); IntRect unclippedArea(); bool singleLayer() { return m_layers.size() == 1; } - bool useAggressiveRendering() { return isBase(); } - + void updateBackground(const Color& background); + bool useAggressiveRendering(); const TransformationMatrix* drawTransform(); IntRect m_unclippedArea; @@ -79,6 +83,8 @@ private: bool m_needsTexture; bool m_hasText; Vector<LayerAndroid*> m_layers; + + Color m_background; }; class LayerMergeState { diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index bcfe7d8..a012c8b 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -23,11 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "RasterRenderer" +#define LOG_NDEBUG 1 + #include "config.h" #include "RasterRenderer.h" #if USE(ACCELERATED_COMPOSITING) +#include "AndroidLog.h" #include "GLUtils.h" #include "SkBitmap.h" #include "SkBitmapRef.h" @@ -66,8 +70,16 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can g_bitmap->setIsOpaque(false); g_bitmap->eraseARGB(0, 0, 0, 0); } else { - g_bitmap->setIsOpaque(true); - g_bitmap->eraseARGB(255, 255, 255, 255); + Color defaultBackground = Color::white; + Color* background = renderInfo.tilePainter->background(); + if (!background) { + ALOGV("No background color for base layer!"); + background = &defaultBackground; + } + ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); + g_bitmap->setIsOpaque(!background->hasAlpha()); + g_bitmap->eraseARGB(background->alpha(), background->red(), + background->green(), background->blue()); } SkDevice* device = new SkDevice(*g_bitmap); diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp index d1b70f7..257e68f 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -502,7 +502,7 @@ void ShaderProgram::drawQuad(const SkRect& geometry, int textureId, float opacit setProjectionMatrix(geometry, projectionMatrix); finalMatrix = projectionMatrix; } - setBlendingState(opacity < 1.0); + setBlendingState(opacity < 1.0 || pureColor.hasAlpha()); drawQuadInternal(type, finalMatrix, textureId, opacity, textureTarget, texFilter, pureColor); } diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp index 1ea192c..78c3fbb 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/SurfaceCollection.cpp @@ -63,8 +63,11 @@ SurfaceCollection::SurfaceCollection(LayerAndroid* layer) // set the layergroups' and tiledpages' update count, to be drawn on painted tiles unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates(); - for (unsigned int i = 0; i < m_layerGroups.size(); i++) + for (unsigned int i = 0; i < m_layerGroups.size(); i++) { m_layerGroups[i]->setUpdateCount(updateCount); + if (m_layerGroups[i]->isBase()) + m_layerGroups[i]->setBackground(getBackground()); + } #ifdef DEBUG_COUNT ClassTracker::instance()->increment("SurfaceCollection"); diff --git a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp index 52bcaf0..c3c4bda 100644 --- a/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp @@ -227,7 +227,10 @@ bool SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, } // Start doing the actual GL drawing. - GLUtils::drawBackground(&background); + ALOGV("background is %x", background.rgb()); + // If background is opaque, we can safely and efficiently clear it here. + // Otherwise, we have to calculate all the missing tiles and blend the background. + GLUtils::clearBackgroundIfOpaque(&background); if (m_drawingCollection) ret |= m_drawingCollection->drawGL(visibleRect); diff --git a/Source/WebCore/platform/graphics/android/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h index 34e877e..a5dafa9 100644 --- a/Source/WebCore/platform/graphics/android/TilePainter.h +++ b/Source/WebCore/platform/graphics/android/TilePainter.h @@ -34,6 +34,7 @@ class SkCanvas; namespace WebCore { class BaseTile; +class Color; class TilePainter : public SkRefCnt { // TODO: investigate webkit threadsafe ref counting @@ -43,6 +44,7 @@ public: virtual float opacity() { return 1.0; } enum SurfaceType { Painted, Image }; virtual SurfaceType type() { return Painted; } + virtual Color* background() { return 0; } unsigned int getUpdateCount() { return m_updateCount; } void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; } diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index b993501..11cf906 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -259,18 +259,29 @@ int TiledTexture::nbTextures(IntRect& area, float scale) } bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform) + const TransformationMatrix* transform, + const Color* background) { m_area = computeTilesArea(visibleArea, m_scale); if (m_area.width() == 0 || m_area.height() == 0) return false; - float m_invScale = 1 / m_scale; - const float tileWidth = TilesManager::tileWidth() * m_invScale; - const float tileHeight = TilesManager::tileHeight() * m_invScale; + float invScale = 1 / m_scale; + const float tileWidth = TilesManager::tileWidth() * invScale; + const float tileHeight = TilesManager::tileHeight() * invScale; int drawn = 0; bool askRedraw = false; + + SkRegion missingRegion; + bool translucentBaseSurface = + background ? (background->hasAlpha() && background->alpha() > 0) : false; + if (translucentBaseSurface) { + SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(), + m_area.width(), m_area.height()); + missingRegion = SkRegion(totalArea); + } + for (unsigned int i = 0; i < m_tiles.size(); i++) { BaseTile* tile = m_tiles[i]; @@ -285,14 +296,25 @@ bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d", tile, tile->isLayerTile(), tile->x(), tile->y(), tile->scale(), m_scale, tile->isTileReady(), tile->isDirty()); - tile->drawGL(opacity, rect, m_scale, transform); + + bool success = tile->drawGL(opacity, rect, m_scale, transform); + if (translucentBaseSurface && success) { + // Cut the successful drawn tile area from the missing region. + missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1), + SkRegion::kDifference_Op); + } if (tile->frontTexture()) drawn++; } - if (m_isBaseSurface) - TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); + if (translucentBaseSurface) + TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView); } + + // Draw missing Regions with blend turned on + if (translucentBaseSurface) + drawMissingRegion(missingRegion, opacity, background); + ALOGV("TT %p drew %d tiles, redraw due to notready %d, scale %f", this, drawn, askRedraw, m_scale); @@ -300,6 +322,32 @@ bool TiledTexture::drawGL(const IntRect& visibleArea, float opacity, return askRedraw; } +void TiledTexture::drawMissingRegion(const SkRegion& region, float opacity, + const Color* background) +{ + SkRegion::Iterator iterator(region); + const float tileWidth = TilesManager::tileWidth() / m_scale; + const float tileHeight = TilesManager::tileHeight() / m_scale; + ShaderProgram* shader = TilesManager::instance()->shader(); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + SkRect rect; + rect.fLeft = r.x() * tileWidth; + rect.fTop = r.y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth * r.width(); + rect.fBottom = rect.fTop + tileHeight * r.height(); + ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(), + r.width(), r.height(), opacity); + // Skia is using pre-multiplied color. + Color postAlpha = Color(background->red() * background->alpha() / 255, + background->green() * background->alpha() / 255, + background->blue() * background->alpha() / 255, + background->alpha() ); + shader->drawQuad(rect, 0, opacity, postAlpha); + iterator.next(); + } +} + void TiledTexture::removeTiles() { for (unsigned int i = 0; i < m_tiles.size(); i++) { @@ -382,13 +430,13 @@ void DualTiledTexture::prepareGL(GLWebViewState* state, bool allowZoom, bool DualTiledTexture::drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform, - bool aggressiveRendering) + bool aggressiveRendering, const Color* background) { // draw low res prefetch page, if needed if (aggressiveRendering && !m_zooming && m_frontTexture->isMissingContent()) m_backTexture->drawGL(visibleArea, opacity, transform); - bool needsRepaint = m_frontTexture->drawGL(visibleArea, opacity, transform); + bool needsRepaint = m_frontTexture->drawGL(visibleArea, opacity, transform, background); needsRepaint |= m_zooming; needsRepaint |= (m_scale <= 0); return needsRepaint; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index d1b0818..2e19cea 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.h +++ b/Source/WebCore/platform/graphics/android/TiledTexture.h @@ -62,7 +62,8 @@ public: TilePainter* painter, bool isLowResPrefetch = false, bool useExpandPrefetch = false); void swapTiles(); - bool drawGL(const IntRect& visibleArea, float opacity, const TransformationMatrix* transform); + bool drawGL(const IntRect& visibleArea, float opacity, + const TransformationMatrix* transform, const Color* background = 0); void prepareTile(int x, int y, TilePainter* painter, GLWebViewState* state, bool isLowResPrefetch, bool isExpandPrefetch); @@ -79,6 +80,7 @@ public: int nbTextures(IntRect& area, float scale); private: + void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground); Vector<BaseTile*> m_tiles; IntRect m_area; @@ -94,7 +96,6 @@ private: class DualTiledTexture : public SkRefCnt { // TODO: investigate webkit threadsafe ref counting public: - DualTiledTexture(bool isBaseSurface); ~DualTiledTexture(); void prepareGL(GLWebViewState* state, bool allowZoom, @@ -102,7 +103,8 @@ public: TilePainter* painter, bool aggressiveRendering); void swapTiles(); bool drawGL(const IntRect& visibleArea, float opacity, - const TransformationMatrix* transform, bool aggressiveRendering); + const TransformationMatrix* transform, bool aggressiveRendering, + const Color* background); void markAsDirty(const SkRegion& dirtyArea); void computeTexturesAmount(TexturesResult* result, LayerAndroid* layer); void discardTextures() diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 8f7efe2..540b1dd 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -871,16 +871,25 @@ BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region) #if USE(ACCELERATED_COMPOSITING) // We set the background color + Color background = Color::white; if (m_mainFrame && m_mainFrame->document() && m_mainFrame->document()->body()) { + bool hasCSSBackground = false; + Document* document = m_mainFrame->document(); RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body()); if (style->hasBackground()) { - Color color = style->visitedDependentColor(CSSPropertyBackgroundColor); - if (color.isValid() && color.alpha() > 0) - base->setBackgroundColor(color); + background = style->visitedDependentColor(CSSPropertyBackgroundColor); + hasCSSBackground = true; + } + + WebCore::FrameView* view = m_mainFrame->view(); + if (view) { + Color viewBackground = view->baseBackgroundColor(); + background = hasCSSBackground ? viewBackground.blend(background) : viewBackground; } } + base->setBackgroundColor(background); // We update the layers ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); |