Bug 721741 - Add support for Flash on Android 4.0+ r=blassey

This commit is contained in:
James Willcox 2012-01-31 09:40:58 -05:00
parent 6982c1b717
commit de86b5b89d
34 changed files with 1640 additions and 73 deletions

View File

@ -138,6 +138,7 @@ endif
LOCAL_INCLUDES += \
-DSK_BUILD_FOR_ANDROID_NDK \
-I$(topsrcdir)/widget/android \
-I$(topsrcdir)/xpcom/base/ \
-I$(topsrcdir)/gfx/skia/include/core \
-I$(topsrcdir)/gfx/skia/include/config \

View File

@ -306,7 +306,6 @@ anp_audio_start(ANPAudioTrack* s)
if (s->keepGoing) {
// we are already playing. Ignore.
LOG("anp_audio_start called twice!");
return;
}
@ -359,7 +358,14 @@ anp_audio_isStopped(ANPAudioTrack* s)
return s->isStopped;
}
void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i) {
uint32_t
anp_audio_trackLatency(ANPAudioTrack* s) {
// Bug 721835
NOT_IMPLEMENTED();
return 1;
}
void InitAudioTrackInterfaceV0(ANPAudioTrackInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, newTrack);
ASSIGN(i, deleteTrack);
@ -368,3 +374,14 @@ void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i) {
ASSIGN(i, stop);
ASSIGN(i, isStopped);
}
void InitAudioTrackInterfaceV1(ANPAudioTrackInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, newTrack);
ASSIGN(i, deleteTrack);
ASSIGN(i, start);
ASSIGN(i, pause);
ASSIGN(i, stop);
ASSIGN(i, isStopped);
ASSIGN(i, trackLatency);
}

View File

@ -36,8 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "android_npapi.h"
#include <stdlib.h>
#include "android_npapi.h"
#include "nsAutoPtr.h"
#include "nsISupportsImpl.h"
@ -53,7 +53,8 @@
"!!!!!!!!!!!!!! %s not implemented %s, %d", \
__PRETTY_FUNCTION__, __FILE__, __LINE__); \
void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i);
void InitAudioTrackInterfaceV0(ANPAudioTrackInterfaceV0 *i);
void InitAudioTrackInterfaceV1(ANPAudioTrackInterfaceV1* i);
void InitBitmapInterface(ANPBitmapInterfaceV0 *i);
void InitCanvasInterface(ANPCanvasInterfaceV0 *i);
void InitEventInterface(ANPEventInterfaceV0 *i);
@ -63,5 +64,13 @@ void InitPaintInterface(ANPPaintInterfaceV0 *i);
void InitPathInterface(ANPPathInterfaceV0 *i);
void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i);
void InitSystemInterface(ANPSystemInterfaceV0 *i);
void InitSystemInterfaceV1(ANPSystemInterfaceV1 *i);
void InitSystemInterfaceV2(ANPSystemInterfaceV2 *i);
void InitTypeFaceInterface(ANPTypefaceInterfaceV0 *i);
void InitWindowInterface(ANPWindowInterfaceV0 *i);
void InitWindowInterfaceV1(ANPWindowInterfaceV1 *i);
void InitWindowInterfaceV2(ANPWindowInterfaceV2 *i);
void InitVideoInterfaceV0(ANPVideoInterfaceV0 *i);
void InitVideoInterfaceV1(ANPVideoInterfaceV1 *i);
void InitOpenGLInterface(ANPOpenGLInterfaceV0 *i);
void InitNativeWindowInterface(ANPNativeWindowInterfaceV0 *i);

View File

@ -0,0 +1,85 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// must include config.h first for webkit to fiddle with new/delete
#include <android/log.h>
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
#include "ANPBase.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
#include "gfxRect.h"
using namespace mozilla;
using namespace mozilla;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_native_window_##name
static ANPNativeWindow anp_native_window_acquireNativeWindow(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return NULL;
}
ANPNativeWindow window = owner->Layer()->GetNativeWindowForContent();
owner->Invalidate();
return window;
}
static void anp_native_window_invertPluginContent(NPP instance, bool isContentInverted) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return;
}
owner->Layer()->SetInverted(isContentInverted);
}
void InitNativeWindowInterface(ANPNativeWindowInterfaceV0* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, invertPluginContent);
}

View File

