summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2012-01-03 15:08:57 -0800
committerTeng-Hui Zhu <ztenghui@google.com>2012-01-03 17:33:27 -0800
commit309ae897e0ad3493fc6acd97a39c631f90580d57 (patch)
treecc8132a00f1df47ac8e179b66eb7856f2dcde90b /Source/WebCore/platform/graphics
parent7eb17b2e00c46869b21bf5795fd9cdc93fca98e7 (diff)
downloadexternal_webkit-309ae897e0ad3493fc6acd97a39c631f90580d57.zip
external_webkit-309ae897e0ad3493fc6acd97a39c631f90580d57.tar.gz
external_webkit-309ae897e0ad3493fc6acd97a39c631f90580d57.tar.bz2
Employ the transfer queue to the pure color tiles
This fixed the sync problem for the pure color tiles. When Tex Gen thread detect that the tile is pure color, UI need to pick it up in the right time. To avoid adding too many sync object, the simplest way is following the same idea of transfer queue. At the same time, using a separate queue and adding simple operation on top of it can limit the impact to the original transfer queue which is highly coupled with SurfTex implemenation. bug:5808996 Change-Id: I518d358c5626815b27f285d4dcadcee9c3234835
Diffstat (limited to 'Source/WebCore/platform/graphics')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp31
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTileTexture.cpp26
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTileTexture.h9
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.cpp35
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.cpp6
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.h4
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp83
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.h16
9 files changed, 132 insertions, 80 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
index ea546ef..76ee1e7 100644
--- a/Source/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -124,7 +124,6 @@ void BaseTile::reserveTexture()
this, texture, m_backTexture, m_frontTexture);
m_state = Unpainted;
m_backTexture = texture;
- m_backTexture->setPure(false);
}
if (m_state == UpToDate) {
@@ -247,30 +246,9 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale)
if (!isTexturePainted)
return;
- if (m_frontTexture->readyFor(this)) {
- if (isLayerTile() && m_painter && m_painter->transform()) {
- if (m_frontTexture->isPureColor()) {
- TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(),
- rect, 0,
- transparency, true,
- GL_TEXTURE_2D,
- m_frontTexture->pureColor());
- } else {
- TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(),
- rect, m_frontTexture->m_ownTextureId,
- transparency, true);
- }
- } else {
- if (m_frontTexture->isPureColor()) {
- TilesManager::instance()->shader()->drawQuad(rect, 0,
- transparency,
- m_frontTexture->pureColor());
- } else {
- TilesManager::instance()->shader()->drawQuad(rect, m_frontTexture->m_ownTextureId,
- transparency);
- }
- }
- } else {
+ if (m_frontTexture->readyFor(this))
+ m_frontTexture->draw(isLayerTile(), m_painter, rect, transparency);
+ else {
XLOG("tile %p at %d, %d not readyfor (at draw),", this, m_x, m_y);
}
}
@@ -555,8 +533,7 @@ void BaseTile::validatePaint() {
// when both have happened, mark as 'ReadyToSwap'
if (m_state == PaintingStarted)
m_state = ValidatedUntransferred;
- else if (m_state == TransferredUnvalidated
- || (m_backTexture && m_backTexture->isPureColor())) {
+ else if (m_state == TransferredUnvalidated) {
// When the backTexture has been marked pureColor, we will skip the
// transfer and marked as ReadyToSwap, in this case, we don't want
// to reset m_dirty bit to true.
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
index ae6f1e8..b3a6b84 100644
--- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
@@ -149,12 +149,14 @@ void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info
bool BaseTileTexture::readyFor(BaseTile* baseTile)
{
- if (isPureColor()) {
+ const TextureTileInfo* info = &m_ownTextureTileInfo;
+
+ if (isPureColor() && info->m_painter == baseTile->painter()) {
XLOG("ReadyFor saw a pureColor tile (%p) at (%d, %d), rgb %x",
this, baseTile->x(), baseTile->y(), pureColor().rgb());
return true;
}
- const TextureTileInfo* info = &m_ownTextureTileInfo;
+
if (info &&
(info->m_x == baseTile->x()) &&
(info->m_y == baseTile->y()) &&
@@ -170,4 +172,24 @@ bool BaseTileTexture::readyFor(BaseTile* baseTile)
return false;
}
+void BaseTileTexture::draw(bool isLayer, TilePainter* painter,
+ SkRect& rect, float transparency)
+{
+ ShaderProgram* shader = TilesManager::instance()->shader();
+ if (isLayer && painter && painter->transform()) {
+ if (isPureColor()) {
+ shader->drawLayerQuad(*painter->transform(), rect, 0, transparency,
+ true, GL_TEXTURE_2D, pureColor());
+ } else {
+ shader->drawLayerQuad(*painter->transform(), rect, m_ownTextureId,
+ transparency, true);
+ }
+ } else {
+ if (isPureColor())
+ shader->drawQuad(rect, 0,transparency, pureColor());
+ else
+ shader->drawQuad(rect, m_ownTextureId, transparency);
+ }
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
index 74f9e5d..55314c7 100644
--- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
@@ -95,12 +95,15 @@ public:
TextureInfo* getTextureInfo() { return &m_ownTextureInfo; }
- void setPure(bool pure){ m_isPureColor = pure; }
+ // Make sure the following pureColor getter/setter are only read/written
+ // in UI thread. Therefore no need for a lock.
+ void setPure(bool pure) { m_isPureColor = pure; }
bool isPureColor() {return m_isPureColor; }
-
- void setPureColor(const Color& color) { m_pureColor = color; }
+ void setPureColor(const Color& color) { m_pureColor = color; setPure(true); }
Color pureColor() { return m_pureColor; }
+ void draw(bool isLayer, TilePainter* painter, SkRect& rect,
+ float transparency);
private:
TextureTileInfo m_ownTextureTileInfo;
// TODO: Merge this info into the TextureTileInfo.
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp
index 38e1ce9..2d18032 100644
--- a/Source/WebCore/platform/graphics/android/GLUtils.cpp
+++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp
@@ -387,6 +387,9 @@ bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor)
int bitmapWidth = bitmap.width();
// Create a row of pure color using the first pixel.
+ // TODO: improve the perf here, by either picking a random pixel, or
+ // creating an array of rows with pre-defined commonly used color, add
+ // smart LUT to speed things up if possible.
int* firstPixelPtr = static_cast<int*> (bitmap.getPixels());
int* pixelsRow = new int[bitmapWidth];
for (int i = 0; i < bitmapWidth; i++)
@@ -424,31 +427,17 @@ bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo,
BaseTileTexture* tileTexture = tilePtr->backTexture();
// Check the bitmap, and make everything ready here.
Color pureColor;
- bool pure = isPureColorBitmap(bitmap, pureColor);
- if (pure) {
+ if (tileTexture && isPureColorBitmap(bitmap, pureColor)) {
// update basetile's info
// Note that we are skipping the whole TransferQueue.
- if (tileTexture) {
- tileTexture->setPure(true);
- tileTexture->setPureColor(pureColor);
-
- TextureTileInfo info;
- // Now fill the tileInfo.
- info.m_x = renderInfo->x;
- info.m_y = renderInfo->y;
- info.m_scale = renderInfo->scale;
- info.m_painter = renderInfo->tilePainter;
- info.m_picture = renderInfo->textureInfo->m_pictureCount;
- info.m_inverted = TilesManager::instance()->invertedScreen();
-
- // Make sure the tile is considered ready!
- tileTexture->setOwnTextureTileInfoFromQueue(&info);
-
- renderInfo->textureInfo->m_width = bitmap.width();
- renderInfo->textureInfo->m_height = bitmap.height();
- renderInfo->textureInfo->m_internalFormat = GL_RGBA;
- skipTransfer = true;
- }
+ renderInfo->textureInfo->m_width = bitmap.width();
+ renderInfo->textureInfo->m_height = bitmap.height();
+ renderInfo->textureInfo->m_internalFormat = GL_RGBA;
+
+ TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo,
+ pureColor);
+
+ skipTransfer = true;
}
}
return skipTransfer;
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 89f1d27..ece019c 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -354,7 +354,7 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
int height = viewRect.height();
ShaderProgram* shader = TilesManager::instance()->shader();
- if (shader->needInit()) {
+ if (shader->needsInit()) {
XLOG("Reinit shader");
shader->init();
}
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
index e7d9434..62c00e7 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -217,7 +217,7 @@ ShaderProgram::ShaderProgram()
, m_contrast(1)
, m_alphaLayer(false)
, m_currentScale(1.0f)
- , m_needInit(true)
+ , m_needsInit(true)
{
init();
}
@@ -239,10 +239,10 @@ void ShaderProgram::init()
|| videoProgram == -1
|| texOESProgram == -1
|| texOESInvProgram == -1) {
- m_needInit = true;
+ m_needsInit = true;
return;
}
- m_needInit = false;
+ m_needsInit = false;
GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition");
GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix");
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
index 1bb40a4..3d7aab5 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -147,7 +147,7 @@ public:
void calculateAnimationDelta();
int getAnimationDeltaX() { return m_animationDelta.x(); }
int getAnimationDeltaY() { return m_animationDelta.y(); }
- bool needInit() { return m_needInit; }
+ bool needsInit() { return m_needsInit; }
private:
GLuint loadShader(GLenum shaderType, const char* pSource);
@@ -201,7 +201,7 @@ private:
// If there is any GL error happens such that the Shaders are not initialized
// successfully at the first time, then we need to init again when we draw.
- bool m_needInit;
+ bool m_needsInit;
// For transfer queue blitting, we need a special matrix map from (0,1) to
// (-1,1)
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
index bb7ed9b..5d47629 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -118,9 +118,9 @@ void TransferQueue::initSharedSurfaceTextures(int width, int height)
// When bliting, if the item from the transfer queue is mismatching b/t the
// BaseTile and the content, then the item is considered as obsolete, and
// the content is discarded.
-bool TransferQueue::checkObsolete(int index)
+bool TransferQueue::checkObsolete(const TileTransferData* data)
{
- BaseTile* baseTilePtr = m_transferQueue[index].savedBaseTilePtr;
+ BaseTile* baseTilePtr = data->savedBaseTilePtr;
if (!baseTilePtr) {
XLOG("Invalid savedBaseTilePtr , such that the tile is obsolete");
return true;
@@ -132,7 +132,7 @@ bool TransferQueue::checkObsolete(int index)
return true;
}
- const TextureTileInfo* tileInfo = &m_transferQueue[index].tileInfo;
+ const TextureTileInfo* tileInfo = &(data->tileInfo);
if (tileInfo->m_x != baseTilePtr->x()
|| tileInfo->m_y != baseTilePtr->y()
@@ -269,6 +269,8 @@ void TransferQueue::discardQueue()
if (m_transferQueue[i].status == pendingBlit)
m_transferQueue[i].status = pendingDiscard;
+ m_pureColorTileQueue.clear();
+
bool GLContextExisted = getHasGLContext();
// Unblock the Tex Gen thread first before Tile Page deletion.
// Otherwise, there will be a deadlock while removing operations.
@@ -279,6 +281,26 @@ void TransferQueue::discardQueue()
m_transferQueueItemCond.signal();
}
+void TransferQueue::updatePureColorTiles()
+{
+ for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
+ TileTransferData* data = &m_pureColorTileQueue[i];
+ if (data->status == pendingBlit) {
+ BaseTileTexture* destTexture = 0;
+ bool obsoleteBaseTile = checkObsolete(data);
+ if (!obsoleteBaseTile) {
+ destTexture = data->savedBaseTilePtr->backTexture();
+ destTexture->setPureColor(data->pureColor);
+ destTexture->setOwnTextureTileInfoFromQueue(&data->tileInfo);
+ }
+ } else if (data->status == emptyItem || data->status == pendingDiscard) {
+ // The queue should be clear instead of setting to different status.
+ XLOG("Warning: Don't expect an emptyItem here.");
+ }
+ }
+ m_pureColorTileQueue.clear();
+}
+
// Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture.
void TransferQueue::updateDirtyBaseTiles()
{
@@ -288,6 +310,9 @@ void TransferQueue::updateDirtyBaseTiles()
if (!getHasGLContext())
setHasGLContext(true);
+ // Check the pure color tile first, since it is simpler.
+ updatePureColorTiles();
+
// Start from the oldest item, we call the updateTexImage to retrive
// the texture and blit that into each BaseTile's texture.
const int nextItemIndex = getNextTransferQueueIndex();
@@ -295,7 +320,7 @@ void TransferQueue::updateDirtyBaseTiles()
bool usedFboForUpload = false;
for (int k = 0; k < ST_BUFFER_NUMBER ; k++) {
if (m_transferQueue[index].status == pendingBlit) {
- bool obsoleteBaseTile = checkObsolete(index);
+ bool obsoleteBaseTile = checkObsolete(&m_transferQueue[index]);
// Save the needed info, update the Surf Tex, clean up the item in
// the queue. Then either move on to next item or copy the content.
BaseTileTexture* destTexture = 0;
@@ -337,6 +362,7 @@ void TransferQueue::updateDirtyBaseTiles()
// will find the latest texture's info
// We don't need a map any more, each texture contains its own
// texturesTileInfo.
+ destTexture->setPure(false);
destTexture->setOwnTextureTileInfoFromQueue(&m_transferQueue[index].tileInfo);
XLOG("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
@@ -433,6 +459,39 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
return true;
}
+void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color)
+{
+ // The pure color tiles' queue will be read from UI thread and written in
+ // Tex Gen thread, thus we need to have a lock here.
+ android::Mutex::Autolock lock(m_transferQueueItemLocks);
+ TileTransferData data;
+ addItemCommon(renderInfo, GpuUpload, &data);
+ data.pureColor = color;
+ m_pureColorTileQueue.append(data);
+}
+
+// Translates the info from TileRenderInfo and others to TileTransferData.
+// This is used by pure color tiles and normal tiles.
+void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo,
+ TextureUploadType type,
+ TileTransferData* data)
+{
+ data->savedBaseTileTexturePtr = renderInfo->baseTile->backTexture();
+ data->savedBaseTilePtr = renderInfo->baseTile;
+ data->status = pendingBlit;
+ data->uploadType = type;
+
+ // Now fill the tileInfo.
+ TextureTileInfo* textureInfo = &(data->tileInfo);
+
+ textureInfo->m_x = renderInfo->x;
+ textureInfo->m_y = renderInfo->y;
+ textureInfo->m_scale = renderInfo->scale;
+ textureInfo->m_painter = renderInfo->tilePainter;
+
+ textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount;
+}
+
// Note that there should be lock/unlock around this function call.
// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
@@ -447,10 +506,8 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
XLOG("ERROR update a tile which is dirty already @ index %d", index);
}
- m_transferQueue[index].savedBaseTileTexturePtr = renderInfo->baseTile->backTexture();
- m_transferQueue[index].savedBaseTilePtr = renderInfo->baseTile;
- m_transferQueue[index].status = pendingBlit;
- m_transferQueue[index].uploadType = type;
+ TileTransferData* data = &m_transferQueue[index];
+ addItemCommon(renderInfo, type, data);
if (type == CpuUpload && bitmap) {
// Lazily create the bitmap
if (!m_transferQueue[index].bitmap) {
@@ -462,16 +519,6 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config());
}
- // Now fill the tileInfo.
- TextureTileInfo* textureInfo = &m_transferQueue[index].tileInfo;
-
- textureInfo->m_x = renderInfo->x;
- textureInfo->m_y = renderInfo->y;
- textureInfo->m_scale = renderInfo->scale;
- textureInfo->m_painter = renderInfo->tilePainter;
-
- textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount;
-
m_emptyItemCount--;
}
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h
index b33a576..629935f 100644
--- a/Source/WebCore/platform/graphics/android/TransferQueue.h
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.h
@@ -93,6 +93,9 @@ public:
// lazily allocated.
SkBitmap* bitmap;
+ // Specific data to the pure color tiles' queue.
+ Color pureColor;
+
// Sync object for GPU fence, this is the only the info passed from UI
// thread to Tex Gen thread. The reason of having this is due to the
// missing sync mechanism on Surface Texture on some vendor. b/5122031.
@@ -133,6 +136,8 @@ public:
void lockQueue() { m_transferQueueItemLocks.lock(); }
void unlockQueue() { m_transferQueueItemLocks.unlock(); }
+ void addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color);
+
// This queue can be accessed from UI and TexGen thread, therefore, we need
// a lock to protect its access
TileTransferData* m_transferQueue;
@@ -157,7 +162,7 @@ private:
void restoreGLState();
// Check the current transfer queue item is obsolete or not.
- bool checkObsolete(int index);
+ bool checkObsolete(const TileTransferData* data);
// Before each draw call and the blit operation, clean up all the
// pendingDiscard items.
@@ -167,6 +172,10 @@ private:
GLuint srcTexId, GLenum srcTexTarget,
int index);
+ void addItemCommon(const TileRenderInfo* renderInfo,
+ TextureUploadType type, TileTransferData* data);
+
+ void updatePureColorTiles();
// Note that the m_transferQueueIndex only changed in the TexGen thread
// where we are going to move on to update the next item in the queue.
int m_transferQueueIndex;
@@ -202,6 +211,11 @@ private:
// This should be GpuUpload for production, but for debug purpose or working
// around driver/HW issue, we can set it to CpuUpload.
TextureUploadType m_currentUploadType;
+
+ // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is
+ // resource limited. To get better performance, it is better to separate
+ // the pure color tile into another queue.
+ WTF::Vector<TileTransferData> m_pureColorTileQueue;
};
} // namespace WebCore