summaryrefslogtreecommitdiffstats
path: root/Source/WebCore
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2012-04-02 09:47:14 -0700
committerTeng-Hui Zhu <ztenghui@google.com>2012-04-02 16:23:43 -0700
commitafe34397d6d4655c908f0995e760772980722da3 (patch)
tree5a1380e2d581391c33713c793b06cd577ca09da6 /Source/WebCore
parentde5a3eeb42d8930d4fd09d86953de929c450f7a6 (diff)
downloadexternal_webkit-afe34397d6d4655c908f0995e760772980722da3.zip
external_webkit-afe34397d6d4655c908f0995e760772980722da3.tar.gz
external_webkit-afe34397d6d4655c908f0995e760772980722da3.tar.bz2
Translucent background color support for webview
We need to respect the background color set for webview and combine that with the CSS background. Since we are tiled based and need to avoid double drawing, we need to determine the areas not covered by available tiles and draw the background. This involves a bit computation overhead. Therefore, we only compute those areas when alpha is between 1 to 254. When alpha is 255, we just need a glClear. When alpha is 0, nothing need to be drawn. Due to the fact that the tile can be partially drawn, texture generator need to know the background color to clear the tiles for the base layer. bug:5684832 Change-Id: I51f9d219f2722cc088eeea603623f9660f7a136a
Diffstat (limited to 'Source/WebCore')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp9
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.h3
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.cpp24
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.h2
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.cpp21
-rw-r--r--Source/WebCore/platform/graphics/android/LayerGroup.h10
-rw-r--r--Source/WebCore/platform/graphics/android/RasterRenderer.cpp16
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/SurfaceCollection.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/SurfaceCollectionManager.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/TilePainter.h2
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.cpp66
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.h8
14 files changed, 138 insertions, 40 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()