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
This commit is contained in:
Chris Craik
2011-08-04 17:41:20 -07:00
parent a131fa0b3a
commit aceb2e3bda
7 changed files with 146 additions and 74 deletions

View File

@@ -61,6 +61,7 @@ LOCAL_C_INCLUDES += \
LOCAL_SHARED_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \
libnativehelper \ libnativehelper \
libandroid \
libutils \ libutils \
libcutils \ libcutils \
libEGL \ libEGL \

View File

@@ -24,30 +24,55 @@
*/ */
#include "RenderingThread.h" #include "RenderingThread.h"
#include "ANPOpenGL_npapi.h" #include "ANPNativeWindow_npapi.h"
extern ANPLogInterfaceV0 gLogI; extern ANPLogInterfaceV0 gLogI;
extern ANPOpenGLInterfaceV0 gOpenGLI; extern ANPNativeWindowInterfaceV0 gNativeWindowI;
RenderingThread::RenderingThread(NPP npp) : android::Thread() { RenderingThread::RenderingThread(NPP npp) : android::Thread() {
m_npp = npp; m_npp = npp;
m_width = -1; m_width = -1;
m_height = -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() { android::status_t RenderingThread::readyToRun() {
while (m_ANW == NULL) {
gLogI.log(kError_ANPLogType, "in ready to run"); m_ANW = gNativeWindowI.acquireNativeWindow(m_npp);
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;
} }
#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; return android::NO_ERROR;
} }
@@ -109,34 +134,70 @@ GLenum RenderingThread::getType(SkBitmap::Config config)
} }
} }
void RenderingThread::createTextureWithBitmap(GLuint texture, SkBitmap& bitmap) { void RenderingThread::setupNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); {
glBindTexture(GL_TEXTURE_2D, texture); int result = ANativeWindow_setBuffersGeometry(ANW, bitmap.width(),
checkGlError("glBindTexture"); bitmap.height(), WINDOW_FORMAT_RGBA_8888);
SkBitmap::Config config = bitmap.getConfig();
int internalformat = getInternalFormat(config); if (android::NO_ERROR != result) {
int type = getType(config); gLogI.log(kError_ANPLogType, "ERROR setBuffersGeometry() status is (%d)", result);
bitmap.lockPixels(); }
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(),
0, internalformat, type, bitmap.getPixels()); #if (!USE_SOFTWARE_RENDERING)
bitmap.unlockPixels(); if (m_eglSurface != EGL_NO_SURFACE) {
checkGlError("glTexImage2D"); gLogI.log(kDebug_ANPLogType, "destroying old surface");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); eglDestroySurface(m_eglDisplay, m_eglSurface);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }
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) { void RenderingThread::updateNativeWindow(ANativeWindow* ANW,
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const SkBitmap& bitmap)
glBindTexture(GL_TEXTURE_2D, texture); {
checkGlError("glBindTexture"); #if USE_SOFTWARE_RENDERING
SkBitmap::Config config = bitmap.getConfig();
int internalformat = getInternalFormat(config); //STEP 1: lock the ANW, getting a buffer
int type = getType(config); 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(); bitmap.lockPixels();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
internalformat, type, 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(); bitmap.unlockPixels();
checkGlError("glTexSubImage2D");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //STEP 3: push the buffer to the queue
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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
} }

View File

