summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/Android.mk1
-rw-r--r--Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp3
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.h3
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp37
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerAndroid.h3
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerManager.cpp242
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerManager.h98
-rw-r--r--Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp4
8 files changed, 375 insertions, 16 deletions
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 4529f83..c0e6d91 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -647,6 +647,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/TilesManager.cpp \
platform/graphics/android/TiledPage.cpp \
platform/graphics/android/VideoLayerAndroid.cpp \
+ platform/graphics/android/VideoLayerManager.cpp \
platform/graphics/android/android_graphics.cpp \
ifeq ($(ENABLE_SVG), true)
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 8aa334f..cd19e55 100644
--- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -352,6 +352,9 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot,
// the unnecessary ones to make space...
TilesManager::instance()->cleanupLayersTextures(compositedRoot);
}
+ // Clean up GL textures for video layer.
+ TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
+
// Finally do another pass to create new textures and schedule
// repaints if needed
compositedRoot->createGLTextures();
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h
index 6d49cca..e43afed 100644
--- a/Source/WebCore/platform/graphics/android/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/TilesManager.h
@@ -35,6 +35,7 @@
#include "ShaderProgram.h"
#include "TexturesGenerator.h"
#include "TiledPage.h"
+#include "VideoLayerManager.h"
#include <utils/threads.h>
namespace WebCore {
@@ -76,6 +77,7 @@ public:
}
ShaderProgram* shader() { return &m_shader; }
+ VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; }
BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner);
@@ -153,6 +155,7 @@ private:
static TilesManager* gInstance;
ShaderProgram m_shader;
+ VideoLayerManager m_videoLayerManager;
SkBitmap* m_tilesBitmap;
};
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
index 32e518d..aee5ae0 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
@@ -75,9 +75,7 @@ void VideoLayerAndroid::init()
{
// m_surfaceTexture is only useful on UI thread, no need to copy.
// And it will be set at setBaseLayer timeframe
-
m_playerState = INITIALIZED;
- m_textureId = 0;
}
// We can use this function to set the Layer to point to surface texture.
@@ -85,9 +83,8 @@ void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture,
int textureName, PlayerState playerState)
{
m_surfaceTexture = texture;
- m_textureId = textureName;
-
m_playerState = playerState;
+ TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName);
}
GLuint VideoLayerAndroid::createSpinnerInnerTexture()
@@ -199,18 +196,32 @@ bool VideoLayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
// Show the real video.
m_surfaceTexture->updateTexImage();
m_surfaceTexture->getTransformMatrix(surfaceMatrix);
+ GLuint textureId =
+ TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
TilesManager::instance()->shader()->drawVideoLayerQuad(drawTransform(),
surfaceMatrix,
- rect, m_textureId);
+ rect, textureId);
+ TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(),
+ surfaceMatrix);
} else {
- // Show the poster
- TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect,
- m_backgroundTextureId,
- 0.5, true);
-
- TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), innerRect,
- m_posterTextureId,
- 1, true);
+ GLuint textureId =
+ TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
+ GLfloat* matrix =
+ TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId());
+ if (textureId && matrix) {
+ // Show the screen shot for each video.
+ TilesManager::instance()->shader()->drawVideoLayerQuad(drawTransform(),
+ matrix,
+ rect, textureId);
+ } else {
+ // Show the static poster b/c there is no screen shot available.
+ TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect,
+ m_backgroundTextureId,
+ 0.5, true);
+ TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), innerRect,
+ m_posterTextureId,
+ 1, true);
+ }
}
return drawChildrenGL(glWebViewState, matrix);
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
index eac565e..0f3f007 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
@@ -68,14 +68,11 @@ private:
void init();
// Surface texture for showing the video is actually allocated in Java side
// and passed into this native code.
- GLuint m_textureId;
sp<android::SurfaceTexture> m_surfaceTexture;
PlayerState m_playerState;
// Texture for showing the static image will be created at native side.
- // TODO: instead using a shared texture, we could make a texture pool to
- // show different screen shots for different videos
static bool m_createdTexture;
static GLuint m_backgroundTextureId;
static GLuint m_posterTextureId;
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
new file mode 100644
index 0000000..cec4d67
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "VideoLayerManager.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#ifdef DEBUG
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// Define the max sum of all the video's sizes.
+// Note that video_size = width * height. If there is no compression, then the
+// maximum memory consumption could be 4 * video_size.
+// Setting this to 2M, means that maximum memory consumption of all the
+// screenshots would not be above 8M.
+#define MAX_VIDEOSIZE_SUM 2097152
+
+namespace WebCore {
+
+VideoLayerManager::VideoLayerManager()
+{
+ m_currentTimeStamp = 0;
+}
+
+// Getting TextureId for GL draw call, in the UI thread.
+GLuint VideoLayerManager::getTextureId(const int layerId)
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ GLuint result = 0;
+ if (m_videoLayerInfoMap.contains(layerId))
+ result = m_videoLayerInfoMap.get(layerId)->textureId;
+ return result;
+}
+
+// Getting matrix for GL draw call, in the UI thread.
+GLfloat* VideoLayerManager::getMatrix(const int layerId)
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ GLfloat* result = 0;
+ if (m_videoLayerInfoMap.contains(layerId))
+ result = m_videoLayerInfoMap.get(layerId)->surfaceMatrix;
+ return result;
+}
+
+int VideoLayerManager::getTotalMemUsage()
+{
+ int sum = 0;
+ InfoIterator end = m_videoLayerInfoMap.end();
+ for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
+ sum += it->second->videoSize;
+ return sum;
+}
+
+// When the video start, we know its texture info, so we register when we
+// recieve the setSurfaceTexture call, this happens on UI thread.
+void VideoLayerManager::registerTexture(const int layerId, const GLuint textureId)
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ // If the texture has been registered, then early return.
+ if (m_videoLayerInfoMap.get(layerId)) {
+ GLuint oldTextureId = m_videoLayerInfoMap.get(layerId)->textureId;
+ if (oldTextureId != textureId)
+ removeLayerInternal(layerId);
+ else
+ return;
+ }
+ // The old info is deleted and now complete the new info and store it.
+ VideoLayerInfo* pInfo = new VideoLayerInfo();
+ pInfo->textureId = textureId;
+ memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix));
+ pInfo->videoSize = 0;
+ m_currentTimeStamp++;
+ pInfo->timeStamp = m_currentTimeStamp;
+
+ m_videoLayerInfoMap.add(layerId, pInfo);
+ XLOG("GL texture %d regisered for layerId %d", textureId, layerId);
+
+ return;
+}
+
+// Only when the video is prepared, we got the video size. So we should update
+// the size for the video accordingly.
+// This is called from webcore thread, from MediaPlayerPrivateAndroid.
+void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size )
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ if (m_videoLayerInfoMap.contains(layerId)) {
+ VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
+ if (pInfo)
+ pInfo->videoSize = size;
+ }
+
+ // If the memory usage is out of bound, then just delete the oldest ones.
+ // Because we only recycle the texture before the current timestamp, the
+ // current video's texture will not be deleted.
+ while (getTotalMemUsage() > MAX_VIDEOSIZE_SUM)
+ if (!recycleTextureMem())
+ break;
+ return;
+}
+
+// This is called only from UI thread, at drawGL time.
+void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix)
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ if (m_videoLayerInfoMap.contains(layerId)) {
+ // If the existing video layer's matrix is matching the incoming one,
+ // then skip the update.
+ VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
+ ASSERT(matrix);
+ if (pInfo && !memcmp(matrix, pInfo->surfaceMatrix, sizeof(pInfo->surfaceMatrix)))
+ return;
+ memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix));
+ } else {
+ XLOG("Error: should not reach here, the layerId %d should exist!", layerId);
+ ASSERT(false);
+ }
+ return;
+}
+
+// This is called on the webcore thread, save the GL texture for recycle in
+// the retired queue. They will be deleted in deleteUnusedTextures() in the UI
+// thread.
+// Return true when we found one texture to retire.
+bool VideoLayerManager::recycleTextureMem()
+{
+ // Find the oldest texture int the m_videoLayerInfoMap, put it in m_retiredTextures
+ int oldestTimeStamp = m_currentTimeStamp;
+ int oldestLayerId = -1;
+
+ InfoIterator end = m_videoLayerInfoMap.end();
+#ifdef DEBUG
+ XLOG("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains");
+ for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
+ XLOG(" layerId %d, textureId %d, videoSize %d, timeStamp %d ",
+ it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp);
+#endif
+ for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) {
+ if (it->second->timeStamp < oldestTimeStamp) {
+ oldestTimeStamp = it->second->timeStamp;
+ oldestLayerId = it->first;
+ }
+ }
+
+ bool foundTextureToRetire = (oldestLayerId != -1);
+ if (foundTextureToRetire)
+ removeLayerInternal(oldestLayerId);
+
+ return foundTextureToRetire;
+}
+
+// This is only called in the UI thread, b/c glDeleteTextures need to be called
+// on the right context.
+void VideoLayerManager::deleteUnusedTextures()
+{
+ m_retiredTexturesLock.lock();
+ int size = m_retiredTextures.size();
+ if (size > 0) {
+ GLuint* textureNames = new GLuint[size];
+ int index = 0;
+ Vector<GLuint>::const_iterator end = m_retiredTextures.end();
+ for (Vector<GLuint>::const_iterator it = m_retiredTextures.begin();
+ it != end; ++it) {
+ GLuint textureName = *it;
+ if (textureName) {
+ textureNames[index] = textureName;
+ index++;
+ XLOG("GL texture %d will be deleted", textureName);
+ }
+ }
+ glDeleteTextures(size, textureNames);
+ delete textureNames;
+ m_retiredTextures.clear();
+ }
+ m_retiredTexturesLock.unlock();
+ return;
+}
+
+// This can be called in the webcore thread in the media player's dtor.
+void VideoLayerManager::removeLayer(const int layerId)
+{
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ removeLayerInternal(layerId);
+}
+
+// This can be called on both UI and webcore thread. Since this is a private
+// function, it is up to the public function to handle the lock for
+// m_videoLayerInfoMap.
+void VideoLayerManager::removeLayerInternal(const int layerId)
+{
+ // Delete the layerInfo corresponding to this layerId and remove from the map.
+ if (m_videoLayerInfoMap.contains(layerId)) {
+ GLuint textureId = m_videoLayerInfoMap.get(layerId)->textureId;
+ if (textureId) {
+ // Buffer up the retired textures in either UI or webcore thread,
+ // will be purged at deleteUnusedTextures in the UI thread.
+ m_retiredTexturesLock.lock();
+ m_retiredTextures.append(textureId);
+ m_retiredTexturesLock.unlock();
+ }
+ delete m_videoLayerInfoMap.get(layerId);
+ m_videoLayerInfoMap.remove(layerId);
+ }
+ return;
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
new file mode 100644
index 0000000..de2dafc
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VideoLayerManager_h
+#define VideoLayerManager_h
+
+#include "GLUtils.h"
+#include <wtf/HashMap.h>
+#include <wtf/Vector.h>
+
+#if USE(ACCELERATED_COMPOSITING)
+
+namespace WebCore {
+
+// Every video layer can use its uniqueId to query VideoLayerManager about such
+// info globally.
+struct VideoLayerInfo {
+ GLuint textureId; // GL texture bound with the surface texture.
+ int videoSize; // The size of the video.
+ int timeStamp; // Used to decide which VideoLayerInfo is the oldest one.
+ GLfloat surfaceMatrix[16];
+};
+
+
+class VideoLayerManager {
+
+public:
+ typedef HashMap<int, VideoLayerInfo*>::const_iterator InfoIterator;
+
+ VideoLayerManager();
+
+ // Register the texture when we got setSurfaceTexture call.
+ void registerTexture(const int layerId, const GLuint textureId);
+ // Update the size when the video is prepared.
+ void updateVideoLayerSize(const int layerId, const int size);
+ // At draw time, update the matrix for every video frame update.
+ void updateMatrix(const int layerId, const GLfloat* matrix);
+ // Remove the layer info from the mapping.
+ void removeLayer(const int layerId);
+
+ // Return the texture name corresponding to the layerId
+ GLuint getTextureId(const int layerId);
+ // Return the matrix for surface texture corresponding to the layerId
+ GLfloat* getMatrix(const int layerId);
+
+ // Delete the GL textures
+ void deleteUnusedTextures();
+
+private:
+ // Get the sum of all the video size stored in m_videoLayerInfoMap.
+ int getTotalMemUsage();
+ // If the memory consumption is out of bound, recycle some textures.
+ bool recycleTextureMem();
+ // The private function to remove layer.
+ void removeLayerInternal(const int layerId);
+
+ // 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;
+ android::Mutex m_videoLayerInfoMapLock;
+
+ // Everytime we add one item to the map, we update the timestamp.
+ int m_currentTimeStamp;
+
+ // The retiredTextures is used to communicate between UI thread and webcore
+ // thread. Basically, GL textures are determined to retire in the webcore
+ // thread, and really get deleted in the UI thread.
+ Vector<GLuint> m_retiredTextures;
+ android::Mutex m_retiredTexturesLock;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+ //
+#endif // VideoLayerManager_h
diff --git a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
index e6a2710..0a4acad 100644
--- a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
@@ -35,6 +35,7 @@
#include "FrameView.h"
#include "GraphicsContext.h"
#include "SkiaUtils.h"
+#include "TilesManager.h"
#include "VideoLayerAndroid.h"
#include "WebCoreJni.h"
#include "WebViewCore.h"
@@ -72,6 +73,7 @@ struct MediaPlayerPrivate::JavaGlue {
MediaPlayerPrivate::~MediaPlayerPrivate()
{
+ TilesManager::instance()->videoLayerManager()->removeLayer(m_videoLayer->uniqueId());
// m_videoLayer is reference counted, unref is enough here.
m_videoLayer->unref();
if (m_glue->m_javaProxy) {
@@ -290,6 +292,8 @@ public:
m_naturalSizeUnknown = false;
m_player->durationChanged();
m_player->sizeChanged();
+ TilesManager::instance()->videoLayerManager()->updateVideoLayerSize(
+ m_player->platformLayer()->uniqueId(), width*height);
}
virtual bool hasAudio() const { return false; } // do not display the audio UI