Bug 687267 - Initial support for Flash on Honeycomb r=bgirard,vlad,jgilbert,blassey

--HG--
extra : rebase_source : 450055ae3e71ea84f74252d3bf100fe970d29d14
This commit is contained in:
James Willcox 2012-07-20 15:20:51 -04:00
parent bc60033ff2
commit a2f250042f
46 changed files with 1981 additions and 878 deletions

View File

@ -6,7 +6,6 @@
// must include config.h first for webkit to fiddle with new/delete
#include <android/log.h>
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
#include "ANPBase.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
@ -19,29 +18,14 @@ using namespace mozilla;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_native_window_##name
static nsresult GetOwner(NPP instance, nsPluginInstanceOwner** owner) {
static ANPNativeWindow anp_native_window_acquireNativeWindow(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
return pinst->GetOwner((nsIPluginInstanceOwner**)owner);
}
static ANPNativeWindow anp_native_window_acquireNativeWindow(NPP instance) {
nsRefPtr<nsPluginInstanceOwner> owner;
if (NS_FAILED(GetOwner(instance, getter_AddRefs(owner))))
return NULL;
ANPNativeWindow window = owner->Layer()->GetNativeWindowForContent();
owner->Invalidate();
return window;
return pinst->AcquireContentWindow();
}
static void anp_native_window_invertPluginContent(NPP instance, bool isContentInverted) {
nsRefPtr<nsPluginInstanceOwner> owner;
if (NS_FAILED(GetOwner(instance, getter_AddRefs(owner))))
return;
owner->Layer()->SetInverted(isContentInverted);
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
pinst->SetInverted(isContentInverted);
}

View File

@ -8,6 +8,8 @@
#include "ANPBase.h"
#include "GLContextProvider.h"
#include "nsNPAPIPluginInstance.h"
#include "nsPluginInstanceOwner.h"
#include "GLContextProvider.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_opengl_##name
@ -15,24 +17,53 @@
using namespace mozilla;
using namespace mozilla::gl;
static ANPEGLContext anp_opengl_acquireContext(NPP inst) {
// Bug 687267
NOT_IMPLEMENTED();
return NULL;
typedef nsNPAPIPluginInstance::TextureInfo TextureInfo;
static ANPEGLContext anp_opengl_acquireContext(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
GLContext* context = pinst->GLContext();
if (!context)
return NULL;
context->MakeCurrent();
return context->GetNativeData(GLContext::NativeGLContext);
}
static ANPTextureInfo anp_opengl_lockTexture(NPP instance) {
ANPTextureInfo info = { 0, 0, 0, 0 };
NOT_IMPLEMENTED();
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
TextureInfo pluginInfo = pinst->LockContentTexture();
ANPTextureInfo info;
info.textureId = pluginInfo.mTexture;
info.width = pluginInfo.mWidth;
info.height = pluginInfo.mHeight;
// It looks like we should be passing whatever
// internal format Flash told us it used previously
// (e.g., the value of pluginInfo.mInternalFormat),
// but if we do that it doesn't upload to the texture
// for some reason.
info.internalFormat = 0;
return info;
}
static void anp_opengl_releaseTexture(NPP instance, const ANPTextureInfo* info) {
NOT_IMPLEMENTED();
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
TextureInfo pluginInfo(info->textureId, info->width, info->height, info->internalFormat);
pinst->ReleaseContentTexture(pluginInfo);
pinst->RedrawPlugin();
}
static void anp_opengl_invertPluginContent(NPP instance, bool isContentInverted) {
NOT_IMPLEMENTED();
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
// Our definition of inverted is the opposite of the plugin's
pinst->SetInverted(!isContentInverted);
pinst->RedrawPlugin();
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <android/log.h>
#include "AndroidBridge.h"
#include "ANPBase.h"
#include "AndroidMediaLayer.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
@ -15,58 +15,30 @@
using namespace mozilla;
static nsresult GetOwner(NPP instance, nsPluginInstanceOwner** owner) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
return pinst->GetOwner((nsIPluginInstanceOwner**)owner);
}
static AndroidMediaLayer* GetLayerForInstance(NPP instance) {
nsRefPtr<nsPluginInstanceOwner> owner;
if (NS_FAILED(GetOwner(instance, getter_AddRefs(owner))))
return NULL;
return owner->Layer();
}
static void Invalidate(NPP instance) {
nsRefPtr<nsPluginInstanceOwner> owner;
if (NS_FAILED(GetOwner(instance, getter_AddRefs(owner))))
return;
owner->Invalidate();
}
typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
static ANPNativeWindow anp_video_acquireNativeWindow(NPP instance) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return NULL;
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
return layer->RequestNativeWindowForVideo();
return pinst->AcquireVideoWindow();
}
static void anp_video_setWindowDimensions(NPP instance, const ANPNativeWindow window,
const ANPRectF* dimensions) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
const ANPRectF* dimensions) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
gfxRect rect(dimensions->left, dimensions->top,
dimensions->right - dimensions->left,
dimensions->bottom - dimensions->top);
layer->SetNativeWindowDimensions(window, rect);
Invalidate(instance);
pinst->SetVideoDimensions(window, rect);
pinst->RedrawPlugin();
}
static void anp_video_releaseNativeWindow(NPP instance, ANPNativeWindow window) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
layer->ReleaseNativeWindowForVideo(window);
Invalidate(instance);
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
pinst->ReleaseVideoWindow(window);
pinst->RedrawPlugin();
}
static void anp_video_setFramerateCallback(NPP instance, const ANPNativeWindow window, ANPVideoFrameCallbackProc callback) {

View File

@ -42,6 +42,14 @@
#include "AndroidBridge.h"
#include "mozilla/dom/ScreenOrientation.h"
#include "mozilla/Hal.h"
#include "GLContextProvider.h"
#include "TexturePoolOGL.h"
using namespace mozilla;
using namespace mozilla::gl;
typedef nsNPAPIPluginInstance::TextureInfo TextureInfo;
typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
class PluginEventRunnable : public nsRunnable
{
@ -65,6 +73,89 @@ private:
bool mCanceled;
};
static nsRefPtr<GLContext> sPluginContext = nsnull;
static bool EnsureGLContext()
{
if (!sPluginContext) {
sPluginContext = GLContextProvider::CreateOffscreen(gfxIntSize(16, 16));
}
return sPluginContext != nsnull;
}
class SharedPluginTexture {
public:
NS_INLINE_DECL_REFCOUNTING(SharedPluginTexture)
SharedPluginTexture() :
mCurrentHandle(0), mNeedNewImage(false), mLock("SharedPluginTexture.mLock")
{
}
~SharedPluginTexture()
{
// This will be destroyed in the compositor (as it normally is)
mCurrentHandle = nsnull;
}
TextureInfo Lock()
{
if (!EnsureGLContext()) {
mTextureInfo.mTexture = 0;
return mTextureInfo;
}
if (!mTextureInfo.mTexture && sPluginContext->MakeCurrent()) {
sPluginContext->fGenTextures(1, &mTextureInfo.mTexture);
}
mLock.Lock();
return mTextureInfo;
}
void Release(TextureInfo& aTextureInfo)
{
mNeedNewImage = true;
mTextureInfo = aTextureInfo;
mLock.Unlock();
}
SharedTextureHandle CreateSharedHandle()
{
MutexAutoLock lock(mLock);
if (!mNeedNewImage)
return mCurrentHandle;
if (!EnsureGLContext())
return nsnull;
mNeedNewImage = false;
if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
return nsnull;
mCurrentHandle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
// We want forget about this now, so delete the texture. Assigning it to zero
// ensures that we create a new one in Lock()
sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
mTextureInfo.mTexture = 0;
return mCurrentHandle;
}
private:
TextureInfo mTextureInfo;
SharedTextureHandle mCurrentHandle;
bool mNeedNewImage;
Mutex mLock;
};
#endif
using namespace mozilla;
@ -78,12 +169,12 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance()
:
mDrawingModel(kDefaultDrawingModel),
#ifdef MOZ_WIDGET_ANDROID
mSurface(nsnull),
mANPDrawingModel(0),
mOnScreen(true),
mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
mWakeLocked(false),
mFullScreen(false),
mInverted(false),
#endif
mRunning(NOT_STARTED),
mWindowless(false),
@ -118,10 +209,6 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
PR_Free((void *)mMIMEType);
mMIMEType = nsnull;
}
#if MOZ_WIDGET_ANDROID
SetWakeLock(false);
#endif
}
void
@ -129,6 +216,18 @@ nsNPAPIPluginInstance::Destroy()
{
Stop();
mPlugin = nsnull;
#if MOZ_WIDGET_ANDROID
mContentTexture = nsnull;
mContentSurface = nsnull;
std::map<void*, VideoInfo*>::iterator it;
for (it = mVideos.begin(); it != mVideos.end(); it++) {
delete it->second;
}
mVideos.clear();
SetWakeLock(false);
#endif
}
TimeStamp
@ -772,6 +871,24 @@ void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen)
}
}
void nsNPAPIPluginInstance::NotifySize(nsIntSize size)
{
if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() ||
size == mCurrentSize)
return;
mCurrentSize = size;
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kDraw_ANPEventType;
event.data.draw.model = kOpenGL_ANPDrawingModel;
event.data.draw.data.surfaceSize.width = size.width;
event.data.draw.data.surfaceSize.height = size.height;
HandleEvent(&event, nsnull);
}
void nsNPAPIPluginInstance::SetANPDrawingModel(PRUint32 aModel)
{
mANPDrawingModel = aModel;
@ -832,6 +949,122 @@ void nsNPAPIPluginInstance::SetWakeLock(bool aLocked)
hal::WAKE_LOCK_NO_CHANGE);
}
void nsNPAPIPluginInstance::EnsureSharedTexture()
{
if (!mContentTexture)
mContentTexture = new SharedPluginTexture();
}
GLContext* nsNPAPIPluginInstance::GLContext()
{
if (!EnsureGLContext())
return nsnull;
return sPluginContext;
}
TextureInfo nsNPAPIPluginInstance::LockContentTexture()
{
EnsureSharedTexture();
return mContentTexture->Lock();
}
void nsNPAPIPluginInstance::ReleaseContentTexture(TextureInfo& aTextureInfo)
{
EnsureSharedTexture();
mContentTexture->Release(aTextureInfo);
}
nsSurfaceTexture* nsNPAPIPluginInstance::CreateSurfaceTexture()
{
if (!EnsureGLContext())
return nsnull;
GLuint texture = TexturePoolOGL::AcquireTexture();
if (!texture)
return nsnull;
nsSurfaceTexture* surface = nsSurfaceTexture::Create(texture);
if (!surface)
return nsnull;
nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::RedrawPlugin);
surface->SetFrameAvailableCallback(frameCallback);
return surface;
}
void* nsNPAPIPluginInstance::AcquireContentWindow()
{
if (!mContentSurface) {
mContentSurface = CreateSurfaceTexture();
if (!mContentSurface)
return nsnull;
}
return mContentSurface->GetNativeWindow();
}
SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
{
if (mContentTexture) {
return mContentTexture->CreateSharedHandle();
} else if (mContentSurface) {
EnsureGLContext();
return sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, mContentSurface, GLContext::SurfaceTexture);
} else return nsnull;
}
void* nsNPAPIPluginInstance::AcquireVideoWindow()
{
nsSurfaceTexture* surface = CreateSurfaceTexture();
if (!surface)
return nsnull;
VideoInfo* info = new VideoInfo(surface);
void* window = info->mSurfaceTexture->GetNativeWindow();
mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
return window;
}
void nsNPAPIPluginInstance::ReleaseVideoWindow(void* window)
{
std::map<void*, VideoInfo*>::iterator it = mVideos.find(window);
if (it == mVideos.end())
return;
delete it->second;
mVideos.erase(window);
}
void nsNPAPIPluginInstance::SetVideoDimensions(void* window, gfxRect aDimensions)
{
std::map<void*, VideoInfo*>::iterator it;
it = mVideos.find(window);
if (it == mVideos.end())
return;
it->second->mDimensions = aDimensions;
}
void nsNPAPIPluginInstance::GetVideos(nsTArray<VideoInfo*>& aVideos)
{
std::map<void*, VideoInfo*>::iterator it;
for (it = mVideos.begin(); it != mVideos.end(); it++)
aVideos.AppendElement(it->second);
}
void nsNPAPIPluginInstance::SetInverted(bool aInverted)
{
if (aInverted == mInverted)
return;
mInverted = aInverted;
}
#endif
nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel)

View File