@ -0,0 +1,65 @@
/* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <dlfcn.h>
#include <android/log.h>
#include "AndroidBridge.h"
#include "ANPBase.h"
#include "GLContextProvider.h"
#include "nsNPAPIPluginInstance.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_opengl_##name
using namespace mozilla;
using namespace mozilla::gl;
static ANPEGLContext anp_opengl_acquireContext(NPP inst) {
// Bug 687267
NOT_IMPLEMENTED();
return NULL;
}
static ANPTextureInfo anp_opengl_lockTexture(NPP instance) {
ANPTextureInfo info = { 0, 0, 0, 0 };
NOT_IMPLEMENTED();
return info;
}
static void anp_opengl_releaseTexture(NPP instance, const ANPTextureInfo* info) {
NOT_IMPLEMENTED();
}
static void anp_opengl_invertPluginContent(NPP instance, bool isContentInverted) {
NOT_IMPLEMENTED();
}
///////////////////////////////////////////////////////////////////////////////
void InitOpenGLInterface(ANPOpenGLInterfaceV0* i) {
ASSIGN(i, acquireContext);
ASSIGN(i, lockTexture);
ASSIGN(i, releaseTexture);
ASSIGN(i, invertPluginContent);
}

View File

@ -62,6 +62,12 @@ anp_system_getApplicationDataDirectory()
return dir;
}
const char*
anp_system_getApplicationDataDirectory(NPP instance)
{
return anp_system_getApplicationDataDirectory();
}
jclass anp_system_loadJavaClass(NPP instance, const char* className)
{
LOG("%s", __PRETTY_FUNCTION__);
@ -88,8 +94,27 @@ jclass anp_system_loadJavaClass(NPP instance, const char* className)
return reinterpret_cast<jclass>(obj);
}
void anp_system_setPowerState(NPP instance, ANPPowerState powerState)
{
NOT_IMPLEMENTED();
}
void InitSystemInterface(ANPSystemInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
}
void InitSystemInterfaceV1(ANPSystemInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
ASSIGN(i, setPowerState);
}
void InitSystemInterfaceV2(ANPSystemInterfaceV2 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, getApplicationDataDirectory);
ASSIGN(i, loadJavaClass);
ASSIGN(i, setPowerState);
}

View File

@ -0,0 +1,109 @@
/* The Original Code is Android NPAPI support code
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <android/log.h>
#include "ANPBase.h"
#include "AndroidMediaLayer.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#include "nsNPAPIPluginInstance.h"
#include "gfxRect.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_video_##name
using namespace mozilla;
static AndroidMediaLayer* GetLayerForInstance(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return NULL;
}
return owner->Layer();
}
static void Invalidate(NPP instance) {
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner)))
return;
owner->Invalidate();
}
static ANPNativeWindow anp_video_acquireNativeWindow(NPP instance) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return NULL;
return layer->RequestNativeWindowForVideo();
}
static void anp_video_setWindowDimensions(NPP instance, const ANPNativeWindow window,
const ANPRectF* dimensions) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
gfxRect rect(dimensions->left, dimensions->top,
dimensions->right - dimensions->left,
dimensions->bottom - dimensions->top);
layer->SetNativeWindowDimensions(window, rect);
Invalidate(instance);
}
static void anp_video_releaseNativeWindow(NPP instance, ANPNativeWindow window) {
AndroidMediaLayer* layer = GetLayerForInstance(instance);
if (!layer)
return;
layer->ReleaseNativeWindowForVideo(window);
Invalidate(instance);
}
static void anp_video_setFramerateCallback(NPP instance, const ANPNativeWindow window, ANPVideoFrameCallbackProc callback) {
// Bug 722682
NOT_IMPLEMENTED();
}
///////////////////////////////////////////////////////////////////////////////
void InitVideoInterfaceV0(ANPVideoInterfaceV0* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, setWindowDimensions);
ASSIGN(i, releaseNativeWindow);
}
void InitVideoInterfaceV1(ANPVideoInterfaceV1* i) {
ASSIGN(i, acquireNativeWindow);
ASSIGN(i, setWindowDimensions);
ASSIGN(i, releaseNativeWindow);
ASSIGN(i, setFramerateCallback);
}

View File

@ -39,10 +39,16 @@
#include "assert.h"
#include "ANPBase.h"
#include <android/log.h>
#include "AndroidBridge.h"
#include "nsNPAPIPluginInstance.h"
#include "nsIPluginInstanceOwner.h"
#include "nsPluginInstanceOwner.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#define ASSIGN(obj, name) (obj)->name = anp_window_##name
using namespace mozilla;
void
anp_window_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count)
{
@ -79,6 +85,32 @@ anp_window_requestCenterFitZoom(NPP instance)
NOT_IMPLEMENTED();
}
ANPRectI
anp_window_visibleRect(NPP instance)
{
ANPRectI rect = { 0, 0, 0, 0 };
nsNPAPIPluginInstance* pinst = static_cast<nsNPAPIPluginInstance*>(instance->ndata);
nsPluginInstanceOwner* owner;
if (NS_FAILED(pinst->GetOwner((nsIPluginInstanceOwner**)&owner))) {
return rect;
}
nsIntRect visibleRect = owner->GetVisibleRect();
rect.left = visibleRect.x;
rect.top = visibleRect.y;
rect.right = visibleRect.x + visibleRect.width;
rect.bottom = visibleRect.y + visibleRect.height;
return rect;
}
void anp_window_requestFullScreenOrientation(NPP instance, ANPScreenOrientation orientation)
{
NOT_IMPLEMENTED();
}
void InitWindowInterface(ANPWindowInterfaceV0 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
@ -89,3 +121,26 @@ void InitWindowInterface(ANPWindowInterfaceV0 *i) {
ASSIGN(i, requestCenterFitZoom);
}
void InitWindowInterfaceV1(ANPWindowInterfaceV1 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
ASSIGN(i, clearVisibleRects);
ASSIGN(i, showKeyboard);
ASSIGN(i, requestFullScreen);
ASSIGN(i, exitFullScreen);
ASSIGN(i, requestCenterFitZoom);
ASSIGN(i, visibleRect);
}
void InitWindowInterfaceV2(ANPWindowInterfaceV2 *i) {
_assert(i->inSize == sizeof(*i));
ASSIGN(i, setVisibleRects);
ASSIGN(i, clearVisibleRects);
ASSIGN(i, showKeyboard);
ASSIGN(i, requestFullScreen);
ASSIGN(i, exitFullScreen);
ASSIGN(i, requestCenterFitZoom);
ASSIGN(i, visibleRect);
ASSIGN(i, requestFullScreenOrientation);
}

View File

@ -63,12 +63,17 @@ CPPSRCS += ANPAudio.cpp \
ANPWindow.cpp \
ANPBitmap.cpp \
ANPLog.cpp \
ANPNativeWindow.cpp \
ANPSurface.cpp \
ANPVideo.cpp \
ANPOpenGL.cpp \
$(NULL)
LOCAL_INCLUDES += \
-I$(topsrcdir)/widget/android \
-I$(topsrcdir)/dom/plugins/base \
-I$(topsrcdir)/dom/plugins/base/android/include \
-I$(topsrcdir)/gfx/gl \
$(MOZ_CAIRO_CFLAGS) \
$(NULL)

View File

@ -36,8 +36,9 @@
#define android_npapi_H
#include <stdint.h>
#include "npapi.h"
#include <jni.h>
#include "npapi.h"
#include "GLDefs.h"
///////////////////////////////////////////////////////////////////////////////
// General types
@ -120,6 +121,16 @@ typedef uint32_t ANPMatrixFlag;
#define kSystemInterfaceV0_ANPGetValue ((NPNVariable)1010)
#define kEventInterfaceV0_ANPGetValue ((NPNVariable)1011)
#define kAudioTrackInterfaceV1_ANPGetValue ((NPNVariable)1012)
#define kOpenGLInterfaceV0_ANPGetValue ((NPNVariable)1013)
#define kWindowInterfaceV1_ANPGetValue ((NPNVariable)1014)
#define kVideoInterfaceV0_ANPGetValue ((NPNVariable)1015)
#define kSystemInterfaceV1_ANPGetValue ((NPNVariable)1016)
#define kSystemInterfaceV2_ANPGetValue ((NPNVariable)1017)
#define kWindowInterfaceV2_ANPGetValue ((NPNVariable)1018)
#define kNativeWindowInterfaceV0_ANPGetValue ((NPNVariable)1019)
#define kVideoInterfaceV1_ANPGetValue ((NPNVariable)1020)
/** queries for the drawing models supported on this device.
NPN_GetValue(inst, kSupportedDrawingModel_ANPGetValue, uint32_t* bits)
@ -180,6 +191,7 @@ enum ANPDrawingModels {
surface object.
*/
kSurface_ANPDrawingModel = 1 << 1,
kOpenGL_ANPDrawingModel = 1 << 2,
};
typedef int32_t ANPDrawingModel;
@ -678,6 +690,25 @@ struct ANPWindowInterfaceV0 : ANPInterface {
void (*requestCenterFitZoom)(NPP instance);
};
struct ANPWindowInterfaceV1 : ANPWindowInterfaceV0 {
/** Returns a rectangle representing the visible area of the plugin on
screen. The coordinates are relative to the size of the plugin in the
document and therefore will never be negative or exceed the plugin's size.
*/
ANPRectI (*visibleRect)(NPP instance);
};
typedef int32_t ANPScreenOrientation;
struct ANPWindowInterfaceV2 : ANPWindowInterfaceV1 {
/** Called when the plugin wants to specify a particular screen orientation
when entering into full screen mode. The orientation must be set prior
to entering into full screen. After entering full screen any subsequent
changes will be updated the next time the plugin goes full screen.
*/
void (*requestFullScreenOrientation)(NPP instance, ANPScreenOrientation orientation);
};
///////////////////////////////////////////////////////////////////////////////
enum ANPSampleFormats {
@ -762,6 +793,12 @@ struct ANPAudioTrackInterfaceV0 : ANPInterface {
bool (*isStopped)(ANPAudioTrack*);
};
struct ANPAudioTrackInterfaceV1 : ANPAudioTrackInterfaceV0 {
/** Returns the track's latency in milliseconds. */
uint32_t (*trackLatency)(ANPAudioTrack*);
};
///////////////////////////////////////////////////////////////////////////////
// DEFINITION OF VALUES PASSED THROUGH NPP_HandleEvent
@ -922,12 +959,16 @@ struct ANPEvent {
// use based on the value in model
union {
ANPBitmap bitmap;
struct {
int32_t width;
int32_t height;
} surfaceSize;
} data;
} draw;
int32_t other[8];
} data;
};
struct ANPEventInterfaceV0 : ANPInterface {
/** Post a copy of the specified event to the plugin. The event will be
delivered to the plugin in its main thread (the thread that receives
@ -976,4 +1017,117 @@ typedef uint32_t uint32;
typedef int16_t int16;
typedef uint16_t uint16;
/**
* TODO should we not use EGL and GL data types for ABI safety?
*/
struct ANPTextureInfo {
GLuint textureId;
uint32_t width;
uint32_t height;
GLenum internalFormat;
};
typedef void* ANPEGLContext;
struct ANPOpenGLInterfaceV0 : ANPInterface {
ANPEGLContext (*acquireContext)(NPP instance);
ANPTextureInfo (*lockTexture)(NPP instance);
void (*releaseTexture)(NPP instance, const ANPTextureInfo*);
/**
* Invert the contents of the plugin on the y-axis.
* default is to not be inverted (i.e. use OpenGL coordinates)
*/
void (*invertPluginContent)(NPP instance, bool isContentInverted);
};
enum ANPPowerStates {
kDefault_ANPPowerState = 0,
kScreenOn_ANPPowerState = 1
};
typedef int32_t ANPPowerState;
struct ANPSystemInterfaceV1 : ANPSystemInterfaceV0 {
void (*setPowerState)(NPP instance, ANPPowerState powerState);
};
struct ANPSystemInterfaceV2 : ANPInterface {
/** Return the path name for the current Application's plugin data directory,
or NULL if not supported. This directory will change depending on whether
or not the plugin is found within an incognito tab.
*/
const char* (*getApplicationDataDirectory)(NPP instance);
// redeclaration of existing features
jclass (*loadJavaClass)(NPP instance, const char* className);
void (*setPowerState)(NPP instance, ANPPowerState powerState);
};
typedef void* ANPNativeWindow;
struct ANPVideoInterfaceV0 : ANPInterface {
/**
* Constructs a new native window to be used for rendering video content.
*
* Subsequent calls will produce new windows, but may also return NULL after
* n attempts if the browser has reached it's limit. Further, if the browser
* is unable to acquire the window quickly it may also return NULL in order
* to not prevent the plugin from executing. A subsequent call will then
* return the window if it is avaiable.
*
* NOTE: The hardware may fail if you try to decode more than the allowable
* number of videos supported on that device.
*/
ANPNativeWindow (*acquireNativeWindow)(NPP instance);
/**
* Sets the rectangle that specifies where the video content is to be drawn.
* The dimensions are in document space. Further, if the rect is NULL the
* browser will not attempt to draw the window, therefore do not set the
* dimensions until you queue the first buffer in the window.
*/
void (*setWindowDimensions)(NPP instance, const ANPNativeWindow window, const ANPRectF* dimensions);
/**
*/
void (*releaseNativeWindow)(NPP instance, ANPNativeWindow window);
};
/** Called to notify the plugin that a video frame has been composited by the
* browser for display. This will be called in a separate thread and as such
* you cannot call releaseNativeWindow from the callback.
*
* The timestamp is in nanoseconds, and is monotonically increasing.
*/
typedef void (*ANPVideoFrameCallbackProc)(ANPNativeWindow* window, int64_t timestamp);
struct ANPVideoInterfaceV1 : ANPVideoInterfaceV0 {
/** Set a callback to be notified when an ANPNativeWindow is composited by
* the browser.
*/
void (*setFramerateCallback)(NPP instance, const ANPNativeWindow window, ANPVideoFrameCallbackProc);
};
struct ANPNativeWindowInterfaceV0 : ANPInterface {
/**
* Constructs a new native window to be used for rendering plugin content.
*
* Subsequent calls will return the original constructed window. Further, if
* the browser is unable to acquire the window quickly it may return NULL in
* order to not block the plugin indefinitely. A subsequent call will then
* return the window if it is available.
*/
ANPNativeWindow (*acquireNativeWindow)(NPP instance);
/**
* Invert the contents of the plugin on the y-axis.
* default is to not be inverted (e.g. use OpenGL coordinates)
*/
void (*invertPluginContent)(NPP instance, bool isContentInverted);
};
#endif

View File

@ -132,9 +132,10 @@ using mozilla::plugins::PluginModuleParent;
#endif
#ifdef MOZ_WIDGET_ANDROID
#include <android/log.h>
#include "android_npapi.h"
#include "ANPBase.h"
#include "AndroidBridge.h"
#include <android/log.h>
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#endif
@ -2348,7 +2349,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
case kAudioTrackInterfaceV0_ANPGetValue: {
LOG("get audio interface");
ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result;
InitAudioTrackInterface(i);
InitAudioTrackInterfaceV0(i);
return NPERR_NO_ERROR;
}
@ -2363,7 +2364,6 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
LOG("get system interface");
ANPSystemInterfaceV0* i = reinterpret_cast<ANPSystemInterfaceV0*>(result);
InitSystemInterface(i);
LOG("done system interface");
return NPERR_NO_ERROR;
}
@ -2395,6 +2395,71 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
*i = reinterpret_cast<int32_t>(ret);
return NPERR_NO_ERROR;
}
case kAudioTrackInterfaceV1_ANPGetValue: {
LOG("get audio interface v1");
ANPAudioTrackInterfaceV1 *i = (ANPAudioTrackInterfaceV1 *) result;
InitAudioTrackInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kNativeWindowInterfaceV0_ANPGetValue: {
LOG("get native window interface v0");
ANPNativeWindowInterfaceV0* i = (ANPNativeWindowInterfaceV0 *) result;
InitNativeWindowInterface(i);
return NPERR_NO_ERROR;
}
case kOpenGLInterfaceV0_ANPGetValue: {
LOG("get openGL interface");
ANPOpenGLInterfaceV0 *i = (ANPOpenGLInterfaceV0*) result;
InitOpenGLInterface(i);
return NPERR_NO_ERROR;
}
case kWindowInterfaceV1_ANPGetValue: {
LOG("get Window interface V1");
ANPWindowInterfaceV1 *i = (ANPWindowInterfaceV1 *) result;
InitWindowInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kWindowInterfaceV2_ANPGetValue: {
LOG("get Window interface V2");
ANPWindowInterfaceV2 *i = (ANPWindowInterfaceV2 *) result;
InitWindowInterfaceV2(i);
return NPERR_NO_ERROR;
}
case kVideoInterfaceV0_ANPGetValue: {
LOG("get video interface");
ANPVideoInterfaceV0 *i = (ANPVideoInterfaceV0*) result;
InitVideoInterfaceV0(i);
return NPERR_NO_ERROR;
}
case kVideoInterfaceV1_ANPGetValue: {
LOG("get video interface");
ANPVideoInterfaceV1 *i = (ANPVideoInterfaceV1*) result;
InitVideoInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kSystemInterfaceV1_ANPGetValue: {
LOG("get system interface v1");
ANPSystemInterfaceV1* i = reinterpret_cast<ANPSystemInterfaceV1*>(result);
InitSystemInterfaceV1(i);
return NPERR_NO_ERROR;
}
case kSystemInterfaceV2_ANPGetValue: {
LOG("get system interface v2");
ANPSystemInterfaceV2* i = reinterpret_cast<ANPSystemInterfaceV2*>(result);
InitSystemInterfaceV2(i);
return NPERR_NO_ERROR;
}
#endif
// we no longer hand out any XPCOM objects

View File

@ -152,6 +152,8 @@ public:
#ifdef MOZ_WIDGET_ANDROID
PRUint32 GetANPDrawingModel() { return mANPDrawingModel; }
void SetANPDrawingModel(PRUint32 aModel);
// This stuff is for kSurface_ANPDrawingModel
void* GetJavaSurface();
void SetJavaSurface(void* aSurface);
void RequestJavaSurface();

View File

@ -120,6 +120,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#include "ANPBase.h"
#include "android_npapi.h"
#include "AndroidBridge.h"
#include "AndroidMediaLayer.h"
using namespace mozilla::dom;
#include <android/log.h>
@ -323,8 +324,9 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mWaitingForPaint = false;
#ifdef MOZ_WIDGET_ANDROID
mPluginViewAdded = false;
mLastPluginRect = gfxRect(0, 0, 0, 0);
mOnScreen = false;
mInverted = false;
mLayer = new AndroidMediaLayer();
#endif
}
@ -380,6 +382,13 @@ nsPluginInstanceOwner::~nsPluginInstanceOwner()
mPluginWindow = nsnull;
}
#ifdef MOZ_WIDGET_ANDROID
if (mLayer) {
delete mLayer;
mLayer = nsnull;
}
#endif
if (mInstance) {
mInstance->InvalidateOwner();
}
@ -1658,6 +1667,43 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY)
}
#ifdef MOZ_WIDGET_ANDROID
void nsPluginInstanceOwner::SendSize(int width, int height)
{
if (!mInstance)
return;
PRInt32 model = mInstance->GetANPDrawingModel();
if (model != kOpenGL_ANPDrawingModel)
return;
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kDraw_ANPEventType;
event.data.draw.model = kOpenGL_ANPDrawingModel;
event.data.draw.data.surfaceSize.width = width;
event.data.draw.data.surfaceSize.height = height;
mInstance->HandleEvent(&event, nsnull);
}
void nsPluginInstanceOwner::SendOnScreenEvent(bool onScreen)
{
if (!mInstance)
return;
if ((onScreen && !mOnScreen) || (!onScreen && mOnScreen)) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = onScreen ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
mOnScreen = onScreen;
}
}
bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
{
void* javaSurface = mInstance->GetJavaSurface();
@ -1666,11 +1712,6 @@ bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
return false;
}
if (aRect.IsEqualEdges(mLastPluginRect)) {
// Already added and in position, no work to do
return true;
}
JNIEnv* env = GetJNIForThread();
if (!env)
return false;
@ -1713,26 +1754,16 @@ bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
aRect.height);
#endif
if (!mPluginViewAdded) {
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
mPluginViewAdded = true;
}
SendOnScreenEvent(true);
return true;
}
void nsPluginInstanceOwner::RemovePluginView()
{
if (!mInstance || !mObjectFrame | !mPluginViewAdded)
if (!mInstance || !mObjectFrame | !mOnScreen)
return;
mPluginViewAdded = false;
void* surface = mInstance->GetJavaSurface();
if (!surface)
return;
@ -1748,13 +1779,17 @@ void nsPluginInstanceOwner::RemovePluginView()
"removePluginView",
"(Landroid/view/View;)V");
env->CallStaticVoidMethod(cls, method, surface);
ANPEvent event;
event.inSize = sizeof(ANPEvent);
event.eventType = kLifecycle_ANPEventType;
event.data.lifecycle.action = kOffScreen_ANPLifecycleAction;
mInstance->HandleEvent(&event, nsnull);
SendOnScreenEvent(false);
}
void nsPluginInstanceOwner::Invalidate() {
NPRect rect;
rect.left = rect.top = 0;
rect.right = mPluginWindow->width;
rect.bottom = mPluginWindow->height;
InvalidateRect(&rect);
}
#endif
nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
@ -2779,7 +2814,15 @@ nsPluginInstanceOwner::PrepareToStop(bool aDelayedStop)
#endif
#ifdef MOZ_WIDGET_ANDROID
RemovePluginView();
PRInt32 model = mInstance->GetANPDrawingModel();
if (model == kSurface_ANPDrawingModel) {
RemovePluginView();
} else if (model == kOpenGL_ANPDrawingModel && mLayer) {
delete mLayer;
mLayer = nsnull;
}
#endif
// Unregister scroll position listeners
@ -2891,15 +2934,21 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext,
if (model == kSurface_ANPDrawingModel) {
if (!AddPluginView(aFrameRect)) {
NPRect rect;
rect.left = rect.top = 0;
rect.right = aFrameRect.width;
rect.bottom = aFrameRect.height;
InvalidateRect(&rect);
Invalidate();
}
return;
}
if (model == kOpenGL_ANPDrawingModel) {
// FIXME: this is gross
float zoomLevel = aFrameRect.width / (float)mPluginWindow->width;
mLayer->UpdatePosition(aFrameRect, zoomLevel);
SendOnScreenEvent(true);
SendSize((int)aFrameRect.width, (int)aFrameRect.height);
return;
}
if (model != kBitmap_ANPDrawingModel)
return;
@ -3590,8 +3639,16 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(bool aSetWindow)
} else {
mPluginWindow->clipRect.right = 0;
mPluginWindow->clipRect.bottom = 0;
#ifdef MOZ_WIDGET_ANDROID
RemovePluginView();
#if 0 //MOZ_WIDGET_ANDROID
if (mInstance) {
PRInt32 model = mInstance->GetANPDrawingModel();
if (model == kSurface_ANPDrawingModel) {
RemovePluginView();
} else if (model == kOpenGL_ANPDrawingModel) {
HidePluginLayer();
}
}
#endif
}

