diff options
Diffstat (limited to 'WebKit/android/plugins/PluginSurface.cpp')
-rw-r--r-- | WebKit/android/plugins/PluginSurface.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
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 |