@ -16,8 +16,13 @@
#include "nsInterfaceHashtable.h"
#include "nsHashKeys.h"
#ifdef MOZ_WIDGET_ANDROID
#include "nsAutoPtr.h"
#include "nsIRunnable.h"
#include "GLContext.h"
#include "nsSurfaceTexture.h"
#include <map>
class PluginEventRunnable;
class SharedPluginTexture;
#endif
#include "mozilla/TimeStamp.h"
@ -124,6 +129,7 @@ public:
void NotifyOnScreen(bool aOnScreen);
void MemoryPressure();
void NotifyFullScreen(bool aFullScreen);
void NotifySize(nsIntSize size);
bool IsOnScreen() {
return mOnScreen;
@ -142,6 +148,61 @@ public:
void SetFullScreenOrientation(PRUint32 orientation);
void SetWakeLock(bool aLock);
mozilla::gl::GLContext* GLContext();
// For ANPOpenGL
class TextureInfo {
public:
TextureInfo() :
mTexture(0), mWidth(0), mHeight(0), mInternalFormat(0)
{
}
TextureInfo(GLuint aTexture, PRInt32 aWidth, PRInt32 aHeight, GLuint aInternalFormat) :
mTexture(aTexture), mWidth(aWidth), mHeight(aHeight), mInternalFormat(aInternalFormat)
{
}
GLuint mTexture;
PRInt32 mWidth;
PRInt32 mHeight;
GLuint mInternalFormat;
};
TextureInfo LockContentTexture();
void ReleaseContentTexture(TextureInfo& aTextureInfo);
// For ANPNativeWindow
void* AcquireContentWindow();
mozilla::gl::SharedTextureHandle CreateSharedHandle();
// For ANPVideo
class VideoInfo {
public:
VideoInfo(nsSurfaceTexture* aSurfaceTexture) :
mSurfaceTexture(aSurfaceTexture)
{
}
~VideoInfo()
{
mSurfaceTexture = nsnull;
}
nsRefPtr<nsSurfaceTexture> mSurfaceTexture;
gfxRect mDimensions;
};
void* AcquireVideoWindow();
void ReleaseVideoWindow(void* aWindow);
void SetVideoDimensions(void* aWindow, gfxRect aDimensions);
void GetVideos(nsTArray<VideoInfo*>& aVideos);
void SetInverted(bool aInverted);
bool Inverted() { return mInverted; }
#endif
nsresult NewStreamListener(const char* aURL, void* notifyData,
@ -220,7 +281,6 @@ protected:
#ifdef MOZ_WIDGET_ANDROID
PRUint32 mANPDrawingModel;
nsCOMPtr<nsIRunnable> mSurfaceGetter;
friend class PluginEventRunnable;
@ -230,6 +290,10 @@ protected:
PRUint32 mFullScreenOrientation;
bool mWakeLocked;
bool mFullScreen;
bool mInverted;
nsRefPtr<SharedPluginTexture> mContentTexture;
nsRefPtr<nsSurfaceTexture> mContentSurface;
#endif
enum {
@ -278,8 +342,13 @@ private:
bool mUsePluginLayersPref;
#ifdef MOZ_WIDGET_ANDROID
void* mSurface;
void EnsureSharedTexture();
nsSurfaceTexture* CreateSurfaceTexture();
std::map<void*, VideoInfo*> mVideos;
bool mOnScreen;
nsIntSize mCurrentSize;
#endif
};

View File

@ -36,6 +36,7 @@ using mozilla::DefaultXDisplay;
#include "nsSize.h"
#include "nsDisplayList.h"
#include "ImageLayers.h"
#include "SharedTextureImage.h"
#include "nsIDOMEventTarget.h"
#include "nsObjectFrame.h"
#include "nsIPluginDocument.h"
@ -84,7 +85,6 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#ifdef MOZ_WIDGET_ANDROID
#include "ANPBase.h"
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
#include "nsWindow.h"
static nsPluginInstanceOwner* sFullScreenInstance = nsnull;
@ -170,6 +170,38 @@ static void OnDestroyImage(void* aPluginInstanceOwner)
already_AddRefed<ImageContainer>
nsPluginInstanceOwner::GetImageContainer()
{
#if MOZ_WIDGET_ANDROID
// Right now we only draw with Gecko layers on Honeycomb and higher. See Paint()
// for what we do on other versions.
if (AndroidBridge::Bridge()->GetAPIVersion() < 11)
return NULL;
nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
Image::Format format = Image::SHARED_TEXTURE;
nsRefPtr<Image> img = container->CreateImage(&format, 1);
SharedTextureImage::Data data;
data.mHandle = mInstance->CreateSharedHandle();
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
data.mInverted = mInstance->Inverted();
gfxRect r = GetPluginRect();
data.mSize = gfxIntSize(r.width, r.height);
SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
pluginImage->SetData(data);
container->SetCurrentImage(img);
float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
r.Scale(xResolution, yResolution);
mInstance->NotifySize(nsIntSize(r.width, r.height));
return container.forget();
#endif
if (mInstance) {
nsRefPtr<ImageContainer> container;
// Every call to nsIPluginInstance::GetImage() creates
@ -306,9 +338,7 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mWaitingForPaint = false;
#ifdef MOZ_WIDGET_ANDROID
mInverted = false;
mFullScreen = false;
mLayer = nsnull;
mJavaView = nsnull;
#endif
}
@ -1724,26 +1754,6 @@ gfxRect nsPluginInstanceOwner::GetPluginRect()
return gfxRect(intBounds);
}
void nsPluginInstanceOwner::SendSize(int width, int height)
{
if (!mInstance)
return;
PRInt32 model = mInstance->GetANPDrawingModel();
if (model != kOpenGL_ANPDrawingModel)
return;
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kDraw_ANPEventType;
event.data.draw.model = kOpenGL_ANPDrawingModel;
event.data.draw.data.surfaceSize.width = width;
event.data.draw.data.surfaceSize.height = height;
mInstance->HandleEvent(&event, nsnull);
}
bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect /* = gfxRect(0, 0, 0, 0) */)
{
if (!mJavaView) {
@ -1779,6 +1789,46 @@ void nsPluginInstanceOwner::RemovePluginView()
sFullScreenInstance = nsnull;
}
void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
{
if (!mInstance)
return;
mInstance->GetVideos(aVideos);
}
already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
{
nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
Image::Format format = Image::SHARED_TEXTURE;
nsRefPtr<Image> img = container->CreateImage(&format, 1);
SharedTextureImage::Data data;
data.mHandle = mInstance->GLContext()->CreateSharedHandle(gl::TextureImage::ThreadShared, aVideoInfo->mSurfaceTexture, gl::GLContext::SurfaceTexture);
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
data.mInverted = mInstance->Inverted();
data.mSize = gfxIntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
pluginImage->SetData(data);
container->SetCurrentImage(img);
return container.forget();
}
nsIntRect nsPluginInstanceOwner::GetVisibleRect()
{
gfxRect r = nsIntRect(0, 0, mPluginWindow->width, mPluginWindow->height);
float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
r.Scale(xResolution, yResolution);
return nsIntRect(r.x, r.y, r.width, r.height);
}
void nsPluginInstanceOwner::Invalidate() {
NPRect rect;
rect.left = rect.top = 0;
@ -2756,10 +2806,6 @@ nsPluginInstanceOwner::Destroy()
#if MOZ_WIDGET_ANDROID
RemovePluginView();
if (mLayer)
mLayer->SetVisible(false);
#endif
if (mWidget) {
@ -2875,29 +2921,13 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
PRInt32 model = mInstance->GetANPDrawingModel();
gfxRect pluginRect = GetPluginRect();
if (model == kSurface_ANPDrawingModel) {
if (!AddPluginView(pluginRect)) {
if (!AddPluginView(GetPluginRect())) {
Invalidate();
}
return;
}
if (model == kOpenGL_ANPDrawingModel) {
if (!mLayer)
mLayer = new AndroidMediaLayer();
mLayer->UpdatePosition(pluginRect);
float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
pluginRect.Scale(xResolution, yResolution);
SendSize((int)pluginRect.width, (int)pluginRect.height);
return;
}
if (model != kBitmap_ANPDrawingModel)
return;
@ -3634,9 +3664,6 @@ nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
#ifdef MOZ_WIDGET_ANDROID
if (mInstance) {
if (mLayer)
mLayer->SetVisible(mPluginDocumentActiveState);
if (!mPluginDocumentActiveState)
RemovePluginView();

View File

@ -51,12 +51,6 @@ class gfxXlibSurface;
#include <os2.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
namespace mozilla {
class AndroidMediaLayer;
}
#endif
// X.h defines KeyPress
#ifdef KeyPress
#undef KeyPress
@ -260,21 +254,11 @@ public:
bool UseAsyncRendering();
#ifdef MOZ_WIDGET_ANDROID
nsIntRect GetVisibleRect() {
return nsIntRect(0, 0, mPluginWindow->width, mPluginWindow->height);
}
// Returns the image container for the specified VideoInfo
void GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos);
already_AddRefed<ImageContainer> GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo);
void SetInverted(bool aInverted) {
mInverted = aInverted;
}
bool Inverted() {
return mInverted;
}
mozilla::AndroidMediaLayer* Layer() {
return mLayer;
}
nsIntRect GetVisibleRect();
void Invalidate();
@ -297,19 +281,12 @@ private:
void FixUpURLS(const nsString &name, nsAString &value);
#ifdef MOZ_WIDGET_ANDROID
void SendSize(int width, int height);
gfxRect GetPluginRect();
bool AddPluginView(const gfxRect& aRect = gfxRect(0, 0, 0, 0));
void RemovePluginView();
bool mInverted;
bool mFullScreen;
void* mJavaView;
// For kOpenGL_ANPDrawingModel
nsRefPtr<mozilla::AndroidMediaLayer> mLayer;
#endif
nsPluginNativeWindow *mPluginWindow;

View File

@ -102,7 +102,7 @@ public class GeckoAppShell
public static native void notifyListCreated(int aListId, int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
public static native void notifyGotNextMessage(int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
public static native void notifyReadingMessageListFailed(int aError, int aRequestId, long aProcessId);
public static native void onSurfaceTextureFrameAvailable(SurfaceTexture surfaceTexture, int id);
public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
// A looper thread, accessed by GeckoAppShell.getHandler
private static class LooperThread extends Thread {
@ -1848,4 +1848,10 @@ public class GeckoAppShell
public static String getGfxInfoData() {
return null;
}
public static void registerSurfaceTextureFrameListener(Object surfaceTexture, final int id) {
}
public static void unregisterSurfaceTextureFrameListener(Object surfaceTexture) {
}
}

View File

@ -23,6 +23,7 @@
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "gfxRect.h"
#include "gfx3DMatrix.h"
#include "nsISupportsImpl.h"
#include "prlink.h"
@ -51,6 +52,7 @@ typedef uintptr_t SharedTextureHandle;
enum ShaderProgramType {
RGBALayerProgramType,
RGBALayerExternalProgramType,
BGRALayerProgramType,
RGBXLayerProgramType,
BGRXLayerProgramType,
@ -856,10 +858,26 @@ public:
return IsExtensionSupported(EXT_framebuffer_blit) || IsExtensionSupported(ANGLE_framebuffer_blit);
}
enum SharedTextureBufferType {
TextureID
#ifdef MOZ_WIDGET_ANDROID
, SurfaceTexture
#endif
};
/**
* Create new shared GLContext content handle, must be released by ReleaseSharedHandle.
*/
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType) { return 0; }
/*
* Create a new shared GLContext content handle, using the passed buffer as a source.
* Must be released by ReleaseSharedHandle. UpdateSharedHandle will have no effect
* on handles created with this method, as the caller owns the source (the passed buffer)
* and is responsible for updating it accordingly.
*/
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType,
void* aBuffer,
SharedTextureBufferType aBufferType) { return nsnull; }
/**
* Publish GLContext content to intermediate buffer attached to shared handle.
* Shared handle content is ready to be used after call returns, and no need extra Flush/Finish are required.
@ -882,12 +900,28 @@ public:
*/
virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle) { }
typedef struct {
GLenum mTarget;
ShaderProgramType mProgramType;
gfx3DMatrix mTextureTransform;
} SharedHandleDetails;
/**
* Returns information necessary for rendering a shared handle.
* These values change depending on what sharing mechanism is in use
*/
virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle,
SharedHandleDetails& aDetails) { return false; }
/**
* Attach Shared GL Handle to GL_TEXTURE_2D target
* GLContext must be current before this call
*/
virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle) { return false; }
/**
* Detach Shared GL Handle from GL_TEXTURE_2D target
*/

View File

@ -32,6 +32,7 @@
/* from widget */
#if defined(MOZ_WIDGET_ANDROID)
#include "AndroidBridge.h"
#include "nsSurfaceTexture.h"
#endif
#include <android/log.h>
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
@ -119,6 +120,7 @@ public:
#include "gfxCrashReporterUtils.h"
#if defined(MOZ_PLATFORM_MAEMO) || defined(MOZ_WIDGET_GONK)
static bool gUseBackingSurface = true;
#else
@ -625,10 +627,16 @@ public:
}
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType);
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType,
void* aBuffer,
SharedTextureBufferType aBufferType);
virtual void UpdateSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle);
virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle);
virtual bool GetSharedHandleDetails(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle,
SharedHandleDetails& aDetails);
virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle);
protected:
@ -690,14 +698,61 @@ protected:
}
};
class EGLTextureWrapper
typedef enum {
Image
#ifdef MOZ_WIDGET_ANDROID
, SurfaceTexture
#endif
} SharedHandleType;
class SharedTextureHandleWrapper
{
public:
EGLTextureWrapper(GLContext* aContext, GLuint aTexture)
: mContext(aContext)
SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
{
}
virtual ~SharedTextureHandleWrapper()
{
}
SharedHandleType Type() { return mHandleType; }
SharedHandleType mHandleType;
};
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureWrapper: public SharedTextureHandleWrapper
{
public:
SurfaceTextureWrapper(nsSurfaceTexture* aSurfaceTexture) :
SharedTextureHandleWrapper(SharedHandleType::SurfaceTexture)
, mSurfaceTexture(aSurfaceTexture)
{
}
virtual ~SurfaceTextureWrapper() {
mSurfaceTexture = nsnull;
}
nsSurfaceTexture* SurfaceTexture() { return mSurfaceTexture; }
nsRefPtr<nsSurfaceTexture> mSurfaceTexture;
};
#endif // MOZ_WIDGET_ANDROID
class EGLTextureWrapper : public SharedTextureHandleWrapper
{
public:
EGLTextureWrapper(GLContext* aContext, GLuint aTexture, bool aOwnsTexture) :
SharedTextureHandleWrapper(SharedHandleType::Image)
, mContext(aContext)
, mTexture(aTexture)
, mEGLImage(nsnull)
, mSyncObject(nsnull)
, mOwnsTexture(aOwnsTexture)
{
}
@ -772,11 +827,16 @@ public:
return result == LOCAL_EGL_CONDITION_SATISFIED;
}
bool OwnsTexture() {
return mOwnsTexture;
}
private:
nsRefPtr<GLContext> mContext;
GLuint mTexture;
EGLImage mEGLImage;
EGLSync mSyncObject;
bool mOwnsTexture;
};
void
@ -788,9 +848,12 @@ GLContextEGL::UpdateSharedHandle(TextureImage::TextureShareType aType,
return;
}
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
NS_ASSERTION(wrapper->Type() == SharedHandleType::Image, "Expected EGLImage shared handle");
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
EGLTextureWrapper* wrap = reinterpret_cast<EGLTextureWrapper*>(wrapper);
// We need to copy the current GLContext drawing buffer to the texture
// exported by the EGLImage. Need to save both the read FBO and the texture
// binding, because we're going to munge them to do this.
@ -830,19 +893,56 @@ GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
CreateTextureForOffscreen(ChooseGLFormats(fmt, GLContext::ForceRGBA), mOffscreenSize, texture);
// texture ownership moved to EGLTextureWrapper after this point
// and texture will be deleted in EGLTextureWrapper dtor
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture);
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, true);
if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
// Stop trying to create shared image Handle
mShareWithEGLImage = false;
return nsnull;
}
// Raw pointer shared across threads
return (SharedTextureHandle)tex;
}
SharedTextureHandle
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType,
void* aBuffer,
SharedTextureBufferType aBufferType)
{
// Both EGLImage and SurfaceTexture only support ThreadShared currently, but
// it's possible to make SurfaceTexture work across processes. We should do that.
if (aType != TextureImage::ThreadShared)
return nsnull;
switch (aBufferType) {
#ifdef MOZ_WIDGET_ANDROID
case SharedTextureBufferType::SurfaceTexture:
if (!IsExtensionSupported(GLContext::OES_EGL_image_external)) {
NS_WARNING("Missing GL_OES_EGL_image_external");
return nsnull;
}
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(aBuffer));
#endif
case SharedTextureBufferType::TextureID: {
if (!mShareWithEGLImage)
return nsnull;
GLuint texture = (GLuint)aBuffer;
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture, false);
if (!tex->CreateEGLImage()) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
delete tex;
return nsnull;
}
return (SharedTextureHandle)tex;
}
default:
NS_ERROR("Unknown shared texture buffer type");
return nsnull;
}
}
void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle)
{
@ -851,22 +951,72 @@ void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
return;
}
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
GLContext *ctx = wrap->GetContext();
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
ctx = ctx->GetSharedContext();
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType::SurfaceTexture:
delete wrapper;
break;
#endif
case SharedHandleType::Image: {
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
GLContext *ctx = wrap->GetContext();
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
ctx = ctx->GetSharedContext();
}
// If we have a context, then we need to delete the texture;
// if we don't have a context (either real or shared),
// then they went away when the contex was deleted, because it
// was the only one that had access to it.
if (wrap->OwnsTexture() && ctx && !ctx->IsDestroyed() && ctx->MakeCurrent()) {
GLuint texture = wrap->GetTextureID();
ctx->fDeleteTextures(1, &texture);
}
delete wrap;
break;
}
// If we have a context, then we need to delete the texture;
// if we don't have a context (either real or shared),
// then they went away when the contex was deleted, because it
// was the only one that had access to it.
if (ctx && !ctx->IsDestroyed() && ctx->MakeCurrent()) {
GLuint texture = wrap->GetTextureID();
ctx->fDeleteTextures(1, &texture);
default:
NS_ERROR("Unknown shared handle type");
}
delete wrap;
}
bool GLContextEGL::GetSharedHandleDetails(TextureImage::TextureShareType aType,
SharedTextureHandle aSharedHandle,
SharedHandleDetails& aDetails)
{
if (aType != TextureImage::ThreadShared)
return false;
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType::SurfaceTexture: {
SurfaceTextureWrapper* surfaceWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
aDetails.mTarget = LOCAL_GL_TEXTURE_EXTERNAL;
aDetails.mProgramType = RGBALayerExternalProgramType;
surfaceWrapper->SurfaceTexture()->GetTransformMatrix(aDetails.mTextureTransform);
break;
}
#endif
case SharedHandleType::Image:
aDetails.mTarget = LOCAL_GL_TEXTURE_2D;
aDetails.mProgramType = RGBALayerProgramType;
break;
default:
NS_ERROR("Unknown shared handle type");
return false;
}
return true;
}
bool GLContextEGL::AttachSharedHandle(TextureImage::TextureShareType aType,
@ -875,11 +1025,41 @@ bool GLContextEGL::AttachSharedHandle(TextureImage::TextureShareType aType,
if (aType != TextureImage::ThreadShared)
return false;
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType::SurfaceTexture: {
#ifndef DEBUG
/**
* NOTE: SurfaceTexture spams us if there are any existing GL errors, so we'll clear
* them here in order to avoid that.
*/
GetAndClearError();
#endif
SurfaceTextureWrapper* surfaceTextureWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
// FIXME: SurfaceTexture provides a transform matrix which is supposed to
// be applied to the texture coordinates. We should return that here
// so we can render correctly. Bug 775083
surfaceTextureWrapper->SurfaceTexture()->UpdateTexImage();
break;
}
#endif // MOZ_WIDGET_ANDROID
case SharedHandleType::Image: {
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
break;
}
default:
NS_ERROR("Unknown shared handle type");
return false;
}
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
wrap->WaitSync();
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
return true;
}

