summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/WebCore/platform/graphics/android/MediaLayer.cpp48
-rw-r--r--Source/WebCore/platform/graphics/android/MediaLayer.h3
-rw-r--r--Source/WebCore/platform/graphics/android/MediaTexture.cpp229
-rw-r--r--Source/WebCore/platform/graphics/android/MediaTexture.h43
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/ShaderProgram.h2
6 files changed, 198 insertions, 132 deletions
diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp
index 85fb92f..500fbfc 100644
--- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp
+++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp
@@ -42,10 +42,8 @@ namespace WebCore {
MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL)
{
- m_contentTexture = new MediaTexture(webViewRef);
- m_contentTexture->incStrong(this);
- m_videoTexture = new MediaTexture(webViewRef);
- m_videoTexture->incStrong(this);
+ m_mediaTexture = new MediaTexture(webViewRef);
+ m_mediaTexture->incStrong(this);
m_isCopy = false;
m_isContentInverted = false;
@@ -55,10 +53,8 @@ MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL)
MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer)
{
- m_contentTexture = layer.m_contentTexture;
- m_contentTexture->incStrong(this);
- m_videoTexture = layer.m_videoTexture;
- m_videoTexture->incStrong(this);
+ m_mediaTexture = layer.m_mediaTexture;
+ m_mediaTexture->incStrong(this);
m_isCopy = true;
m_isContentInverted = layer.m_isContentInverted;
@@ -69,8 +65,7 @@ MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer)
MediaLayer::~MediaLayer()
{
XLOG("Deleting Media Layer");
- m_contentTexture->decStrong(this);
- m_videoTexture->decStrong(this);
+ m_mediaTexture->decStrong(this);
}
bool MediaLayer::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
@@ -85,10 +80,8 @@ bool MediaLayer::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
mediaBounds.set(0, 0, getSize().width(), getSize().height());
mediaBounds.inset(m_outlineSize, m_outlineSize);
- // check to see if we need to create a video texture
- m_videoTexture->initNativeWindowIfNeeded();
- // draw any video content if present
- m_videoTexture->drawVideo(m_drawTransform, mediaBounds);
+ // check to see if we need to create a content or video texture
+ m_mediaTexture->initNativeWindowIfNeeded();
// the layer's shader draws the content inverted so we must undo
// that change in the transformation matrix
@@ -98,50 +91,37 @@ bool MediaLayer::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix)
m.translate(0, -getSize().height());
}
- // check to see if we need to create a content texture
- m_contentTexture->initNativeWindowIfNeeded();
- // draw any content if present
- m_contentTexture->setDimensions(mediaBounds);
- m_contentTexture->drawContent(m);
+ // draw any content or video if present
+ m_mediaTexture->draw(m, m_drawTransform, mediaBounds);
return drawChildrenGL(glWebViewState, matrix);
}
ANativeWindow* MediaLayer::acquireNativeWindowForContent()
{
- ANativeWindow* anw = m_contentTexture->getNativeWindow();
- if (!anw) {
- anw = m_contentTexture->requestNewWindow();
- }
- return anw;
+ return m_mediaTexture->getNativeWindowForContent();
}
ANativeWindow* MediaLayer::acquireNativeWindowForVideo()
{
- return m_videoTexture->requestNewWindow();
+ return m_mediaTexture->requestNativeWindowForVideo();
}
void MediaLayer::setWindowDimensionsForVideo(const ANativeWindow* window, const SkRect& dimensions)
{
- if (window != m_videoTexture->getNativeWindow())
- return;
-
//TODO validate that the dimensions do not exceed the plugin's bounds
- m_videoTexture->setDimensions(dimensions);
+ m_mediaTexture->setDimensions(window, dimensions);
}
void MediaLayer::releaseNativeWindowForVideo(ANativeWindow* window)
{
- if (window == m_videoTexture->getNativeWindow())
- m_videoTexture->releaseNativeWindow();
+ m_mediaTexture->releaseNativeWindow(window);
}
void MediaLayer::setFramerateCallback(const ANativeWindow* window, FramerateCallbackProc callback)
{
- if (window != m_videoTexture->getNativeWindow())
- return;
- m_videoTexture->setFramerateCallback(callback);
+ m_mediaTexture->setFramerateCallback(window, callback);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/MediaLayer.h
index cd15d9e..30a293d 100644
--- a/Source/WebCore/platform/graphics/android/MediaLayer.h
+++ b/Source/WebCore/platform/graphics/android/MediaLayer.h
@@ -61,8 +61,7 @@ private:
int m_outlineSize;
// SurfaceTexture member variables
- MediaTexture* m_contentTexture;
- MediaTexture* m_videoTexture;
+ MediaTexture* m_mediaTexture;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp
index 0de7dfa..1a5e2cc 100644
--- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp
@@ -46,6 +46,12 @@
#endif // DEBUG
+// Limits the number of ANativeWindows that can be allocated for video playback.
+// The limit is currently set to 2 as that is the current max number of
+// simultaneous HW decodes that our OMX implementation allows. This forces the
+// media producer to use their own SW decoders for subsequent video streams.
+#define MAX_WINDOW_COUNT 2
+
namespace WebCore {
MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase<MediaTexture>()
@@ -57,17 +63,17 @@ MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase<MediaText
m_weakWebViewRef = 0;
}
- m_textureId = 0;
- m_dimensions.setEmpty();
+ m_contentTexture = 0;
m_newWindowRequest = false;
- m_newWindowReady = false;
}
MediaTexture::~MediaTexture()
{
- releaseNativeWindow();
- if (m_textureId)
- glDeleteTextures(1, &m_textureId);
+ deleteTexture(m_contentTexture);
+ for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
+ deleteTexture(m_videoTextures[i], true);
+ }
+
if (m_weakWebViewRef) {
JNIEnv* env = JSC::Bindings::getJNIEnv();
env->DeleteWeakGlobalRef(m_weakWebViewRef);
@@ -79,39 +85,76 @@ void MediaTexture::initNativeWindowIfNeeded()
{
android::Mutex::Autolock lock(m_mediaLock);
- if(!m_newWindowRequest)
- return;
+ // check to see if there are any unused textures to delete
+ if (m_unusedTextures.size() != 0) {
+ for (unsigned int i = 0; i < m_unusedTextures.size(); i++) {
+ glDeleteTextures(1, &m_unusedTextures[i]);
+ }
+ m_unusedTextures.clear();
+ }
- // reuse an existing texture if possible
- if (!m_textureId)
- glGenTextures(1, &m_textureId);
+ // create a content texture if none exists
+ if (!m_contentTexture) {
+ m_contentTexture = createTexture();
+ }
- m_surfaceTexture = new android::SurfaceTexture(m_textureId);
- m_surfaceTextureClient = new android::SurfaceTextureClient(m_surfaceTexture);
+ // finally create a video texture if needed
+ if (!m_newWindowRequest)
+ return;
- //setup callback
- m_mediaListener = new MediaListener(m_weakWebViewRef,
- m_surfaceTexture,
- m_surfaceTextureClient);
- m_surfaceTexture->setFrameAvailableListener(m_mediaListener);
+ // add the texture and add it to the list
+ TextureWrapper* videoTexture = createTexture();
+ m_videoTextures.append(videoTexture);
+ // setup the state variables to signal the other thread
m_newWindowRequest = false;
- m_newWindowReady = true;
+ m_newWindow = videoTexture->nativeWindow;
}
m_newMediaRequestCond.signal();
}
-void MediaTexture::drawContent(const TransformationMatrix& matrix)
+void MediaTexture::draw(const TransformationMatrix& contentMatrix,
+ const TransformationMatrix& videoMatrix,
+ const SkRect& mediaBounds)
{
android::Mutex::Autolock lock(m_mediaLock);
- if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
- || !m_mediaListener->isFrameAvailable())
+ if (mediaBounds.isEmpty())
return;
- m_surfaceTexture->updateTexImage();
+ // draw all the video textures first
+ for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
+
+ TextureWrapper* video = m_videoTextures[i];
- sp<GraphicBuffer> buf = m_surfaceTexture->getCurrentBuffer();
+ if (!video->surfaceTexture.get() || video->dimensions.isEmpty()
+ || !video->mediaListener->isFrameAvailable())
+ return;
+
+ video->surfaceTexture->updateTexImage();
+
+ float surfaceMatrix[16];
+ video->surfaceTexture->getTransformMatrix(surfaceMatrix);
+
+ SkRect dimensions = video->dimensions;
+ dimensions.offset(mediaBounds.fLeft, mediaBounds.fTop);
+
+#ifdef DEBUG
+ if (!mediaBounds.contains(dimensions)) {
+ XLOG("The video exceeds is parent's bounds.");
+ }
+#endif // DEBUG
+
+ TilesManager::instance()->shader()->drawVideoLayerQuad(videoMatrix,
+ surfaceMatrix, dimensions, video->textureId);
+ }
+
+ if (!m_contentTexture->mediaListener->isFrameAvailable())
+ return;
+
+ m_contentTexture->surfaceTexture->updateTexImage();
+
+ sp<GraphicBuffer> buf = m_contentTexture->surfaceTexture->getCurrentBuffer();
PixelFormat f = buf->getPixelFormat();
// only attempt to use alpha blending if alpha channel exists
@@ -121,49 +164,25 @@ void MediaTexture::drawContent(const TransformationMatrix& matrix)
PIXEL_FORMAT_RGB_565 == f ||
PIXEL_FORMAT_RGB_332 == f);
- TilesManager::instance()->shader()->drawLayerQuad(matrix, m_dimensions,
- m_textureId, 1.0f,
- forceAlphaBlending,
+ TilesManager::instance()->shader()->drawLayerQuad(contentMatrix,
+ mediaBounds,
+ m_contentTexture->textureId,
+ 1.0f, forceAlphaBlending,
GL_TEXTURE_EXTERNAL_OES);
}
-void MediaTexture::drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds)
-{
- android::Mutex::Autolock lock(m_mediaLock);
-
- if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
- || !m_mediaListener->isFrameAvailable())
- return;
-
- m_surfaceTexture->updateTexImage();
-
- float surfaceMatrix[16];
- m_surfaceTexture->getTransformMatrix(surfaceMatrix);
-
- SkRect dimensions = m_dimensions;
- dimensions.offset(parentBounds.fLeft, parentBounds.fTop);
-
-#ifdef DEBUG
- if (!parentBounds.contains(dimensions)) {
- XLOG("The video exceeds is parent's bounds.");
- }
-#endif // DEBUG
-
- TilesManager::instance()->shader()->drawVideoLayerQuad(matrix, surfaceMatrix,
- dimensions, m_textureId);
-}
-
-ANativeWindow* MediaTexture::requestNewWindow()
+ANativeWindow* MediaTexture::requestNativeWindowForVideo()
{
android::Mutex::Autolock lock(m_mediaLock);
// the window was not ready before the timeout so return it this time
- if (m_newWindowReady) {
- m_newWindowReady = false;
- return m_surfaceTextureClient.get();
+ if (ANativeWindow* window = m_newWindow.get()) {
+ m_newWindow.clear();
+ return window;
}
- // we only allow for one texture, so if one already exists return null
- else if (m_surfaceTextureClient.get()) {
+
+ // we only allow for so many textures, so return NULL if we exceed that limit
+ else if (m_videoTextures.size() >= MAX_WINDOW_COUNT) {
return 0;
}
@@ -190,42 +209,94 @@ ANativeWindow* MediaTexture::requestNewWindow()
timedOut = ret == TIMED_OUT;
}
- if (m_surfaceTextureClient.get())
- m_newWindowReady = false;
-
- return m_surfaceTextureClient.get();
+ // if the window is ready then return it otherwise return NULL
+ if (ANativeWindow* window = m_newWindow.get()) {
+ m_newWindow.clear();
+ return window;
+ }
+ return 0;
}
-ANativeWindow* MediaTexture::getNativeWindow()
+ANativeWindow* MediaTexture::getNativeWindowForContent()
{
android::Mutex::Autolock lock(m_mediaLock);
- return m_surfaceTextureClient.get();
+ if (m_contentTexture)
+ return m_contentTexture->nativeWindow.get();
+ else
+ return 0;
}
-void MediaTexture::releaseNativeWindow()
+void MediaTexture::releaseNativeWindow(const ANativeWindow* window)
{
android::Mutex::Autolock lock(m_mediaLock);
- m_dimensions.setEmpty();
-
- if (m_surfaceTexture.get())
- m_surfaceTexture->setFrameAvailableListener(0);
-
- // clear the strong pointer references
- m_mediaListener.clear();
- m_surfaceTextureClient.clear();
- m_surfaceTexture.clear();
+ for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
+ if (m_videoTextures[i]->nativeWindow.get() == window) {
+ deleteTexture(m_videoTextures[i]);
+ m_videoTextures.remove(i);
+ break;
+ }
+ }
}
-void MediaTexture::setDimensions(const SkRect& dimensions)
+void MediaTexture::setDimensions(const ANativeWindow* window,
+ const SkRect& dimensions)
{
android::Mutex::Autolock lock(m_mediaLock);
- m_dimensions = dimensions;
+ for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
+ if (m_videoTextures[i]->nativeWindow.get() == window) {
+ m_videoTextures[i]->dimensions = dimensions;
+ break;
+ }
+ }
}
-void MediaTexture::setFramerateCallback(FramerateCallbackProc callback)
+void MediaTexture::setFramerateCallback(const ANativeWindow* window,
+ FramerateCallbackProc callback)
{
android::Mutex::Autolock lock(m_mediaLock);
- m_mediaListener->setFramerateCallback(callback);
+ for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
+ if (m_videoTextures[i]->nativeWindow.get() == window) {
+ m_videoTextures[i]->mediaListener->setFramerateCallback(callback);
+ break;
+ }
+ }
+}
+
+MediaTexture::TextureWrapper* MediaTexture::createTexture()
+{
+ TextureWrapper* wrapper = new TextureWrapper();
+
+ // populate the wrapper
+ glGenTextures(1, &wrapper->textureId);
+ wrapper->surfaceTexture = new android::SurfaceTexture(wrapper->textureId);
+ wrapper->nativeWindow = new android::SurfaceTextureClient(wrapper->surfaceTexture);
+ wrapper->dimensions.setEmpty();
+
+ // setup callback
+ wrapper->mediaListener = new MediaListener(m_weakWebViewRef,
+ wrapper->surfaceTexture,
+ wrapper->nativeWindow);
+ wrapper->surfaceTexture->setFrameAvailableListener(wrapper->mediaListener);
+
+ return wrapper;
+}
+
+void MediaTexture::deleteTexture(TextureWrapper* texture, bool force)
+{
+ if (texture->surfaceTexture.get())
+ texture->surfaceTexture->setFrameAvailableListener(0);
+
+ if (force)
+ glDeleteTextures(1, &texture->textureId);
+ else
+ m_unusedTextures.append(texture->textureId);
+
+ // clear the strong pointer references
+ texture->mediaListener.clear();
+ texture->nativeWindow.clear();
+ texture->surfaceTexture.clear();
+
+ delete texture;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.h b/Source/WebCore/platform/graphics/android/MediaTexture.h
index d5ecd7b..964b87b 100644
--- a/Source/WebCore/platform/graphics/android/MediaTexture.h
+++ b/Source/WebCore/platform/graphics/android/MediaTexture.h
@@ -20,8 +20,10 @@
#if USE(ACCELERATED_COMPOSITING)
#include "RefPtr.h"
-#include "DoubleBufferedTexture.h"
#include "LayerAndroid.h"
+#include "Vector.h"
+#include <GLES2/gl2.h>
+#include <ui/GraphicBuffer.h>
#include <utils/RefBase.h>
#include <jni.h>
@@ -42,24 +44,37 @@ public:
~MediaTexture();
void initNativeWindowIfNeeded();
- void drawContent(const TransformationMatrix& matrix);
- void drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds);
+ void draw(const TransformationMatrix& contentMatrix,
+ const TransformationMatrix& videoMatrix,
+ const SkRect& mediaBounds);
- ANativeWindow* requestNewWindow();
- ANativeWindow* getNativeWindow();
- void releaseNativeWindow();
- void setDimensions(const SkRect& dimensions);
- void setFramerateCallback(FramerateCallbackProc callback);
+ ANativeWindow* getNativeWindowForContent();
+ ANativeWindow* requestNativeWindowForVideo();
+ void releaseNativeWindow(const ANativeWindow* window);
+ void setDimensions(const ANativeWindow* window, const SkRect& dimensions);
+ void setFramerateCallback(const ANativeWindow* window,
+ FramerateCallbackProc callback);
private:
- GLuint m_textureId;
- sp<android::SurfaceTexture> m_surfaceTexture;
- sp<ANativeWindow> m_surfaceTextureClient;
- sp<MediaListener> m_mediaListener;
- SkRect m_dimensions;
+ struct TextureWrapper {
+ GLuint textureId;
+ sp<android::SurfaceTexture> surfaceTexture;
+ sp<ANativeWindow> nativeWindow;
+ sp<MediaListener> mediaListener;
+ SkRect dimensions; // only used by the video layer
+ };
+
+ TextureWrapper* createTexture();
+ void deleteTexture(TextureWrapper* item, bool force = false);
+
+ TextureWrapper* m_contentTexture;
+ Vector<TextureWrapper*> m_videoTextures;
+ Vector<GLuint> m_unusedTextures;
+
+ // used to generate new video textures
bool m_newWindowRequest;
- bool m_newWindowReady;
+ sp<ANativeWindow> m_newWindow;
jobject m_weakWebViewRef;
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
index 797da52..0aad081 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -543,8 +543,9 @@ void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
- SkRect& geometry, int textureId, float opacity,
- bool forceBlending, GLenum textureTarget)
+ const SkRect& geometry, int textureId,
+ float opacity, bool forceBlending,
+ GLenum textureTarget)
{
TransformationMatrix modifiedDrawMatrix = drawMatrix;
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
index bfb1fb6..dbacd57 100644
--- a/Source/WebCore/platform/graphics/android/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -54,7 +54,7 @@ public:
GLenum textureTarget = GL_TEXTURE_2D,
GLint texFilter = GL_LINEAR);
void drawLayerQuad(const TransformationMatrix& drawMatrix,
- SkRect& geometry, int textureId, float opacity,
+ const SkRect& geometry, int textureId, float opacity,
bool forceBlending = false,
GLenum textureTarget = GL_TEXTURE_2D);
void drawVideoLayerQuad(const TransformationMatrix& drawMatrix,