2014-10-18 03:34:01 +04:00
|
|
|
/* -*- 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 <map>
|
|
|
|
#include <android/log.h>
|
2014-10-21 17:53:00 +04:00
|
|
|
#include "AndroidSurfaceTexture.h"
|
|
|
|
#include "gfxImageSurface.h"
|
2015-08-21 20:21:58 +03:00
|
|
|
#include "gfxPrefs.h"
|
2014-10-18 03:34:01 +04:00
|
|
|
#include "AndroidBridge.h"
|
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "mozilla/gfx/Matrix.h"
|
2014-10-21 17:53:00 +04:00
|
|
|
#include "GeneratedJNIWrappers.h"
|
2014-11-13 21:47:24 +03:00
|
|
|
#include "SurfaceTexture.h"
|
2014-10-21 17:53:01 +04:00
|
|
|
#include "GLContext.h"
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2015-01-10 03:33:57 +03:00
|
|
|
using namespace mozilla::jni;
|
2016-07-21 20:49:04 +03:00
|
|
|
using namespace mozilla::java;
|
|
|
|
using namespace mozilla::java::sdk;
|
2014-10-21 17:53:00 +04:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gl {
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2016-02-19 01:55:15 +03:00
|
|
|
// Maintains a mapping between AndroidSurfaceTexture instances and their
|
|
|
|
// unique numerical IDs. [thread-safe]
|
|
|
|
class InstanceMap
|
|
|
|
{
|
|
|
|
typedef AndroidSurfaceTexture* InstancePtr;
|
|
|
|
typedef std::map<int, InstancePtr> MapType;
|
|
|
|
|
|
|
|
public:
|
|
|
|
InstanceMap()
|
|
|
|
: mNextId(0)
|
|
|
|
, mMonitor("AndroidSurfaceTexture::InstanceMap::mMonitor")
|
|
|
|
{}
|
|
|
|
|
|
|
|
int Add(InstancePtr aInstance)
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mInstances.insert({++mNextId, aInstance});
|
|
|
|
return mNextId;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Remove(int aId)
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mInstances.erase(aId);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstancePtr Get(int aId) const
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
|
|
|
auto it = mInstances.find(aId);
|
|
|
|
if (it == mInstances.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
MapType mInstances;
|
|
|
|
int mNextId;
|
|
|
|
|
|
|
|
mutable Monitor mMonitor;
|
|
|
|
};
|
|
|
|
|
|
|
|
static InstanceMap sInstances;
|
|
|
|
|
|
|
|
AndroidSurfaceTexture*
|
|
|
|
AndroidSurfaceTexture::Find(int aId)
|
|
|
|
{
|
|
|
|
return sInstances.Get(aId);
|
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2014-10-21 17:53:01 +04:00
|
|
|
static bool
|
|
|
|
IsSTSupported()
|
|
|
|
{
|
|
|
|
return AndroidBridge::Bridge()->GetAPIVersion() >= 14; /* ICS */
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<AndroidSurfaceTexture>
|
2014-10-21 17:53:01 +04:00
|
|
|
AndroidSurfaceTexture::Create()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-10-21 17:53:01 +04:00
|
|
|
return Create(nullptr, 0);
|
|
|
|
}
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
already_AddRefed<AndroidSurfaceTexture>
|
2014-10-21 17:53:01 +04:00
|
|
|
AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture)
|
|
|
|
{
|
|
|
|
if (!IsSTSupported()) {
|
2014-10-18 03:34:01 +04:00
|
|
|
return nullptr;
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AndroidSurfaceTexture> st = new AndroidSurfaceTexture();
|
2014-10-21 17:53:01 +04:00
|
|
|
if (!st->Init(aContext, aTexture)) {
|
2014-10-21 17:53:00 +04:00
|
|
|
printf_stderr("Failed to initialize AndroidSurfaceTexture");
|
2014-10-18 03:34:01 +04:00
|
|
|
st = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-11-13 21:47:24 +03:00
|
|
|
return st.forget();
|
2014-10-18 03:34:01 +04:00
|
|
|
}
|
|
|
|
|
2014-11-13 21:47:24 +03:00
|
|
|
nsresult
|
2014-10-21 17:53:01 +04:00
|
|
|
AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-10-21 17:53:01 +04:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
|
|
|
if (mAttachedContext == aContext) {
|
|
|
|
NS_WARNING("Tried to attach same GLContext to AndroidSurfaceTexture");
|
2014-11-13 21:47:24 +03:00
|
|
|
return NS_OK;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
2015-02-03 00:25:22 +03:00
|
|
|
if (!CanDetach()) {
|
2014-11-13 21:47:24 +03:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
while (mAttachedContext) {
|
|
|
|
// Wait until it's detached (or we time out)
|
|
|
|
if (NS_FAILED(lock.Wait(aTimeout))) {
|
2014-11-13 21:47:24 +03:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aContext->IsOwningThreadCurrent(), "Trying to attach GLContext from different thread");
|
|
|
|
|
|
|
|
aContext->fGenTextures(1, &mTexture);
|
|
|
|
|
2016-03-02 19:29:10 +03:00
|
|
|
if (NS_FAILED(mSurfaceTexture->AttachToGLContext(mTexture))) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
mAttachedContext = aContext;
|
|
|
|
mAttachedContext->MakeCurrent();
|
2015-08-05 17:24:55 +03:00
|
|
|
|
2016-03-02 19:29:10 +03:00
|
|
|
return NS_OK;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
2014-11-13 21:47:24 +03:00
|
|
|
nsresult
|
2014-10-21 17:53:01 +04:00
|
|
|
AndroidSurfaceTexture::Detach()
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
|
2015-02-03 00:25:22 +03:00
|
|
|
if (!CanDetach() ||
|
|
|
|
!mAttachedContext ||
|
|
|
|
!mAttachedContext->IsOwningThreadCurrent())
|
|
|
|
{
|
2014-11-13 21:47:24 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mAttachedContext->MakeCurrent();
|
|
|
|
|
2014-11-13 21:47:24 +03:00
|
|
|
mSurfaceTexture->DetachFromGLContext();
|
2014-10-21 17:53:01 +04:00
|
|
|
|
|
|
|
mTexture = 0;
|
|
|
|
mAttachedContext = nullptr;
|
|
|
|
lock.NotifyAll();
|
2014-11-13 21:47:24 +03:00
|
|
|
return NS_OK;
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
2016-03-02 19:29:10 +03:00
|
|
|
bool
|
|
|
|
AndroidSurfaceTexture::CanDetach() const
|
2015-08-05 17:24:55 +03:00
|
|
|
{
|
|
|
|
// The API for attach/detach only exists on 16+, and PowerVR has some sort of
|
2016-03-02 19:29:10 +03:00
|
|
|
// fencing issue. Additionally, attach/detach seems to be busted on at least
|
|
|
|
// some Mali adapters (400MP2 for sure, bug 1131793)
|
|
|
|
return AndroidBridge::Bridge()->GetAPIVersion() >= 16 &&
|
2015-08-05 17:24:55 +03:00
|
|
|
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::Imagination) &&
|
|
|
|
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::ARM /* Mali */) &&
|
2016-03-02 19:29:10 +03:00
|
|
|
gfxPrefs::SurfaceTextureDetachEnabled();
|
2015-08-05 17:24:55 +03:00
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:01 +04:00
|
|
|
bool
|
|
|
|
AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
|
|
|
|
{
|
2015-08-05 17:24:55 +03:00
|
|
|
|
2015-02-03 00:25:22 +03:00
|
|
|
if (!aTexture && !CanDetach()) {
|
2014-10-21 17:53:01 +04:00
|
|
|
// We have no texture and cannot initialize detached, bail out
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-01-10 03:33:57 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(
|
|
|
|
SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) {
|
2014-10-18 03:34:01 +04:00
|
|
|
return false;
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2014-10-21 17:53:01 +04:00
|
|
|
if (!aTexture) {
|
2014-11-13 21:47:24 +03:00
|
|
|
mSurfaceTexture->DetachFromGLContext();
|
2014-10-21 17:53:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
mAttachedContext = aContext;
|
|
|
|
|
2015-01-10 03:33:57 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(
|
|
|
|
Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) {
|
2014-10-21 17:53:00 +04:00
|
|
|
return false;
|
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
2015-08-13 07:53:39 +03:00
|
|
|
mNativeWindow = AndroidNativeWindow::CreateFromSurface(jni::GetEnvForThread(),
|
2015-01-10 03:33:57 +03:00
|
|
|
mSurface.Get());
|
2014-11-13 21:47:24 +03:00
|
|
|
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
|
2014-10-21 17:53:00 +04:00
|
|
|
|
2016-02-19 01:55:15 +03:00
|
|
|
mID = sInstances.Add(this);
|
2014-10-21 17:53:00 +04:00
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::AndroidSurfaceTexture()
|
2014-10-21 17:53:01 +04:00
|
|
|
: mTexture(0)
|
2015-01-10 03:33:57 +03:00
|
|
|
, mSurfaceTexture()
|
|
|
|
, mSurface()
|
2014-10-21 17:53:01 +04:00
|
|
|
, mAttachedContext(nullptr)
|
2016-02-19 01:55:15 +03:00
|
|
|
, mMonitor("AndroidSurfaceTexture::mContextMonitor")
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::~AndroidSurfaceTexture()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2016-02-19 01:55:15 +03:00
|
|
|
sInstances.Remove(mID);
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
mFrameAvailableCallback = nullptr;
|
|
|
|
|
|
|
|
if (mSurfaceTexture) {
|
2015-01-10 03:33:57 +03:00
|
|
|
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
|
2014-10-18 03:34:01 +04:00
|
|
|
mSurfaceTexture = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::UpdateTexImage()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-11-13 21:47:24 +03:00
|
|
|
mSurfaceTexture->UpdateTexImage();
|
2014-10-18 03:34:01 +04:00
|
|
|
}
|
|
|
|
|
2014-11-13 21:47:24 +03:00
|
|
|
void
|
2016-02-19 01:56:31 +03:00
|
|
|
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2015-08-13 07:53:39 +03:00
|
|
|
JNIEnv* const env = jni::GetEnvForThread();
|
2014-11-13 21:47:24 +03:00
|
|
|
|
2015-01-10 03:33:57 +03:00
|
|
|
auto jarray = FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
|
2014-11-13 21:47:24 +03:00
|
|
|
mSurfaceTexture->GetTransformMatrix(jarray);
|
|
|
|
|
2015-01-10 03:33:57 +03:00
|
|
|
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
|
2014-11-13 21:47:24 +03:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2015-01-10 03:33:57 +03:00
|
|
|
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
|
2014-10-18 03:34:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
2014-10-21 17:53:00 +04:00
|
|
|
if (aRunnable) {
|
2015-01-10 03:33:57 +03:00
|
|
|
GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
|
2014-10-21 17:53:00 +04:00
|
|
|
} else {
|
2015-01-10 03:33:57 +03:00
|
|
|
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
2014-10-18 03:34:01 +04:00
|
|
|
|
|
|
|
mFrameAvailableCallback = aRunnable;
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
void
|
|
|
|
AndroidSurfaceTexture::SetDefaultSize(mozilla::gfx::IntSize size)
|
|
|
|
{
|
2014-11-13 21:47:24 +03:00
|
|
|
mSurfaceTexture->SetDefaultBufferSize(size.width, size.height);
|
2014-10-21 17:53:00 +04:00
|
|
|
}
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
void
|
2014-10-21 17:53:00 +04:00
|
|
|
AndroidSurfaceTexture::NotifyFrameAvailable()
|
2014-10-18 03:34:01 +04:00
|
|
|
{
|
|
|
|
if (mFrameAvailableCallback) {
|
|
|
|
// Proxy to main thread if we aren't on it
|
|
|
|
if (!NS_IsMainThread()) {
|
2014-10-21 17:53:00 +04:00
|
|
|
// Proxy to main thread
|
2016-05-05 11:45:00 +03:00
|
|
|
NS_DispatchToCurrentThread(NewRunnableMethod(this, &AndroidSurfaceTexture::NotifyFrameAvailable));
|
2014-10-18 03:34:01 +04:00
|
|
|
} else {
|
|
|
|
mFrameAvailableCallback->Run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-21 17:53:00 +04:00
|
|
|
} // gl
|
|
|
|
} // mozilla
|
|
|
|
|
2014-10-18 03:34:01 +04:00
|
|
|
#endif // MOZ_WIDGET_ANDROID
|