View File

@ -3252,6 +3252,7 @@ typedef void* GLeglImage;
#define LOCAL_EGL_CORE_NATIVE_ENGINE 0x305B
#define LOCAL_EGL_READ 0x305A
#define LOCAL_EGL_DRAW 0x3059
#define LOCAL_EGL_BAD_PARAMETER 0x300C
#define LOCAL_EGL_CONTEXT_LOST 0x300E
// EGL_KHR_image_base (not supplied by EGL_KHR_image!)
@ -3263,6 +3264,9 @@ typedef void* GLeglImage;
// EGL_KHR_gl_texture_2D_image
#define LOCAL_EGL_GL_TEXTURE_2D 0x30B1
// OES_EGL_image_external
#define LOCAL_GL_TEXTURE_EXTERNAL 0x8D65
// EGL_KHR_fence_sync
#define LOCAL_EGL_SYNC_FENCE 0x30F9
#define LOCAL_EGL_SYNC_TYPE 0x30F7

View File

@ -6,6 +6,7 @@
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ipc/CrossProcessMutex.h"
#include "ImageLayers.h"
#include "SharedTextureImage.h"
#include "gfxImageSurface.h"
#include "gfxSharedImageSurface.h"
#include "yuv_convert.h"
@ -43,6 +44,8 @@ ImageFactory::CreateImage(const Image::Format *aFormats,
img = new PlanarYCbCrImage(aRecycleBin);
} else if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) {
img = new CairoImage();
} else if (FormatInList(aFormats, aNumFormats, Image::SHARED_TEXTURE)) {
img = new SharedTextureImage();
#ifdef XP_MACOSX
} else if (FormatInList(aFormats, aNumFormats, Image::MAC_IO_SURFACE)) {
img = new MacIOSurfaceImage();

View File

@ -122,6 +122,11 @@ public:
*/
REMOTE_IMAGE_BITMAP,
/**
* A OpenGL texture that can be shared across threads or processes
*/
SHARED_TEXTURE,
/**
* An DXGI shared surface handle that can be shared with a remote process.
*/

View File

@ -39,6 +39,8 @@ EXPORTS = \
LayerManagerOGLProgram.h \
ReadbackLayer.h \
LayerSorter.h \
TexturePoolOGL.h \
SharedTextureImage.h \
$(NULL)
CPPSRCS = \
@ -67,6 +69,7 @@ CPPSRCS = \
LayerManagerOGLProgram.cpp \
LayerSorter.cpp \
ImageLayers.cpp \
TexturePoolOGL.cpp \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)

View File

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_SHAREDTEXTUREIMAGE_H
#define GFX_SHAREDTEXTUREIMAGE_H
#include "ImageLayers.h"
#include "GLContext.h"
// Split into a separate header from ImageLayers.h due to GLContext.h dependence
// Implementation remains in ImageLayers.cpp
namespace mozilla {
namespace layers {
class THEBES_API SharedTextureImage : public Image {
public:
struct Data {
gl::SharedTextureHandle mHandle;
gl::TextureImage::TextureShareType mShareType;
gfxIntSize mSize;
bool mInverted;
};
void SetData(const Data& aData) { mData = aData; }
const Data* GetData() { return &mData; }
gfxIntSize GetSize() { return mData.mSize; }
virtual already_AddRefed<gfxASurface> GetAsSurface() { return NULL; }
SharedTextureImage() : Image(NULL, SHARED_TEXTURE) {}
private:
Data mData;
};
} // layers
} // mozilla
#endif // GFX_SHAREDTEXTUREIMAGE_H

View File

@ -387,7 +387,7 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
if (!handle) {
handle = mGLContext->CreateSharedHandle(flags);
if (handle) {
mBackBuffer = SharedTextureDescriptor(flags, handle, mBounds.Size());
mBackBuffer = SharedTextureDescriptor(flags, handle, mBounds.Size(), false);
}
}
if (handle) {

View File

@ -5,6 +5,7 @@
#include "mozilla/layers/PLayersParent.h"
#include "BasicLayersImpl.h"
#include "SharedTextureImage.h"
#include "gfxUtils.h"
#include "gfxSharedImageSurface.h"
#include "mozilla/layers/ImageContainerChild.h"
@ -277,6 +278,17 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
->Paint(aContext, nsnull);
}
if (image->GetFormat() == Image::SHARED_TEXTURE &&
BasicManager()->GetParentBackendType() == mozilla::layers::LAYERS_OPENGL) {
SharedTextureImage *sharedImage = static_cast<SharedTextureImage*>(image);
const SharedTextureImage::Data *data = sharedImage->GetData();
SharedTextureDescriptor texture(data->mShareType, data->mHandle, data->mSize, data->mInverted);
SurfaceDescriptor descriptor(texture);
BasicManager()->PaintedImage(BasicManager()->Hold(this), descriptor);
return;
}
if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();

