summaryrefslogtreecommitdiffstats
path: root/WebKit/android/plugins/PluginSurface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/plugins/PluginSurface.cpp')
-rw-r--r--WebKit/android/plugins/PluginSurface.cpp185
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