View File

@ -94,6 +94,12 @@ class gfxXlibSurface;
#include <os2.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
namespace mozilla {
class AndroidMediaLayer;
}
#endif
// X.h defines KeyPress
#ifdef KeyPress
#undef KeyPress
@ -297,6 +303,26 @@ public:
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
bool UseAsyncRendering();
#ifdef ANDROID
nsIntRect GetVisibleRect() {
return nsIntRect(0, 0, mPluginWindow->width, mPluginWindow->height);
}
void SetInverted(bool aInverted) {
mInverted = aInverted;
}
bool Inverted() {
return mInverted;
}
mozilla::AndroidMediaLayer* Layer() {
return mLayer;
}
void Invalidate();
#endif
private:
@ -310,10 +336,17 @@ private:
void FixUpURLS(const nsString &name, nsAString &value);
#ifdef ANDROID
void SendSize(int width, int height);
void SendOnScreenEvent(bool onScreen);
bool AddPluginView(const gfxRect& aRect);
void RemovePluginView();
bool mPluginViewAdded;
gfxRect mLastPluginRect;
bool mOnScreen;
bool mInverted;
// For kOpenGL_ANPDrawingModel
mozilla::AndroidMediaLayer *mLayer;
#endif
nsPluginNativeWindow *mPluginWindow;