View File

@ -40,6 +40,7 @@ struct SharedTextureDescriptor {
TextureShareType shareType;
SharedTextureHandle handle;
nsIntSize size;
bool inverted;
};
struct SurfaceDescriptorGralloc {

View File

@ -335,7 +335,7 @@ ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
if (IsValidSharedTexDescriptor(aNewFront)) {
MakeTextureIfNeeded(gl(), mTexture);
if (!IsValidSharedTexDescriptor(mFrontBufferDescriptor)) {
mFrontBufferDescriptor = SharedTextureDescriptor(TextureImage::ThreadShared, 0, nsIntSize(0, 0));
mFrontBufferDescriptor = SharedTextureDescriptor(TextureImage::ThreadShared, 0, nsIntSize(0, 0), false);
}
*aNewBack = mFrontBufferDescriptor;
mFrontBufferDescriptor = aNewFront;

View File

@ -18,12 +18,32 @@
# include "mozilla/X11Util.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "nsSurfaceTexture.h"
#endif
using namespace mozilla::gfx;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
static void
MakeTextureIfNeeded(GLContext* gl, GLuint& aTexture)
{
if (aTexture != 0)
return;
gl->fGenTextures(1, &aTexture);
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
}
/**
* This is an event used to unref a GLContext on the main thread and
* optionally delete a texture associated with that context.
@ -676,6 +696,9 @@ ImageLayerOGL::LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize)
ShadowImageLayerOGL::ShadowImageLayerOGL(LayerManagerOGL* aManager)
: ShadowImageLayer(aManager, nsnull)
, LayerOGL(aManager)
, mSharedHandle(0)
, mInverted(false)
, mTexture(0)
{
mImplData = static_cast<LayerOGL*>(this);
}
@ -687,15 +710,23 @@ bool
ShadowImageLayerOGL::Init(const SharedImage& aFront)
{
if (aFront.type() == SharedImage::TSurfaceDescriptor) {
AutoOpenSurface autoSurf(OPEN_READ_ONLY, aFront.get_SurfaceDescriptor());
mSize = autoSurf.Size();
mTexImage = gl()->CreateTextureImage(nsIntSize(mSize.width, mSize.height),
autoSurf.ContentType(),
LOCAL_GL_CLAMP_TO_EDGE,
mForceSingleTile
? TextureImage::ForceSingleTile
: TextureImage::NoFlags);
return true;
SurfaceDescriptor surface = aFront.get_SurfaceDescriptor();
if (surface.type() == SurfaceDescriptor::TSharedTextureDescriptor) {
SharedTextureDescriptor texture = surface.get_SharedTextureDescriptor();
mSize = texture.size();
mSharedHandle = texture.handle();
mShareType = texture.shareType();
mInverted = texture.inverted();
} else {
AutoOpenSurface autoSurf(OPEN_READ_ONLY, surface);
mSize = autoSurf.Size();
mTexImage = gl()->CreateTextureImage(nsIntSize(mSize.width, mSize.height),
autoSurf.ContentType(),
LOCAL_GL_CLAMP_TO_EDGE,
mForceSingleTile
? TextureImage::ForceSingleTile
: TextureImage::NoFlags);
}
} else {
YUVImage yuv = aFront.get_YUVImage();
@ -739,15 +770,31 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
mImageVersion = 0;
}
} else if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.get_SurfaceDescriptor());
gfxIntSize size = surf.Size();
if (mSize != size || !mTexImage ||
mTexImage->GetContentType() != surf.ContentType()) {
Init(aNewFront);
SurfaceDescriptor surface = aNewFront.get_SurfaceDescriptor();
if (surface.type() == SurfaceDescriptor::TSharedTextureDescriptor) {
SharedTextureDescriptor texture = surface.get_SharedTextureDescriptor();
SharedTextureHandle newHandle = texture.handle();
mSize = texture.size();
mInverted = texture.inverted();
if (mSharedHandle && newHandle != mSharedHandle)
gl()->ReleaseSharedHandle(mShareType, mSharedHandle);
mSharedHandle = newHandle;
mShareType = texture.shareType();
} else {
AutoOpenSurface surf(OPEN_READ_ONLY, surface);
gfxIntSize size = surf.Size();
if (mSize != size || !mTexImage ||
mTexImage->GetContentType() != surf.ContentType()) {
Init(aNewFront);
}
// XXX this is always just ridiculously slow
nsIntRegion updateRegion(nsIntRect(0, 0, size.width, size.height));
mTexImage->DirectUpdate(surf.Get(), updateRegion);
}
// XXX this is always just ridiculously slow
nsIntRegion updateRegion(nsIntRect(0, 0, size.width, size.height));
mTexImage->DirectUpdate(surf.Get(), updateRegion);
} else {
const YUVImage& yuv = aNewFront.get_YUVImage();
UploadSharedYUVToTexture(yuv);
@ -880,7 +927,39 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
mTexImage->GetTileRect().Size());
} while (mTexImage->NextTile());
}
} else if (mSharedHandle) {
GLContext::SharedHandleDetails handleDetails;
if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
NS_ERROR("Failed to get shared handle details");
return;
}
ShaderProgramOGL* program = mOGLManager->GetProgram(handleDetails.mProgramType, GetMaskLayer());
program->Activate();
program->SetLayerTransform(GetEffectiveTransform());
program->SetLayerOpacity(GetEffectiveOpacity());
program->SetRenderOffset(aOffset);
program->SetTextureUnit(0);
program->SetTextureTransform(handleDetails.mTextureTransform);
program->LoadMask(GetMaskLayer());
MakeTextureIfNeeded(gl(), mTexture);
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(handleDetails.mTarget, mTexture);
if (!gl()->AttachSharedHandle(mShareType, mSharedHandle)) {
NS_ERROR("Failed to bind shared texture handle");
return;
}
gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
LOCAL_GL_ONE, LOCAL_GL_ONE);
gl()->ApplyFilterToBoundTexture(mFilter);
program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mSize));
mOGLManager->BindAndDrawQuad(program, mInverted);
gl()->fBindTexture(handleDetails.mTarget, 0);
gl()->DetachSharedHandle(mShareType, mSharedHandle);
} else {
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[0].GetTextureID());
@ -932,6 +1011,11 @@ ShadowImageLayerOGL::LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize)
void
ShadowImageLayerOGL::CleanupResources()
{
if (mSharedHandle) {
gl()->ReleaseSharedHandle(mShareType, mSharedHandle);
mSharedHandle = NULL;
}
mYUVTexture[0].Release();
mYUVTexture[1].Release();
mYUVTexture[2].Release();

View File

@ -180,6 +180,13 @@ private:
nsRefPtr<TextureImage> mTexImage;
// For SharedTextureHandle
gl::SharedTextureHandle mSharedHandle;
gl::TextureImage::TextureShareType mShareType;
bool mInverted;
GLuint mTexture;
GLTexture mYUVTexture[3];
gfxIntSize mSize;
gfxIntSize mCbCrSize;

View File

@ -17,6 +17,7 @@
#include "TiledThebesLayerOGL.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Preferences.h"
#include "TexturePoolOGL.h"
#include "gfxContext.h"
#include "gfxUtils.h"
@ -751,6 +752,10 @@ LayerManagerOGL::Render()
MakeCurrent();
}
#if MOZ_WIDGET_ANDROID
TexturePoolOGL::Fill(gl());
#endif
SetupBackBuffer(width, height);
SetupPipeline(width, height, ApplyWorldTransform);

View File

@ -53,6 +53,23 @@ ProgramProfileOGL::GetProfileFor(gl::ShaderProgramType aType,
AddCommonTextureArgs(result);
result.mTextureCount = 1;
break;
case gl::RGBALayerExternalProgramType:
if (aMask == Mask3d) {
result.mVertexShaderString = sLayerMask3DVS;
result.mFragmentShaderString = sRGBATextureLayerExternalMask3DFS;
} else if (aMask == Mask2d) {
result.mVertexShaderString = sLayerMaskVS;
result.mFragmentShaderString = sRGBATextureLayerExternalMaskFS;
} else {
result.mVertexShaderString = sLayerVS;
result.mFragmentShaderString = sRGBATextureLayerExternalFS;
}
AddCommonArgs(result);
AddCommonTextureArgs(result);
result.mUniforms.AppendElement(Argument("uTextureTransform"));
result.mHasTextureTransform = true;
result.mTextureCount = 1;
break;
case gl::BGRALayerProgramType:
if (aMask == Mask2d) {
result.mVertexShaderString = sLayerMaskVS;

View File

@ -111,10 +111,12 @@ struct ProgramProfileOGL
nsTArray<Argument> mAttributes;
PRUint32 mTextureCount;
bool mHasMatrixProj;
bool mHasTextureTransform;
private:
ProgramProfileOGL() :
mTextureCount(0),
mHasMatrixProj(false) {}
mHasMatrixProj(false),
mHasTextureTransform(false) {}
};
@ -142,7 +144,6 @@ public:
mIsProjectionMatrixStale(false), mGL(aGL), mProgram(0),
mProfile(aProfile), mProgramState(STATE_NEW) { }
~ShaderProgramOGL() {
if (mProgram <= 0) {
return;
@ -246,6 +247,12 @@ public:
mIsProjectionMatrixStale = false;
}
// sets this program's texture transform, if it uses one
void SetTextureTransform(const gfx3DMatrix& aMatrix) {
if (mProfile.mHasTextureTransform)
SetMatrixUniform(mProfile.LookupUniformLocation("uTextureTransform"), aMatrix);
}
void SetRenderOffset(const nsIntPoint& aOffset) {
float vals[4] = { float(aOffset.x), float(aOffset.y), 0.0f, 0.0f };
SetUniform(mProfile.LookupUniformLocation("uRenderTargetOffset"), 4, vals);

View File

@ -232,6 +232,91 @@ gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;\n\
}\n\
";
static const char sRGBATextureLayerExternalFS[] = "/* sRGBATextureLayerExternalFS */\n\
/* Fragment Shader */\n\
#ifdef GL_ES\n\
precision lowp float;\n\
#endif\n\
\n\
#ifndef NO_LAYER_OPACITY\n\
uniform float uLayerOpacity;\n\
#endif\n\
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
varying mediump vec2 vTexCoord;\n\
#else\n\
varying vec2 vTexCoord;\n\
#endif\n\
\n\
#extension GL_OES_EGL_image_external : require\n\
uniform samplerExternalOES uTexture;\n\
uniform mat4 uTextureTransform;\n\
void main()\n\
{\n\
float mask = 1.0;\n\
\n\
gl_FragColor = texture2D(uTexture, (uTextureTransform * vec4(vTexCoord.x, vTexCoord.y, 0.0, 1.0)).xy) * uLayerOpacity * mask;\n\
}\n\
";
static const char sRGBATextureLayerExternalMaskFS[] = "/* sRGBATextureLayerExternalMaskFS */\n\
/* Fragment Shader */\n\
#ifdef GL_ES\n\
precision lowp float;\n\
#endif\n\
\n\
#ifndef NO_LAYER_OPACITY\n\
uniform float uLayerOpacity;\n\
#endif\n\
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
varying mediump vec2 vTexCoord;\n\
#else\n\
varying vec2 vTexCoord;\n\
#endif\n\
\n\
varying vec2 vMaskCoord;\n\
uniform sampler2D uMaskTexture;\n\
\n\
#extension GL_OES_EGL_image_external : require\n\
uniform samplerExternalOES uTexture;\n\
uniform mat4 uTextureTransform;\n\
void main()\n\
{\n\
float mask = texture2D(uMaskTexture, vMaskCoord).r;\n\
\n\
gl_FragColor = texture2D(uTexture, (uTextureTransform * vec4(vTexCoord.x, vTexCoord.y, 0.0, 1.0)).xy) * uLayerOpacity * mask;\n\
}\n\
";
static const char sRGBATextureLayerExternalMask3DFS[] = "/* sRGBATextureLayerExternalMask3DFS */\n\
/* Fragment Shader */\n\
#ifdef GL_ES\n\
precision lowp float;\n\
#endif\n\
\n\
#ifndef NO_LAYER_OPACITY\n\
uniform float uLayerOpacity;\n\
#endif\n\
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
varying mediump vec2 vTexCoord;\n\
#else\n\
varying vec2 vTexCoord;\n\
#endif\n\
\n\
varying vec3 vMaskCoord;\n\
uniform sampler2D uMaskTexture;\n\
\n\
#extension GL_OES_EGL_image_external : require\n\
uniform samplerExternalOES uTexture;\n\
uniform mat4 uTextureTransform;\n\
void main()\n\
{\n\
vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;\n\
float mask = texture2D(uMaskTexture, maskCoords).r;\n\
\n\
gl_FragColor = texture2D(uTexture, (uTextureTransform * vec4(vTexCoord.x, vTexCoord.y, 0.0, 1.0)).xy) * uLayerOpacity * mask;\n\
}\n\
";
static const char sRGBARectTextureLayerFS[] = "/* sRGBARectTextureLayerFS */\n\
#extension GL_ARB_texture_rectangle : enable\n\
/* Fragment Shader */\n\

View File

@ -211,6 +211,20 @@ $FRAGMENT_CALC_MASK<mask>$
}
@end
// Single texture in RGBA format for use with GL_TEXTURE_EXTERNAL_OES
@shader sRGBATextureLayerExternal<mask:,Mask,Mask3D>FS
$LAYER_FRAGMENT<mask>$
#extension GL_OES_EGL_image_external : require
uniform samplerExternalOES uTexture;
uniform mat4 uTextureTransform;
void main()
{
$FRAGMENT_CALC_MASK<mask>$
gl_FragColor = texture2D(uTexture, (uTextureTransform * vec4(vTexCoord.x, vTexCoord.y, 0.0, 1.0)).xy) * uLayerOpacity * mask;
}
@end
// Single texture in RGBA format, but with a Rect texture.
// Container layer needs this to render a FBO group.

View File

@ -0,0 +1,115 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TexturePoolOGL.h"
#include "GLContext.h"
#include "nsDeque.h"
#include "mozilla/Monitor.h"
#define TEXTURE_POOL_SIZE 10
namespace mozilla {
namespace gl {
static GLContext* sActiveContext = NULL;
static Monitor* sMonitor = NULL;
static nsDeque* sTextures = NULL;
GLuint TexturePoolOGL::AcquireTexture()
{
NS_ASSERTION(sMonitor, "not initialized");
MonitorAutoLock lock(*sMonitor);
if (!sActiveContext) {
// Wait for a context
sMonitor->Wait();
if (!sActiveContext)
return 0;
}
GLuint texture = 0;
if (sActiveContext->IsOwningThreadCurrent()) {
sActiveContext->MakeCurrent();
sActiveContext->fGenTextures(1, &texture);
} else {
while (sTextures->GetSize() == 0) {
NS_WARNING("Waiting for texture");
sMonitor->Wait();
}
GLuint* popped = (GLuint*) sTextures->Pop();
if (!popped) {
NS_ERROR("Failed to pop texture pool item");
return 0;
}
texture = *popped;
delete popped;
NS_ASSERTION(texture, "Failed to retrieve texture from pool");
}
return texture;
}
static void Clear()
{
if (!sActiveContext)
return;
sActiveContext->MakeCurrent();
GLuint* item;
while (sTextures->GetSize()) {
item = (GLuint*)sTextures->Pop();
sActiveContext->fDeleteTextures(1, item);
delete item;
}
}
void TexturePoolOGL::Fill(GLContext* aContext)
{
NS_ASSERTION(aContext, "NULL GLContext");
NS_ASSERTION(sMonitor, "not initialized");
MonitorAutoLock lock(*sMonitor);
if (sActiveContext != aContext) {
Clear();
sActiveContext = aContext;
}
if (sTextures->GetSize() == TEXTURE_POOL_SIZE)
return;
sActiveContext->MakeCurrent();
GLuint* texture = NULL;
while (sTextures->GetSize() < TEXTURE_POOL_SIZE) {
texture = (GLuint*)malloc(sizeof(GLuint));
sActiveContext->fGenTextures(1, texture);
sTextures->Push((void*) texture);
}
sMonitor->NotifyAll();
}
void TexturePoolOGL::Init()
{
sMonitor = new Monitor("TexturePoolOGL.sMonitor");
sTextures = new nsDeque();
}
void TexturePoolOGL::Shutdown()
{
delete sMonitor;
delete sTextures;
}
} // gl
} // mozilla

View File

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_TEXTUREPOOLOGL_H
#define GFX_TEXTUREPOOLOGL_H
#include "GLContext.h"
namespace mozilla {
namespace gl {
// A texture pool for for the on-screen GLContext. The main purpose of this class
// is to provide the ability to easily allocate an on-screen texture from the
// content thread. The unfortunate nature of the SurfaceTexture API (see nsSurfaceTexture)
// necessitates this.
class TexturePoolOGL
{
public:
// Get a new texture from the pool. Will block
// and wait for one to be created if necessary
static GLuint AcquireTexture();
// Called by the active LayerManagerOGL to fill
// the pool
static void Fill(GLContext* aContext);
// Initializes the pool, but does not fill it. Called by gfxPlatform init.
static void Init();
// Clears all internal data structures in preparation for shutdown
static void Shutdown();
};
} // gl
} // mozilla
#endif // GFX_TEXTUREPOOLOGL_H

View File

@ -49,6 +49,7 @@ EXPORTS = \
gfxUserFontSet.h \
nsCoreAnimationSupport.h \
nsIOSurface.h \
nsSurfaceTexture.h \
gfxSharedImageSurface.h \
gfxReusableSurfaceWrapper.h \
$(NULL)
@ -174,6 +175,7 @@ CPPSRCS = \
gfxHarfBuzzShaper.cpp \
gfxSharedImageSurface.cpp \
gfxReusableSurfaceWrapper.cpp \
nsSurfaceTexture.cpp \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),$(findstring $(MOZ_WIDGET_TOOLKIT),android gtk2 gonk qt))

