summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform
diff options
context:
space:
mode:
authorDerek Sollenberger <djsollen@google.com>2011-09-14 14:11:23 -0400
committerDerek Sollenberger <djsollen@google.com>2011-10-10 09:18:15 -0400
commitb496531c0b33b95e90aea56ea2620bbe7f5f9ae6 (patch)
treef8edaef8db12281fc0d78e0c55ea15c2b728eeb3 /Source/WebCore/platform
parente360cb4d916ace9ec3bb7163ab6d8b827470af06 (diff)
downloadexternal_webkit-b496531c0b33b95e90aea56ea2620bbe7f5f9ae6.zip
external_webkit-b496531c0b33b95e90aea56ea2620bbe7f5f9ae6.tar.gz
external_webkit-b496531c0b33b95e90aea56ea2620bbe7f5f9ae6.tar.bz2
Adding support for multiple video surfaces per plugin.
This CL refactors our implementation to support multiple non-overlapping video surfaces per plugin instance. This will allow plugins to hardware decode simulatenous video streams using hardware. Additionally, this CL improves plugin startup latency by constructing the primary plugin surface as soon as possible in the UI thread. bug: 5318290 Change-Id: I53ceb8b6696159ecc4765c922704727a9a75a17d
Diffstat (limited to 'Source/WebCore/platform')
-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,