updated Animation Plugin for NativeWindow interface
bug:5114637
Uses new ANativeWindow plugin API, supports either software rendering or GL
rendering via flag in RenderingThread.h
Note: Currently crashes on close
Change-Id: Ia7338a6c38c0ca9db02c19814d99b29970cc7b8e
diff --git a/samples/BrowserPlugin/jni/Android.mk b/samples/BrowserPlugin/jni/Android.mk
index 641ac63..7636de9 100644
--- a/samples/BrowserPlugin/jni/Android.mk
+++ b/samples/BrowserPlugin/jni/Android.mk
@@ -61,6 +61,7 @@
LOCAL_SHARED_LIBRARIES := \
libnativehelper \
+ libandroid \
libutils \
libcutils \
libEGL \
diff --git a/samples/BrowserPlugin/jni/RenderingThread.cpp b/samples/BrowserPlugin/jni/RenderingThread.cpp
index 7f267ed..91ffb4a 100644
--- a/samples/BrowserPlugin/jni/RenderingThread.cpp
+++ b/samples/BrowserPlugin/jni/RenderingThread.cpp
@@ -24,30 +24,55 @@
*/
#include "RenderingThread.h"
-#include "ANPOpenGL_npapi.h"
+#include "ANPNativeWindow_npapi.h"
-extern ANPLogInterfaceV0 gLogI;
-extern ANPOpenGLInterfaceV0 gOpenGLI;
+extern ANPLogInterfaceV0 gLogI;
+extern ANPNativeWindowInterfaceV0 gNativeWindowI;
RenderingThread::RenderingThread(NPP npp) : android::Thread() {
m_npp = npp;
m_width = -1;
m_height = -1;
- gLogI.log(kError_ANPLogType, "Created Rendering Thread");
+
+ m_ANW = NULL;
+#if (!USE_SOFTWARE_RENDERING)
+ m_eglSurface = EGL_NO_SURFACE;
+ m_eglContext = EGL_NO_CONTEXT;
+ m_eglDisplay = EGL_NO_DISPLAY;
+#endif
}
android::status_t RenderingThread::readyToRun() {
-
- gLogI.log(kError_ANPLogType, "in ready to run");
-
- EGLContext context = gOpenGLI.acquireContext(m_npp);
-
- gLogI.log(kError_ANPLogType, "context: %p", context);
-
- if (context == EGL_NO_CONTEXT) {
- gLogI.log(kError_ANPLogType, "Unable to create EGLContext for a TextureProducer thread");
- return android::UNKNOWN_ERROR;
+ while (m_ANW == NULL) {
+ m_ANW = gNativeWindowI.acquireNativeWindow(m_npp);
}
+
+#if (!USE_SOFTWARE_RENDERING)
+ m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ //initialize context
+ EGLint numConfigs;
+ static const EGLint configAttribs[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE
+ };
+
+ eglChooseConfig(m_eglDisplay, configAttribs, &m_eglConfig, 1, &numConfigs);
+ checkGlError("eglChooseConfig");
+
+ static const EGLint contextAttribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, NULL, contextAttribs);
+ checkGlError("eglCreateContext");
+#endif
+
return android::NO_ERROR;
}
@@ -109,34 +134,70 @@
}
}
-void RenderingThread::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glBindTexture(GL_TEXTURE_2D, texture);
- checkGlError("glBindTexture");
- SkBitmap::Config config = bitmap.getConfig();
- int internalformat = getInternalFormat(config);
- int type = getType(config);
- bitmap.lockPixels();
- glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(),
- 0, internalformat, type, bitmap.getPixels());
- bitmap.unlockPixels();
- checkGlError("glTexImage2D");
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+void RenderingThread::setupNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap)
+{
+ int result = ANativeWindow_setBuffersGeometry(ANW, bitmap.width(),
+ bitmap.height(), WINDOW_FORMAT_RGBA_8888);
+
+ if (android::NO_ERROR != result) {
+ gLogI.log(kError_ANPLogType, "ERROR setBuffersGeometry() status is (%d)", result);
+ }
+
+#if (!USE_SOFTWARE_RENDERING)
+ if (m_eglSurface != EGL_NO_SURFACE) {
+ gLogI.log(kDebug_ANPLogType, "destroying old surface");
+ eglDestroySurface(m_eglDisplay, m_eglSurface);
+ }
+
+ m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, ANW, NULL);
+ checkGlError("eglCreateWindowSurface");
+
+ eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
+
+ //optional: enable async mode
+ //eglSwapInterval(m_eglDisplay, 0);
+#endif
+
+ updateNativeWindow(ANW, bitmap);
}
-void RenderingThread::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glBindTexture(GL_TEXTURE_2D, texture);
- checkGlError("glBindTexture");
- SkBitmap::Config config = bitmap.getConfig();
- int internalformat = getInternalFormat(config);
- int type = getType(config);
+void RenderingThread::updateNativeWindow(ANativeWindow* ANW,
+ const SkBitmap& bitmap)
+{
+#if USE_SOFTWARE_RENDERING
+
+ //STEP 1: lock the ANW, getting a buffer
+ ANativeWindow_Buffer buffer;
+ if (ANativeWindow_lock(ANW, &buffer, NULL) < 0 ) // todo: use rect parameter for efficiency
+ return;
+
+ //STEP 2: draw into the buffer
+ uint8_t* img = (uint8_t*)buffer.bits;
+ int row, col;
+ int bpp = 4; // Here we only deal with RGBA8888 format.
bitmap.lockPixels();
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
- internalformat, type, bitmap.getPixels());
+ uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
+ // Copy line by line to handle offsets and stride
+ for (row = 0 ; row < bitmap.height(); row ++) {
+ uint8_t* dst = &(img[(buffer.stride * (row + 0) + 0) * bpp]);
+ uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
+ memcpy(dst, src, bpp * bitmap.width());
+ }
bitmap.unlockPixels();
- checkGlError("glTexSubImage2D");
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ //STEP 3: push the buffer to the queue
+ ANativeWindow_unlockAndPost(ANW);
+
+#else
+
+ //rotate the intensity of the green channel, other channels fixed
+ static int i = 0;
+ i = (i >= 245) ? 0 : i+10;
+
+ glClearColor(0.6, (i*1.0/256), 0.6, 0.6);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ eglSwapBuffers(m_eglDisplay, m_eglSurface);
+#endif
}
+
diff --git a/samples/BrowserPlugin/jni/RenderingThread.h b/samples/BrowserPlugin/jni/RenderingThread.h
index 41f0ce8..cb4fb96 100644
--- a/samples/BrowserPlugin/jni/RenderingThread.h
+++ b/samples/BrowserPlugin/jni/RenderingThread.h
@@ -32,6 +32,8 @@
#ifndef RenderingThread__DEFINED
#define RenderingThread__DEFINED
+#define USE_SOFTWARE_RENDERING false
+#define MS_PER_FRAME 17 // approx 60 fps
class RenderingThread : public android::Thread {
public:
@@ -44,13 +46,14 @@
protected:
NPP m_npp;
+ ANativeWindow* m_ANW;
static void printGLString(const char *name, GLenum s);
static void checkGlError(const char* op);
static GLenum getInternalFormat(SkBitmap::Config config);
static GLenum getType(SkBitmap::Config config);
- static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap);
- static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap);
+ void setupNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap);
+ void updateNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap);
private:
virtual bool threadLoop() = 0;
@@ -58,6 +61,13 @@
android::Mutex m_sync;
int m_width;
int m_height;
+
+#if (!USE_SOFTWARE_RENDERING)
+ EGLDisplay m_eglDisplay;
+ EGLSurface m_eglSurface;
+ EGLContext m_eglContext;
+ EGLConfig m_eglConfig;
+#endif
};
diff --git a/samples/BrowserPlugin/jni/animation/AnimationThread.cpp b/samples/BrowserPlugin/jni/animation/AnimationThread.cpp
index 9e6342d..1388fe3 100644
--- a/samples/BrowserPlugin/jni/animation/AnimationThread.cpp
+++ b/samples/BrowserPlugin/jni/animation/AnimationThread.cpp
@@ -23,14 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "AnimationThread.h"
-#include "ANPOpenGL_npapi.h"
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
#include <utils/SystemClock.h>
+#include "ANPNativeWindow_npapi.h"
-extern ANPLogInterfaceV0 gLogI;
-extern ANPOpenGLInterfaceV0 gOpenGLI;
+extern ANPLogInterfaceV0 gLogI;
+extern ANPNativeWindowInterfaceV0 gNativeWindowI;
AnimationThread::AnimationThread(NPP npp) : RenderingThread(npp) {
m_counter = 0;
@@ -52,6 +50,8 @@
m_startExecutionTime = 0;
m_startTime = android::uptimeMillis();
+ m_stallTime = android::uptimeMillis();
+
}
AnimationThread::~AnimationThread() {
@@ -84,15 +84,14 @@
}
bool AnimationThread::threadLoop() {
-
- m_startIdleTime = android::uptimeMillis();
-
- ANPTextureInfo textureInfo = gOpenGLI.lockTexture(m_npp);
- GLuint textureId = textureInfo.textureId;
+ if (android::uptimeMillis() - m_stallTime < MS_PER_FRAME)
+ return true;
+ m_stallTime = android::uptimeMillis();
m_idleTime += android::uptimeMillis() - m_startIdleTime;
m_startExecutionTime = android::uptimeMillis();
+ bool reCreateFlag = false;
int width, height;
getDimensions(width, height);
@@ -110,6 +109,7 @@
// change the ball's speed to match the size
m_dx = width * .005f;
m_dy = height * .007f;
+ reCreateFlag = true;
}
// setup variables
@@ -131,20 +131,15 @@
m_paint->setColor(0xAAFF0000);
m_canvas->drawOval(m_oval, *m_paint);
- if (textureInfo.width == width && textureInfo.height == height) {
- updateTextureWithBitmap(textureId, *m_bitmap);
+ if (!reCreateFlag) {
+ updateNativeWindow(m_ANW, *m_bitmap);
} else {
- createTextureWithBitmap(textureId, *m_bitmap);
- textureInfo.width = width;
- textureInfo.height = height;
- textureInfo.internalFormat = GL_RGBA;
+ setupNativeWindow(m_ANW, *m_bitmap);
}
m_executionTime += android::uptimeMillis() - m_startExecutionTime;
m_counter++;
- gOpenGLI.releaseTexture(m_npp, &textureInfo);
-
if (android::uptimeMillis() - m_lastPrintTime > 5000) {
float fps = m_counter / ((android::uptimeMillis() - m_startTime) / 1000);
float spf = ((android::uptimeMillis() - m_startTime)) / m_counter;
@@ -160,5 +155,6 @@
m_startTime = android::uptimeMillis();
}
+ m_startIdleTime = android::uptimeMillis(); // count delay between frames
return true;
}
diff --git a/samples/BrowserPlugin/jni/animation/AnimationThread.h b/samples/BrowserPlugin/jni/animation/AnimationThread.h
index 4f74e94..e95ecce 100644
--- a/samples/BrowserPlugin/jni/animation/AnimationThread.h
+++ b/samples/BrowserPlugin/jni/animation/AnimationThread.h
@@ -48,6 +48,7 @@
int64_t m_startTime;
int64_t m_startExecutionTime;
int64_t m_startIdleTime;
+ int64_t m_stallTime;
float m_x;
float m_y;
diff --git a/samples/BrowserPlugin/jni/main.cpp b/samples/BrowserPlugin/jni/main.cpp
index 9854848..f6e3400 100644
--- a/samples/BrowserPlugin/jni/main.cpp
+++ b/samples/BrowserPlugin/jni/main.cpp
@@ -77,7 +77,7 @@
ANPSystemInterfaceV0 gSystemI;
ANPTypefaceInterfaceV0 gTypefaceI;
ANPWindowInterfaceV1 gWindowI;
-ANPOpenGLInterfaceV0 gOpenGLI;
+ANPNativeWindowInterfaceV0 gNativeWindowI;
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
#define DEBUG_PLUGIN_EVENTS 0
@@ -115,18 +115,18 @@
uint32_t size;
ANPInterface* i;
} gPairs[] = {
- { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
- { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI },
- { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
- { kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI },
- { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
- { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
- { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI },
- { kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI },
- { kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI },
- { kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI },
- { kWindowInterfaceV1_ANPGetValue, sizeof(gWindowI), &gWindowI },
- { kOpenGLInterfaceV0_ANPGetValue, sizeof(gOpenGLI), &gOpenGLI },
+ { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
+ { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI },
+ { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
+ { kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI },
+ { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
+ { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
+ { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI },
+ { kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI },
+ { kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI },
+ { kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI },
+ { kWindowInterfaceV1_ANPGetValue, sizeof(gWindowI), &gWindowI },
+ { kNativeWindowInterfaceV0_ANPGetValue, sizeof(gNativeWindowI), &gNativeWindowI },
};
for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) {
gPairs[i].i->inSize = gPairs[i].size;
@@ -234,6 +234,9 @@
obj->pluginType = kVideo_PluginType;
obj->activePlugin = new VideoPlugin(instance);
}
+ else {
+ gLogI.log(kError_ANPLogType, "PluginType %s unknown!", argv[i]);
+ }
break;
}
}
diff --git a/samples/BrowserPlugin/jni/main.h b/samples/BrowserPlugin/jni/main.h
index ebfb4b2..b50ad56 100644
--- a/samples/BrowserPlugin/jni/main.h
+++ b/samples/BrowserPlugin/jni/main.h
@@ -27,7 +27,7 @@
#include <npfunctions.h>
#include <npruntime.h>
#include "android_npapi.h"
-#include "ANPOpenGL_npapi.h"
+#include "ANPNativeWindow_npapi.h"
#include "ANPSurface_npapi.h"
#include "ANPSystem_npapi.h"