View File

@ -59,6 +59,10 @@
#include "GLContext.h"
#include "GLContextProvider.h"
#ifdef MOZ_WIDGET_ANDROID
#include "TexturePoolOGL.h"
#endif
#include "mozilla/FunctionTimer.h"
#include "mozilla/Preferences.h"
#include "mozilla/Assertions.h"
@ -335,6 +339,11 @@ gfxPlatform::Init()
gPlatform->mWorkAroundDriverBugs = Preferences::GetBool("gfx.work-around-driver-bugs", true);
#ifdef MOZ_WIDGET_ANDROID
// Texture pool init
mozilla::gl::TexturePoolOGL::Init();
#endif
// Force registration of the gfx component, thus arranging for
// ::Shutdown to be called.
nsCOMPtr<nsISupports> forceReg
@ -371,6 +380,11 @@ gfxPlatform::Shutdown()
gPlatform->mFontPrefsObserver = nsnull;
}
#ifdef MOZ_WIDGET_ANDROID
// Shut down the texture pool
mozilla::gl::TexturePoolOGL::Shutdown();
#endif
// Shut down the default GL context provider.
mozilla::gl::GLContextProvider::Shutdown();

View File

@ -0,0 +1,263 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef MOZ_WIDGET_ANDROID
#include <set>
#include <map>
#include <android/log.h>
#include "nsSurfaceTexture.h"
#include "gfxImageSurface.h"
#include "AndroidBridge.h"
using namespace mozilla;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsSurfaceTexture" , ## args)
// UGH
static std::map<int, nsSurfaceTexture*> sInstances;
static int sNextID = 0;
static class JNIFunctions {
public:
JNIFunctions() : mInitialized(false)
{
}
bool EnsureInitialized()
{
if (mInitialized)
return true;
JNIEnv* env = GetJNIForThread();
if (!env)
return false;
AutoLocalJNIFrame jniFrame(env);
jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture"));
jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V");
jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V");
jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V");
mInitialized = true;
return true;
}
jobject CreateSurfaceTexture(GLuint aTexture)
{
if (!EnsureInitialized())
return NULL;
JNIEnv* env = GetJNIForThread();
if (!env)
return NULL;
AutoLocalJNIFrame jniFrame(env);
return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture));
}
void ReleaseSurfaceTexture(jobject aSurfaceTexture)
{
JNIEnv* env = GetJNIForThread();
if (!env)
return;
env->DeleteGlobalRef(aSurfaceTexture);
}
void UpdateTexImage(jobject aSurfaceTexture)
{
JNIEnv* env = GetJNIForThread();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
env->CallObjectMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage);
}
bool GetTransformMatrix(jobject aSurfaceTexture, gfx3DMatrix& aMatrix)
{
JNIEnv* env = GetJNIForThread();
if (!env)
return false;
AutoLocalJNIFrame jniFrame(env);
jfloatArray jarray = env->NewFloatArray(16);
env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray);
jfloat* array = env->GetFloatArrayElements(jarray, NULL);
aMatrix._11 = array[0];
aMatrix._12 = array[1];
aMatrix._13 = array[2];
aMatrix._14 = array[3];
aMatrix._21 = array[4];
aMatrix._22 = array[5];
aMatrix._23 = array[6];
aMatrix._24 = array[7];
aMatrix._31 = array[8];
aMatrix._32 = array[9];
aMatrix._33 = array[10];
aMatrix._34 = array[11];
aMatrix._41 = array[12];
aMatrix._42 = array[13];
aMatrix._43 = array[14];
aMatrix._44 = array[15];
env->ReleaseFloatArrayElements(jarray, array, 0);
return false;
}
private:
bool mInitialized;
jclass jSurfaceTextureClass;
jmethodID jSurfaceTexture_Ctor;
jmethodID jSurfaceTexture_updateTexImage;
jmethodID jSurfaceTexture_getTransformMatrix;
} sJNIFunctions;
nsSurfaceTexture*
nsSurfaceTexture::Create(GLuint aTexture)
{
// Right now we only support creating this on the main thread because
// of the JNIEnv assumptions in JNIHelper and elsewhere
if (!NS_IsMainThread())
return NULL;
nsSurfaceTexture* st = new nsSurfaceTexture();
if (!st->Init(aTexture)) {
LOG("Failed to initialize nsSurfaceTexture");
delete st;
st = NULL;
}
return st;
}
nsSurfaceTexture*
nsSurfaceTexture::Find(int id)
{
std::map<int, nsSurfaceTexture*>::iterator it;
it = sInstances.find(id);
if (it == sInstances.end())
return NULL;
return it->second;
}
bool
nsSurfaceTexture::Check()
{
return sJNIFunctions.EnsureInitialized();
}
bool
nsSurfaceTexture::Init(GLuint aTexture)
{
if (!sJNIFunctions.EnsureInitialized())
return false;
JNIEnv* env = GetJNIForThread();
if (!env)
return false;
mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture);
if (!mSurfaceTexture)
return false;
mNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindowFromSurfaceTexture(env, mSurfaceTexture);
mID = ++sNextID;
sInstances.insert(std::pair<int, nsSurfaceTexture*>(mID, this));
return true;
}
nsSurfaceTexture::nsSurfaceTexture()
: mSurfaceTexture(NULL), mNativeWindow(NULL)
{
}
nsSurfaceTexture::~nsSurfaceTexture()
{
sInstances.erase(mID);
mFrameAvailableCallback = NULL;
if (mNativeWindow) {
AndroidBridge::Bridge()->ReleaseNativeWindowForSurfaceTexture(mSurfaceTexture);
mNativeWindow = NULL;
}
JNIEnv* env = GetJNIForThread();
if (!env)
return;
if (mSurfaceTexture && env) {
AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
env->DeleteGlobalRef(mSurfaceTexture);
mSurfaceTexture = NULL;
}
}
void*
nsSurfaceTexture::GetNativeWindow()
{
return mNativeWindow;
}
void
nsSurfaceTexture::UpdateTexImage()
{
sJNIFunctions.UpdateTexImage(mSurfaceTexture);
}
bool
nsSurfaceTexture::GetTransformMatrix(gfx3DMatrix& aMatrix)
{
return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix);
}
void
nsSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
{
if (aRunnable)
AndroidBridge::Bridge()->RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
else
AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
mFrameAvailableCallback = aRunnable;
}
void
nsSurfaceTexture::NotifyFrameAvailable()
{
if (mFrameAvailableCallback) {
// Proxy to main thread if we aren't on it
if (!NS_IsMainThread()) {
// Proxy to main thread
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsSurfaceTexture::NotifyFrameAvailable);
NS_DispatchToCurrentThread(event);
} else {
mFrameAvailableCallback->Run();
}
}
}
#endif // MOZ_WIDGET_ANDROID

View File

