diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2012-03-01 11:33:01 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-03-01 11:33:01 -0800 |
commit | 56b4137d1b6400ff25b9d6b00c8f12846a616f95 (patch) | |
tree | 43c07d32d9e70f739cc3974d9694b14ac652ebd9 /Source | |
parent | a0798fea895a9be431e9357b9a0481a189b69980 (diff) | |
parent | 00144be011338276839a08a66ae79b14629b268b (diff) | |
download | external_webkit-56b4137d1b6400ff25b9d6b00c8f12846a616f95.zip external_webkit-56b4137d1b6400ff25b9d6b00c8f12846a616f95.tar.gz external_webkit-56b4137d1b6400ff25b9d6b00c8f12846a616f95.tar.bz2 |
Merge "Cleanup GL resource for HTML5 Video."
Diffstat (limited to 'Source')
5 files changed, 171 insertions, 133 deletions
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp index 46a8c1d..e48d36c 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(bool layerTilesDisabled) { // 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(bool layerTilesDisabled) } // 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(bool layerTilesDisabled) // 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(bool layerTilesDisabled) // 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(bool layerTilesDisabled) 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 8ec16d4..29b1bdc 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(bool layerTilesDisabled); 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 diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 09b6c3d..ba6d121 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -1418,14 +1418,16 @@ static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) // make sure the transfer queue is empty and then abandon the Surface // Texture to avoid ANR b/c framework may destroy the EGL context. // Refer to WindowManagerImpl.java for conditions we followed. + TilesManager* tilesManager = TilesManager::instance(); if (level >= TRIM_MEMORY_MODERATE - && !TilesManager::instance()->highEndGfx()) { - TilesManager::instance()->transferQueue()->emptyQueue(); - TilesManager::instance()->shader()->cleanupGLResources(); + && !tilesManager->highEndGfx()) { + tilesManager->transferQueue()->emptyQueue(); + tilesManager->shader()->cleanupGLResources(); + tilesManager->videoLayerManager()->cleanupGLResources(); } bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; - TilesManager::instance()->discardTextures(freeAllTextures, glTextures); + tilesManager->discardTextures(freeAllTextures, glTextures); } } |