diff options
Diffstat (limited to 'WebKit/android/plugins')
-rw-r--r-- | WebKit/android/plugins/ANPSurfaceInterface.cpp | 44 | ||||
-rw-r--r-- | WebKit/android/plugins/PluginSurface.cpp | 185 | ||||
-rw-r--r-- | WebKit/android/plugins/PluginSurface.h | 75 | ||||
-rw-r--r-- | WebKit/android/plugins/PluginWidgetAndroid.cpp | 28 | ||||
-rw-r--r-- | WebKit/android/plugins/PluginWidgetAndroid.h | 13 | ||||
-rw-r--r-- | WebKit/android/plugins/SurfaceCallback.h | 42 | ||||
-rw-r--r-- | WebKit/android/plugins/android_npapi.h | 45 |
7 files changed, 420 insertions, 12 deletions
diff --git a/WebKit/android/plugins/ANPSurfaceInterface.cpp b/WebKit/android/plugins/ANPSurfaceInterface.cpp index a64af1e..835f45a 100644 --- a/WebKit/android/plugins/ANPSurfaceInterface.cpp +++ b/WebKit/android/plugins/ANPSurfaceInterface.cpp @@ -25,23 +25,61 @@ // must include config.h first for webkit to fiddle with new/delete #include "config.h" + +#include "PluginSurface.h" +#include "PluginView.h" +#include "PluginWidgetAndroid.h" #include "SkANP.h" -static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType) { +using namespace WebCore; + +static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType type) { + if (instance && instance->ndata) { + PluginView* view = static_cast<PluginView*>(instance->ndata); + PluginWidgetAndroid* widget = view->platformPluginWidget(); + return widget->createSurface(type); + } return NULL; } static void anp_deleteSurface(ANPSurface* surface) { - + if (surface) { + if (surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->destroy(); + } + delete surface; + } } static bool anp_lock(ANPSurface* surface, ANPBitmap* bitmap, ANPRectI* dirtyRect) { + if (bitmap && surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + SkBitmap src; + bool res = false; + if (dirtyRect) { + SkIRect rect; + res = s->lock(SkANP::SetRect(&rect, *dirtyRect), &src); + } else { + res = s->lock(NULL, &src); + } + if (res) { + res &= SkANP::SetBitmap(bitmap, src); + } + return res; + } return false; } static void anp_unlock(ANPSurface* surface) { - + if (surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->unlock(); + } } /////////////////////////////////////////////////////////////////////////////// diff --git a/WebKit/android/plugins/PluginSurface.cpp b/WebKit/android/plugins/PluginSurface.cpp new file mode 100644 index 0000000..e57ecbc --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.cpp @@ -0,0 +1,185 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PluginSurface.h" + +#include "android_graphics.h" +#include "PluginWidgetAndroid.h" +#include "WebViewCore.h" +#include "jni_utility.h" + +#include <ui/Rect.h> +#include <ui/Region.h> +#include <ui/Surface.h> + +namespace android { + +// jni field offset for the native surface pointer. +static jfieldID gSurfaceField; +static jmethodID gGetHolder; +static jmethodID gGetSurface; + +static void initFields(JNIEnv* env) { + if (gSurfaceField) + return; + + jclass clazz = env->FindClass("android/view/Surface"); + gSurfaceField = env->GetFieldID(clazz, "mSurface", "I"); + + clazz = env->FindClass("android/view/SurfaceView"); + gGetHolder = env->GetMethodID(clazz, "getHolder", "()Landroid/view/SurfaceHolder;"); + + clazz = env->FindClass("android/view/SurfaceHolder"); + gGetSurface = env->GetMethodID(clazz, "getSurface", "()Landroid/view/Surface;"); +} + +static inline sp<Surface> getSurface(jobject view) { + if (!view) { + return NULL; + } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + initFields(env); + jobject holder = env->CallObjectMethod(view, gGetHolder); + jobject surface = env->CallObjectMethod(holder, gGetSurface); + return sp<Surface>((Surface*) env->GetIntField(surface, gSurfaceField)); +} + +static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { + switch (format) { + case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; + case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; + default: return SkBitmap::kNo_Config; + } +} + +PluginSurface::PluginSurface(PluginWidgetAndroid* widget) + : m_jSurfaceView(0) + , m_widget(widget) { + // Create our java SurfaceView. + jobject obj = widget->webViewCore()->createSurface(this); + if (obj) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_jSurfaceView = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } +} + +void PluginSurface::attach(int x, int y, int width, int height) { + if (m_jSurfaceView) { + m_widget->webViewCore()->attachSurface(m_jSurfaceView, x, y, width, + height); + } +} + +void PluginSurface::destroy() { + m_surface.clear(); + if (m_jSurfaceView) { + m_widget->webViewCore()->destroySurface(m_jSurfaceView); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteGlobalRef(m_jSurfaceView); + m_jSurfaceView = 0; + } +} + +bool PluginSurface::lock(SkIRect* dirty, SkBitmap* bitmap) { + if (!bitmap || !Surface::isValid(m_surface)) { + return false; + } + + Region dirtyRegion; + if (dirty) { + Rect rect(dirty->fLeft, dirty->fTop, dirty->fRight, dirty->fBottom); + if (!rect.isEmpty()) { + dirtyRegion.set(rect); + } + } else { + dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); + } + + Surface::SurfaceInfo info; + status_t err = m_surface->lock(&info, &dirtyRegion); + if (err < 0) { + return false; + } + + ssize_t bpr = info.s * bytesPerPixel(info.format); + bitmap->setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); + if (info.w > 0 && info.h > 0) { + bitmap->setPixels(info.bits); + } else { + bitmap->setPixels(NULL); + } + + return true; +} + +void PluginSurface::unlock() { + if (!Surface::isValid(m_surface)) { + return; + } + + m_surface->unlockAndPost(); +} + +static void sendSurfaceEvent(PluginWidgetAndroid* widget, + ANPSurfaceAction action, int format = 0, int width = 0, + int height = 0) { + ANPEvent event; + SkANP::InitEvent(&event, kSurface_ANPEventType); + + event.data.surface.action = action; + if (action == kChanged_ANPSurfaceAction) { + event.data.surface.data.changed.format = format; + event.data.surface.data.changed.width = width; + event.data.surface.data.changed.height = height; + } + + widget->sendEvent(event); +} + +// SurfaceCallback methods +void PluginSurface::surfaceCreated() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kCreated_ANPSurfaceAction); +} + +void PluginSurface::surfaceChanged(int format, int width, int height) { + m_surface = getSurface(m_jSurfaceView); + sendSurfaceEvent(m_widget, kChanged_ANPSurfaceAction, format, width, + height); +} + +void PluginSurface::surfaceDestroyed() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kDestroyed_ANPSurfaceAction); +} + +} // namespace android diff --git a/WebKit/android/plugins/PluginSurface.h b/WebKit/android/plugins/PluginSurface.h new file mode 100644 index 0000000..b8cbac9 --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.h @@ -0,0 +1,75 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PluginSurface_H +#define PluginSurface_H + +#include "android_npapi.h" +#include "SkANP.h" +#include "SurfaceCallback.h" + +#include <jni.h> +#include <ui/Surface.h> +#include <utils/RefBase.h> + +struct PluginWidgetAndroid; +class SkBitmap; +struct SkIRect; + +struct ANPSurface { + void* data; + ANPSurfaceType type; +}; + +namespace android { + +class Surface; + +class PluginSurface : public SurfaceCallback { +public: + PluginSurface(PluginWidgetAndroid* widget); + virtual ~PluginSurface() { + destroy(); + } + + void attach(int x, int y, int width, int height); + void destroy(); + bool lock(SkIRect* dirty, SkBitmap* bitmap); + void unlock(); + + virtual void surfaceCreated(); + virtual void surfaceChanged(int format, int width, int height); + virtual void surfaceDestroyed(); + +private: + jobject m_jSurfaceView; + sp<Surface> m_surface; + PluginWidgetAndroid* m_widget; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp index 7566d63..bf9b1bf 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.cpp +++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp @@ -29,6 +29,7 @@ #include "Element.h" #include "Frame.h" #include "PluginPackage.h" +#include "PluginSurface.h" #include "PluginView.h" #include "PluginWidgetAndroid.h" #include "SkANP.h" @@ -65,9 +66,16 @@ void PluginWidgetAndroid::setWindow(int x, int y, int width, int height, bool isTransparent) { m_x = x; m_y = y; - m_flipPixelRef->safeUnref(); - m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), - width, height); + + if (m_drawingModel == kSurface_ANPDrawingModel) { + if (m_surface) { + m_surface->attach(x, y, width, height); + } + } else { + m_flipPixelRef->safeUnref(); + m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), + width, height); + } } bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { @@ -98,7 +106,8 @@ bool PluginWidgetAndroid::isDirty(SkIRect* rect) const { void PluginWidgetAndroid::inval(const WebCore::IntRect& rect, bool signalRedraw) { - // nothing to do if we haven't had setWindow() called yet + // nothing to do if we haven't had setWindow() called yet. m_flipPixelRef + // will also be null if this is a Surface model. if (NULL == m_flipPixelRef) { return; } @@ -182,3 +191,14 @@ void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) { bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) { return m_eventFlags & flag; } + +ANPSurface* PluginWidgetAndroid::createSurface(ANPSurfaceType ignored) { + if (m_drawingModel != kSurface_ANPDrawingModel) { + return NULL; + } + m_surface.set(new android::PluginSurface(this)); + ANPSurface* surface = new ANPSurface; + surface->data = m_surface.get(); + surface->type = ignored; + return surface; +} diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h index c8d1ffe..84ac729 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.h +++ b/WebKit/android/plugins/PluginWidgetAndroid.h @@ -28,11 +28,14 @@ #include "android_npapi.h" +#include <wtf/OwnPtr.h> + namespace WebCore { class PluginView; } namespace android { + class PluginSurface; class WebViewCore; } @@ -52,6 +55,9 @@ struct PluginWidgetAndroid { WebCore::PluginView* pluginView() const { return m_pluginView; } + // Needed by PluginSurface to manage the java SurfaceView. + android::WebViewCore* webViewCore() const { return m_core; } + /* Can't determine our core at construction time, so PluginView calls this as soon as it has a parent. */ @@ -101,6 +107,12 @@ struct PluginWidgetAndroid { */ bool isAcceptingEvent(ANPEventFlag); + /* Create an ANPSurface that the plugin may draw in to. The drawing model + must be kSurface_ANPDrawingModel for this call to succeed. The type + specifies what kind of pixel access will be available. + */ + ANPSurface* createSurface(ANPSurfaceType type); + private: WebCore::PluginView* m_pluginView; android::WebViewCore* m_core; @@ -109,6 +121,7 @@ private: ANPEventFlags m_eventFlags; int m_x; int m_y; + OwnPtr<android::PluginSurface> m_surface; }; #endif diff --git a/WebKit/android/plugins/SurfaceCallback.h b/WebKit/android/plugins/SurfaceCallback.h new file mode 100644 index 0000000..fb2e015 --- /dev/null +++ b/WebKit/android/plugins/SurfaceCallback.h @@ -0,0 +1,42 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceCallback_H +#define SurfaceCallback_H + +namespace android { + + class SurfaceCallback { + public: + virtual ~SurfaceCallback() {} + virtual void surfaceCreated() = 0; + virtual void surfaceChanged(int format, int width, int height) = 0; + virtual void surfaceDestroyed() = 0; + }; + +} // namespace android + +#endif diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h index 41c1080..2d86b9c 100644 --- a/WebKit/android/plugins/android_npapi.h +++ b/WebKit/android/plugins/android_npapi.h @@ -200,11 +200,6 @@ struct ANPBitmapInterfaceV0 : ANPInterface { bool (*getPixelPacking)(ANPBitmapFormat, ANPPixelPacking* packing); }; -/** The ANPSurface acts as a handle between the plugin and the native libraries - that render the surface to the screen. - */ -struct ANPSurface; - /** The surfaceType is the mechanism by which the plugin informs the native libraries which type of surface view it wishes to use. */ @@ -213,6 +208,11 @@ enum ANPSurfaceTypes { }; typedef int32_t ANPSurfaceType; +/** The ANPSurface acts as a handle between the plugin and the native libraries + that render the surface to the screen. + */ +struct ANPSurface; + struct ANPSurfaceInterfaceV0 : ANPInterface { /** Creates a new surface handle based on the given surface type. If the given surface type is not supported then NULL is returned. @@ -717,6 +717,7 @@ enum ANPEventTypes { kDraw_ANPEventType = 4, kLifecycle_ANPEventType = 5, kVisibleRect_ANPEventType = 6, + kSurface_ANPEventType = 7, }; typedef int32_t ANPEventType; @@ -759,6 +760,23 @@ enum ANPLifecycleActions { }; typedef uint32_t ANPLifecycleAction; +enum ANPSurfaceActions { + /** The surface has been created and is ready to be used. Any calls to + lock/unlock before this action will fail. + */ + kCreated_ANPSurfaceAction = 0, + /** The surface has changed format or dimensions. + */ + kChanged_ANPSurfaceAction = 1, + /** The surface has been destroyed. This happens when the view system has + remove the surface (possibly due to the plugin being offscreen). Calls + to lock/unlock will fail after this action and before + kCreate_ANPSurfaceAction. + */ + kDestroyed_ANPSurfaceAction = 2, +}; +typedef uint32_t ANPSurfaceAction; + /* This is what is passed to NPP_HandleEvent() */ struct ANPEvent { uint32_t inSize; // size of this struct in bytes @@ -800,6 +818,23 @@ struct ANPEvent { ANPRectI rect; // in global document coordinates float zoomScale; // 1.0 means no zoom scale } visibleRect; + struct { + ANPSurfaceAction action; + /** This union is based on the value of action and contains data + specific to the given action. + */ + union { + /** This struct is filled in only during the + kChanged_ANPSurfaceAction action. For all other actions, + this struct is undefined. + */ + struct { + int32_t format; + int32_t width; + int32_t height; + } changed; + } data; + } surface; int32_t other[8]; } data; }; |