@ -0,0 +1,64 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsSurfaceTexture_h__
#define nsSurfaceTexture_h__
#ifdef MOZ_WIDGET_ANDROID
#include <jni.h>
#include "nsIRunnable.h"
#include "gfxPlatform.h"
#include "gfx3DMatrix.h"
#include "GLDefs.h"
class gfxASurface;
/**
* This class is a wrapper around Android's SurfaceTexture class.
* Usage is pretty much exactly like the Java class, so see
* the Android documentation for details.
*/
class THEBES_API nsSurfaceTexture {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsSurfaceTexture)
public:
static nsSurfaceTexture* Create(GLuint aTexture);
static nsSurfaceTexture* Find(int id);
// Returns with reasonable certainty whether or not we'll
// be able to create and use a SurfaceTexture
static bool Check();
~nsSurfaceTexture();
// This is an ANativeWindow. Use AndroidBridge::LockWindow and
// friends for manipulating it.
void* GetNativeWindow();
// This attaches the updated data to the TEXTURE_EXTERNAL target
void UpdateTexImage();
bool GetTransformMatrix(gfx3DMatrix& aMatrix);
int ID() { return mID; }
void SetFrameAvailableCallback(nsIRunnable* aRunnable);
// Only should be called by AndroidJNI when we get a
// callback from the underlying SurfaceTexture instance
void NotifyFrameAvailable();
private:
nsSurfaceTexture();
bool Init(GLuint aTexture);
jobject mSurfaceTexture;
void* mNativeWindow;
int mID;
nsRefPtr<nsIRunnable> mFrameAvailableCallback;
};
#endif
#endif

View File

@ -49,6 +49,7 @@ enum Type {
TYPE_PAGE_SEQUENCE,
TYPE_PLUGIN,
TYPE_PLUGIN_READBACK,
TYPE_PLUGIN_VIDEO,
TYPE_PRINT_PLUGIN,
TYPE_REMOTE,
TYPE_REMOTE_SHADOW,

View File

@ -145,6 +145,11 @@ using mozilla::DefaultXDisplay;
#include "gfxOS2Surface.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#include "GLContext.h"
#endif
#ifdef CreateEvent // Thank you MS.
#undef CreateEvent
#endif
@ -932,6 +937,66 @@ nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
return true;
}
#ifdef MOZ_WIDGET_ANDROID
class nsDisplayPluginVideo : public nsDisplayItem {
public:
nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
: nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo)
{
MOZ_COUNT_CTOR(nsDisplayPluginVideo);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayPluginVideo() {
MOZ_COUNT_DTOR(nsDisplayPluginVideo);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO)
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters)
{
return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this);
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aParameters)
{
return LAYER_ACTIVE;
}
nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; }
private:
nsNPAPIPluginInstance::VideoInfo* mVideoInfo;
};
nsRect
nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
*aSnap = false;
return GetDisplayItemBounds(aBuilder, this, mFrame);
}
bool
nsDisplayPluginVideo::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion);
}
#endif
nsRect
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
{
@ -1086,6 +1151,9 @@ nsObjectFrame::IsOpaque() const
#if defined(XP_MACOSX)
// ???
return false;
#elif defined(MOZ_WIDGET_ANDROID)
// We don't know, so just assume transparent
return false;
#else
return !IsTransparentMode();
#endif
@ -1174,6 +1242,8 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
nsDisplayItem::TYPE_PRINT_PLUGIN));
} else {
// We don't need this on Android, and it just confuses things
#if !MOZ_WIDGET_ANDROID
if (aBuilder->IsPaintingToWindow() &&
GetLayerState(aBuilder, nsnull) == LAYER_ACTIVE &&
IsTransparentMode()) {
@ -1181,6 +1251,22 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayPluginReadback(aBuilder, this));
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
#if MOZ_WIDGET_ANDROID
if (aBuilder->IsPaintingToWindow() &&
GetLayerState(aBuilder, nsnull) == LAYER_ACTIVE) {
nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos;
mInstanceOwner->GetVideos(videos);
for (int i = 0; i < videos.Length(); i++) {
rv = replacedContent.AppendNewToTop(new (aBuilder)
nsDisplayPluginVideo(aBuilder, this, videos[i]));
NS_ENSURE_SUCCESS(rv, rv);
}
}
#endif
rv = replacedContent.AppendNewToTop(new (aBuilder)
nsDisplayPlugin(aBuilder, this));
@ -1488,6 +1574,12 @@ nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
}
#endif
#ifdef MOZ_WIDGET_ANDROID
// We always want a layer on Honeycomb and later
if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
return LAYER_ACTIVE;
#endif
if (!mInstanceOwner->UseAsyncRendering()) {
return LAYER_NONE;
}
@ -1566,6 +1658,32 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
imglayer->SetFilter(filter);
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
#ifdef MOZ_WIDGET_ANDROID
} else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) {
nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem);
nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo();
nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo);
if (!container)
return nsnull;
if (!layer) {
// Initialize ImageLayer
layer = aManager->CreateImageLayer();
if (!layer)
return nsnull;
}
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
imglayer->SetContainer(container);
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
// Set the offset and size according to the video dimensions
r.MoveBy(videoInfo->mDimensions.TopLeft());
size.width = videoInfo->mDimensions.width;
size.height = videoInfo->mDimensions.height;
#endif
} else {
NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
"Unknown item type");

View File

@ -12,7 +12,6 @@ import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PluginLayer;
import org.mozilla.gecko.gfx.PointUtils;
import org.mozilla.gecko.gfx.SurfaceTextureLayer;
import org.mozilla.gecko.ui.PanZoomController;
import java.io.*;
@ -235,14 +234,6 @@ abstract public class GeckoApp
}
}
// we don't support Honeycomb
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
Build.VERSION.SDK_INT < 14 /*Build.VERSION_CODES.ICE_CREAM_SANDWICH*/ )
{
Log.w(LOGTAG, "Blocking plugins because of Honeycomb");
return new String[0];
}
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - start of getPluginDirectories");
ArrayList<String> directories = new ArrayList<String>();
@ -1612,51 +1603,6 @@ abstract public class GeckoApp
}
});
}
public Surface createSurface() {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return null;
SurfaceTextureLayer layer = SurfaceTextureLayer.create();
if (layer == null)
return null;
Surface surface = layer.getSurface();
tab.addPluginLayer(surface, layer);
return surface;
}
public void destroySurface(Surface surface) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
Layer layer = tab.removePluginLayer(surface);
hidePluginLayer(layer);
}
public void showSurface(Surface surface, int x, int y,
int w, int h, boolean inverted, boolean blend) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
LayerView layerView = mLayerController.getView();
SurfaceTextureLayer layer = (SurfaceTextureLayer)tab.getPluginLayer(surface);
if (layer == null)
return;
layer.update(new Rect(x, y, x + w, y + h), inverted, blend);
layerView.addLayer(layer);
// FIXME: shouldn't be necessary, layer will request
// one when it gets first frame
layerView.requestRender();
}
private void hidePluginLayer(Layer layer) {
LayerView layerView = mLayerController.getView();
@ -1670,19 +1616,6 @@ abstract public class GeckoApp
layerView.requestRender();
}
public void hideSurface(Surface surface) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
Layer layer = tab.getPluginLayer(surface);
if (layer == null)
return;
hidePluginLayer(layer);
}
public void requestRender() {
mLayerController.getView().requestRender();
}

View File

@ -145,6 +145,7 @@ public class GeckoAppShell
public static native void loadNSSLibsNative(String apkName, boolean shouldExtract);
public static native void onChangeNetworkLinkStatus(String status);
public static native Message getNextMessageFromQueue(MessageQueue queue);
public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
public static void registerGlobalExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@ -1690,35 +1691,6 @@ public class GeckoAppShell
GeckoApp.mAppContext.removePluginView(view, isFullScreen);
}
public static Surface createSurface() {
Log.i(LOGTAG, "createSurface");
return GeckoApp.mAppContext.createSurface();
}
public static void showSurface(Surface surface,
int x, int y,
int w, int h,
boolean inverted,
boolean blend)
{
Log.i(LOGTAG, "showSurface:" + surface + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " inverted: " + inverted + " blend: " + blend);
try {
GeckoApp.mAppContext.showSurface(surface, x, y, w, h, inverted, blend);
} catch (Exception e) {
Log.i(LOGTAG, "Error in showSurface:", e);
}
}
public static void hideSurface(Surface surface) {
Log.i(LOGTAG, "hideSurface:" + surface);
GeckoApp.mAppContext.hideSurface(surface);
}
public static void destroySurface(Surface surface) {
Log.i(LOGTAG, "destroySurface:" + surface);
GeckoApp.mAppContext.destroySurface(surface);
}
public static Class<?> loadPluginClass(String className, String libName) {
Log.i(LOGTAG, "in loadPluginClass... attempting to access className, then libName.....");
Log.i(LOGTAG, "className: " + className);
@ -2284,6 +2256,17 @@ public class GeckoAppShell
return data;
}
public static void registerSurfaceTextureFrameListener(Object surfaceTexture, final int id) {
((SurfaceTexture)surfaceTexture).setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
GeckoAppShell.onSurfaceTextureFrameAvailable(surfaceTexture, id);
}
});
}
public static void unregisterSurfaceTextureFrameListener(Object surfaceTexture) {
((SurfaceTexture)surfaceTexture).setOnFrameAvailableListener(null);
}
}
class ScreenshotHandler implements Runnable {

View File

@ -137,7 +137,6 @@ FENNEC_JAVA_FILES = \
gfx/ScreenshotLayer.java \
gfx/ScrollbarLayer.java \
gfx/SingleTileLayer.java \
gfx/SurfaceTextureLayer.java \
gfx/TextLayer.java \
gfx/TextureGenerator.java \
gfx/TextureReaper.java \

View File

@ -1,279 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoApp;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.util.Log;
import android.view.Surface;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class SurfaceTextureLayer extends Layer implements SurfaceTexture.OnFrameAvailableListener {
private static final String LOGTAG = "SurfaceTextureLayer";
private static final int LOCAL_GL_TEXTURE_EXTERNAL_OES = 0x00008d65; // This is only defined in API level 15 for some reason (Android 4.0.3)
private final SurfaceTexture mSurfaceTexture;
private final Surface mSurface;
private int mTextureId;
private boolean mHaveFrame;
private float[] mTextureTransform = new float[16];
private Rect mPageRect;
private boolean mInverted;
private boolean mNewInverted;
private boolean mBlend;
private boolean mNewBlend;
private static int mProgram;
private static int mPositionHandle;
private static int mTextureHandle;
private static int mSampleHandle;
private static int mProjectionMatrixHandle;
private static int mTextureMatrixHandle;
private static final float[] PROJECTION_MATRIX = {
2.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 2.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 1.0f
};
private static final String VERTEX_SHADER =
"uniform mat4 projectionMatrix;\n" +
"uniform mat4 textureMatrix;\n" +
"attribute vec4 vPosition;\n" +
"attribute vec4 aTexCoord;\n" +
"varying vec2 vTexCoord;\n" +
"void main() {\n" +
" gl_Position = projectionMatrix * vPosition;\n" +
" vTexCoord = (textureMatrix * vec4(aTexCoord.x, aTexCoord.y, 0.0, 1.0)).xy;\n" +
"}\n";
private static String FRAGMENT_SHADER_OES =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" +
"varying vec2 vTexCoord; \n" +
"uniform samplerExternalOES sTexture; \n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTexCoord); \n" +
"}\n";
private static final float TEXTURE_MAP[] = {
0.0f, 1.0f, // top left
0.0f, 0.0f, // bottom left
1.0f, 1.0f, // top right
1.0f, 0.0f, // bottom right
};
private static final float TEXTURE_MAP_INVERTED[] = {
0.0f, 0.0f, // bottom left
0.0f, 1.0f, // top left
1.0f, 0.0f, // bottom right
1.0f, 1.0f, // top right
};
private SurfaceTextureLayer(int textureId) {
mTextureId = textureId;
mHaveFrame = true;
mInverted = false;
// We have our own special shaders necessary for rendering the SurfaceTexture
this.mUsesDefaultProgram = false;
mSurfaceTexture = new SurfaceTexture(mTextureId);
mSurfaceTexture.setOnFrameAvailableListener(this);
Surface tmp = null;
try {
tmp = Surface.class.getConstructor(SurfaceTexture.class).newInstance(mSurfaceTexture); }
catch (Exception ie) {
Log.e(LOGTAG, "error constructing the surface", ie);
}
mSurface = tmp;
}
public static SurfaceTextureLayer create() {
int textureId = TextureGenerator.get().take();
if (textureId == 0)
return null;
return new SurfaceTextureLayer(textureId);
}
// For SurfaceTexture.OnFrameAvailableListener
public void onFrameAvailable(SurfaceTexture texture) {
mHaveFrame = true;
GeckoApp.mAppContext.requestRender();
}
public void update(Rect rect, boolean inverted, boolean blend) {
beginTransaction();
setPosition(rect);
mNewInverted = inverted;
mNewBlend = blend;
endTransaction();
}
@Override
protected void finalize() throws Throwable {
try {
if (mTextureId > 0)
TextureReaper.get().add(mTextureId);
} finally {
super.finalize();
}
}
@Override
protected void performUpdates(RenderContext context) {
super.performUpdates(context);
mInverted = mNewInverted;
mBlend = mNewBlend;
}
private static boolean ensureProgram() {
if (mProgram != 0)
return true;
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER_OES);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoord");
mSampleHandle = GLES20.glGetUniformLocation(mProgram, "sTexture");
mProjectionMatrixHandle = GLES20.glGetUniformLocation(mProgram, "projectionMatrix");
mTextureMatrixHandle = GLES20.glGetUniformLocation(mProgram, "textureMatrix");
return mProgram != 0;
}
private static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private static void activateProgram() {
GLES20.glUseProgram(mProgram);
}
public static void deactivateProgram() {
GLES20.glDisableVertexAttribArray(mTextureHandle);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glUseProgram(0);
}
@Override
public void draw(RenderContext context) {
if (!ensureProgram() || !mHaveFrame)
return;
RectF rect = getBounds(context);
RectF viewport = context.viewport;
rect.offset(-viewport.left, -viewport.top);
float viewWidth = viewport.width();
float viewHeight = viewport.height();
float top = viewHeight - rect.top;
float bot = viewHeight - rect.bottom;
float[] textureCoords = mInverted ? TEXTURE_MAP_INVERTED : TEXTURE_MAP;
float[] coords = {
// x, y, z, texture_x, texture_y
rect.left/viewWidth, bot/viewHeight, 0,
textureCoords[0], textureCoords[1],
rect.left/viewWidth, (bot+rect.height())/viewHeight, 0,
textureCoords[2], textureCoords[3],
(rect.left+rect.width())/viewWidth, bot/viewHeight, 0,
textureCoords[4], textureCoords[5],
(rect.left+rect.width())/viewWidth, (bot+rect.height())/viewHeight, 0,
textureCoords[6], textureCoords[7]
};
FloatBuffer coordBuffer = context.coordBuffer;
coordBuffer.position(0);
coordBuffer.put(coords);
activateProgram();
// Set the transformation matrix
GLES20.glUniformMatrix4fv(mProjectionMatrixHandle, 1, false, PROJECTION_MATRIX, 0);
// Enable the arrays from which we get the vertex and texture coordinates
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glEnableVertexAttribArray(mTextureHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glUniform1i(mSampleHandle, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
GLES20.glBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureId);
mSurfaceTexture.updateTexImage();
mSurfaceTexture.getTransformMatrix(mTextureTransform);
GLES20.glUniformMatrix4fv(mTextureMatrixHandle, 1, false, mTextureTransform, 0);
// Unbind any the current array buffer so we can use client side buffers
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
// Vertex coordinates are x,y,z starting at position 0 into the buffer.
coordBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 20,
coordBuffer);
// Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
coordBuffer.position(3);
GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, 20,
coordBuffer);
if (mBlend) {
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
}
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
if (mBlend)
GLES20.glDisable(GLES20.GL_BLEND);
deactivateProgram();
}
public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
public Surface getSurface() {
return mSurface;
}
}

