diff options
Diffstat (limited to 'Source/WebCore/platform/graphics')
15 files changed, 516 insertions, 298 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 73b6422..76ee1e7 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -246,15 +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()) - TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(), - rect, m_frontTexture->m_ownTextureId, - transparency, true); - 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); } } @@ -539,9 +533,12 @@ void BaseTile::validatePaint() { // when both have happened, mark as 'ReadyToSwap' if (m_state == PaintingStarted) m_state = ValidatedUntransferred; - else if (m_state == TransferredUnvalidated) + 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. m_state = ReadyToSwap; - else { + } else { XLOG("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d", this, m_x, m_y, m_state); // failed transferring, in which case mark dirty (since diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index 6da1b77..b3a6b84 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -54,6 +54,7 @@ namespace WebCore { BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) : m_owner(0) + , m_isPureColor(false) { m_size.set(w, h); m_ownTextureId = 0; @@ -149,6 +150,13 @@ void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info bool BaseTileTexture::readyFor(BaseTile* baseTile) { 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; + } + if (info && (info->m_x == baseTile->x()) && (info->m_y == baseTile->y()) && @@ -164,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 379d587..55314c7 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -95,6 +95,15 @@ public: TextureInfo* getTextureInfo() { return &m_ownTextureInfo; } + // 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; 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. @@ -104,6 +113,11 @@ private: // BaseTile owning the texture, only modified by UI thread TextureOwner* m_owner; + + // When the whole tile is single color, skip the transfer queue and draw + // it directly through shader. + bool m_isPureColor; + Color m_pureColor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp index e4fa435..fc254c0 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp @@ -198,10 +198,6 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) void FontPlatformData::setupPaint(SkPaint* paint) const { - float ts = mTextSize; - if (!(ts > 0)) - ts = 12; - if (hashTableDeletedFontValue() == mTypeface) paint->setTypeface(0); else @@ -210,7 +206,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); - paint->setTextSize(SkFloatToScalar(ts)); + paint->setTextSize(SkFloatToScalar(mTextSize)); paint->setFakeBoldText(mFakeBold); paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); #ifndef SUPPORT_COMPLEX_SCRIPTS diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index afb9bb0..2693651 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -237,7 +237,7 @@ static EGLConfig defaultPbufferConfig(EGLDisplay display) eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); GLUtils::checkEglError("eglPbufferConfig"); if (numConfigs != 1) - LOGI("eglPbufferConfig failed (%d)\n", numConfigs); + ALOGI("eglPbufferConfig failed (%d)\n", numConfigs); return config; } @@ -376,6 +376,73 @@ GLuint GLUtils::createBaseTileGLTexture(int width, int height) return texture; } +bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) +{ + // If the bitmap is the pure color, skip the transfer step, and update the BaseTile Info. + // This check is taking < 1ms if we do full bitmap check per tile. + // TODO: use the SkPicture to determine whether or not a tile is single color. + pureColor = Color(Color::transparent); + bitmap.lockPixels(); + bool sameColor = true; + 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++) + pixelsRow[i] = (*firstPixelPtr); + + // Then compare the pure color row with each row of the bitmap. + for (int j = 0; j < bitmap.height(); j++) { + if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) { + sameColor = false; + break; + } + } + delete pixelsRow; + pixelsRow = 0; + + if (sameColor) { + char* rgbaPtr = static_cast<char*>(bitmap.getPixels()); + pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + XLOG("sameColor tile found , %x at (%d, %d, %d, %d)", + *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]); + } + bitmap.unlockPixels(); + + return sameColor; +} + +// Return true when the tile is pure color. +bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) +{ + bool skipTransfer = false; + BaseTile* tilePtr = renderInfo->baseTile; + + if (tilePtr) { + BaseTileTexture* tileTexture = tilePtr->backTexture(); + // Check the bitmap, and make everything ready here. + Color pureColor; + if (tileTexture && isPureColorBitmap(bitmap, pureColor)) { + // update basetile's info + // Note that we are skipping the whole TransferQueue. + 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; +} + void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { @@ -386,6 +453,9 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkSize& requiredSize = renderInfo->tileSize; TextureInfo* textureInfo = renderInfo->textureInfo; + if (skipTransferForPureColor(renderInfo, bitmap)) + return; + if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); else { diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 48235a5..3475760 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -28,6 +28,7 @@ #if USE(ACCELERATED_COMPOSITING) +#include "Color.h" #include "SkBitmap.h" #include "SkMatrix.h" #include "SkSize.h" @@ -80,6 +81,10 @@ public: static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap); static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); + + static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); + static bool skipTransferForPureColor(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap); }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index a6b3d11..bcb85bc 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -116,9 +116,6 @@ GLWebViewState::GLWebViewState() GLWebViewState::~GLWebViewState() { - // Take care of the transfer queue such that Tex Gen thread will not stuck - TilesManager::instance()->unregisterGLWebViewState(this); - // We have to destroy the two tiled pages first as their destructor // may depend on the existence of this GLWebViewState and some of its // instance variables in order to complete. @@ -354,7 +351,7 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect, int height = viewRect.height(); ShaderProgram* shader = TilesManager::instance()->shader(); - if (shader->program() == -1) { + 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 2a6a488..a706276 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -62,6 +62,26 @@ static const char gFragmentShader[] = " gl_FragColor *= alpha; " "}\n"; +// We could pass the pureColor into either Vertex or Frag Shader. +// The reason we passed the color into the Vertex Shader is that some driver +// might create redundant copy when uniforms in fragment shader changed. +static const char gPureColorVertexShader[] = + "attribute vec4 vPosition;\n" + "uniform mat4 projectionMatrix;\n" + "uniform vec4 inputColor;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_Position = projectionMatrix * vPosition;\n" + " v_color = inputColor;\n" + "}\n"; + +static const char gPureColorFragmentShader[] = + "precision mediump float;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " gl_FragColor = v_color;\n" + "}\n"; + static const char gFragmentShaderInverted[] = "precision mediump float;\n" "varying vec2 v_texCoord; \n" @@ -151,7 +171,7 @@ GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource) return shader; } -GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) +GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource) { GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); if (!vertexShader) { @@ -197,57 +217,80 @@ ShaderProgram::ShaderProgram() , m_contrast(1) , m_alphaLayer(false) , m_currentScale(1.0f) + , m_needsInit(true) { init(); } void ShaderProgram::init() { - m_program = createProgram(gVertexShader, gFragmentShader); - m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted); - m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); - m_surfTexOESProgram = + GLint tex2DProgram = createProgram(gVertexShader, gFragmentShader); + GLint pureColorProgram = createProgram(gPureColorVertexShader, gPureColorFragmentShader); + GLint tex2DInvProgram = createProgram(gVertexShader, gFragmentShaderInverted); + GLint videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader); + GLint texOESProgram = createProgram(gVertexShader, gSurfaceTextureOESFragmentShader); - m_surfTexOESProgramInverted = + GLint texOESInvProgram = createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted); - if (m_program == -1 - || m_programInverted == -1 - || m_videoProgram == -1 - || m_surfTexOESProgram == -1 - || m_surfTexOESProgramInverted == -1) + if (tex2DProgram == -1 + || pureColorProgram == -1 + || tex2DInvProgram == -1 + || videoProgram == -1 + || texOESProgram == -1 + || texOESInvProgram == -1) { + m_needsInit = true; return; - - m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix"); - m_hAlpha = glGetUniformLocation(m_program, "alpha"); - m_hTexSampler = glGetUniformLocation(m_program, "s_texture"); - m_hPosition = glGetAttribLocation(m_program, "vPosition"); - - m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix"); - m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha"); - m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast"); - m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture"); - m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition"); - - m_hVideoProjectionMatrix = - glGetUniformLocation(m_videoProgram, "projectionMatrix"); - m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix"); - m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture"); - m_hVideoPosition = glGetAttribLocation(m_program, "vPosition"); - - m_hSTOESProjectionMatrix = - glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix"); - m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha"); - m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture"); - m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition"); - - m_hSTOESProjectionMatrixInverted = - glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix"); - m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha"); - m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast"); - m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture"); - m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition"); - + } + m_needsInit = false; + + GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition"); + GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix"); + GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor"); + m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram, + pureColorProjMtx, pureColorValue, -1, -1); + + GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha"); + GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition"); + GLint tex2DProjMtx = glGetUniformLocation(tex2DProgram, "projectionMatrix"); + GLint tex2DTexSampler = glGetUniformLocation(tex2DProgram, "s_texture"); + m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram, + tex2DProjMtx, -1, tex2DTexSampler, -1); + + GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha"); + GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast"); + GLint tex2DInvPosition = glGetAttribLocation(tex2DInvProgram, "vPosition"); + GLint tex2DInvProjMtx = glGetUniformLocation(tex2DInvProgram, "projectionMatrix"); + GLint tex2DInvTexSampler = glGetUniformLocation(tex2DInvProgram, "s_texture"); + m_handleArray[Tex2DInv].init(tex2DInvAlpha, tex2DInvContrast, + tex2DInvPosition, tex2DInvProgram, + tex2DInvProjMtx, -1, + tex2DInvTexSampler, -1); + + GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha"); + GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition"); + GLint texOESProjMtx = glGetUniformLocation(texOESProgram, "projectionMatrix"); + GLint texOESTexSampler = glGetUniformLocation(texOESProgram, "s_texture"); + m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram, + texOESProjMtx, -1, texOESTexSampler, -1); + + GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha"); + GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast"); + GLint texOESInvPosition = glGetAttribLocation(texOESInvProgram, "vPosition"); + GLint texOESInvProjMtx = glGetUniformLocation(texOESInvProgram, "projectionMatrix"); + GLint texOESInvTexSampler = glGetUniformLocation(texOESInvProgram, "s_texture"); + m_handleArray[TexOESInv].init(texOESInvAlpha, texOESInvContrast, + texOESInvPosition, texOESInvProgram, + texOESInvProjMtx, -1, + texOESInvTexSampler, -1); + + GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition"); + GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix"); + GLint videoTexSampler = glGetUniformLocation(videoProgram, "s_yuvTexture"); + GLint videoTexMtx = glGetUniformLocation(videoProgram, "textureMatrix"); + m_handleArray[Video].init(-1, -1, videoPosition, videoProgram, + videoProjMtx, -1, videoTexSampler, + videoTexMtx); const GLfloat coord[] = { 0.0f, 0.0f, // C @@ -260,6 +303,12 @@ void ShaderProgram::init() glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW); + TransformationMatrix matrix; + // Map x,y from (0,1) to (-1, 1) + matrix.scale3d(2, 2, 1); + matrix.translate3d(-0.5, -0.5, 0); + GLUtils::toGLMatrix(m_transferProjMtx, matrix); + GLUtils::checkGlError("init"); } @@ -298,7 +347,8 @@ void ShaderProgram::setViewport(SkRect& viewport, float scale) m_currentScale = scale; } -void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle) +// Calculate the matrix given the geometry. +void ShaderProgram::setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr) { TransformationMatrix translate; translate.translate3d(geometry.fLeft, geometry.fTop, 0.0); @@ -312,89 +362,73 @@ void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrix else total = m_projectionMatrix * translate * scale; - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, total); - glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); + GLUtils::toGLMatrix(mtxPtr, total); } -void ShaderProgram::drawQuadInternal(SkRect& geometry, - GLint textureId, - float opacity, - GLint program, - GLint projectionMatrixHandle, - GLint texSampler, - GLenum textureTarget, - GLint position, - GLint alpha, - GLint texFilter, - GLint contrast) +// Calculate the right color value sent into the shader considering the (0,1) +// clamp and alpha blending. +Color ShaderProgram::shaderColor(Color pureColor, float opacity) { - glUseProgram(program); - - if (!geometry.isEmpty()) - setProjectionMatrix(geometry, projectionMatrixHandle); - else { - TransformationMatrix matrix; - // Map x,y from (0,1) to (-1, 1) - matrix.scale3d(2, 2, 1); - matrix.translate3d(-0.5, -0.5, 0); - GLfloat projectionMatrix[16]; - GLUtils::toGLMatrix(projectionMatrix, matrix); - glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); + float r = pureColor.red() / 255.0; + float g = pureColor.green() / 255.0; + float b = pureColor.blue() / 255.0; + float a = pureColor.alpha() / 255.0; + + if (TilesManager::instance()->invertedScreen()) { + float intensity = a - (0.2989 * r + 0.5866 * g + 0.1145 * b); + intensity = ((intensity - a / 2.0) * m_contrast) + a / 2.0; + intensity *= opacity; + return Color(intensity, intensity, intensity, a * opacity); } - - glActiveTexture(GL_TEXTURE0); - glUniform1i(texSampler, 0); - glBindTexture(textureTarget, textureId); - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(position); - glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glUniform1f(alpha, opacity); - if (contrast != -1) - glUniform1f(contrast, m_contrast); - - setBlendingState(opacity < 1.0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + return Color(r * opacity, g * opacity, b * opacity, a * opacity); } -void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity, - GLenum textureTarget, GLint texFilter) +// For shaders using texture, it is easy to get the type from the textureTarget. +ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget) { + ShaderType type = UndefinedShader; if (textureTarget == GL_TEXTURE_2D) { - if (!TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_program, - m_hProjectionMatrix, - m_hTexSampler, GL_TEXTURE_2D, - m_hPosition, m_hAlpha, texFilter); - } else { + if (!TilesManager::instance()->invertedScreen()) + type = Tex2D; + else { // With the new GPU texture upload path, we do not use an FBO // to blit the texture we receive from the TexturesGenerator thread. // To implement inverted rendering, we thus have to do the rendering // live, by using a different shader. - drawQuadInternal(geometry, textureId, opacity, m_programInverted, - m_hProjectionMatrixInverted, - m_hTexSamplerInverted, GL_TEXTURE_2D, - m_hPositionInverted, m_hAlphaInverted, texFilter, - m_hContrastInverted); + type = Tex2DInv; } - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && !TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram, - m_hSTOESProjectionMatrix, - m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES, - m_hSTOESPosition, m_hSTOESAlpha, texFilter); - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && TilesManager::instance()->invertedScreen()) { - drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted, - m_hSTOESProjectionMatrixInverted, - m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES, - m_hSTOESPositionInverted, m_hSTOESAlphaInverted, - texFilter, m_hSTOESContrastInverted); + } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES) { + if (!TilesManager::instance()->invertedScreen()) + type = TexOES; + else + type = TexOESInv; + } + return type; +} + +void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity, + Color pureColor, GLenum textureTarget, GLint texFilter) +{ + ShaderType type = UndefinedShader; + if (!textureId) { + pureColor = shaderColor(pureColor, opacity); + if (pureColor.rgb() == Color::transparent && opacity < 1.0) + return; + type = PureColor; + } else + type = getTextureShaderType(textureTarget); + + if (type != UndefinedShader) { + // The matrix is either for the transfer queue or the tiles + GLfloat* finalMatrix = m_transferProjMtx; + GLfloat projectionMatrix[16]; + if (!geometry.isEmpty()) { + setProjectionMatrix(geometry, projectionMatrix); + finalMatrix = projectionMatrix; + } + setBlendingState(opacity < 1.0); + drawQuadInternal(type, finalMatrix, textureId, opacity, textureTarget, + texFilter, pureColor); } GLUtils::checkGlError("drawQuad"); } @@ -530,40 +564,45 @@ float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, flo return result.z(); } -void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix, - int textureId, float opacity, - GLenum textureTarget, GLint program, - GLint matrix, GLint texSample, - GLint position, GLint alpha, - GLint contrast) +void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix, + int textureId, float opacity, + GLenum textureTarget, GLenum filter, + const Color& pureColor) { - glUseProgram(program); - glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix); - - glActiveTexture(GL_TEXTURE0); - glUniform1i(texSample, 0); - glBindTexture(textureTarget, textureId); - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + glUseProgram(m_handleArray[type].programHandle); + glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix); + + if (type != PureColor) { + glActiveTexture(GL_TEXTURE0); + glUniform1i(m_handleArray[type].texSamplerHandle, 0); + glBindTexture(textureTarget, textureId); + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter); + glUniform1f(m_handleArray[type].alphaHandle, opacity); + + GLint contrastHandle = m_handleArray[type].contrastHandle; + if (contrastHandle != -1) + glUniform1f(contrastHandle, m_contrast); + } else { + glUniform4f(m_handleArray[type].pureColorHandle, + pureColor.red() / 255.0, pureColor.green() / 255.0, + pureColor.blue() / 255.0, pureColor.alpha() / 255.0); + } + GLint positionHandle = m_handleArray[type].positionHandle; glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(position); - glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0); - glUniform1f(alpha, opacity); - if (contrast != -1) - glUniform1f(contrast, m_contrast); -} + glEnableVertexAttribArray(positionHandle); + glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, const SkRect& geometry, int textureId, float opacity, bool forceBlending, - GLenum textureTarget) + GLenum textureTarget, + Color pureColor) { - TransformationMatrix modifiedDrawMatrix = drawMatrix; // move the drawing depending on where the texture is on the layer modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); @@ -578,37 +617,23 @@ void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, renderMatrix); - if (textureTarget == GL_TEXTURE_2D) { - if (!TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_2D, m_program, - m_hProjectionMatrix, m_hTexSampler, - m_hPosition, m_hAlpha); - } else { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_2D, m_programInverted, - m_hProjectionMatrixInverted, m_hTexSamplerInverted, - m_hPositionInverted, m_hAlphaInverted, - m_hContrastInverted); - } - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && !TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram, - m_hSTOESProjectionMatrix, m_hSTOESTexSampler, - m_hSTOESPosition, m_hSTOESAlpha); - } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES - && TilesManager::instance()->invertedScreen()) { - drawLayerQuadInternal(projectionMatrix, textureId, opacity, - GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted, - m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted, - m_hSTOESPositionInverted, m_hSTOESAlphaInverted, - m_hSTOESContrastInverted); + bool enableBlending = forceBlending || opacity < 1.0; + + ShaderType type = UndefinedShader; + if (!textureId) { + pureColor = shaderColor(pureColor, opacity); + if (pureColor.rgb() == Color::transparent && enableBlending) + return; + type = PureColor; + } else + type = getTextureShaderType(textureTarget); + + if (type != UndefinedShader) { + setBlendingState(enableBlending); + drawQuadInternal(type, projectionMatrix, textureId, opacity, + textureTarget, GL_LINEAR, pureColor); } - setBlendingState(forceBlending || opacity < 1.0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - GLUtils::checkGlError("drawLayerQuad"); } @@ -617,7 +642,7 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, int textureId) { // switch to our custom yuv video rendering program - glUseProgram(m_videoProgram); + glUseProgram(m_handleArray[Video].programHandle); TransformationMatrix modifiedDrawMatrix = drawMatrix; modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop); @@ -626,16 +651,19 @@ void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix, GLfloat projectionMatrix[16]; GLUtils::toGLMatrix(projectionMatrix, renderMatrix); - glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix); - glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix); + glUniformMatrix4fv(m_handleArray[Video].projMtxHandle, 1, GL_FALSE, + projectionMatrix); + glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE, + textureMatrix); glActiveTexture(GL_TEXTURE0); - glUniform1i(m_hVideoTexSampler, 0); + glUniform1i(m_handleArray[Video].texSamplerHandle, 0); glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); + GLint videoPosition = m_handleArray[Video].positionHandle; glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]); - glEnableVertexAttribArray(m_hVideoPosition); - glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(videoPosition); + glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0); setBlendingState(false); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h index 9ab7a46..3d7aab5 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h @@ -19,6 +19,7 @@ #if USE(ACCELERATED_COMPOSITING) +#include "Color.h" #include "FloatRect.h" #include "IntRect.h" #include "SkRect.h" @@ -29,11 +30,60 @@ namespace WebCore { +enum ShaderType { + UndefinedShader = -1, + PureColor, + Tex2D, + Tex2DInv, + TexOES, + TexOESInv, + Video, + // When growing this enum list, make sure to insert before the + // MaxShaderNumber and init the m_handleArray accordingly. + MaxShaderNumber +}; + +struct ShaderHandles { + ShaderHandles() + : alphaHandle(-1) + , contrastHandle(-1) + , positionHandle(-1) + , programHandle(-1) + , projMtxHandle(-1) + , pureColorHandle(-1) + , texSamplerHandle(-1) + , videoMtxHandle(-1) + { + } + + void init(GLint alphaHdl, GLint contrastHdl, GLint posHdl, GLint pgmHdl, + GLint projMtxHdl, GLint colorHdl, GLint texSamplerHdl, + GLint videoMtxHdl) + { + alphaHandle = alphaHdl; + contrastHandle = contrastHdl; + positionHandle = posHdl; + programHandle = pgmHdl; + projMtxHandle = projMtxHdl; + pureColorHandle = colorHdl; + texSamplerHandle = texSamplerHdl; + videoMtxHandle = videoMtxHdl; + } + + GLint alphaHandle; + GLint contrastHandle; + GLint positionHandle; + GLint programHandle; + GLint projMtxHandle; + GLint pureColorHandle; + GLint texSamplerHandle; + GLint videoMtxHandle; +}; + class ShaderProgram { public: ShaderProgram(); void init(); - int program() { return m_program; } // Drawing void setViewport(SkRect& viewport, float scale); @@ -44,19 +94,16 @@ public: // Normal texture in GL_TEXTURE_2D target. // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES // Surface texture in GL_TEXTURE_EXTERNAL_OES target. - // 3) textureTarget == 0 (Will be deprecated soon) - // Surface texture in GL_TEXTURE_2D target. - // - // TODO: Shrink the support modes into 2 (1 and 2) after media framework - // support Surface texture in GL_TEXTURE_EXTERNAL_OES target on all - // platforms. - void drawQuad(SkRect& geometry, int textureId, float opacity, + // 3) textureId == 0 + // No texture needed, just a pureColor quad. + void drawQuad(SkRect& geometry, int textureId, float opacity, Color pureColor = Color(), GLenum textureTarget = GL_TEXTURE_2D, GLint texFilter = GL_LINEAR); void drawLayerQuad(const TransformationMatrix& drawMatrix, const SkRect& geometry, int textureId, float opacity, bool forceBlending = false, - GLenum textureTarget = GL_TEXTURE_2D); + GLenum textureTarget = GL_TEXTURE_2D, + Color pureColor = Color()); void drawVideoLayerQuad(const TransformationMatrix& drawMatrix, float* textureMatrix, SkRect& geometry, int textureId); void setViewRect(const IntRect& viewRect); @@ -100,33 +147,21 @@ public: void calculateAnimationDelta(); int getAnimationDeltaX() { return m_animationDelta.x(); } int getAnimationDeltaY() { return m_animationDelta.y(); } + bool needsInit() { return m_needsInit; } private: GLuint loadShader(GLenum shaderType, const char* pSource); - GLuint createProgram(const char* vertexSource, const char* fragmentSource); - void setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle); - + GLint createProgram(const char* vertexSource, const char* fragmentSource); + void setProjectionMatrix(const SkRect& geometry, GLfloat* mtxPtr); void setBlendingState(bool enableBlending); - - void drawQuadInternal(SkRect& geometry, GLint textureId, float opacity, - GLint program, GLint projectionMatrixHandle, - GLint texSampler, GLenum textureTarget, - GLint position, GLint alpha, - GLint texFilter, GLint contrast = -1); - - void drawLayerQuadInternal(const GLfloat* projectionMatrix, int textureId, - float opacity, GLenum textureTarget, GLint program, - GLint matrix, GLint texSample, - GLint position, GLint alpha, GLint contrast = -1); + void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId, + float opacity, GLenum textureTarget, GLenum filter, + const Color& pureColor); + Color shaderColor(Color pureColor, float opacity); + ShaderType getTextureShaderType(GLenum textureTarget); bool m_blendingEnabled; - int m_program; - int m_programInverted; - int m_videoProgram; - int m_surfTexOESProgram; - int m_surfTexOESProgramInverted; - TransformationMatrix m_projectionMatrix; GLuint m_textureBuffer[1]; @@ -141,37 +176,9 @@ private: FloatRect m_documentViewport; - // uniforms - GLint m_hProjectionMatrix; - GLint m_hAlpha; - GLint m_hTexSampler; - GLint m_hProjectionMatrixInverted; - GLint m_hAlphaInverted; - GLint m_hContrastInverted; - GLint m_hTexSamplerInverted; - GLint m_hVideoProjectionMatrix; - GLint m_hVideoTextureMatrix; - GLint m_hVideoTexSampler; - - GLint m_hSTOESProjectionMatrix; - GLint m_hSTOESAlpha; - GLint m_hSTOESTexSampler; - GLint m_hSTOESPosition; - - GLint m_hSTOESProjectionMatrixInverted; - GLint m_hSTOESAlphaInverted; - GLint m_hSTOESContrastInverted; - GLint m_hSTOESTexSamplerInverted; - GLint m_hSTOESPositionInverted; - float m_contrast; - // attribs - GLint m_hPosition; - GLint m_hPositionInverted; - GLint m_hVideoPosition; - - bool m_alphaLayer; + bool m_alphaLayer; TransformationMatrix m_webViewMatrix; float m_currentScale; @@ -184,8 +191,21 @@ private: // TODO: Given that m_webViewMatrix contains most of the tranformation // information, we should be able to get rid of some parameter we got from // Java side and simplify our code. - TransformationMatrix m_repositionMatrix; + TransformationMatrix m_repositionMatrix; IntPoint m_animationDelta; + + // Put all the uniform location (handle) info into an array, and group them + // by the shader's type, this can help to clean up the interface. + // TODO: use the type and data comparison to skip GL call if possible. + ShaderHandles m_handleArray[MaxShaderNumber]; + + // 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_needsInit; + + // For transfer queue blitting, we need a special matrix map from (0,1) to + // (-1,1) + GLfloat m_transferProjMtx[16]; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 452a010..136b5a7 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -93,9 +93,13 @@ void TiledPage::updateBaseTileSize() TiledPage::~TiledPage() { + TilesManager* tilesManager = TilesManager::instance(); // 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::instance()->removeOperationsForPage(this); + tilesManager->removeOperationsForPage(this); + // 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()->discardQueue(); delete[] m_baseTiles; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledPage"); diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index e36ba36..fbf7ae6 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -113,7 +113,7 @@ TilesManager::TilesManager() m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_pixmapsGenerationThread = new TexturesGenerator(); - m_pixmapsGenerationThread->run("TexturesGenerator", android::PRIORITY_BACKGROUND); + m_pixmapsGenerationThread->run("TexturesGenerator"); } void TilesManager::allocateTiles() @@ -479,13 +479,6 @@ void TilesManager::paintedSurfacesCleanup(GLWebViewState* state) } } -void TilesManager::unregisterGLWebViewState(GLWebViewState* state) -{ - // Discard the whole queue b/c we lost GL context already. - // Note the real updateTexImage will still wait for the next draw. - transferQueue()->discardQueue(); -} - TilesManager* TilesManager::instance() { if (!gInstance) { diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 396cf93..f798196 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -115,7 +115,6 @@ public: static float layerTileWidth(); static float layerTileHeight(); void paintedSurfacesCleanup(GLWebViewState* state = 0); - void unregisterGLWebViewState(GLWebViewState* state); void allocateTiles(); 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 diff --git a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp index 6e715e2..47c0613 100644 --- a/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp +++ b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp @@ -34,27 +34,30 @@ static const UChar vTextCnvTable[][2] = { // TODO: uncomment mappings once we add glyphs for vertical forms. - // {0x0021, 0xfe15}, // exclamation mark + {0x0021, 0xfe15}, // exclamation mark {0x0028, 0xfe35}, // left paren {0x0029, 0xfe36}, // right paren - // {0x002c, 0xfe10}, // comma + {0x002c, 0xfe10}, // comma + {0x002d, 0xfe32}, // hyphen {0x003a, 0xfe30}, // colon - {0x003b, 0x007c}, // hyphen - // {0x003f, 0xfe16}, // question mark - // {0x005b, 0xfe14}, // semicolon - {0x005d, 0xfe47}, // left square bracket - {0x005f, 0xfe48}, // right square bracket + {0x003b, 0xfe14}, // semicolon + {0x003f, 0xfe16}, // question mark + {0x005b, 0xfe47}, // left square bracket + {0x005d, 0xfe48}, // right square bracket {0x007b, 0xfe37}, // left curly bracket {0x007d, 0xfe38}, // right curly bracket {0x007e, 0x007c}, // tilde to vertical line + {0x00ab, 0xfe3d}, // left pointing double angle quotation mark + {0x00bb, 0xfe3e}, // right pointing double angle quotation mark + {0x2010, 0xfe32}, // hyphen {0x2013, 0xfe32}, // en dash {0x2014, 0xfe31}, // em dash {0x2015, 0xfe31}, // horizontal bar {0x2025, 0xfe30}, // two dot leader - // TODO: change the mapping 0x2026 -> 0xFE19 once Android has the glyph for 0xFE19. - {0x2026, 0xfe30}, // three dot leader - // {0x3001, 0xfe11}, // Ideographic comma - // {0x3002, 0xfe12}, // Ideographic full stop + {0x2026, 0xfe19}, // three dot leader + // TODO: change the mapping 0x3001 -> 0xFE11 once Android has the glyph for 0xFE11. + {0x3001, 0xfe10}, // Ideographic comma + {0x3002, 0xfe12}, // Ideographic full stop {0x3008, 0xfe3f}, // left angle bracket {0x3009, 0xfe40}, // right angle bracket {0x300a, 0xfe3d}, // left double angle bracket @@ -67,19 +70,22 @@ static const UChar vTextCnvTable[][2] = { {0x3011, 0xfe3c}, // right black lenticular bracket {0x3014, 0xfe39}, // left black lenticular bracket {0x3015, 0xfe3a}, // right tortise shell bracket - // {0x3016, 0xfe17}, // left white lenticular bracket - // {0x3017, 0xfe18}, // right white lenticular bracket - // {0x3019, 0xfe19}, // horizontal ellipses + {0x3016, 0xfe17}, // left white lenticular bracket + {0x3017, 0xfe18}, // right white lenticular bracket {0x30fc, 0x3021}, // prolonged sound {0xfe4f, 0xfe34}, // wavy low line {0xff08, 0xfe35}, // full width left paren {0xff09, 0xfe36}, // full width right paren + {0xff0c, 0xfe10}, // full width comma {0xff3b, 0xfe47}, // full width left square bracket {0xff3d, 0xfe48}, // full width right square bracket {0xff5b, 0xfe37}, // full width left curly bracket + {0xff5c, 0xfe31}, // fullwidth vertical line {0xff5d, 0xfe38}, // full width right curly bracket - // {0xff64, 0xfe11}, // halfwidth ideo comma - // {0xff61, 0xfe12}, // halfwidth ideo full stop + {0xff5e, 0x007c}, // tilde to vertical line + // TODO: change the mapping 0xff64 -> 0xFE11 once Android has the glyph for 0xFE11. + {0xff64, 0xfe10}, // halfwidth ideo comma + {0xff61, 0xfe12}, // halfwidth ideo full stop }; namespace WebCore { |