@@ -32,6 +32,8 @@
#ifndef RenderingThread__DEFINED #ifndef RenderingThread__DEFINED
#define RenderingThread__DEFINED #define RenderingThread__DEFINED
#define USE_SOFTWARE_RENDERING false
#define MS_PER_FRAME 17 // approx 60 fps
class RenderingThread : public android::Thread { class RenderingThread : public android::Thread {
public: public:
@@ -44,13 +46,14 @@ public:
protected: protected:
NPP m_npp; NPP m_npp;
ANativeWindow* m_ANW;
static void printGLString(const char *name, GLenum s); static void printGLString(const char *name, GLenum s);
static void checkGlError(const char* op); static void checkGlError(const char* op);
static GLenum getInternalFormat(SkBitmap::Config config); static GLenum getInternalFormat(SkBitmap::Config config);
static GLenum getType(SkBitmap::Config config); static GLenum getType(SkBitmap::Config config);
static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap); void setupNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap);
static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap); void updateNativeWindow(ANativeWindow* ANW, const SkBitmap& bitmap);
private: private:
virtual bool threadLoop() = 0; virtual bool threadLoop() = 0;
@@ -58,6 +61,13 @@ private:
android::Mutex m_sync; android::Mutex m_sync;
int m_width; int m_width;
int m_height; int m_height;
#if (!USE_SOFTWARE_RENDERING)
EGLDisplay m_eglDisplay;
EGLSurface m_eglSurface;
EGLContext m_eglContext;
EGLConfig m_eglConfig;
#endif
}; };

View File