View File

@ -323,6 +323,7 @@ SHELL_WRAPPER2(notifyFilePickerResult, jstring, jlong)
SHELL_WRAPPER1_WITH_RETURN(getSurfaceBits, jobject, jobject)
SHELL_WRAPPER1(onFullScreenPluginHidden, jobject)
SHELL_WRAPPER1_WITH_RETURN(getNextMessageFromQueue, jobject, jobject)
SHELL_WRAPPER2(onSurfaceTextureFrameAvailable, jobject, jint);
static void * xul_handle = NULL;
static void * sqlite_handle = NULL;
@ -746,6 +747,7 @@ loadGeckoLibs(const char *apkName)
GETFUNC(getSurfaceBits);
GETFUNC(onFullScreenPluginHidden);
GETFUNC(getNextMessageFromQueue);
GETFUNC(onSurfaceTextureFrameAvailable);
#undef GETFUNC
void (*XRE_StartupTimelineRecord)(int, MOZTime);

View File

@ -31,6 +31,7 @@
#include "mozilla/dom/ScreenOrientation.h"
#include "nsIDOMWindowUtils.h"
#include "nsIDOMClientRect.h"
#include "StrongPointer.h"
#ifdef DEBUG
#define ALOG_BRIDGE(args...) ALOG(args)
@ -49,6 +50,15 @@ AndroidBridge *AndroidBridge::sBridge = 0;
static PRUintn sJavaEnvThreadIndex = 0;
static void JavaThreadDetachFunc(void *arg);
// This is a dummy class that can be used in the template for android::sp
class AndroidRefable {
void incStrong(void* thing) { }
void decStrong(void* thing) { }
};
// This isn't in AndroidBridge.h because including StrongPointer.h there is gross
static android::sp<AndroidRefable> (*android_SurfaceTexture_getNativeWindow)(JNIEnv* env, jobject surfaceTexture) = nsnull;
AndroidBridge *
AndroidBridge::ConstructBridge(JNIEnv *jEnv,
jclass jGeckoAppShellClass)
@ -178,11 +188,10 @@ AndroidBridge::Init(JNIEnv *jEnv,
jSurfaceClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("android/view/Surface"));
PRInt32 apiVersion = 0;
if (!GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &apiVersion, jEnv))
if (!GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &mAPIVersion, jEnv))
ALOG_BRIDGE("Failed to find API version");
if (apiVersion <= 8 /* Froyo */)
if (mAPIVersion <= 8 /* Froyo */)
jSurfacePointerField = jEnv->GetFieldID(jSurfaceClass, "mSurface", "I");
else /* not Froyo */
jSurfacePointerField = jEnv->GetFieldID(jSurfaceClass, "mNativeSurface", "I");
@ -190,6 +199,8 @@ AndroidBridge::Init(JNIEnv *jEnv,
jNotifyWakeLockChanged = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyWakeLockChanged", "(Ljava/lang/String;Ljava/lang/String;)V");
jGetGfxInfoData = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getGfxInfoData", "()Ljava/lang/String;");
jRegisterSurfaceTextureFrameListener = jEnv->GetStaticMethodID(jGeckoAppShellClass, "registerSurfaceTextureFrameListener", "(Ljava/lang/Object;I)V");
jUnregisterSurfaceTextureFrameListener = jEnv->GetStaticMethodID(jGeckoAppShellClass, "unregisterSurfaceTextureFrameListener", "(Ljava/lang/Object;)V");
#ifdef MOZ_JAVA_COMPOSITOR
jPumpMessageLoop = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "pumpMessageLoop", "()V");
@ -197,11 +208,6 @@ AndroidBridge::Init(JNIEnv *jEnv,
jAddPluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "addPluginView", "(Landroid/view/View;IIIIZ)V");
jRemovePluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "removePluginView", "(Landroid/view/View;Z)V");
jCreateSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "createSurface", "()Landroid/view/Surface;");
jShowSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "showSurface", "(Landroid/view/Surface;IIIIZZ)V");
jHideSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideSurface", "(Landroid/view/Surface;)V");
jDestroySurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "destroySurface", "(Landroid/view/Surface;)V");
jLayerView = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("org/mozilla/gecko/gfx/LayerView"));
AndroidGLController::Init(jEnv);
@ -1396,11 +1402,20 @@ AndroidBridge::OpenGraphicsLibraries()
ANativeWindow_lock = (int (*)(void*, void*, void*)) dlsym(handle, "ANativeWindow_lock");
ANativeWindow_unlockAndPost = (int (*)(void*))dlsym(handle, "ANativeWindow_unlockAndPost");
// This is only available in Honeycomb and ICS. It was removed in Jelly Bean
ANativeWindow_fromSurfaceTexture = (void* (*)(JNIEnv*, jobject))dlsym(handle, "ANativeWindow_fromSurfaceTexture");
mHasNativeWindowAccess = ANativeWindow_fromSurface && ANativeWindow_release && ANativeWindow_lock && ANativeWindow_unlockAndPost;
ALOG_BRIDGE("Successfully opened libandroid.so, have native window access? %d", mHasNativeWindowAccess);
}
// We need one symbol from here on Jelly Bean
handle = dlopen("libandroid_runtime.so", RTLD_LAZY | RTLD_LOCAL);
if (handle) {
android_SurfaceTexture_getNativeWindow = (android::sp<AndroidRefable> (*)(JNIEnv*, jobject))dlsym(handle, "_ZN7android38android_SurfaceTexture_getNativeWindowEP7_JNIEnvP8_jobject");
}
if (mHasNativeWindowAccess)
return;
@ -1939,10 +1954,11 @@ AndroidBridge::AcquireNativeWindow(JNIEnv* aEnv, jobject aSurface)
if (mHasNativeWindowAccess)
return ANativeWindow_fromSurface(aEnv, aSurface);
else if (mHasNativeWindowFallback)
if (mHasNativeWindowFallback)
return GetNativeSurface(aEnv, aSurface);
else
return nsnull;
return nsnull;
}
void
@ -1958,6 +1974,31 @@ AndroidBridge::ReleaseNativeWindow(void *window)
// have nothing to do here. We should probably ref it.
}
void*
AndroidBridge::AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurfaceTexture)
{
OpenGraphicsLibraries();
if (mHasNativeWindowAccess && ANativeWindow_fromSurfaceTexture)
return ANativeWindow_fromSurfaceTexture(aEnv, aSurfaceTexture);
if (mHasNativeWindowAccess && android_SurfaceTexture_getNativeWindow) {
android::sp<AndroidRefable> window = android_SurfaceTexture_getNativeWindow(aEnv, aSurfaceTexture);
return window.get();
}
return nsnull;
}
void
AndroidBridge::ReleaseNativeWindowForSurfaceTexture(void *window)
{
if (!window)
return;
// FIXME: we don't ref the pointer we get, so nothing to do currently. We should ref it.
}
bool
AndroidBridge::SetNativeWindowFormat(void *window, int width, int height, int format)
{
@ -2190,75 +2231,6 @@ extern "C" {
}
}
jobject
AndroidBridge::CreateSurface()
{
#ifndef MOZ_JAVA_COMPOSITOR
return NULL;
#else
JNIEnv* env = GetJNIEnv();
if (!env)
return nsnull;
AutoLocalJNIFrame jniFrame(env);
jobject surface = env->CallStaticObjectMethod(mGeckoAppShellClass, jCreateSurface);
if (jniFrame.CheckForException())
return nsnull;
if (surface)
surface = env->NewGlobalRef(surface);
return surface;
#endif
}
void
AndroidBridge::DestroySurface(jobject surface)
{
#ifdef MOZ_JAVA_COMPOSITOR
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
env->CallStaticVoidMethod(mGeckoAppShellClass, jDestroySurface, surface);
env->DeleteGlobalRef(surface);
#endif
}
void
AndroidBridge::ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend)
{
#ifdef MOZ_JAVA_COMPOSITOR
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jShowSurface, surface,
(int)aRect.x, (int)aRect.y,
(int)aRect.width, (int)aRect.height,
aInverted, aBlend);
#endif
}
void
AndroidBridge::HideSurface(jobject surface)
{
#ifdef MOZ_JAVA_COMPOSITOR
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
env->CallStaticVoidMethod(mGeckoAppShellClass, jHideSurface, surface);
#endif
}
uint32_t
AndroidBridge::GetScreenOrientation()
{
@ -2358,6 +2330,38 @@ AndroidBridge::NotifyWakeLockChanged(const nsAString& topic, const nsAString& st
env->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyWakeLockChanged, jstrTopic, jstrState);
}
void
AndroidBridge::ScheduleComposite()
{
#if MOZ_JAVA_COMPOSITOR
nsWindow::ScheduleComposite();
#endif
}
void
AndroidBridge::RegisterSurfaceTextureFrameListener(jobject surfaceTexture, int id)
{
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
env->CallStaticVoidMethod(mGeckoAppShellClass, jRegisterSurfaceTextureFrameListener, surfaceTexture, id);
}
void
AndroidBridge::UnregisterSurfaceTextureFrameListener(jobject surfaceTexture)
{
JNIEnv* env = GetJNIEnv();
if (!env)
return;
AutoLocalJNIFrame jniFrame(env);
env->CallStaticVoidMethod(mGeckoAppShellClass, jUnregisterSurfaceTextureFrameListener, surfaceTexture);
}
void
AndroidBridge::GetGfxInfoData(nsACString& aRet)
{

View File

@ -297,6 +297,10 @@ public:
void *AcquireNativeWindow(JNIEnv* aEnv, jobject aSurface);
void ReleaseNativeWindow(void *window);
void *AcquireNativeWindowFromSurfaceTexture(JNIEnv* aEnv, jobject aSurface);
void ReleaseNativeWindowForSurfaceTexture(void *window);
bool SetNativeWindowFormat(void *window, int width, int height, int format);
bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride);
@ -335,11 +339,6 @@ public:
void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
jobject CreateSurface();
void DestroySurface(jobject surface);
void ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend);
void HideSurface(jobject surface);
void AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen);
void RemovePluginView(jobject view, bool isFullScreen);
@ -357,6 +356,13 @@ public:
void NotifyWakeLockChanged(const nsAString& topic, const nsAString& state);
int GetAPIVersion() { return mAPIVersion; }
bool IsHoneycomb() { return mAPIVersion >= 11 && mAPIVersion <= 13; }
void ScheduleComposite();
void RegisterSurfaceTextureFrameListener(jobject surfaceTexture, int id);
void UnregisterSurfaceTextureFrameListener(jobject surfaceTexture);
void GetGfxInfoData(nsACString& aRet);
protected:
@ -390,6 +396,8 @@ protected:
bool mHasNativeWindowAccess;
bool mHasNativeWindowFallback;
int mAPIVersion;
nsCOMArray<nsIRunnable> mRunnableQueue;
// other things
@ -479,6 +487,8 @@ protected:
jmethodID jUnlockScreenOrientation;
jmethodID jPumpMessageLoop;
jmethodID jNotifyWakeLockChanged;
jmethodID jRegisterSurfaceTextureFrameListener;
jmethodID jUnregisterSurfaceTextureFrameListener;
// for GfxInfo (gfx feature detection and blacklisting)
jmethodID jGetGfxInfoData;
@ -507,6 +517,7 @@ protected:
int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
void* (*ANativeWindow_fromSurface)(JNIEnv *env, jobject surface);
void* (*ANativeWindow_fromSurfaceTexture)(JNIEnv *env, jobject surfaceTexture);
void (*ANativeWindow_release)(void *window);
int (*ANativeWindow_setBuffersGeometry)(void *window, int width, int height, int format);

