зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset b50714bd8d10 (bug 1322650) for failing chrome's test_video_discovery.html and mda's test_Eviction_mp4.html, both on Android. r=backout
This commit is contained in:
Родитель
087bd41f0f
Коммит
6ff84ee171
|
@ -1,20 +1,204 @@
|
||||||
|
/* -*- 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
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <android/log.h>
|
||||||
#include "AndroidSurfaceTexture.h"
|
#include "AndroidSurfaceTexture.h"
|
||||||
|
#include "gfxImageSurface.h"
|
||||||
|
#include "gfxPrefs.h"
|
||||||
|
#include "AndroidBridge.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
#include "mozilla/gfx/Matrix.h"
|
||||||
|
#include "GeneratedJNINatives.h"
|
||||||
|
#include "GLContext.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gl {
|
namespace gl {
|
||||||
|
|
||||||
|
class AndroidSurfaceTexture::Listener
|
||||||
|
: public java::SurfaceTextureListener::Natives<Listener>
|
||||||
|
{
|
||||||
|
using Base = java::SurfaceTextureListener::Natives<Listener>;
|
||||||
|
|
||||||
|
const nsCOMPtr<nsIRunnable> mCallback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Base::AttachNative;
|
||||||
|
using Base::DisposeNative;
|
||||||
|
|
||||||
|
Listener(nsIRunnable* aCallback) : mCallback(aCallback) {}
|
||||||
|
|
||||||
|
void OnFrameAvailable()
|
||||||
|
{
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
mCallback->Run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NS_DispatchToMainThread(mCallback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
already_AddRefed<AndroidSurfaceTexture>
|
||||||
|
AndroidSurfaceTexture::Create()
|
||||||
|
{
|
||||||
|
return Create(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<AndroidSurfaceTexture>
|
||||||
|
AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
|
||||||
|
aContext->fGenTextures(1, &mTexture);
|
||||||
|
|
||||||
|
if (NS_FAILED(mSurfaceTexture->AttachToGLContext(mTexture))) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
mAttachedContext = aContext;
|
||||||
|
mAttachedContext->MakeCurrent();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AndroidSurfaceTexture::CanDetach() const
|
||||||
|
{
|
||||||
|
// 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)
|
||||||
|
return AndroidBridge::Bridge()->GetAPIVersion() >= 16 &&
|
||||||
|
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::Imagination) &&
|
||||||
|
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::ARM /* Mali */) &&
|
||||||
|
gfxPrefs::SurfaceTextureDetachEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!aTexture && !CanDetach()) {
|
||||||
|
// We have no texture and cannot initialize detached, bail out
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(
|
||||||
|
java::sdk::SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aTexture) {
|
||||||
|
mSurfaceTexture->DetachFromGLContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
mAttachedContext = aContext;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(
|
||||||
|
java::sdk::Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
|
||||||
|
mSurface.Get());
|
||||||
|
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidSurfaceTexture::AndroidSurfaceTexture()
|
||||||
|
: mTexture(0)
|
||||||
|
, mSurfaceTexture()
|
||||||
|
, mSurface()
|
||||||
|
, mAttachedContext(nullptr)
|
||||||
|
, mMonitor("AndroidSurfaceTexture")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidSurfaceTexture::~AndroidSurfaceTexture()
|
||||||
|
{
|
||||||
|
if (mSurfaceTexture) {
|
||||||
|
SetFrameAvailableCallback(nullptr);
|
||||||
|
mSurfaceTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mNativeWindow) {
|
||||||
|
ANativeWindow_release(mNativeWindow);
|
||||||
|
mNativeWindow = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
|
AndroidSurfaceTexture::UpdateTexImage()
|
||||||
gfx::Matrix4x4& aMatrix)
|
{
|
||||||
|
mSurfaceTexture->UpdateTexImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
|
||||||
{
|
{
|
||||||
JNIEnv* const env = jni::GetEnvForThread();
|
JNIEnv* const env = jni::GetEnvForThread();
|
||||||
|
|
||||||
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
|
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
|
||||||
aSurfaceTexture->GetTransformMatrix(jarray);
|
mSurfaceTexture->GetTransformMatrix(jarray);
|
||||||
|
|
||||||
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
|
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
|
||||||
|
|
||||||
|
@ -41,6 +225,36 @@ AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aS
|
||||||
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
|
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
|
||||||
|
{
|
||||||
|
java::SurfaceTextureListener::LocalRef newListener;
|
||||||
|
|
||||||
|
if (aRunnable) {
|
||||||
|
newListener = java::SurfaceTextureListener::New();
|
||||||
|
Listener::AttachNative(newListener, MakeUnique<Listener>(aRunnable));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aRunnable || mListener) {
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||||
|
mSurfaceTexture->SetOnFrameAvailableListener(newListener)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mListener) {
|
||||||
|
Listener::DisposeNative(java::SurfaceTextureListener::LocalRef(
|
||||||
|
newListener.Env(), mListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
mListener = newListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AndroidSurfaceTexture::SetDefaultSize(mozilla::gfx::IntSize size)
|
||||||
|
{
|
||||||
|
mSurfaceTexture->SetDefaultBufferSize(size.width, size.height);
|
||||||
|
}
|
||||||
|
|
||||||
} // gl
|
} // gl
|
||||||
} // mozilla
|
} // mozilla
|
||||||
|
|
||||||
#endif // MOZ_WIDGET_ANDROID
|
#endif // MOZ_WIDGET_ANDROID
|
||||||
|
|
|
@ -8,23 +8,100 @@
|
||||||
#define AndroidSurfaceTexture_h__
|
#define AndroidSurfaceTexture_h__
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
#include "mozilla/gfx/Matrix.h"
|
#include <jni.h>
|
||||||
#include "SurfaceTexture.h"
|
#include <android/native_window.h>
|
||||||
|
#include "nsIRunnable.h"
|
||||||
|
#include "gfxPlatform.h"
|
||||||
|
#include "GLDefs.h"
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/gfx/MatrixFwd.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
|
|
||||||
typedef uint32_t AndroidSurfaceTextureHandle;
|
#include "GeneratedJNIWrappers.h"
|
||||||
|
#include "SurfaceTexture.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace gl {
|
namespace gl {
|
||||||
|
|
||||||
class AndroidSurfaceTexture {
|
class GLContext;
|
||||||
public:
|
|
||||||
static void GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
|
|
||||||
mozilla::gfx::Matrix4x4& aMatrix);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 AndroidSurfaceTexture {
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidSurfaceTexture)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// The SurfaceTexture is created in an attached state. This method requires
|
||||||
|
// Android Ice Cream Sandwich.
|
||||||
|
static already_AddRefed<AndroidSurfaceTexture> Create(GLContext* aGLContext, GLuint aTexture);
|
||||||
|
|
||||||
|
// Here the SurfaceTexture will be created in a detached state. You must call
|
||||||
|
// Attach() with the GLContext you wish to composite with. It must be done
|
||||||
|
// on the thread where that GLContext is current. This method requires
|
||||||
|
// Android Jelly Bean.
|
||||||
|
static already_AddRefed<AndroidSurfaceTexture> Create();
|
||||||
|
|
||||||
|
// If we are on Jelly Bean, the SurfaceTexture can be detached and reattached
|
||||||
|
// to allow consumption from different GLContexts. It is recommended to only
|
||||||
|
// attach while you are consuming in order to allow this.
|
||||||
|
//
|
||||||
|
// Only one GLContext may be attached at any given time. If another is already
|
||||||
|
// attached, we try to wait for it to become detached.
|
||||||
|
nsresult Attach(GLContext* aContext, PRIntervalTime aTiemout = PR_INTERVAL_NO_TIMEOUT);
|
||||||
|
|
||||||
|
nsresult Detach();
|
||||||
|
|
||||||
|
// Ability to detach is based on API version (16+), and we also block PowerVR
|
||||||
|
// since it has some type of fencing problem. Bug 1100126.
|
||||||
|
bool CanDetach() const;
|
||||||
|
|
||||||
|
GLContext* AttachedContext() const { return mAttachedContext; }
|
||||||
|
|
||||||
|
ANativeWindow* NativeWindow() const {
|
||||||
|
return mNativeWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This attaches the updated data to the TEXTURE_EXTERNAL target
|
||||||
|
void UpdateTexImage();
|
||||||
|
|
||||||
|
void GetTransformMatrix(mozilla::gfx::Matrix4x4& aMatrix) const;
|
||||||
|
|
||||||
|
void SetDefaultSize(mozilla::gfx::IntSize size);
|
||||||
|
|
||||||
|
// The callback is guaranteed to be called on the main thread even
|
||||||
|
// if the upstream callback is received on a different thread
|
||||||
|
void SetFrameAvailableCallback(nsIRunnable* aRunnable);
|
||||||
|
|
||||||
|
GLuint Texture() const { return mTexture; }
|
||||||
|
const java::sdk::Surface::Ref& JavaSurface() const { return mSurface; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Listener;
|
||||||
|
|
||||||
|
AndroidSurfaceTexture();
|
||||||
|
~AndroidSurfaceTexture();
|
||||||
|
|
||||||
|
bool Init(GLContext* aContext, GLuint aTexture);
|
||||||
|
|
||||||
|
GLuint mTexture;
|
||||||
|
java::sdk::SurfaceTexture::GlobalRef mSurfaceTexture;
|
||||||
|
java::sdk::Surface::GlobalRef mSurface;
|
||||||
|
java::SurfaceTextureListener::GlobalRef mListener;
|
||||||
|
|
||||||
|
GLContext* mAttachedContext;
|
||||||
|
|
||||||
|
ANativeWindow* mNativeWindow;
|
||||||
|
|
||||||
|
Monitor mMonitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // gl
|
}
|
||||||
} // mozilla
|
}
|
||||||
|
|
||||||
#endif // MOZ_WIDGET_ANDROID
|
|
||||||
#endif // AndroidSurfaceTexture_h__
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -473,12 +473,5 @@
|
||||||
android:isolatedProcess="false">
|
android:isolatedProcess="false">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
|
||||||
android:name="org.mozilla.gecko.gfx.SurfaceAllocatorService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false"
|
|
||||||
android:isolatedProcess="false">
|
|
||||||
</service>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -547,7 +547,6 @@ libs:: classes.dex
|
||||||
GECKOVIEW_AIDLS = \
|
GECKOVIEW_AIDLS = \
|
||||||
org/mozilla/gecko/IGeckoEditableChild.aidl \
|
org/mozilla/gecko/IGeckoEditableChild.aidl \
|
||||||
org/mozilla/gecko/IGeckoEditableParent.aidl \
|
org/mozilla/gecko/IGeckoEditableParent.aidl \
|
||||||
org/mozilla/gecko/gfx/ISurfaceAllocator.aidl \
|
|
||||||
org/mozilla/gecko/media/ICodec.aidl \
|
org/mozilla/gecko/media/ICodec.aidl \
|
||||||
org/mozilla/gecko/media/ICodecCallbacks.aidl \
|
org/mozilla/gecko/media/ICodecCallbacks.aidl \
|
||||||
org/mozilla/gecko/media/IMediaDrmBridge.aidl \
|
org/mozilla/gecko/media/IMediaDrmBridge.aidl \
|
||||||
|
|
|
@ -379,8 +379,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
||||||
'gfx/FloatSize.java',
|
'gfx/FloatSize.java',
|
||||||
'gfx/FullScreenState.java',
|
'gfx/FullScreenState.java',
|
||||||
'gfx/GeckoLayerClient.java',
|
'gfx/GeckoLayerClient.java',
|
||||||
'gfx/GeckoSurface.java',
|
|
||||||
'gfx/GeckoSurfaceTexture.java',
|
|
||||||
'gfx/ImmutableViewportMetrics.java',
|
'gfx/ImmutableViewportMetrics.java',
|
||||||
'gfx/IntSize.java',
|
'gfx/IntSize.java',
|
||||||
'gfx/LayerView.java',
|
'gfx/LayerView.java',
|
||||||
|
@ -393,8 +391,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
||||||
'gfx/RectUtils.java',
|
'gfx/RectUtils.java',
|
||||||
'gfx/RenderTask.java',
|
'gfx/RenderTask.java',
|
||||||
'gfx/StackScroller.java',
|
'gfx/StackScroller.java',
|
||||||
'gfx/SurfaceAllocator.java',
|
|
||||||
'gfx/SurfaceAllocatorService.java',
|
|
||||||
'gfx/SurfaceTextureListener.java',
|
'gfx/SurfaceTextureListener.java',
|
||||||
'gfx/ViewTransform.java',
|
'gfx/ViewTransform.java',
|
||||||
'gfx/VsyncSource.java',
|
'gfx/VsyncSource.java',
|
||||||
|
@ -1261,7 +1257,6 @@ DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
|
||||||
FINAL_TARGET_PP_FILES += ['package-name.txt.in']
|
FINAL_TARGET_PP_FILES += ['package-name.txt.in']
|
||||||
|
|
||||||
gvjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
|
gvjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
|
||||||
'gfx/ISurfaceAllocator.java',
|
|
||||||
'IGeckoEditableChild.java',
|
'IGeckoEditableChild.java',
|
||||||
'IGeckoEditableParent.java',
|
'IGeckoEditableParent.java',
|
||||||
'media/ICodec.java',
|
'media/ICodec.java',
|
||||||
|
|
|
@ -53,13 +53,6 @@
|
||||||
android:process=":tab"
|
android:process=":tab"
|
||||||
android:isolatedProcess="false">
|
android:isolatedProcess="false">
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service
|
|
||||||
android:name="org.mozilla.gecko.gfx.SurfaceAllocatorService"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false"
|
|
||||||
android:isolatedProcess="false">
|
|
||||||
</service>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
/* 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;
|
|
||||||
|
|
||||||
parcelable GeckoSurface;
|
|
|
@ -1,12 +0,0 @@
|
||||||
/* 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.gfx.GeckoSurface;
|
|
||||||
|
|
||||||
interface ISurfaceAllocator {
|
|
||||||
GeckoSurface acquireSurface(in int width, in int height, in boolean singleBufferMode);
|
|
||||||
void releaseSurface(in int handle);
|
|
||||||
}
|
|
|
@ -1,98 +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 android.graphics.SurfaceTexture;
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
import android.view.Surface;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
|
||||||
import org.mozilla.gecko.AppConstants.Versions;
|
|
||||||
|
|
||||||
public final class GeckoSurface extends Surface {
|
|
||||||
private static final String LOGTAG = "GeckoSurface";
|
|
||||||
|
|
||||||
private static HashMap<Integer, GeckoSurfaceTexture> sSurfaceTextures = new HashMap<Integer, GeckoSurfaceTexture>();
|
|
||||||
|
|
||||||
private int mHandle;
|
|
||||||
private boolean mIsSingleBuffer;
|
|
||||||
private volatile boolean mIsAvailable;
|
|
||||||
|
|
||||||
private SurfaceTexture mDummySurfaceTexture;
|
|
||||||
|
|
||||||
@WrapForJNI(exceptionMode = "nsresult")
|
|
||||||
public GeckoSurface(GeckoSurfaceTexture gst) {
|
|
||||||
super(gst);
|
|
||||||
mHandle = gst.getHandle();
|
|
||||||
mIsSingleBuffer = gst.isSingleBuffer();
|
|
||||||
mIsAvailable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeckoSurface(SurfaceTexture st) {
|
|
||||||
super(st);
|
|
||||||
mDummySurfaceTexture = st;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeckoSurface() {
|
|
||||||
// A no-arg constructor exists, but is hidden in the SDK. We need to create a dummy
|
|
||||||
// SurfaceTexture here in order to create the instance. This is used to transfer the
|
|
||||||
// GeckoSurface across binder.
|
|
||||||
super(new SurfaceTexture(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readFromParcel(Parcel p) {
|
|
||||||
super.readFromParcel(p);
|
|
||||||
mHandle = p.readInt();
|
|
||||||
mIsSingleBuffer = p.readByte() == 1 ? true : false;
|
|
||||||
mIsAvailable = (p.readByte() == 1 ? true : false);
|
|
||||||
|
|
||||||
if (mDummySurfaceTexture != null) {
|
|
||||||
mDummySurfaceTexture.release();
|
|
||||||
mDummySurfaceTexture = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<GeckoSurface> CREATOR = new Parcelable.Creator<GeckoSurface>() {
|
|
||||||
public GeckoSurface createFromParcel(Parcel p) {
|
|
||||||
GeckoSurface surf = new GeckoSurface();
|
|
||||||
surf.readFromParcel(p);
|
|
||||||
return surf;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GeckoSurface[] newArray(int size) {
|
|
||||||
return new GeckoSurface[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
|
||||||
super.writeToParcel(out, flags);
|
|
||||||
out.writeInt(mHandle);
|
|
||||||
out.writeByte((byte) (mIsSingleBuffer ? 1 : 0));
|
|
||||||
out.writeByte((byte) (mIsAvailable ? 1 : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public int getHandle() {
|
|
||||||
return mHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public boolean getAvailable() {
|
|
||||||
return mIsAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public void setAvailable(boolean available) {
|
|
||||||
mIsAvailable = available;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,140 +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 android.graphics.SurfaceTexture;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
|
||||||
import org.mozilla.gecko.AppConstants.Versions;
|
|
||||||
|
|
||||||
public final class GeckoSurfaceTexture extends SurfaceTexture {
|
|
||||||
private static final String LOGTAG = "GeckoSurfaceTexture";
|
|
||||||
private static volatile int sNextHandle = 1;
|
|
||||||
private static HashMap<Integer, GeckoSurfaceTexture> sSurfaceTextures = new HashMap<Integer, GeckoSurfaceTexture>();
|
|
||||||
|
|
||||||
private int mHandle;
|
|
||||||
private boolean mIsSingleBuffer;
|
|
||||||
private int mTexName;
|
|
||||||
private GeckoSurfaceTexture.Callbacks mListener;
|
|
||||||
|
|
||||||
@WrapForJNI(dispatchTo = "current")
|
|
||||||
private static native int nativeAcquireTexture();
|
|
||||||
|
|
||||||
private GeckoSurfaceTexture(int handle, int texName) {
|
|
||||||
super(texName);
|
|
||||||
mHandle = handle;
|
|
||||||
mIsSingleBuffer = false;
|
|
||||||
mTexName = texName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GeckoSurfaceTexture(int handle, int texName, boolean singleBufferMode) {
|
|
||||||
super(texName, singleBufferMode);
|
|
||||||
mHandle = handle;
|
|
||||||
mIsSingleBuffer = singleBufferMode;
|
|
||||||
mTexName = texName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public int getHandle() {
|
|
||||||
return mHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public int getTexName() {
|
|
||||||
return mTexName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public boolean isSingleBuffer() {
|
|
||||||
return mIsSingleBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@WrapForJNI
|
|
||||||
public synchronized void updateTexImage() {
|
|
||||||
super.updateTexImage();
|
|
||||||
if (mListener != null) {
|
|
||||||
mListener.onUpdateTexImage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@WrapForJNI
|
|
||||||
public synchronized void releaseTexImage() {
|
|
||||||
if (!mIsSingleBuffer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.releaseTexImage();
|
|
||||||
if (mListener != null) {
|
|
||||||
mListener.onReleaseTexImage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void setListener(GeckoSurfaceTexture.Callbacks listener) {
|
|
||||||
mListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public static boolean isSingleBufferSupported() {
|
|
||||||
return Versions.feature19Plus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GeckoSurfaceTexture acquire(boolean singleBufferMode) {
|
|
||||||
if (singleBufferMode && !isSingleBufferSupported()) {
|
|
||||||
throw new IllegalArgumentException("single buffer mode not supported on API version < 19");
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle = sNextHandle++;
|
|
||||||
int texName = nativeAcquireTexture();
|
|
||||||
|
|
||||||
final GeckoSurfaceTexture gst;
|
|
||||||
if (isSingleBufferSupported()) {
|
|
||||||
gst = new GeckoSurfaceTexture(handle, texName, singleBufferMode);
|
|
||||||
} else {
|
|
||||||
gst = new GeckoSurfaceTexture(handle, texName);
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (sSurfaceTextures) {
|
|
||||||
if (sSurfaceTextures.containsKey(handle)) {
|
|
||||||
gst.release();
|
|
||||||
throw new IllegalArgumentException("Already have a GeckoSurfaceTexture with that handle");
|
|
||||||
}
|
|
||||||
|
|
||||||
sSurfaceTextures.put(handle, gst);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return gst;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void dispose(int handle) {
|
|
||||||
final GeckoSurfaceTexture gst;
|
|
||||||
synchronized (sSurfaceTextures) {
|
|
||||||
gst = sSurfaceTextures.remove(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gst != null) {
|
|
||||||
gst.setListener(null);
|
|
||||||
gst.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public static GeckoSurfaceTexture lookup(int handle) {
|
|
||||||
synchronized (sSurfaceTextures) {
|
|
||||||
return sSurfaceTextures.get(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callbacks {
|
|
||||||
void onUpdateTexImage();
|
|
||||||
void onReleaseTexImage();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +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 android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
|
|
||||||
import android.graphics.SurfaceTexture;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Surface;
|
|
||||||
|
|
||||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
|
||||||
import org.mozilla.gecko.GeckoAppShell;
|
|
||||||
|
|
||||||
public final class SurfaceAllocator {
|
|
||||||
private static final String LOGTAG = "SurfaceAllocator";
|
|
||||||
|
|
||||||
private static SurfaceAllocatorConnection sConnection;
|
|
||||||
|
|
||||||
private static synchronized void ensureConnection() throws Exception {
|
|
||||||
if (sConnection != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sConnection = new SurfaceAllocatorConnection();
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setClassName(GeckoAppShell.getApplicationContext(),
|
|
||||||
"org.mozilla.gecko.gfx.SurfaceAllocatorService");
|
|
||||||
|
|
||||||
// FIXME: may not want to auto create
|
|
||||||
if (!GeckoAppShell.getApplicationContext().bindService(intent, sConnection, Context.BIND_AUTO_CREATE)) {
|
|
||||||
throw new Exception("Failed to connect to surface allocator service!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public static GeckoSurface acquireSurface(int width, int height, boolean singleBufferMode) throws Exception {
|
|
||||||
ensureConnection();
|
|
||||||
|
|
||||||
try {
|
|
||||||
return sConnection.getAllocator().acquireSurface(width, height, singleBufferMode);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw new Exception("Failed to acquire GeckoSurface", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@WrapForJNI
|
|
||||||
public static void disposeSurface(GeckoSurface surface) {
|
|
||||||
try {
|
|
||||||
ensureConnection();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.w(LOGTAG, "Failed to dispose surface, no connection");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the SurfaceTexture on the other side
|
|
||||||
try {
|
|
||||||
sConnection.getAllocator().releaseSurface(surface.getHandle());
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(LOGTAG, "Failed to release surface texture", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// And now our Surface
|
|
||||||
try {
|
|
||||||
surface.release();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.w(LOGTAG, "Failed to release surface", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class SurfaceAllocatorConnection implements ServiceConnection {
|
|
||||||
private ISurfaceAllocator mAllocator;
|
|
||||||
|
|
||||||
public synchronized ISurfaceAllocator getAllocator() {
|
|
||||||
while (mAllocator == null) {
|
|
||||||
try {
|
|
||||||
this.wait();
|
|
||||||
} catch(InterruptedException e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void onServiceConnected(ComponentName name, IBinder service) {
|
|
||||||
mAllocator = ISurfaceAllocator.Stub.asInterface(service);
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void onServiceDisconnected(ComponentName name) {
|
|
||||||
mAllocator = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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 android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class SurfaceAllocatorService extends Service {
|
|
||||||
|
|
||||||
static private String LOGTAG = "SurfaceAllocatorService";
|
|
||||||
|
|
||||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
|
||||||
return Service.START_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Binder mBinder = new ISurfaceAllocator.Stub() {
|
|
||||||
public GeckoSurface acquireSurface(int width, int height, boolean singleBufferMode) {
|
|
||||||
GeckoSurfaceTexture gst = GeckoSurfaceTexture.acquire(singleBufferMode);
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
gst.setDefaultBufferSize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GeckoSurface(gst);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseSurface(int handle) {
|
|
||||||
GeckoSurfaceTexture.dispose(handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public IBinder onBind(final Intent intent) {
|
|
||||||
return mBinder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onUnbind(Intent intent) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
Загрузка…
Ссылка в новой задаче