@@ -23,14 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "AnimationThread.h" #include "AnimationThread.h"
#include "ANPOpenGL_npapi.h"
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <utils/SystemClock.h> #include <utils/SystemClock.h>
#include "ANPNativeWindow_npapi.h"
extern ANPLogInterfaceV0 gLogI; extern ANPLogInterfaceV0 gLogI;
extern ANPOpenGLInterfaceV0 gOpenGLI; extern ANPNativeWindowInterfaceV0 gNativeWindowI;
AnimationThread::AnimationThread(NPP npp) : RenderingThread(npp) { AnimationThread::AnimationThread(NPP npp) : RenderingThread(npp) {
m_counter = 0; m_counter = 0;
@@ -52,6 +50,8 @@ AnimationThread::AnimationThread(NPP npp) : RenderingThread(npp) {
m_startExecutionTime = 0; m_startExecutionTime = 0;
m_startTime = android::uptimeMillis(); m_startTime = android::uptimeMillis();
m_stallTime = android::uptimeMillis();
} }
AnimationThread::~AnimationThread() { AnimationThread::~AnimationThread() {
@@ -84,15 +84,14 @@ static void bounce(float* x, float* dx, const float max) {
} }
bool AnimationThread::threadLoop() { bool AnimationThread::threadLoop() {
if (android::uptimeMillis() - m_stallTime < MS_PER_FRAME)
m_startIdleTime = android::uptimeMillis(); return true;
m_stallTime = android::uptimeMillis();
ANPTextureInfo textureInfo = gOpenGLI.lockTexture(m_npp);
GLuint textureId = textureInfo.textureId;
m_idleTime += android::uptimeMillis() - m_startIdleTime; m_idleTime += android::uptimeMillis() - m_startIdleTime;
m_startExecutionTime = android::uptimeMillis(); m_startExecutionTime = android::uptimeMillis();
bool reCreateFlag = false;
int width, height; int width, height;
getDimensions(width, height); getDimensions(width, height);
@@ -110,6 +109,7 @@ bool AnimationThread::threadLoop() {
// change the ball's speed to match the size // change the ball's speed to match the size
m_dx = width * .005f; m_dx = width * .005f;
m_dy = height * .007f; m_dy = height * .007f;
reCreateFlag = true;
} }
// setup variables // setup variables
@@ -131,20 +131,15 @@ bool AnimationThread::threadLoop() {
m_paint->setColor(0xAAFF0000); m_paint->setColor(0xAAFF0000);
m_canvas->drawOval(m_oval, *m_paint); m_canvas->drawOval(m_oval, *m_paint);
if (textureInfo.width == width && textureInfo.height == height) { if (!reCreateFlag) {
updateTextureWithBitmap(textureId, *m_bitmap); updateNativeWindow(m_ANW, *m_bitmap);
} else { } else {
createTextureWithBitmap(textureId, *m_bitmap); setupNativeWindow(m_ANW, *m_bitmap);
textureInfo.width = width;
textureInfo.height = height;
textureInfo.internalFormat = GL_RGBA;
} }
m_executionTime += android::uptimeMillis() - m_startExecutionTime; m_executionTime += android::uptimeMillis() - m_startExecutionTime;
m_counter++; m_counter++;
gOpenGLI.releaseTexture(m_npp, &textureInfo);
if (android::uptimeMillis() - m_lastPrintTime > 5000) { if (android::uptimeMillis() - m_lastPrintTime > 5000) {
float fps = m_counter / ((android::uptimeMillis() - m_startTime) / 1000); float fps = m_counter / ((android::uptimeMillis() - m_startTime) / 1000);
float spf = ((android::uptimeMillis() - m_startTime)) / m_counter; float spf = ((android::uptimeMillis() - m_startTime)) / m_counter;
@@ -160,5 +155,6 @@ bool AnimationThread::threadLoop() {
m_startTime = android::uptimeMillis(); m_startTime = android::uptimeMillis();
} }
m_startIdleTime = android::uptimeMillis(); // count delay between frames
return true; return true;
} }

View File

@@ -48,6 +48,7 @@ private:
int64_t m_startTime; int64_t m_startTime;
int64_t m_startExecutionTime; int64_t m_startExecutionTime;
int64_t m_startIdleTime; int64_t m_startIdleTime;
int64_t m_stallTime;
float m_x; float m_x;
float m_y; float m_y;

View File

@@ -77,7 +77,7 @@ ANPSurfaceInterfaceV0 gSurfaceI;
ANPSystemInterfaceV0 gSystemI; ANPSystemInterfaceV0 gSystemI;
ANPTypefaceInterfaceV0 gTypefaceI; ANPTypefaceInterfaceV0 gTypefaceI;
ANPWindowInterfaceV1 gWindowI; ANPWindowInterfaceV1 gWindowI;
ANPOpenGLInterfaceV0 gOpenGLI; ANPNativeWindowInterfaceV0 gNativeWindowI;
#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
#define DEBUG_PLUGIN_EVENTS 0 #define DEBUG_PLUGIN_EVENTS 0
@@ -115,18 +115,18 @@ NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs,
uint32_t size; uint32_t size;
ANPInterface* i; ANPInterface* i;
} gPairs[] = { } gPairs[] = {
{ kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI }, { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
{ kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI }, { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI },
{ kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI }, { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
{ kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI }, { kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI },
{ kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI }, { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
{ kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI }, { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
{ kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI }, { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI },
{ kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI }, { kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI },
{ kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI }, { kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI },
{ kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI }, { kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI },
{ kWindowInterfaceV1_ANPGetValue, sizeof(gWindowI), &gWindowI }, { kWindowInterfaceV1_ANPGetValue, sizeof(gWindowI), &gWindowI },
{ kOpenGLInterfaceV0_ANPGetValue, sizeof(gOpenGLI), &gOpenGLI }, { kNativeWindowInterfaceV0_ANPGetValue, sizeof(gNativeWindowI), &gNativeWindowI },
}; };
for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) { for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) {
gPairs[i].i->inSize = gPairs[i].size; gPairs[i].i->inSize = gPairs[i].size;
@@ -234,6 +234,9 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc
obj->pluginType = kVideo_PluginType; obj->pluginType = kVideo_PluginType;
obj->activePlugin = new VideoPlugin(instance); obj->activePlugin = new VideoPlugin(instance);
} }
else {
gLogI.log(kError_ANPLogType, "PluginType %s unknown!", argv[i]);
}
break; break;
} }
} }

View File

@@ -27,7 +27,7 @@
#include <npfunctions.h> #include <npfunctions.h>
#include <npruntime.h> #include <npruntime.h>
#include "android_npapi.h" #include "android_npapi.h"
#include "ANPOpenGL_npapi.h" #include "ANPNativeWindow_npapi.h"
#include "ANPSurface_npapi.h" #include "ANPSurface_npapi.h"
#include "ANPSystem_npapi.h" #include "ANPSystem_npapi.h"