View File

@ -38,6 +38,7 @@
#include "nsISmsRequestManager.h"
#include "nsISmsDatabaseService.h"
#include "nsPluginInstanceOwner.h"
#include "nsSurfaceTexture.h"
using namespace mozilla;
using namespace mozilla::dom::sms;
@ -1023,5 +1024,17 @@ Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclas
return msg;
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable(JNIEnv* jenv, jclass, jobject surfaceTexture, jint id)
{
nsSurfaceTexture* st = nsSurfaceTexture::Find(id);
if (!st) {
__android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "Failed to find nsSurfaceTexture with id %d", id);
return;
}
st->NotifyFrameAvailable();
}
#endif
}

View File

@ -1,148 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <android/log.h>
#include "AndroidMediaLayer.h"
#include "AndroidBridge.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidMediaLayer" , ## args)
namespace mozilla {
AndroidMediaLayer::AndroidMediaLayer()
: mInverted(false), mVisible(true) {
}
AndroidMediaLayer::~AndroidMediaLayer() {
if (mContentData.window && AndroidBridge::Bridge()) {
AndroidBridge::Bridge()->ReleaseNativeWindow(mContentData.window);
mContentData.window = NULL;
}
if (mContentData.surface && AndroidBridge::Bridge()) {
AndroidBridge::Bridge()->DestroySurface(mContentData.surface);
mContentData.surface = NULL;
}
std::map<void*, SurfaceData*>::iterator it;
for (it = mVideoSurfaces.begin(); it != mVideoSurfaces.end(); it++) {
SurfaceData* data = it->second;
if (AndroidBridge::Bridge()) {
AndroidBridge::Bridge()->ReleaseNativeWindow(data->window);
AndroidBridge::Bridge()->DestroySurface(data->surface);
}
delete data;
}
mVideoSurfaces.clear();
}
bool AndroidMediaLayer::EnsureContentSurface() {
if (!mContentData.surface && AndroidBridge::Bridge()) {
mContentData.surface = AndroidBridge::Bridge()->CreateSurface();
if (mContentData.surface) {
mContentData.window = AndroidBridge::Bridge()->AcquireNativeWindow(AndroidBridge::GetJNIEnv(), mContentData.surface);
AndroidBridge::Bridge()->SetNativeWindowFormat(mContentData.window, 0, 0, AndroidBridge::WINDOW_FORMAT_RGBA_8888);
}
}
return mContentData.surface && mContentData.window;
}
void* AndroidMediaLayer::GetNativeWindowForContent() {
if (!EnsureContentSurface())
return NULL;
return mContentData.window;
}
void* AndroidMediaLayer::RequestNativeWindowForVideo() {
if (!AndroidBridge::Bridge())
return NULL;
jobject surface = AndroidBridge::Bridge()->CreateSurface();
if (surface) {
void* window = AndroidBridge::Bridge()->AcquireNativeWindow(AndroidBridge::GetJNIEnv(), surface);
if (window) {
AndroidBridge::Bridge()->SetNativeWindowFormat(window, 0, 0, AndroidBridge::WINDOW_FORMAT_RGBA_8888);
mVideoSurfaces[window] = new SurfaceData(surface, window);
return window;
} else {
LOG("Failed to create native window from surface");
// Cleanup
AndroidBridge::Bridge()->DestroySurface(surface);
}
}
return NULL;
}
void AndroidMediaLayer::ReleaseNativeWindowForVideo(void* aWindow) {
if (mVideoSurfaces.find(aWindow) == mVideoSurfaces.end() || !AndroidBridge::Bridge())
return;
SurfaceData* data = mVideoSurfaces[aWindow];
AndroidBridge::Bridge()->ReleaseNativeWindow(data->window);
AndroidBridge::Bridge()->DestroySurface(data->surface);
mVideoSurfaces.erase(aWindow);
delete data;
}
void AndroidMediaLayer::SetNativeWindowDimensions(void* aWindow, const gfxRect& aDimensions) {
if (mVideoSurfaces.find(aWindow) == mVideoSurfaces.end())
return;
SurfaceData* data = mVideoSurfaces[aWindow];
data->dimensions = aDimensions;
}
void AndroidMediaLayer::UpdatePosition(const gfxRect& aRect) {
if (!mVisible || !AndroidBridge::Bridge())
return;
std::map<void*, SurfaceData*>::iterator it;
for (it = mVideoSurfaces.begin(); it != mVideoSurfaces.end(); it++) {
SurfaceData* data = it->second;
gfxRect videoRect(aRect.x + data->dimensions.x, aRect.y + data->dimensions.y,
data->dimensions.width, data->dimensions.height);
AndroidBridge::Bridge()->ShowSurface(data->surface, videoRect, mInverted, false);
}
if (EnsureContentSurface()) {
AndroidBridge::Bridge()->ShowSurface(mContentData.surface, aRect, mInverted, true);
}
}
void AndroidMediaLayer::SetVisible(bool aVisible) {
if (aVisible == mVisible || !AndroidBridge::Bridge())
return;
mVisible = aVisible;
if (mVisible)
return;
// Hide all surfaces
std::map<void*, SurfaceData*>::iterator it;
if (EnsureContentSurface())
AndroidBridge::Bridge()->HideSurface(mContentData.surface);
for (it = mVideoSurfaces.begin(); it != mVideoSurfaces.end(); it++) {
SurfaceData* data = it->second;
AndroidBridge::Bridge()->HideSurface(data->surface);
}
}
} /* mozilla */

View File

@ -1,73 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AndroidMediaLayer_h_
#define AndroidMediaLayer_h_
#include <map>
#include <jni.h>
#include "gfxRect.h"
#include "nsISupports.h"
namespace mozilla {
class AndroidMediaLayer
{
public:
AndroidMediaLayer();
virtual ~AndroidMediaLayer();
NS_INLINE_DECL_REFCOUNTING(AndroidMediaLayer)
void* GetNativeWindowForContent();
void* RequestNativeWindowForVideo();
void ReleaseNativeWindowForVideo(void* aWindow);
void SetNativeWindowDimensions(void* aWindow, const gfxRect& aDimensions);
void UpdatePosition(const gfxRect& aRect);
bool Inverted() {
return mInverted;
}
void SetInverted(bool aInverted) {
mInverted = aInverted;
}
bool IsVisible() {
return mVisible;
}
void SetVisible(bool aVisible);
private:
bool mInverted;
bool mVisible;
class SurfaceData {
public:
SurfaceData() :
surface(NULL), window(NULL) {
}
SurfaceData(jobject aSurface, void* aWindow) :
surface(aSurface), window(aWindow) {
}
jobject surface;
void* window;
gfxRect dimensions;
};
bool EnsureContentSurface();
SurfaceData mContentData;
std::map<void*, SurfaceData*> mVideoSurfaces;
};
} /* mozilla */
#endif /* AndroidMediaLayer_h_ */

View File

@ -32,7 +32,6 @@ CPPSRCS = \
AndroidLayerViewWrapper.cpp \
AndroidGraphicBuffer.cpp \
AndroidJNI.cpp \
AndroidMediaLayer.cpp \
nsWindow.cpp \
nsLookAndFeel.cpp \
nsScreenManagerAndroid.cpp \
@ -74,6 +73,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/docshell/base \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/netwerk/cache \
-I$(topsrcdir)/widget/android/android \
-I$(srcdir) \
$(NULL)

View File

@ -0,0 +1,239 @@
/*
* Copyright (C) 2005 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*************************************************************************
*
* WARNING: EVERYTHING HERE IS NEUTERED
*
* The only reason we need this is to be able to call
* android_SurfaceTexture_getNativeWindow, which returns a
* android::sp<ANativeWindow>. Therefore, we need the definition of
* android::sp (below) in order to get the pointer out. All of the actual
* ref management stuff is commented out by Mozilla. Do not try to use this
* for anything real.
*/
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
// ---------------------------------------------------------------------------
namespace android {
class TextOutput;
TextOutput& printStrongPointer(TextOutput& to, const void* val);
template<typename T> class wp;
// ---------------------------------------------------------------------------
#define COMPARE(_op_) \
inline bool operator _op_ (const sp<T>& o) const { \
return m_ptr _op_ o.m_ptr; \
} \
inline bool operator _op_ (const T* o) const { \
return m_ptr _op_ o; \
} \
template<typename U> \
inline bool operator _op_ (const sp<U>& o) const { \
return m_ptr _op_ o.m_ptr; \
} \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
inline bool operator _op_ (const wp<T>& o) const { \
return m_ptr _op_ o.m_ptr; \
} \
template<typename U> \
inline bool operator _op_ (const wp<U>& o) const { \
return m_ptr _op_ o.m_ptr; \
}
// ---------------------------------------------------------------------------
template <typename T>
class sp
{
public:
inline sp() : m_ptr(0) { }
sp(T* other);
sp(const sp<T>& other);
template<typename U> sp(U* other);
template<typename U> sp(const sp<U>& other);
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (U* other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
#undef COMPARE
template <typename T>
TextOutput& operator<<(TextOutput& to, const sp<T>& val);
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
//if (other) other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
//if (m_ptr) m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
//if (other) ((T*)other)->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
//if (m_ptr) m_ptr->incStrong(this);
}
template<typename T>
sp<T>::~sp()
{
//if (m_ptr) m_ptr->decStrong(this);
}
template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) {
T* otherPtr(other.m_ptr);
/*
if (otherPtr) otherPtr->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
*/
m_ptr = otherPtr;
return *this;
}
template<typename T>
sp<T>& sp<T>::operator = (T* other)
{
/*
if (other) other->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
*/
m_ptr = other;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other)
{
T* otherPtr(other.m_ptr);
/*
if (otherPtr) otherPtr->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
*/
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
/*
if (other) ((T*)other)->incStrong(this);
if (m_ptr) m_ptr->decStrong(this);
*/
m_ptr = other;
return *this;
}
template<typename T>
void sp<T>::force_set(T* other)
{
//other->forceIncStrong(this);
m_ptr = other;
}
template<typename T>
void sp<T>::clear()
{
if (m_ptr) {
m_ptr->decStrong(this);
m_ptr = 0;
}
}
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
template <typename T>
inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)
{
return printStrongPointer(to, val.get());
}
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRONG_POINTER_H