зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1014614
- Expose Android native window via AndroidNativeWindow wrapper r=blassey
--HG-- extra : rebase_source : a2d27a4223c1bd1189c4c6a32431cc306a3e93c6
This commit is contained in:
Родитель
9450484c06
Коммит
399aa1c748
|
@ -0,0 +1,281 @@
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
|
#include "AndroidNativeWindow.h"
|
||||||
|
#include "prlink.h"
|
||||||
|
|
||||||
|
// #define ANDROID_NATIVE_WINDOW_DEBUG
|
||||||
|
|
||||||
|
#if defined(ANDROID_NATIVE_WINDOW_DEBUG) || defined(DEBUG)
|
||||||
|
#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidNativeWindow" , ## args)
|
||||||
|
#else
|
||||||
|
#define ALOG(args...) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace mozilla::gfx;
|
||||||
|
using namespace mozilla::gl;
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
|
class NativeWindowLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
NativeWindowLibrary()
|
||||||
|
: fANativeWindow_fromSurface(nullptr)
|
||||||
|
, fANativeWindow_release(nullptr)
|
||||||
|
, fANativeWindow_setBuffersGeometry(nullptr)
|
||||||
|
, fANativeWindow_lock(nullptr)
|
||||||
|
, fANativeWindow_unlockAndPost(nullptr)
|
||||||
|
, fANativeWindow_getFormat(nullptr)
|
||||||
|
, fANativeWindow_getWidth(nullptr)
|
||||||
|
, fANativeWindow_getHeight(nullptr)
|
||||||
|
{
|
||||||
|
PRLibrary* lib = PR_LoadLibrary("libandroid.so");
|
||||||
|
|
||||||
|
fANativeWindow_fromSurface = (pfnANativeWindow_fromSurface)PR_FindSymbol(lib, "ANativeWindow_fromSurface");
|
||||||
|
fANativeWindow_release = (pfnANativeWindow_release)PR_FindSymbol(lib, "ANativeWindow_release");
|
||||||
|
fANativeWindow_setBuffersGeometry = (pfnANativeWindow_setBuffersGeometry)PR_FindSymbol(lib, "ANativeWindow_setBuffersGeometry");
|
||||||
|
fANativeWindow_lock = (pfnANativeWindow_lock)PR_FindSymbol(lib, "ANativeWindow_lock");
|
||||||
|
fANativeWindow_unlockAndPost = (pfnANativeWindow_unlockAndPost)PR_FindSymbol(lib, "ANativeWindow_unlockAndPost");
|
||||||
|
fANativeWindow_getFormat = (pfnANativeWindow_getFormat)PR_FindSymbol(lib, "ANativeWindow_getFormat");
|
||||||
|
fANativeWindow_getWidth = (pfnANativeWindow_getWidth)PR_FindSymbol(lib, "ANativeWindow_getWidth");
|
||||||
|
fANativeWindow_getHeight = (pfnANativeWindow_getHeight)PR_FindSymbol(lib, "ANativeWindow_getHeight");
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ANativeWindow_fromSurface(JNIEnv* aEnv, jobject aSurface) {
|
||||||
|
ALOG("%s: env=%p, surface=%p\n", __PRETTY_FUNCTION__, aEnv, aSurface);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_fromSurface(aEnv, aSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ANativeWindow_release(void* aWindow) {
|
||||||
|
ALOG("%s: window=%p\n", __PRETTY_FUNCTION__, aWindow);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fANativeWindow_release(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ANativeWindow_setBuffersGeometry(void* aWindow, int32_t aWidth, int32_t aHeight, int32_t aFormat) {
|
||||||
|
ALOG("%s: window=%p, width=%d, height=%d, format=%d\n", __PRETTY_FUNCTION__, aWindow, aWidth, aHeight, aFormat);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_setBuffersGeometry(aWindow, aWidth, aHeight, (int32_t)aFormat) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ANativeWindow_lock(void* aWindow, void* out_buffer, void*in_out_dirtyBounds) {
|
||||||
|
ALOG("%s: window=%p, out_buffer=%p, in_out_dirtyBounds=%p\n", __PRETTY_FUNCTION__,
|
||||||
|
aWindow, out_buffer, in_out_dirtyBounds);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_lock(aWindow, out_buffer, in_out_dirtyBounds) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ANativeWindow_unlockAndPost(void* aWindow) {
|
||||||
|
ALOG("%s: window=%p\n", __PRETTY_FUNCTION__, aWindow);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_unlockAndPost(aWindow) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidWindowFormat ANativeWindow_getFormat(void* aWindow) {
|
||||||
|
ALOG("%s: window=%p\n", __PRETTY_FUNCTION__, aWindow);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return AndroidWindowFormat::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (AndroidWindowFormat)fANativeWindow_getFormat(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ANativeWindow_getWidth(void* aWindow) {
|
||||||
|
ALOG("%s: window=%p\n", __PRETTY_FUNCTION__, aWindow);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_getWidth(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ANativeWindow_getHeight(void* aWindow) {
|
||||||
|
ALOG("%s: window=%p\n", __PRETTY_FUNCTION__, aWindow);
|
||||||
|
if (!Initialized()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fANativeWindow_getHeight(aWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialized() {
|
||||||
|
return fANativeWindow_fromSurface && fANativeWindow_release && fANativeWindow_setBuffersGeometry
|
||||||
|
&& fANativeWindow_lock && fANativeWindow_unlockAndPost && fANativeWindow_getFormat && fANativeWindow_getWidth
|
||||||
|
&& fANativeWindow_getHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef void* (*pfnANativeWindow_fromSurface)(JNIEnv* env, jobject surface);
|
||||||
|
pfnANativeWindow_fromSurface fANativeWindow_fromSurface;
|
||||||
|
|
||||||
|
typedef void (*pfnANativeWindow_release)(void* window);
|
||||||
|
pfnANativeWindow_release fANativeWindow_release;
|
||||||
|
|
||||||
|
typedef int32_t (*pfnANativeWindow_setBuffersGeometry)(void* window, int32_t width, int32_t height, int32_t format);
|
||||||
|
pfnANativeWindow_setBuffersGeometry fANativeWindow_setBuffersGeometry;
|
||||||
|
|
||||||
|
typedef int32_t (*pfnANativeWindow_lock)(void *window, void *out_buffer, void *in_out_dirtyBounds);
|
||||||
|
pfnANativeWindow_lock fANativeWindow_lock;
|
||||||
|
|
||||||
|
typedef int32_t (*pfnANativeWindow_unlockAndPost)(void *window);
|
||||||
|
pfnANativeWindow_unlockAndPost fANativeWindow_unlockAndPost;
|
||||||
|
|
||||||
|
typedef AndroidWindowFormat (*pfnANativeWindow_getFormat)(void* window);
|
||||||
|
pfnANativeWindow_getFormat fANativeWindow_getFormat;
|
||||||
|
|
||||||
|
typedef int32_t (*pfnANativeWindow_getWidth)(void* window);
|
||||||
|
pfnANativeWindow_getWidth fANativeWindow_getWidth;
|
||||||
|
|
||||||
|
typedef int32_t (*pfnANativeWindow_getHeight)(void* window);
|
||||||
|
pfnANativeWindow_getHeight fANativeWindow_getHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
static NativeWindowLibrary* sLibrary = nullptr;
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EnsureInit()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
if (!sLibrary) {
|
||||||
|
sLibrary = new NativeWindowLibrary();
|
||||||
|
}
|
||||||
|
initialized = sLibrary->Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
/* static */ AndroidNativeWindow*
|
||||||
|
AndroidNativeWindow::CreateFromSurface(JNIEnv* aEnv, jobject aSurface)
|
||||||
|
{
|
||||||
|
if (!EnsureInit()) {
|
||||||
|
ALOG("Not initialized");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* window = sLibrary->ANativeWindow_fromSurface(aEnv, aSurface);
|
||||||
|
if (!window) {
|
||||||
|
ALOG("Failed to create window from surface");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AndroidNativeWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidNativeWindow::~AndroidNativeWindow()
|
||||||
|
{
|
||||||
|
if (EnsureInit() && mWindow) {
|
||||||
|
sLibrary->ANativeWindow_release(mWindow);
|
||||||
|
mWindow = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntSize
|
||||||
|
AndroidNativeWindow::Size()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mWindow);
|
||||||
|
if (!EnsureInit()) {
|
||||||
|
return IntSize(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntSize(sLibrary->ANativeWindow_getWidth(mWindow), sLibrary->ANativeWindow_getHeight(mWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidWindowFormat
|
||||||
|
AndroidNativeWindow::Format()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mWindow);
|
||||||
|
if (!EnsureInit()) {
|
||||||
|
return AndroidWindowFormat::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sLibrary->ANativeWindow_getFormat(mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AndroidNativeWindow::SetBuffersGeometry(int32_t aWidth, int32_t aHeight, AndroidWindowFormat aFormat)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mWindow);
|
||||||
|
if (!EnsureInit())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sLibrary->ANativeWindow_setBuffersGeometry(mWindow, aWidth, aHeight, (int32_t)aFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AndroidNativeWindow::Lock(void** out_bits,int32_t* out_width, int32_t* out_height,
|
||||||
|
int32_t* out_stride, AndroidWindowFormat* out_format)
|
||||||
|
{
|
||||||
|
/* Copied from native_window.h in Android NDK (platform-9) */
|
||||||
|
typedef struct ANativeWindow_Buffer {
|
||||||
|
// The number of pixels that are show horizontally.
|
||||||
|
int32_t width;
|
||||||
|
|
||||||
|
// The number of pixels that are shown vertically.
|
||||||
|
int32_t height;
|
||||||
|
|
||||||
|
// The number of *pixels* that a line in the buffer takes in
|
||||||
|
// memory. This may be >= width.
|
||||||
|
int32_t stride;
|
||||||
|
|
||||||
|
// The format of the buffer. One of WINDOW_FORMAT_*
|
||||||
|
int32_t format;
|
||||||
|
|
||||||
|
// The actual bits.
|
||||||
|
void* bits;
|
||||||
|
|
||||||
|
// Do not touch.
|
||||||
|
uint32_t reserved[6];
|
||||||
|
} ANativeWindow_Buffer;
|
||||||
|
|
||||||
|
|
||||||
|
ANativeWindow_Buffer buffer;
|
||||||
|
|
||||||
|
if (!sLibrary->ANativeWindow_lock(mWindow, &buffer, nullptr)) {
|
||||||
|
ALOG("Failed to lock");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_bits = buffer.bits;
|
||||||
|
*out_width = buffer.width;
|
||||||
|
*out_height = buffer.height;
|
||||||
|
*out_stride = buffer.stride;
|
||||||
|
*out_format = (AndroidWindowFormat)buffer.format;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AndroidNativeWindow::UnlockAndPost()
|
||||||
|
{
|
||||||
|
if (!EnsureInit()) {
|
||||||
|
ALOG("Not initialized");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sLibrary->ANativeWindow_unlockAndPost(mWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_WIDGET_ANDROID
|
|
@ -0,0 +1,68 @@
|
||||||
|
/* -*- 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 AndroidNativeWindow_h__
|
||||||
|
#define AndroidNativeWindow_h__
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include "GLDefs.h"
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "mozilla/TypedEnum.h"
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace gl {
|
||||||
|
|
||||||
|
MOZ_BEGIN_ENUM_CLASS(AndroidWindowFormat)
|
||||||
|
Unknown = -1,
|
||||||
|
RGBA_8888 = 1,
|
||||||
|
RGBX_8888 = 1 << 1,
|
||||||
|
RGB_565 = 1 << 2
|
||||||
|
MOZ_END_ENUM_CLASS(AndroidWindowFormat)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 AndroidNativeWindow {
|
||||||
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidNativeWindow)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static AndroidNativeWindow* CreateFromSurface(JNIEnv* aEnv, jobject aSurface);
|
||||||
|
|
||||||
|
gfx::IntSize Size();
|
||||||
|
AndroidWindowFormat Format();
|
||||||
|
|
||||||
|
bool SetBuffersGeometry(int32_t aWidth, int32_t aHeight, AndroidWindowFormat aFormat);
|
||||||
|
|
||||||
|
bool Lock(void** out_bits, int32_t* out_width, int32_t* out_height, int32_t* out_stride, AndroidWindowFormat* out_format);
|
||||||
|
bool UnlockAndPost();
|
||||||
|
|
||||||
|
void* Handle() { return mWindow; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AndroidNativeWindow(void* aWindow)
|
||||||
|
: mWindow(aWindow)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~AndroidNativeWindow();
|
||||||
|
|
||||||
|
void* mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -190,6 +190,8 @@ AndroidSurfaceTexture::Init(GLuint aTexture)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mNativeWindow = AndroidNativeWindow::CreateFromSurface(env, mSurface);
|
||||||
|
|
||||||
mID = ++sNextID;
|
mID = ++sNextID;
|
||||||
sInstances.insert(std::pair<int, AndroidSurfaceTexture*>(mID, this));
|
sInstances.insert(std::pair<int, AndroidSurfaceTexture*>(mID, this));
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ public:
|
||||||
|
|
||||||
~AndroidSurfaceTexture();
|
~AndroidSurfaceTexture();
|
||||||
|
|
||||||
|
AndroidNativeWindow* NativeWindow() {
|
||||||
|
return mNativeWindow;
|
||||||
|
}
|
||||||
|
|
||||||
// This attaches the updated data to the TEXTURE_EXTERNAL target
|
// This attaches the updated data to the TEXTURE_EXTERNAL target
|
||||||
void UpdateTexImage();
|
void UpdateTexImage();
|
||||||
|
|
||||||
|
@ -68,6 +72,7 @@ private:
|
||||||
jobject mSurfaceTexture;
|
jobject mSurfaceTexture;
|
||||||
jobject mSurface;
|
jobject mSurface;
|
||||||
|
|
||||||
|
RefPtr<AndroidNativeWindow> mNativeWindow;
|
||||||
int mID;
|
int mID;
|
||||||
nsRefPtr<nsIRunnable> mFrameAvailableCallback;
|
nsRefPtr<nsIRunnable> mFrameAvailableCallback;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,7 @@ if CONFIG['MOZ_GL_PROVIDER']:
|
||||||
gl_provider = CONFIG['MOZ_GL_PROVIDER']
|
gl_provider = CONFIG['MOZ_GL_PROVIDER']
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
|
'AndroidNativeWindow.h',
|
||||||
'AndroidSurfaceTexture.h',
|
'AndroidSurfaceTexture.h',
|
||||||
'DecomposeIntoNoRepeatTriangles.h',
|
'DecomposeIntoNoRepeatTriangles.h',
|
||||||
'EGLUtils.h',
|
'EGLUtils.h',
|
||||||
|
@ -115,6 +116,7 @@ else:
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
'AndroidNativeWindow.cpp',
|
||||||
'AndroidSurfaceTexture.cpp',
|
'AndroidSurfaceTexture.cpp',
|
||||||
'DecomposeIntoNoRepeatTriangles.cpp',
|
'DecomposeIntoNoRepeatTriangles.cpp',
|
||||||
'EGLUtils.cpp',
|
'EGLUtils.cpp',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче