diff --git a/samples/BrowserPlugin/jni/Android.mk b/samples/BrowserPlugin/jni/Android.mk index 641ac63da..7636de9bc 100644 --- a/samples/BrowserPlugin/jni/Android.mk +++ b/samples/BrowserPlugin/jni/Android.mk @@ -61,6 +61,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ + libandroid \ libutils \ libcutils \ libEGL \ diff --git a/samples/BrowserPlugin/jni/RenderingThread.cpp b/samples/BrowserPlugin/jni/RenderingThread.cpp index 7f267ed64..91ffb4a01 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 @@ GLenum RenderingThread::getType(SkBitmap::Config config) } } -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(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 41f0ce86c..cb4fb969f 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 @@ public: 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 @@ private: 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 9e6342d45..1388fe374 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 -#include #include +#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 @@ AnimationThread::AnimationThread(NPP npp) : RenderingThread(npp) { m_startExecutionTime = 0; m_startTime = android::uptimeMillis(); + m_stallTime = android::uptimeMillis(); + } AnimationThread::~AnimationThread() { @@ -84,15 +84,14 @@ static void bounce(float* x, float* dx, const float max) { } 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 @@ bool AnimationThread::threadLoop() { // 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 @@ bool AnimationThread::threadLoop() { 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 @@ bool AnimationThread::threadLoop() { 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 4f74e9485..e95ecceff 100644 --- a/samples/BrowserPlugin/jni/animation/AnimationThread.h +++ b/samples/BrowserPlugin/jni/animation/AnimationThread.h @@ -48,6 +48,7 @@ private: 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 98548485a..f6e340029 100644 --- a/samples/BrowserPlugin/jni/main.cpp +++ b/samples/BrowserPlugin/jni/main.cpp @@ -77,7 +77,7 @@ ANPSurfaceInterfaceV0 gSurfaceI; 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 @@ NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, 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 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc 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 ebfb4b20e..b50ad5638 100644 --- a/samples/BrowserPlugin/jni/main.h +++ b/samples/BrowserPlugin/jni/main.h @@ -27,7 +27,7 @@ #include #include #include "android_npapi.h" -#include "ANPOpenGL_npapi.h" +#include "ANPNativeWindow_npapi.h" #include "ANPSurface_npapi.h" #include "ANPSystem_npapi.h"