View File

@ -1695,7 +1695,6 @@ nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
// The matrix includes the frame's position, so we need to transform
// from 0,0 to get the correct coordinates.
frameGfxRect.MoveTo(0, 0);
matrix2d.NudgeToIntegers();
mInstanceOwner->Paint(ctx, matrix2d.Transform(frameGfxRect), dirtyGfxRect);
return;

View File

@ -44,10 +44,12 @@ import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.gfx.FloatSize;
import org.mozilla.gecko.gfx.GeckoSoftwareLayerClient;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.PlaceholderLayerClient;
import org.mozilla.gecko.gfx.RectUtils;
import org.mozilla.gecko.gfx.SurfaceTextureLayer;
import org.mozilla.gecko.gfx.ViewportMetrics;
import org.mozilla.gecko.Tab.HistoryEntry;
@ -217,8 +219,9 @@ abstract public class GeckoApp
public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
String[] getPluginDirectories() {
// we don't support Honeycomb and later
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
// we don't support Honeycomb
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH)
return new String[0];
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - start of getPluginDirectories");
@ -749,7 +752,7 @@ abstract public class GeckoApp
mLayerController.setWaitForTouchListeners(false);
if (tab != null)
hidePluginViews(tab);
hidePlugins(tab, true);
}
}
});
@ -1374,8 +1377,6 @@ abstract public class GeckoApp
mMainHandler.post(new Runnable() {
public void run() {
PluginLayoutParams lp;
JSONObject viewportObject;
ViewportMetrics pluginViewport;
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
@ -1384,9 +1385,10 @@ abstract public class GeckoApp
return;
ViewportMetrics targetViewport = mLayerController.getViewportMetrics();
ViewportMetrics pluginViewport;
try {
viewportObject = new JSONObject(metadata);
JSONObject viewportObject = new JSONObject(metadata);
pluginViewport = new ViewportMetrics(viewportObject);
} catch (JSONException e) {
Log.e(LOGTAG, "Bad viewport metadata: ", e);
@ -1441,28 +1443,128 @@ abstract public class GeckoApp
});
}
public void hidePluginViews() {
public Surface createSurface() {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return null;
SurfaceTextureLayer layer = SurfaceTextureLayer.create();
if (layer == null)
return null;
Surface surface = layer.getSurface();
tab.addPluginLayer(surface, layer);
return surface;
}
public void destroySurface(Surface surface) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
tab.removePluginLayer(surface);
}
public void showSurface(Surface surface, int x, int y,
int w, int h, boolean inverted, boolean blend,
String metadata) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
ViewportMetrics metrics;
try {
metrics = new ViewportMetrics(new JSONObject(metadata));
} catch (JSONException e) {
Log.e(LOGTAG, "Bad viewport metadata: ", e);
return;
}
PointF origin = metrics.getDisplayportOrigin();
x = x + (int)origin.x;
y = y + (int)origin.y;
LayerView layerView = mLayerController.getView();
SurfaceTextureLayer layer = (SurfaceTextureLayer)tab.getPluginLayer(surface);
if (layer == null)
return;
layer.update(new Point(x, y), new IntSize(w, h), metrics.getZoomFactor(), inverted, blend);
layerView.addLayer(layer);
// FIXME: shouldn't be necessary, layer will request
// one when it gets first frame
layerView.requestRender();
}
private void hidePluginLayer(Layer layer) {
LayerView layerView = mLayerController.getView();
layerView.removeLayer(layer);
layerView.requestRender();
}
private void showPluginLayer(Layer layer) {
LayerView layerView = mLayerController.getView();
layerView.addLayer(layer);
layerView.requestRender();
}
public void hideSurface(Surface surface) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
Layer layer = tab.getPluginLayer(surface);
if (layer == null)
return;
hidePluginLayer(layer);
}
public void requestRender() {
mLayerController.getView().requestRender();
}
public void hidePlugins(boolean hideLayers) {
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
if (tab == null)
return;
hidePluginViews(tab);
hidePlugins(tab, hideLayers);
}
public void hidePluginViews(Tab tab) {
public void hidePlugins(Tab tab, boolean hideLayers) {
for (View view : tab.getPluginViews()) {
view.setVisibility(View.GONE);
}
if (hideLayers) {
for (Layer layer : tab.getPluginLayers()) {
hidePluginLayer(layer);
}
requestRender();
}
}
public void showPluginViews() {
public void showPlugins() {
repositionPluginViews(true);
}
public void showPluginViews(Tab tab) {
public void showPlugins(Tab tab) {
repositionPluginViews(tab, true);
for (Layer layer : tab.getPluginLayers()) {
showPluginLayer(layer);
}
requestRender();
}
public void repositionPluginViews(boolean setVisible) {
@ -2619,8 +2721,10 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
}
public void reset(int aX, int aY, int aWidth, int aHeight, ViewportMetrics aViewport) {
x = mOriginalX = aX;
y = mOriginalY = aY;
PointF origin = aViewport.getDisplayportOrigin();
x = mOriginalX = aX + (int)origin.x;
y = mOriginalY = aY + (int)origin.y;
width = mOriginalWidth = aWidth;
height = mOriginalHeight = aHeight;
mOriginalViewport = aViewport;
@ -2651,4 +2755,8 @@ class PluginLayoutParams extends AbsoluteLayout.LayoutParams
reposition(offset, viewport.getZoomFactor());
}
public float getLastResolution() {
return mLastResolution;
}
}

View File

@ -226,6 +226,7 @@ public class GeckoAppShell
try {
sHandler = lt.mHandlerQueue.take();
} catch (InterruptedException ie) {}
}
return sHandler;
}
@ -567,7 +568,7 @@ public class GeckoAppShell
while (sGeckoPendingAcks.getCount() != 0) {
try {
sGeckoPendingAcks.await();
} catch (InterruptedException e) {}
} catch(InterruptedException e) {}
}
sGeckoPendingAcks = null;
}
@ -1391,10 +1392,40 @@ public class GeckoAppShell
}
public static void removePluginView(View view) {
Log.i(LOGTAG, "remove view:" + view);
Log.i(LOGTAG, "removePluginView:" + view);
GeckoApp.mAppContext.removePluginView(view);
}
public static Surface createSurface() {
Log.i(LOGTAG, "createSurface");
return GeckoApp.mAppContext.createSurface();
}
public static void showSurface(Surface surface,
int x, int y,
int w, int h,
boolean inverted,
boolean blend,
String metadata)
{
Log.i(LOGTAG, "showSurface:" + surface + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " inverted: " + inverted + " blend: " + blend + " metadata: " + metadata);
try {
GeckoApp.mAppContext.showSurface(surface, x, y, w, h, inverted, blend, metadata);
} catch (Exception e) {
Log.i(LOGTAG, "Error in showSurface:", e);
}
}
public static void hideSurface(Surface surface) {
Log.i(LOGTAG, "hideSurface:" + surface);
GeckoApp.mAppContext.hideSurface(surface);
}
public static void destroySurface(Surface surface) {
Log.i(LOGTAG, "destroySurface:" + surface);
GeckoApp.mAppContext.destroySurface(surface);
}
public static Class<?> loadPluginClass(String className, String libName) {
Log.i(LOGTAG, "in loadPluginClass... attempting to access className, then libName.....");
Log.i(LOGTAG, "className: " + className);

View File

@ -124,7 +124,9 @@ FENNEC_JAVA_FILES = \
gfx/RectUtils.java \
gfx/ScrollbarLayer.java \
gfx/SingleTileLayer.java \
gfx/SurfaceTextureLayer.java \
gfx/TextLayer.java \
gfx/TextureGenerator.java \
gfx/TextureReaper.java \
gfx/TileLayer.java \
gfx/ViewportMetrics.java \

View File

@ -44,13 +44,16 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.gfx.Layer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@ -83,6 +86,7 @@ public final class Tab {
private String mContentType;
private boolean mHasTouchListeners;
private ArrayList<View> mPluginViews;
private HashMap<Surface, Layer> mPluginLayers;
private boolean mHasLoaded;
public static final class HistoryEntry {
@ -117,6 +121,7 @@ public final class Tab {
mDocumentURI = "";
mContentType = "";
mPluginViews = new ArrayList<View>();
mPluginLayers = new HashMap<Surface, Layer>();
mHasLoaded = false;
}
@ -568,4 +573,20 @@ public final class Tab {
public View[] getPluginViews() {
return mPluginViews.toArray(new View[mPluginViews.size()]);
}
public void addPluginLayer(Surface surface, Layer layer) {
mPluginLayers.put(surface, layer);
}
public Layer getPluginLayer(Surface surface) {
return mPluginLayers.get(surface);
}
public Collection<Layer> getPluginLayers() {
return mPluginLayers.values();
}
public Layer removePluginLayer(Surface surface) {
return mPluginLayers.remove(surface);
}
}

View File

@ -136,7 +136,7 @@ public class Tabs implements GeckoEventListener {
GeckoApp.mBrowserToolbar.setShadowVisibility(!(tab.getURL().startsWith("about:")));
if (oldTab != null)
GeckoApp.mAppContext.hidePluginViews(oldTab);
GeckoApp.mAppContext.hidePlugins(oldTab, true);
}
}
});
@ -200,7 +200,7 @@ public class Tabs implements GeckoEventListener {
GeckoApp.mAppContext.onTabsChanged(closedTab);
GeckoApp.mBrowserToolbar.updateTabs(Tabs.getInstance().getCount());
GeckoApp.mDoorHangerPopup.updatePopup();
GeckoApp.mAppContext.hidePluginViews(closedTab);
GeckoApp.mAppContext.hidePlugins(closedTab, true);
}
});

