зеркало из 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
|
||||
|
||||
#include <map>
|
||||
#include <android/native_window_jni.h>
|
||||
#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 "GeneratedJNINatives.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
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
|
||||
AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
|
||||
gfx::Matrix4x4& aMatrix)
|
||||
AndroidSurfaceTexture::UpdateTexImage()
|
||||
{
|
||||
mSurfaceTexture->UpdateTexImage();
|
||||
}
|
||||
|
||||
void
|
||||
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
|
||||
{
|
||||
JNIEnv* const env = jni::GetEnvForThread();
|
||||
|
||||
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
|
||||
aSurfaceTexture->GetTransformMatrix(jarray);
|
||||
mSurfaceTexture->GetTransformMatrix(jarray);
|
||||
|
||||
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
|
||||
|
||||
|
@ -41,6 +225,36 @@ AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aS
|
|||
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
|
||||
} // mozilla
|
||||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
|
|
@ -8,23 +8,100 @@
|
|||
#define AndroidSurfaceTexture_h__
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "SurfaceTexture.h"
|
||||
#include <jni.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 gl {
|
||||
|
||||
class AndroidSurfaceTexture {
|
||||
public:
|
||||
static void GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
|
||||
mozilla::gfx::Matrix4x4& aMatrix);
|
||||
class GLContext;
|
||||
|
||||
/**
|
||||
* 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">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="org.mozilla.gecko.gfx.SurfaceAllocatorService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:isolatedProcess="false">
|
||||
</service>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
@ -547,7 +547,6 @@ libs:: classes.dex
|
|||
GECKOVIEW_AIDLS = \
|
||||
org/mozilla/gecko/IGeckoEditableChild.aidl \
|
||||
org/mozilla/gecko/IGeckoEditableParent.aidl \
|
||||
org/mozilla/gecko/gfx/ISurfaceAllocator.aidl \
|
||||
org/mozilla/gecko/media/ICodec.aidl \
|
||||
org/mozilla/gecko/media/ICodecCallbacks.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/FullScreenState.java',
|
||||
'gfx/GeckoLayerClient.java',
|
||||
'gfx/GeckoSurface.java',
|
||||
'gfx/GeckoSurfaceTexture.java',
|
||||
'gfx/ImmutableViewportMetrics.java',
|
||||
'gfx/IntSize.java',
|
||||
'gfx/LayerView.java',
|
||||
|
@ -393,8 +391,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'gfx/RectUtils.java',
|
||||
'gfx/RenderTask.java',
|
||||
'gfx/StackScroller.java',
|
||||
'gfx/SurfaceAllocator.java',
|
||||
'gfx/SurfaceAllocatorService.java',
|
||||
'gfx/SurfaceTextureListener.java',
|
||||
'gfx/ViewTransform.java',
|
||||
'gfx/VsyncSource.java',
|
||||
|
@ -1261,7 +1257,6 @@ DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
|
|||
FINAL_TARGET_PP_FILES += ['package-name.txt.in']
|
||||
|
||||
gvjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
|
||||
'gfx/ISurfaceAllocator.java',
|
||||
'IGeckoEditableChild.java',
|
||||
'IGeckoEditableParent.java',
|
||||
'media/ICodec.java',
|
||||
|
|
|
@ -53,13 +53,6 @@
|
|||
android:process=":tab"
|
||||
android:isolatedProcess="false">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="org.mozilla.gecko.gfx.SurfaceAllocatorService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:isolatedProcess="false">
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</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;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче