diff options
| author | Teng-Hui Zhu <ztenghui@google.com> | 2012-02-28 16:27:47 -0800 |
|---|---|---|
| committer | Teng-Hui Zhu <ztenghui@google.com> | 2012-03-01 10:46:30 -0800 |
| commit | 00144be011338276839a08a66ae79b14629b268b (patch) | |
| tree | 533e91ef365f0840c77f0a87d19ccb865ed3be8e /Source/WebCore | |
| parent | 7c9401fdc1f052f3e98bac0bef7b24ac743251e5 (diff) | |
| download | external_webkit-00144be011338276839a08a66ae79b14629b268b.zip external_webkit-00144be011338276839a08a66ae79b14629b268b.tar.gz external_webkit-00144be011338276839a08a66ae79b14629b268b.tar.bz2 | |
Cleanup GL resource for HTML5 Video.
Refactor the code such that the shared resources are in the VideoLayerManager
now.
Get rid of the solid color texture and use pure color shader.
bug:6079959
Change-Id: I0d1ce50157fb2ed083b9cc80464a1e61fa8e159f
Diffstat (limited to 'Source/WebCore')
4 files changed, 165 insertions, 129 deletions
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp index a527e6a..d325a7e 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp @@ -26,16 +26,18 @@ #include "config.h" #include "VideoLayerAndroid.h" -#include "RenderSkinMediaButton.h" #include "TilesManager.h" #include <GLES2/gl2.h> +#include <cutils/log.h> #include <gui/SurfaceTexture.h> +#include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) + #ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) @@ -49,18 +51,8 @@ namespace WebCore { -GLuint VideoLayerAndroid::m_spinnerOuterTextureId = 0; -GLuint VideoLayerAndroid::m_spinnerInnerTextureId = 0; -GLuint VideoLayerAndroid::m_posterTextureId = 0; -GLuint VideoLayerAndroid::m_backgroundTextureId = 0; -GLuint VideoLayerAndroid::m_playTextureId = 0; -GLuint VideoLayerAndroid::m_pauseTextureId = 0; -bool VideoLayerAndroid::m_createdTexture = false; - double VideoLayerAndroid::m_rotateDegree = 0; -const IntRect VideoLayerAndroid::buttonRect(0, 0, IMAGESIZE, IMAGESIZE); - VideoLayerAndroid::VideoLayerAndroid() : LayerAndroid((RenderLayer*)0) { @@ -89,93 +81,33 @@ void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture, TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); } -GLuint VideoLayerAndroid::createSpinnerInnerTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); -} - -GLuint VideoLayerAndroid::createSpinnerOuterTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); -} - -GLuint VideoLayerAndroid::createPosterTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::VIDEO); -} - -GLuint VideoLayerAndroid::createPlayTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::PLAY); -} - -GLuint VideoLayerAndroid::createPauseTexture() -{ - return createTextureFromImage(RenderSkinMediaButton::PAUSE); -} - -GLuint VideoLayerAndroid::createTextureFromImage(int buttonType) -{ - SkRect rect = SkRect(buttonRect); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - bitmap.allocPixels(); - bitmap.eraseColor(0); - - SkCanvas canvas(bitmap); - canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true, 0, - false); - - GLuint texture; - glGenTextures(1, &texture); - - GLUtils::createTextureWithBitmap(texture, bitmap); - bitmap.reset(); - return texture; -} - -GLuint VideoLayerAndroid::createBackgroundTexture() -{ - GLuint texture; - glGenTextures(1, &texture); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - GLubyte pixels[4 *3] = { - 128, 128, 128, - 128, 128, 128, - 128, 128, 128, - 128, 128, 128 - }; - glBindTexture(GL_TEXTURE_2D, texture); - GLUtils::checkGlError("glBindTexture"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); - GLUtils::checkGlError("glTexImage2D"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return texture; -} - void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect, const SkRect innerRect) { ShaderProgram* shader = TilesManager::instance()->shader(); - shader->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true); + VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); + // Paint the video content's background. + shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, + Color(128, 128, 128, 255)); TransformationMatrix addReverseRotation; TransformationMatrix addRotation = m_drawTransform; addRotation.translate(innerRect.fLeft, innerRect.fTop); - addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2); + double halfButtonSize = manager->getButtonSize() / 2; + addRotation.translate(halfButtonSize, halfButtonSize); addReverseRotation = addRotation; addRotation.rotate(m_rotateDegree); - addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); + addRotation.translate(-halfButtonSize, -halfButtonSize); SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); - shader->drawLayerQuad(addRotation, size, m_spinnerOuterTextureId, 1, true); + shader->drawLayerQuad(addRotation, size, + manager->getSpinnerOuterTextureId(), 1, true); addReverseRotation.rotate(-m_rotateDegree); - addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); + addReverseRotation.translate(-halfButtonSize, -halfButtonSize); - shader->drawLayerQuad(addReverseRotation, size, m_spinnerInnerTextureId, 1, true); + shader->drawLayerQuad(addReverseRotation, size, + manager->getSpinnerInnerTextureId(), 1, true); m_rotateDegree += ROTATESTEP; } @@ -199,17 +131,11 @@ SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect) bool VideoLayerAndroid::drawGL() { // Lazily allocated the textures. - if (!m_createdTexture) { - m_backgroundTextureId = createBackgroundTexture(); - m_spinnerOuterTextureId = createSpinnerOuterTexture(); - m_spinnerInnerTextureId = createSpinnerInnerTexture(); - m_posterTextureId = createPosterTexture(); - m_playTextureId = createPlayTexture(); - m_pauseTextureId = createPauseTexture(); - m_createdTexture = true; - } + TilesManager* tilesManager = TilesManager::instance(); + VideoLayerManager* manager = tilesManager->videoLayerManager(); + manager->initGLResourcesIfNeeded(); - ShaderProgram* shader = TilesManager::instance()->shader(); + ShaderProgram* shader = tilesManager->shader(); SkRect rect = SkRect::MakeSize(getSize()); GLfloat surfaceMatrix[16]; @@ -224,11 +150,13 @@ bool VideoLayerAndroid::drawGL() } // Inner rect is for the progressing / play / pause animation. - SkRect innerRect = SkRect(buttonRect); + SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(), + manager->getButtonSize()); if (innerRect.contains(videoRect)) innerRect = videoRect; - innerRect.offset(videoRect.fLeft + (videoRect.width() - IMAGESIZE) / 2, - videoRect.fTop + (videoRect.height() - IMAGESIZE) / 2); + double buttonSize = manager->getButtonSize(); + innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2, + videoRect.fTop + (videoRect.height() - buttonSize) / 2); // When we are drawing the animation of the play/pause button in the // middle of the video, we need to ask for redraw. @@ -236,7 +164,6 @@ bool VideoLayerAndroid::drawGL() // Draw the poster image, the progressing image or the Video depending // on the player's state. - VideoLayerManager* manager = TilesManager::instance()->videoLayerManager(); if (m_playerState == PREPARING) { // Show the progressing animation, with two rotating circles showPreparingAnimation(videoRect, innerRect); @@ -253,9 +180,10 @@ bool VideoLayerAndroid::drawGL() // Use the scale to control the fading the sizing during animation double scale = manager->drawIcon(uniqueId(), PlayIcon); if (scale) { - innerRect.inset(IMAGESIZE / 4 * scale, IMAGESIZE / 4 * scale); + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); shader->drawLayerQuad(m_drawTransform, innerRect, - m_playTextureId, scale, true); + manager->getPlayTextureId(), scale, true); needRedraw = true; } @@ -268,18 +196,19 @@ bool VideoLayerAndroid::drawGL() videoRect, textureId); } else { // Show the static poster b/c there is no screen shot available. - shader->drawLayerQuad(m_drawTransform, videoRect, m_backgroundTextureId, - 1, true); - shader->drawLayerQuad(m_drawTransform, innerRect, m_posterTextureId, - 1, true); + shader->drawLayerQuad(m_drawTransform, rect, 0, 1, true, GL_TEXTURE_2D, + Color(128, 128, 128, 255)); + shader->drawLayerQuad(m_drawTransform, innerRect, + manager->getPosterTextureId(), 1, true); } // Use the scale to control the fading and the sizing during animation. double scale = manager->drawIcon(uniqueId(), PauseIcon); if (scale) { - innerRect.inset(IMAGESIZE / 4 * scale, IMAGESIZE / 4 * scale); + innerRect.inset(manager->getButtonSize() / 4 * scale, + manager->getButtonSize() / 4 * scale); shader->drawLayerQuad(m_drawTransform, innerRect, - m_pauseTextureId, scale, true); + manager->getPauseTextureId(), scale, true); needRedraw = true; } diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h index 6bd9fa1..f20eb65 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h @@ -59,15 +59,8 @@ public: // The following 3 functions are called in UI thread only. virtual bool drawGL(); void setSurfaceTexture(sp<SurfaceTexture> texture, int textureName, PlayerState playerState); - GLuint createBackgroundTexture(); - GLuint createSpinnerOuterTexture(); - GLuint createSpinnerInnerTexture(); - GLuint createPosterTexture(); - GLuint createPlayTexture(); - GLuint createPauseTexture(); private: - GLuint createTextureFromImage(int buttonType); void init(); void showPreparingAnimation(const SkRect& rect, const SkRect innerRect); @@ -78,20 +71,9 @@ private: PlayerState m_playerState; - // Texture for showing the static image will be created at native side. - static bool m_createdTexture; - static GLuint m_backgroundTextureId; - static GLuint m_posterTextureId; - static GLuint m_spinnerOuterTextureId; - static GLuint m_spinnerInnerTextureId; - static GLuint m_playTextureId; - static GLuint m_pauseTextureId; - static double m_rotateDegree; static const int ROTATESTEP = 12; - static const int IMAGESIZE = 64; - static const IntRect buttonRect; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp index 521b623..f957aed 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp @@ -26,13 +26,18 @@ #include "config.h" #include "VideoLayerManager.h" +#include "RenderSkinMediaButton.h" +#include "SkCanvas.h" +#include <cutils/log.h> #include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__) + #ifdef DEBUG -#include <cutils/log.h> -#include <wtf/text/CString.h> #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__) @@ -59,11 +64,106 @@ // Assuming 16:9 by default, this will be corrected after video prepared. #define DEFAULT_VIDEO_ASPECT_RATIO 1.78 +#define VIDEO_TEXTURE_NUMBER 5 +#define VIDEO_BUTTON_SIZE 64 + namespace WebCore { VideoLayerManager::VideoLayerManager() + : m_currentTimeStamp(0) + , m_createdTexture(false) + , m_posterTextureId(0) + , m_spinnerOuterTextureId(0) + , m_spinnerInnerTextureId(0) + , m_playTextureId(0) + , m_pauseTextureId(0) + , m_buttonRect(0, 0, VIDEO_BUTTON_SIZE, VIDEO_BUTTON_SIZE) +{ +} + +int VideoLayerManager::getButtonSize() +{ + return VIDEO_BUTTON_SIZE; +} + +GLuint VideoLayerManager::createTextureFromImage(int buttonType) +{ + SkRect rect = SkRect(m_buttonRect); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); + bitmap.allocPixels(); + bitmap.eraseColor(0); + + SkCanvas canvas(bitmap); + canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); + RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0, + false); + + GLuint texture; + glGenTextures(1, &texture); + + GLUtils::createTextureWithBitmap(texture, bitmap); + bitmap.reset(); + return texture; +} + +// Should be called at the VideoLayerAndroid::drawGL to make sure we allocate +// the GL resources lazily. +void VideoLayerManager::initGLResourcesIfNeeded() +{ + if (!m_createdTexture) { + XLOGC("Reinit GLResource for VideoLayer"); + initGLResources(); + } +} + +void VideoLayerManager::initGLResources() { - m_currentTimeStamp = 0; + GLUtils::checkGlError("before initGLResources()"); + if (!m_createdTexture) { + m_spinnerOuterTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); + m_spinnerInnerTextureId = + createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); + m_posterTextureId = + createTextureFromImage(RenderSkinMediaButton::VIDEO); + m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY); + m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE); + } + m_createdTexture = !GLUtils::checkGlError("initGLResources()"); + return; +} + +void VideoLayerManager::cleanupGLResources() +{ + if (m_createdTexture) { + GLuint videoTextures[VIDEO_TEXTURE_NUMBER] = { m_spinnerOuterTextureId, + m_spinnerInnerTextureId, m_posterTextureId, m_playTextureId, + m_pauseTextureId }; + + glDeleteTextures(VIDEO_TEXTURE_NUMBER, videoTextures); + m_createdTexture = false; + } + // Delete the texture in retired mode, but have not hit draw call to be + // removed. + deleteUnusedTextures(); + + // Go over the registered GL textures (screen shot textures) and delete them. + android::Mutex::Autolock lock(m_videoLayerInfoMapLock); + InfoIterator end = m_videoLayerInfoMap.end(); + for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) { + // The map include every video has been played, so their textureId can + // be deleted already, like hitting onTrimMemory multiple times. + if (it->second->textureId) { + XLOG("delete texture from the map %d", it->second->textureId); + glDeleteTextures(1, &it->second->textureId); + // Set the textureID to 0 to show the video icon. + it->second->textureId = 0; + } + } + + GLUtils::checkGlError("cleanupGLResources()"); + return; } // Getting TextureId for GL draw call, in the UI thread. @@ -233,6 +333,7 @@ void VideoLayerManager::deleteUnusedTextures() m_retiredTextures.clear(); } m_retiredTexturesLock.unlock(); + GLUtils::checkGlError("deleteUnusedTextures"); return; } diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h index d554362..c8e420e 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerManager.h +++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.h @@ -27,6 +27,7 @@ #define VideoLayerManager_h #include "GLUtils.h" +#include "IntRect.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> @@ -86,6 +87,17 @@ public: void deleteUnusedTextures(); double drawIcon(const int layerId, IconType type); + + GLuint getSpinnerInnerTextureId() { return m_spinnerInnerTextureId; } + GLuint getSpinnerOuterTextureId() { return m_spinnerOuterTextureId; } + GLuint getPosterTextureId() { return m_posterTextureId; } + GLuint getPlayTextureId() { return m_playTextureId; } + GLuint getPauseTextureId() { return m_pauseTextureId; } + + void initGLResourcesIfNeeded(); + void cleanupGLResources(); + + static int getButtonSize(); private: // Get the sum of all the video size stored in m_videoLayerInfoMap. int getTotalMemUsage(); @@ -93,7 +105,7 @@ private: bool recycleTextureMem(); // The private function to remove layer. void removeLayerInternal(const int layerId); - + void initGLResources(); // Indexed by each layer's uniqueId, this map contains the important info // used for showing the video when playing or the screenshot when paused. HashMap<int, VideoLayerInfo*> m_videoLayerInfoMap; @@ -107,6 +119,18 @@ private: // thread, and really get deleted in the UI thread. Vector<GLuint> m_retiredTextures; android::Mutex m_retiredTexturesLock; + + GLuint createTextureFromImage(int buttonType); + + // Texture for showing the static image will be created at native side. + bool m_createdTexture; + GLuint m_posterTextureId; + GLuint m_spinnerOuterTextureId; + GLuint m_spinnerInnerTextureId; + GLuint m_playTextureId; + GLuint m_pauseTextureId; + + IntRect m_buttonRect; }; } // namespace WebCore |