View File

@ -49,12 +49,13 @@ import org.mozilla.gecko.FloatUtils;
public abstract class Layer {
private final ReentrantLock mTransactionLock;
private boolean mInTransaction;
private Point mOrigin;
private Point mNewOrigin;
private float mResolution;
private float mNewResolution;
private LayerView mView;
protected Point mOrigin;
protected float mResolution;
public Layer() {
mTransactionLock = new ReentrantLock();
mOrigin = new Point(0, 0);

View File

@ -46,6 +46,7 @@ import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.NinePatchTileLayer;
import org.mozilla.gecko.gfx.SingleTileLayer;
import org.mozilla.gecko.gfx.TextureReaper;
import org.mozilla.gecko.gfx.TextureGenerator;
import org.mozilla.gecko.gfx.TextLayer;
import org.mozilla.gecko.gfx.TileLayer;
import android.content.Context;
@ -62,6 +63,7 @@ import android.view.WindowManager;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import java.nio.IntBuffer;
import java.util.ArrayList;
/**
* The layer renderer implements the rendering logic for a layer view.
@ -90,6 +92,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private RenderContext mLastPageContext;
private int mMaxTextureSize;
private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>();
// Dropped frames display
private int[] mFrameTimings;
private int mCurrentFrame, mFrameTimingsSum, mDroppedFrames;
@ -152,12 +156,34 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
int maxTextureSizeResult[] = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSizeResult, 0);
mMaxTextureSize = maxTextureSizeResult[0];
TextureGenerator.get().fill();
}
public int getMaxTextureSize() {
return mMaxTextureSize;
}
public void addLayer(Layer layer) {
LayerController controller = mView.getController();
synchronized (controller) {
if (mExtraLayers.contains(layer)) {
mExtraLayers.remove(layer);
}
mExtraLayers.add(layer);
}
}
public void removeLayer(Layer layer) {
LayerController controller = mView.getController();
synchronized (controller) {
mExtraLayers.remove(layer);
}
}
/**
* Called whenever a new frame is about to be drawn.
*/
@ -165,6 +191,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
long frameStartTime = SystemClock.uptimeMillis();
TextureReaper.get().reap(gl);
TextureGenerator.get().fill();
LayerController controller = mView.getController();
RenderContext screenContext = createScreenContext();
@ -198,6 +225,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
updated &= mVertScrollLayer.update(gl, pageContext);
updated &= mHorizScrollLayer.update(gl, pageContext);
for (Layer layer : mExtraLayers)
updated &= layer.update(gl, pageContext);
/* Draw the background. */
mBackgroundLayer.draw(screenContext);
@ -222,6 +252,10 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
gl.glDisable(GL10.GL_SCISSOR_TEST);
/* Draw any extra layers that were added (likely plugins) */
for (Layer layer : mExtraLayers)
layer.draw(pageContext);
/* Draw the vertical scrollbar. */
IntSize screenSize = new IntSize(controller.getViewportSize());
if (pageRect.height() > screenSize.height)

View File

@ -224,6 +224,14 @@ public class LayerView extends GLSurfaceView
}
}
public void addLayer(Layer layer) {
mRenderer.addLayer(layer);
}
public void removeLayer(Layer layer) {
mRenderer.removeLayer(layer);
}
/**
* Returns the time elapsed between the first call of requestRender() after
* the last call of getRenderTime(), in nanoseconds.

View File

@ -0,0 +1,259 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009-2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoApp;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.opengl.GLES11;
import android.opengl.GLES11Ext;
import android.opengl.Matrix;
import android.util.Log;
import android.view.Surface;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11Ext;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.hardware.Camera;
public class SurfaceTextureLayer extends Layer implements SurfaceTexture.OnFrameAvailableListener {
private static final String LOGTAG = "SurfaceTextureLayer";
private static final int LOCAL_GL_TEXTURE_EXTERNAL_OES = 0x00008d65; // This is only defined in API level 15 for some reason (Android 4.0.3)
private final SurfaceTexture mSurfaceTexture;
private final Surface mSurface;
private int mTextureId;
private boolean mHaveFrame;
private IntSize mSize;
private IntSize mNewSize;
private boolean mInverted;
private boolean mNewInverted;
private boolean mBlend;
private boolean mNewBlend;
private FloatBuffer textureBuffer;
private FloatBuffer textureBufferInverted;
public SurfaceTextureLayer(int textureId) {
mTextureId = textureId;
mHaveFrame = true;
mInverted = false;
mSurfaceTexture = new SurfaceTexture(mTextureId);
mSurfaceTexture.setOnFrameAvailableListener(this);
mSurface = new Surface(mSurfaceTexture);
float textureMap[] = {
0.0f, 1.0f, // top left
0.0f, 0.0f, // bottom left
1.0f, 1.0f, // top right
1.0f, 0.0f, // bottom right
};
textureBuffer = createBuffer(textureMap);
float textureMapInverted[] = {
0.0f, 0.0f, // bottom left
0.0f, 1.0f, // top left
1.0f, 0.0f, // bottom right
1.0f, 1.0f, // top right
};
textureBufferInverted = createBuffer(textureMapInverted);
}
public static SurfaceTextureLayer create() {
int textureId = TextureGenerator.get().take();
if (textureId == 0)
return null;
return new SurfaceTextureLayer(textureId);
}
// For SurfaceTexture.OnFrameAvailableListener
public void onFrameAvailable(SurfaceTexture texture) {
// FIXME: for some reason this doesn't get called
mHaveFrame = true;
GeckoApp.mAppContext.requestRender();
}
private FloatBuffer createBuffer(float[] input) {
// a float has 4 bytes so we allocate for each coordinate 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(input.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
floatBuffer.put(input);
floatBuffer.position(0);
return floatBuffer;
}
public void update(Point origin, IntSize size, float resolution, boolean inverted, boolean blend) {
beginTransaction(null);
setOrigin(origin);
setResolution(resolution);
mNewSize = size;
mNewInverted = inverted;
mNewBlend = blend;
endTransaction();
}
@Override
public IntSize getSize() { return mSize; }
@Override
protected void finalize() throws Throwable {
if (mSurfaceTexture != null)
mSurfaceTexture.release();
if (mTextureId > 0)
TextureReaper.get().add(mTextureId);
}
@Override
protected boolean performUpdates(GL10 gl, RenderContext context) {
super.performUpdates(gl, context);
if (mNewSize != null) {
mSize = mNewSize;
mNewSize = null;
}
mInverted = mNewInverted;
mBlend = mNewBlend;
gl.glEnable(LOCAL_GL_TEXTURE_EXTERNAL_OES);
gl.glBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureId);
mSurfaceTexture.updateTexImage();
gl.glDisable(LOCAL_GL_TEXTURE_EXTERNAL_OES);
// FIXME: we should return true and rely on onFrameAvailable, but
// that isn't working for some reason
return false;
}
private float mapToGLCoords(float input, float viewport, boolean flip) {
if (flip) input = viewport - input;
return ((input / viewport) * 2.0f) - 1.0f;
}
@Override
public void draw(RenderContext context) {
// Enable GL_TEXTURE_EXTERNAL_OES and bind our texture
GLES11.glEnable(LOCAL_GL_TEXTURE_EXTERNAL_OES);
GLES11.glBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureId);
// Enable vertex and texture coordinate buffers
GLES11.glEnableClientState(GL10.GL_VERTEX_ARRAY);
GLES11.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Load whatever texture transform the SurfaceMatrix needs
float[] matrix = new float[16];
mSurfaceTexture.getTransformMatrix(matrix);
GLES11.glMatrixMode(GLES11.GL_TEXTURE);
GLES11.glLoadMatrixf(matrix, 0);
// Figure out vertices to put the texture in the right spot on the screen
IntSize size = getSize();
RectF bounds = getBounds(context, new FloatSize(size));
RectF viewport = context.viewport;
bounds.offset(-viewport.left, -viewport.top);
float vertices[] = new float[8];
// Bottom left
vertices[0] = mapToGLCoords(bounds.left, viewport.width(), false);
vertices[1] = mapToGLCoords(bounds.bottom, viewport.height(), true);
// Top left
vertices[2] = mapToGLCoords(bounds.left, viewport.width(), false);
vertices[3] = mapToGLCoords(bounds.top, viewport.height(), true);
// Bottom right
vertices[4] = mapToGLCoords(bounds.right, viewport.width(), false);
vertices[5] = mapToGLCoords(bounds.bottom, viewport.height(), true);
// Top right
vertices[6] = mapToGLCoords(bounds.right, viewport.width(), false);
vertices[7] = mapToGLCoords(bounds.top, viewport.height(), true);
// Set texture and vertex buffers
GLES11.glVertexPointer(2, GL10.GL_FLOAT, 0, createBuffer(vertices));
GLES11.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mInverted ? textureBufferInverted : textureBuffer);
if (mBlend) {
GLES11.glEnable(GL10.GL_BLEND);
GLES11.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
}
// Draw the vertices as triangle strip
GLES11.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 2);
// Clean up
GLES11.glDisableClientState(GL10.GL_VERTEX_ARRAY);
GLES11.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
GLES11.glDisable(LOCAL_GL_TEXTURE_EXTERNAL_OES);
GLES11.glLoadIdentity();
if (mBlend) {
GLES11.glDisable(GL10.GL_BLEND);
}
}
public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
public Surface getSurface() {
return mSurface;
}
}

View File

@ -0,0 +1,73 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009-2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko.gfx;
import android.opengl.GLES10;
import java.util.Stack;
public class TextureGenerator {
private static final int MIN_TEXTURES = 5;
private static TextureGenerator sSharedInstance;
private Stack<Integer> mTextureIds;
private TextureGenerator() { mTextureIds = new Stack<Integer>(); }
public static TextureGenerator get() {
if (sSharedInstance == null)
sSharedInstance = new TextureGenerator();
return sSharedInstance;
}
public synchronized int take() {
if (mTextureIds.empty())
return 0;
return (int)mTextureIds.pop();
}
public synchronized void fill() {
int[] textures = new int[1];
while (mTextureIds.size() < MIN_TEXTURES) {
GLES10.glGenTextures(1, textures, 0);
mTextureIds.push(textures[0]);
}
}
}

View File

@ -55,7 +55,11 @@ public class TextureReaper {
public void add(int[] textureIDs) {
for (int textureID : textureIDs)
mDeadTextureIDs.add(textureID);
add(textureID);
}
public void add(int textureID) {
mDeadTextureIDs.add(textureID);
}
public void reap(GL10 gl) {

View File

@ -293,6 +293,7 @@ public class PanZoomController
return false;
}
cancelTouch();
GeckoApp.mAppContext.hidePlugins(false /* don't hide layers */);
// fall through
case PANNING_HOLD_LOCKED:
GeckoApp.mAppContext.mAutoCompletePopup.hide();
@ -474,6 +475,8 @@ public class PanZoomController
stopAnimationTimer();
}
GeckoApp.mAppContext.hidePlugins(false /* don't hide layers */);
mAnimationTimer = new Timer("Animation Timer");
mAnimationRunnable = runnable;
mAnimationTimer.scheduleAtFixedRate(new TimerTask() {
@ -492,6 +495,8 @@ public class PanZoomController
mAnimationRunnable.terminate();
mAnimationRunnable = null;
}
GeckoApp.mAppContext.showPlugins();
}
private float getVelocity() {
@ -581,7 +586,6 @@ public class PanZoomController
finishBounce();
finishAnimation();
mState = PanZoomState.NOTHING;
GeckoApp.mAppContext.showPluginViews();
}
/* Performs one frame of a bounce animation. */
@ -661,6 +665,7 @@ public class PanZoomController
stopAnimationTimer();
// Force a viewport synchronisation
GeckoApp.mAppContext.showPlugins();
mController.setForceRedraw();
mController.notifyLayerClientOfGeometryChange();
}
@ -741,7 +746,7 @@ public class PanZoomController
mState = PanZoomState.PINCHING;
mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
GeckoApp.mAppContext.hidePluginViews();
GeckoApp.mAppContext.hidePlugins(false /* don't hide layers, only views */);
GeckoApp.mAppContext.mAutoCompletePopup.hide();
cancelTouch();
@ -806,9 +811,9 @@ public class PanZoomController
startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime());
// Force a viewport synchronisation
GeckoApp.mAppContext.showPlugins();
mController.setForceRedraw();
mController.notifyLayerClientOfGeometryChange();
GeckoApp.mAppContext.showPluginViews();
}
public boolean getRedrawHint() {
@ -862,7 +867,6 @@ public class PanZoomController
}
private boolean animatedZoomTo(RectF zoomToRect) {
GeckoApp.mAppContext.hidePluginViews();
GeckoApp.mAppContext.mAutoCompletePopup.hide();
mState = PanZoomState.ANIMATED_ZOOM;

View File

@ -56,6 +56,7 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/plugins/base/android \
-I$(topsrcdir)/gfx/skia/include/core \
-I$(topsrcdir)/gfx/skia/include/config \
-I$(topsrcdir)/gfx/gl \
$(NULL)

View File

@ -1709,9 +1709,9 @@ AndroidBridge::ReleaseNativeWindow(void *window)
}
bool
AndroidBridge::SetNativeWindowFormat(void *window, int format)
AndroidBridge::SetNativeWindowFormat(void *window, int width, int height, int format)
{
return ANativeWindow_setBuffersGeometry(window, 0, 0, format) == 0;
return ANativeWindow_setBuffersGeometry(window, width, height, format) == 0;
}
bool
@ -1857,3 +1857,85 @@ extern "C" {
return jEnv;
}
}
jobject
AndroidBridge::CreateSurface()
{
#ifndef MOZ_JAVA_COMPOSITOR
return NULL;
#else
AutoLocalJNIFrame frame(1);
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"createSurface",
"()Landroid/view/Surface;");
jobject surface = env->CallStaticObjectMethod(cls, method);
if (surface)
env->NewGlobalRef(surface);
return surface;
#endif
}
void
AndroidBridge::DestroySurface(jobject surface)
{
#ifdef MOZ_JAVA_COMPOSITOR
AutoLocalJNIFrame frame(1);
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"destroySurface",
"(Landroid/view/Surface;)V");
env->CallStaticVoidMethod(cls, method, surface);
env->DeleteGlobalRef(surface);
#endif
}
void
AndroidBridge::ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend)
{
#ifdef MOZ_JAVA_COMPOSITOR
AutoLocalJNIFrame frame;
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
nsAutoString metadata;
nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider = GetDrawMetadataProvider();
metadataProvider->GetDrawMetadata(metadata);
jstring jMetadata = env->NewString(nsPromiseFlatString(metadata).get(), metadata.Length());
jmethodID method = env->GetStaticMethodID(cls,
"showSurface",
"(Landroid/view/Surface;IIIIZZLjava/lang/String;)V");
env->CallStaticVoidMethod(cls, method, surface,
(int)aRect.x, (int)aRect.y,
(int)aRect.width, (int)aRect.height,
aInverted, aBlend, jMetadata);
#endif
}
void
AndroidBridge::HideSurface(jobject surface)
{
#ifdef MOZ_JAVA_COMPOSITOR
AutoLocalJNIFrame frame(1);
JNIEnv* env = GetJNIForThread();
jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
jmethodID method = env->GetStaticMethodID(cls,
"hideSurface",
"(Landroid/view/Surface;)V");
env->CallStaticVoidMethod(cls, method, surface);
#endif
}

View File

@ -54,6 +54,7 @@
#include "nsIMutableArray.h"
#include "nsIMIMEInfo.h"
#include "nsColor.h"
#include "gfxRect.h"
#include "nsIAndroidBridge.h"
@ -341,7 +342,7 @@ public:
void *AcquireNativeWindow(jobject surface);
void ReleaseNativeWindow(void *window);
bool SetNativeWindowFormat(void *window, int format);
bool SetNativeWindowFormat(void *window, int width, int height, int format);
bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride);
bool UnlockWindow(void *window);
@ -378,6 +379,11 @@ public:
void EnableNetworkNotifications();
void DisableNetworkNotifications();
jobject CreateSurface();
void DestroySurface(jobject surface);
void ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend);
void HideSurface(jobject surface);
protected:
static AndroidBridge *sBridge;

View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <android/log.h>
#include "AndroidMediaLayer.h"
#include "AndroidBridge.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AndroidMediaLayer" , ## args)
namespace mozilla {
AndroidMediaLayer::AndroidMediaLayer()
: mInverted(false) {
}
AndroidMediaLayer::~AndroidMediaLayer() {
if (mContentData.window) {
AndroidBridge::Bridge()->ReleaseNativeWindow(mContentData.window);
mContentData.window = NULL;
}
if (mContentData.surface) {
AndroidBridge::Bridge()->DestroySurface(mContentData.surface);
mContentData.surface = NULL;
}
std::map<void*, SurfaceData*>::iterator it;
for (it = mVideoSurfaces.begin(); it != mVideoSurfaces.end(); it++) {
SurfaceData* data = it->second;
AndroidBridge::Bridge()->ReleaseNativeWindow(data->window);
AndroidBridge::Bridge()->DestroySurface(data->surface);
delete data;
}
mVideoSurfaces.clear();
}
bool AndroidMediaLayer::EnsureContentSurface() {
if (!mContentData.surface) {
mContentData.surface = AndroidBridge::Bridge()->CreateSurface();
if (mContentData.surface) {
mContentData.window = AndroidBridge::Bridge()->AcquireNativeWindow(mContentData.surface);
AndroidBridge::Bridge()->SetNativeWindowFormat(mContentData.window, 0, 0, AndroidBridge::WINDOW_FORMAT_RGBA_8888);
}
}
return mContentData.surface && mContentData.window;
}
void* AndroidMediaLayer::GetNativeWindowForContent() {
if (!EnsureContentSurface())
return NULL;
return mContentData.window;
}
void* AndroidMediaLayer::RequestNativeWindowForVideo() {
jobject surface = AndroidBridge::Bridge()->CreateSurface();
if (surface) {
void* window = AndroidBridge::Bridge()->AcquireNativeWindow(surface);
if (window) {
AndroidBridge::Bridge()->SetNativeWindowFormat(window, 0, 0, AndroidBridge::WINDOW_FORMAT_RGBA_8888);
mVideoSurfaces[window] = new SurfaceData(surface, window);
return window;
} else {
LOG("Failed to create native window from surface");
// Cleanup
AndroidBridge::Bridge()->DestroySurface(surface);
}
}
return NULL;
}
void AndroidMediaLayer::ReleaseNativeWindowForVideo(void* aWindow) {
if (mVideoSurfaces.find(aWindow) == mVideoSurfaces.end())
return;
SurfaceData* data = mVideoSurfaces[aWindow];
AndroidBridge::Bridge()->ReleaseNativeWindow(data->window);
AndroidBridge::Bridge()->DestroySurface(data->surface);
mVideoSurfaces.erase(aWindow);
delete data;
}
void AndroidMediaLayer::SetNativeWindowDimensions(void* aWindow, const gfxRect& aDimensions) {
if (mVideoSurfaces.find(aWindow) == mVideoSurfaces.end())
return;
SurfaceData* data = mVideoSurfaces[aWindow];
data->dimensions = aDimensions;
}
void AndroidMediaLayer::UpdatePosition(const gfxRect& aRect, float aZoomLevel) {
std::map<void*, SurfaceData*>::iterator it;
if (EnsureContentSurface())
AndroidBridge::Bridge()->ShowSurface(mContentData.surface, aRect, mInverted, true);
for (it = mVideoSurfaces.begin(); it != mVideoSurfaces.end(); it++) {
SurfaceData* data = it->second;
// The video window dimension we get is not adjusted by zoom factor (unlike the
// content window). Fix it up here.
gfxRect scaledDimensions = data->dimensions;
scaledDimensions.Scale(aZoomLevel);
gfxRect videoRect(aRect.x + scaledDimensions.x, aRect.y + scaledDimensions.y,
scaledDimensions.width, scaledDimensions.height);
AndroidBridge::Bridge()->ShowSurface(data->surface, videoRect, mInverted, false);
}
}
} /* mozilla */

View File

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef AndroidMediaLayer_h_
#define AndroidMediaLayer_h_
#include <map>
#include <jni.h>
#include "gfxRect.h"
namespace mozilla {
class AndroidMediaLayer
{
public:
AndroidMediaLayer();
virtual ~AndroidMediaLayer();
void* GetNativeWindowForContent();
void* RequestNativeWindowForVideo();
void ReleaseNativeWindowForVideo(void* aWindow);
void SetNativeWindowDimensions(void* aWindow, const gfxRect& aDimensions);
void UpdatePosition(const gfxRect& aRect, float aZoomLevel);
bool Inverted() {
return mInverted;
}
void SetInverted(bool aInverted) {
mInverted = aInverted;
}
private:
bool mInverted;
class SurfaceData {
public:
SurfaceData() :
surface(NULL), window(NULL) {
}
SurfaceData(jobject aSurface, void* aWindow) :
surface(aSurface), window(aWindow) {
}
jobject surface;
void* window;
gfxRect dimensions;
};
bool EnsureContentSurface();
SurfaceData mContentData;
std::map<void*, SurfaceData*> mVideoSurfaces;
};
} /* mozilla */
#endif /* AndroidMediaLayer_h_ */

View File

@ -68,6 +68,7 @@ CPPSRCS = \
AndroidDirectTexture.cpp \
AndroidGraphicBuffer.cpp \
AndroidJNI.cpp \
AndroidMediaLayer.cpp \
nsWindow.cpp \
nsLookAndFeel.cpp \
nsScreenManagerAndroid.cpp \

View File

@ -1019,7 +1019,7 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
if (surface) {
sNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindow(surface);
if (sNativeWindow) {
AndroidBridge::Bridge()->SetNativeWindowFormat(sNativeWindow, AndroidBridge::WINDOW_FORMAT_RGB_565);
AndroidBridge::Bridge()->SetNativeWindowFormat(sNativeWindow, 0, 0, AndroidBridge::WINDOW_FORMAT_RGB_565);
}
}
}