gecko-dev/gfx/gl/AndroidSurfaceTexture.cpp

310 строки
7.0 KiB
C++
Исходник Обычный вид История

/* -*- 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>
#include "AndroidSurfaceTexture.h"
#include "gfxImageSurface.h"
#include "gfxPrefs.h"
#include "AndroidBridge.h"
#include "nsThreadUtils.h"
#include "mozilla/gfx/Matrix.h"
#include "GeneratedJNIWrappers.h"
#include "SurfaceTexture.h"
#include "GLContext.h"
using namespace mozilla;
using namespace mozilla::jni;
using namespace mozilla::widget;
using namespace mozilla::widget::sdk;
namespace mozilla {
namespace gl {
// 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);
}
static bool
IsSTSupported()
{
return AndroidBridge::Bridge()->GetAPIVersion() >= 14; /* ICS */
}
already_AddRefed<AndroidSurfaceTexture>
AndroidSurfaceTexture::Create()
{
return Create(nullptr, 0);
}
already_AddRefed<AndroidSurfaceTexture>
AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture)
{
if (!IsSTSupported()) {
return nullptr;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<AndroidSurfaceTexture> st = new AndroidSurfaceTexture();
if (!st->Init(aContext, aTexture)) {
printf_stderr("Failed to initialize AndroidSurfaceTexture");
st = nullptr;
}
return st.forget();
}
nsresult
AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout)
{
MonitorAutoLock lock(mMonitor);
if (mAttachedContext == aContext) {
NS_WARNING("Tried to attach same GLContext to AndroidSurfaceTexture");
return NS_OK;
}
if (!CanDetach()) {
return NS_ERROR_NOT_AVAILABLE;
}
while (mAttachedContext) {
// Wait until it's detached (or we time out)
if (NS_FAILED(lock.Wait(aTimeout))) {
return NS_ERROR_NOT_AVAILABLE;
}
}
MOZ_ASSERT(aContext->IsOwningThreadCurrent(), "Trying to attach GLContext from different thread");
mAttachedContext = aContext;
mAttachedContext->MakeCurrent();
aContext->fGenTextures(1, &mTexture);
UpdateCanDetach();
return mSurfaceTexture->AttachToGLContext(mTexture);
}
nsresult
AndroidSurfaceTexture::Detach()
{
MonitorAutoLock lock(mMonitor);
if (!CanDetach() ||
!mAttachedContext ||
!mAttachedContext->IsOwningThreadCurrent())
{
return NS_ERROR_FAILURE;
}
mAttachedContext->MakeCurrent();
mSurfaceTexture->DetachFromGLContext();
mTexture = 0;
mAttachedContext = nullptr;
lock.NotifyAll();
return NS_OK;
}
void
AndroidSurfaceTexture::UpdateCanDetach()
{
// The API for attach/detach only exists on 16+, and PowerVR has some sort of
// fencing issue. Additionally, attach/detach seems to be busted on at least some
// Mali adapters (400MP2 for sure, bug 1131793)
bool canDetach = gfxPrefs::SurfaceTextureDetachEnabled();
mCanDetach = AndroidBridge::Bridge()->GetAPIVersion() >= 16 &&
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::Imagination) &&
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::ARM /* Mali */) &&
canDetach;
}
bool
AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
{
UpdateCanDetach();
if (!aTexture && !CanDetach()) {
// We have no texture and cannot initialize detached, bail out
return false;
}
if (NS_WARN_IF(NS_FAILED(
SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) {
return false;
}
if (!aTexture) {
mSurfaceTexture->DetachFromGLContext();
}
mAttachedContext = aContext;
if (NS_WARN_IF(NS_FAILED(
Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) {
return false;
}
mNativeWindow = AndroidNativeWindow::CreateFromSurface(jni::GetEnvForThread(),
mSurface.Get());
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
mID = sInstances.Add(this);
return true;
}
AndroidSurfaceTexture::AndroidSurfaceTexture()
: mTexture(0)
, mSurfaceTexture()
, mSurface()
, mAttachedContext(nullptr)
, mCanDetach(false)
, mMonitor("AndroidSurfaceTexture::mContextMonitor")
{
}
AndroidSurfaceTexture::~AndroidSurfaceTexture()
{
sInstances.Remove(mID);
mFrameAvailableCallback = nullptr;
if (mSurfaceTexture) {
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
mSurfaceTexture = nullptr;
}
}
void
AndroidSurfaceTexture::UpdateTexImage()
{
mSurfaceTexture->UpdateTexImage();
}
void
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
{
JNIEnv* const env = jni::GetEnvForThread();
auto jarray = FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
mSurfaceTexture->GetTransformMatrix(jarray);
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
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.Get(), array, 0);
}
void
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
{
if (aRunnable) {
GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
} else {
GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
}
mFrameAvailableCallback = aRunnable;
}
void
AndroidSurfaceTexture::SetDefaultSize(mozilla::gfx::IntSize size)
{
mSurfaceTexture->SetDefaultBufferSize(size.width, size.height);
}
void
AndroidSurfaceTexture::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, &AndroidSurfaceTexture::NotifyFrameAvailable);
NS_DispatchToCurrentThread(event);
} else {
mFrameAvailableCallback->Run();
}
}
}
} // gl
} // mozilla
#endif // MOZ_WIDGET_ANDROID