зеркало из https://github.com/mozilla/gecko-dev.git
Bug 687267 - Initial support for Flash on Honeycomb r=bgirard,vlad,jgilbert,blassey
This commit is contained in:
Родитель
d08031fe5d
Коммит
30e0f551ce
|
@ -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) {
|
||||
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;
|
||||
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
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();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 0; }
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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,6 +951,16 @@ void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
|||
return;
|
||||
}
|
||||
|
||||
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(aSharedHandle);
|
||||
|
||||
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;
|
||||
|
@ -862,11 +972,51 @@ void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
|||
// 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()) {
|
||||
if (wrap->OwnsTexture() && ctx && !ctx->IsDestroyed() && ctx->MakeCurrent()) {
|
||||
GLuint texture = wrap->GetTextureID();
|
||||
ctx->fDeleteTextures(1, &texture);
|
||||
}
|
||||
delete wrap;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ERROR("Unknown shared handle type");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
wrap->WaitSync();
|
||||
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ERROR("Unknown shared handle type");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -40,6 +40,7 @@ struct SharedTextureDescriptor {
|
|||
TextureShareType shareType;
|
||||
SharedTextureHandle handle;
|
||||
nsIntSize size;
|
||||
bool inverted;
|
||||
};
|
||||
|
||||
struct SurfaceDescriptorGralloc {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,7 +710,15 @@ bool
|
|||
ShadowImageLayerOGL::Init(const SharedImage& aFront)
|
||||
{
|
||||
if (aFront.type() == SharedImage::TSurfaceDescriptor) {
|
||||
AutoOpenSurface autoSurf(OPEN_READ_ONLY, aFront.get_SurfaceDescriptor());
|
||||
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(),
|
||||
|
@ -695,7 +726,7 @@ ShadowImageLayerOGL::Init(const SharedImage& aFront)
|
|||
mForceSingleTile
|
||||
? TextureImage::ForceSingleTile
|
||||
: TextureImage::NoFlags);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
YUVImage yuv = aFront.get_YUVImage();
|
||||
|
||||
|
@ -739,7 +770,22 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
|
|||
mImageVersion = 0;
|
||||
}
|
||||
} else if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
|
||||
AutoOpenSurface surf(OPEN_READ_ONLY, aNewFront.get_SurfaceDescriptor());
|
||||
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()) {
|
||||
|
@ -748,6 +794,7 @@ ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
|
|||
// 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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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\
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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))
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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>();
|
||||
|
@ -1613,51 +1604,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();
|
||||
layerView.removeLayer(layer);
|
||||
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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,9 +1954,10 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче