[Libreoffice-commits] .: Branch 'feature/android' - 3 commits - sal/android vcl/android vcl/inc vcl/Library_vcl.mk

Michael Meeks michael at kemper.freedesktop.org
Fri Jan 27 06:56:37 PST 2012


 sal/android/android_native_app_glue.c |   24 +++
 sal/android/lo-bootstrap.c            |   18 +-
 vcl/Library_vcl.mk                    |    1 
 vcl/android/androidinst.cxx           |  226 +++++++++++++++++++++++++---------
 vcl/inc/android/androidinst.hxx       |   10 +
 5 files changed, 215 insertions(+), 64 deletions(-)

New commits:
commit 7acf7c1fd5cddb5aa6210e178bfab924570667c7
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Fri Jan 27 14:51:40 2012 +0000

    android: add EGL and pixel redrawing modes + start of 565 conversion

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index fa6093e..169107d 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -434,6 +434,7 @@ ifeq ($(GUIBASE),android)
 $(eval $(call gb_Library_add_libs,vcl,\
 	-llog \
 	-landroid \
+	-lEGL -lGLESv1_CM \
 	-llo-bootstrap \
 ))
 $(eval $(call gb_Library_add_defs,vcl,\
diff --git a/vcl/android/androidinst.cxx b/vcl/android/androidinst.cxx
index 5adc357..f011858 100644
--- a/vcl/android/androidinst.cxx
+++ b/vcl/android/androidinst.cxx
@@ -36,6 +36,9 @@
 #include <osl/detail/android_native_app_glue.h>
 #include <rtl/strbuf.hxx>
 
+#undef ANDROID_EGL
+#define ANDROID_PIXELS
+
 class AndroidSalData : public SalGenericData
 {
 public:
@@ -74,7 +77,7 @@ static rtl::OString KeyMetaStateToString(int32_t nFlags)
     return aStr.makeStringAndClear();
 }
 
-static void BlitFrameRegionToWindow(ANativeWindow *pWindow,
+static void BlitFrameRegionToWindow(ANativeWindow_Buffer *pOutBuffer,
                                     const basebmp::BitmapDeviceSharedPtr& aDev,
                                     const ARect &rSrcRect,
                                     int nDestX, int nDestY)
@@ -82,22 +85,6 @@ static void BlitFrameRegionToWindow(ANativeWindow *pWindow,
     fprintf (stderr, "Blit frame #2 src %d,%d->%d,%d to position %d, %d\n",
              rSrcRect.left, rSrcRect.top, rSrcRect.right, rSrcRect.bottom,
              nDestX, nDestY);
-    ARect aRect;
-    ANativeWindow_Buffer aOutBuffer;
-    memset ((void *)&aOutBuffer, 0, sizeof (aOutBuffer));
-    fprintf (stderr, "pre lock\n");
-    int32_t nRet = ANativeWindow_lock(pWindow, &aOutBuffer, &aRect);
-    fprintf (stderr, "locked window %d returned rect: %d,%d->%d,%d "
-             "buffer: %dx%d stride %d, format %d, bits %p\n",
-             nRet, aRect.left, aRect.top, aRect.right, aRect.bottom,
-             aOutBuffer.width, aOutBuffer.height, aOutBuffer.stride,
-             aOutBuffer.format, aOutBuffer.bits);
-    if (aOutBuffer.bits == NULL)
-    {
-        fprintf (stderr, "no buffer for locked window\n");
-        ANativeWindow_unlockAndPost(pWindow);
-        return;
-    }
 
     // FIXME: do some cropping goodness on aSrcRect to ensure no overflows etc.
     ARect aSrcRect = rSrcRect;
@@ -105,53 +92,125 @@ static void BlitFrameRegionToWindow(ANativeWindow *pWindow,
     basebmp::RawMemorySharedArray aSrcData = aDev->getBuffer();
     unsigned char *pSrc = aSrcData.get();
 
+    // FIXME: we have WINDOW_FORMAT_RGB_565            = 4 ...
+
     for (unsigned int y = 0; y < (unsigned int)(aSrcRect.bottom - aSrcRect.top); y++)
     {
         unsigned char *sp = ( pSrc + nStride * (y + aSrcRect.top) +
                               aSrcRect.left * 3 /* src pixel size */ );
-        unsigned char *dp = ( (unsigned char *)aOutBuffer.bits +
-                              aOutBuffer.stride * (y + nDestY) +
-                              nDestX * 4 /* dest pixel size */ );
-        fprintf (stderr, "y %d, sp %p dp %p\n", y, sp, dp);
-        for (unsigned int x = 0; x < (unsigned int)(aSrcRect.right - aSrcRect.left); x++)
+
+        switch (pOutBuffer->format) {
+        case WINDOW_FORMAT_RGBA_8888:
+        case WINDOW_FORMAT_RGBX_8888:
+        {
+            unsigned char *dp = ( (unsigned char *)pOutBuffer->bits +
+                                  pOutBuffer->stride * 4 * (y + nDestY) +
+                                  nDestX * 4 /* dest pixel size */ );
+            fprintf (stderr, "y %d, sp %p dp %p\n", y, sp, dp);
+            for (unsigned int x = 0; x < (unsigned int)(aSrcRect.right - aSrcRect.left); x++)
+            {
+                dp[x*4 + 0] = sp[x*3 + 0]; // B
+                dp[x*4 + 1] = sp[x*3 + 1]; // G
+                dp[x*4 + 2] = sp[x*3 + 2]; // R
+                dp[x*4 + 3] = 255; // A
+            }
+            break;
+        }
+        case WINDOW_FORMAT_RGB_565:
         {
-            dp[x*4 + 0] = sp[x*3 + 0]; // B
-            dp[x*4 + 1] = sp[x*3 + 1]; // G
-            dp[x*4 + 2] = sp[x*3 + 2]; // R
-            dp[x*4 + 3] = 255; // A
+            unsigned char *dp = ( (unsigned char *)pOutBuffer->bits +
+                                  pOutBuffer->stride * 2 * (y + nDestY) +
+                                  nDestX * 2 /* dest pixel size */ );
+            fprintf (stderr, "y %d, sp %p dp %p\n", y, sp, dp);
+            for (unsigned int x = 0; x < (unsigned int)(aSrcRect.right - aSrcRect.left); x++)
+            {
+                unsigned char b = sp[x*3 + 0]; // B
+                unsigned char g = sp[x*3 + 1]; // G
+                unsigned char r = sp[x*3 + 2]; // R
+                dp[x*2 + 0] = (r & 0xf8) | (g >> 5);
+                dp[x*2 + 1] = ((g & 0x1c) << 5) | ((b & 0xf8) >> 3);
+            }
+            break;
+        }
+        default:
+            fprintf (stderr, "unknown pixel format %d !\n", pOutBuffer->format);
+            break;
         }
     }
     fprintf (stderr, "done blit!\n");
-#if 0
-    // hard-code / guess at a format ...
-    int32_t *p = (int32_t *)aBuffer.bits;
-    for (int32_t y = 0; y < aBuffer.height; y++)
-    {
-        for (int32_t x = 0; x < aBuffer.stride / 4; x++)
-            *p++ = (y << 24) + x;
-    }
-#endif
-
-    ANativeWindow_unlockAndPost(pWindow);
-    fprintf (stderr, "done render!\n");
 }
 
-void AndroidSalInstance::BlitFrameToWindow(ANativeWindow *pWindow,
+void AndroidSalInstance::BlitFrameToWindow(ANativeWindow_Buffer *pOutBuffer,
                                            const basebmp::BitmapDeviceSharedPtr& aDev)
 {
     basegfx::B2IVector aDevSize = aDev->getSize();
-    ARect aWhole = { 0, 0, 400, 400 }; // FIXME: aDevSize.getX(), aDevSize.getY() };
-    BlitFrameRegionToWindow(pWindow, aDev, aWhole, 0, 0);
+    ARect aWhole = { 0, 0, aDevSize.getX(), aDevSize.getY() };
+    BlitFrameRegionToWindow(pOutBuffer, aDev, aWhole, 0, 0);
 }
 
 void AndroidSalInstance::RedrawWindows(ANativeWindow *pWindow)
 {
-    std::list< SalFrame* >::const_iterator it;
-    for ( it = getFrames().begin(); it != getFrames().end(); it++ )
+    (void)pWindow;
+#ifdef ANDROID_PIXELS
+    ARect aRect;
+    ANativeWindow_Buffer aOutBuffer;
+    memset ((void *)&aOutBuffer, 0, sizeof (aOutBuffer));
+    fprintf (stderr, "pre lock #3\n");
+#endif
+
+#ifdef ANDROID_EGL
+    if (mxDisplay == EGL_NO_DISPLAY)
+    {
+        fprintf (stderr, "wait for the setup\n");
+        return;
+    }
+
+    EGLBoolean nRet = eglMakeCurrent(mxDisplay, mxSurface, mxSurface, mxContext);
+    fprintf (stderr, "make current context %d\n", nRet);
+
+    // Just fill the screen with a color.
+    static int a = 0;
+    a++;
+    glClearColor((a & 0x1) ? 1.0 : 0.0, (a & 0x2) ? 1.0 : 0.0, 0.0, 1);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mxDisplay, mxSurface);
+#endif // ANDROID_EGL
+
+#ifdef ANDROID_PIXELS
+    int32_t nRet = ANativeWindow_lock(pWindow, &aOutBuffer, &aRect);
+    fprintf (stderr, "locked window %d returned rect: %d,%d->%d,%d "
+             "buffer: %dx%d stride %d, format %d, bits %p\n",
+             nRet, aRect.left, aRect.top, aRect.right, aRect.bottom,
+             aOutBuffer.width, aOutBuffer.height, aOutBuffer.stride,
+             aOutBuffer.format, aOutBuffer.bits);
+
+#if 1 // pre-'clean' the buffer with cruft:
+    // hard-code / guess at a format ...
+    int32_t *p = (int32_t *)aOutBuffer.bits;
+    for (int32_t y = 0; y < aOutBuffer.height; y++)
     {
-        SvpSalFrame *pFrame = static_cast<SvpSalFrame *>(*it);
-        BlitFrameToWindow (pWindow, pFrame->getDevice());
+        for (int32_t x = 0; x < aOutBuffer.stride / 2; x++)
+            *p++ = (y << 24) + x;
     }
+#endif
+
+    if (aOutBuffer.bits != NULL)
+    {
+        std::list< SalFrame* >::const_iterator it;
+        for ( it = getFrames().begin(); it != getFrames().end(); it++ )
+        {
+            SvpSalFrame *pFrame = static_cast<SvpSalFrame *>(*it);
+            BlitFrameToWindow (&aOutBuffer, pFrame->getDevice());
+        }
+    }
+    else
+        fprintf (stderr, "no buffer for locked window\n");
+
+    ANativeWindow_unlockAndPost(pWindow);
+    fprintf (stderr, "done render!\n");
+#endif // ANDROID_PIXELS
+
     mbQueueReDraw = false;
 }
 
@@ -194,6 +253,61 @@ void AndroidSalInstance::onAppCmd (struct android_app* app, int32_t cmd)
             fprintf (stderr, "we have an app window ! %p %dx%x (%d)\n",
                      pWindow, aRect.right, aRect.bottom,
                      ANativeWindow_getFormat(pWindow));
+
+#ifdef ANDROID_EGL
+            const EGLint attribs[] = {
+                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+                EGL_BLUE_SIZE, 8,
+                EGL_GREEN_SIZE, 8,
+                EGL_RED_SIZE, 8,
+                EGL_NONE
+            };
+            EGLint w, h, format;
+            EGLint numConfigs;
+            EGLConfig config;
+            EGLSurface surface;
+            EGLContext context;
+
+            EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+            eglInitialize(display, 0, 0);
+
+            /* Here, the application chooses the configuration it desires. In this
+             * sample, we have a very simplified selection process, where we pick
+             * the first EGLConfig that matches our criteria */
+            eglChooseConfig(display, attribs, &config, 1, &numConfigs);
+
+            /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
+             * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
+             * As soon as we picked a EGLConfig, we can safely reconfigure the
+             * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
+            eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
+
+            ANativeWindow_setBuffersGeometry(mpApp->window, 0, 0, format);
+
+            surface = eglCreateWindowSurface(display, config, mpApp->window, NULL);
+            context = eglCreateContext(display, config, NULL, NULL);
+
+            if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
+                fprintf(stderr, "Unable to eglMakeCurrent");
+                break;
+            }
+
+            eglQuerySurface(display, surface, EGL_WIDTH, &w);
+            eglQuerySurface(display, surface, EGL_HEIGHT, &h);
+
+            mxDisplay = display;
+            mxContext = context;
+            mxSurface = surface;
+
+            // Initialize GL state:
+            // FIXME: surely all this glContext - **per-thread** - !
+
+            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+            glEnable(GL_CULL_FACE);
+            glShadeModel(GL_SMOOTH);
+            glDisable(GL_DEPTH_TEST);
+#endif
             break;
         }
         case APP_CMD_WINDOW_RESIZED:
@@ -210,7 +324,7 @@ void AndroidSalInstance::onAppCmd (struct android_app* app, int32_t cmd)
         case APP_CMD_WINDOW_REDRAW_NEEDED:
         {
             fprintf (stderr, "redraw needed\n");
-            mbQueueReDraw = true;
+            AndroidSalInstance::getInstance()->RedrawWindows (pWindow);
             break;
         }
 
@@ -283,31 +397,26 @@ extern "C" {
     {
         return AndroidSalInstance::getInstance()->onInputEvent(app, event);
     }
-    void onNativeWindowRedrawNeeded_cb(ANativeActivity * /* activity */,
-                                       ANativeWindow *pWindow)
-    {
-        fprintf (stderr, "onNativeWindowRedrawNeeded_cb\n");
-        AndroidSalInstance::getInstance()->RedrawWindows (pWindow);
-    }
 }
 
 AndroidSalInstance::AndroidSalInstance( SalYieldMutex *pMutex )
     : SvpSalInstance( pMutex )
     , mpApp( NULL )
     , mbQueueReDraw( false )
+    , mxDisplay( EGL_NO_DISPLAY )
+    , mxSurface( EGL_NO_SURFACE )
+    , mxContext( EGL_NO_CONTEXT )
 {
     mpApp = lo_get_app();
-    fprintf (stderr, "created Android Sal Instance for app %p window %p\n",
+    fprintf (stderr, "created Android Sal Instance for app %p window %p thread: %d\n",
              mpApp,
-             mpApp ? mpApp->window : NULL);
+             mpApp ? mpApp->window : NULL,
+             (int)pthread_self());
     if (mpApp)
     {
         pthread_mutex_lock (&mpApp->mutex);
         mpApp->onAppCmd = onAppCmd_cb;
         mpApp->onInputEvent = onInputEvent_cb;
-        if (mpApp->window != NULL)
-            onAppCmd_cb (mpApp, APP_CMD_INIT_WINDOW);
-        mpApp->activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded_cb;
         pthread_mutex_unlock (&mpApp->mutex);
     }
 }
@@ -331,7 +440,8 @@ void AndroidSalInstance::DoReleaseYield (int nTimeoutMS)
     // release yield mutex
     sal_uLong nAcquireCount = ReleaseYieldMutex();
 
-    fprintf (stderr, "DoReleaseYield #2 %d ms\n", nTimeoutMS);
+    fprintf (stderr, "DoReleaseYield #2 %d thread: %d ms\n",
+             nTimeoutMS, (int)pthread_self());
     void *outData = NULL;
     int outFd = 0, outEvents = 0;
 
diff --git a/vcl/inc/android/androidinst.hxx b/vcl/inc/android/androidinst.hxx
index 8efb963..7372f75 100644
--- a/vcl/inc/android/androidinst.hxx
+++ b/vcl/inc/android/androidinst.hxx
@@ -30,6 +30,9 @@
 #ifndef ANDROID_SALINST_H
 #define ANDROID_SALINST_H
 
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
 #include <android/input.h>
 #include <android/native_window.h>
 #include <headless/svpinst.hxx>
@@ -37,7 +40,7 @@
 
 class AndroidSalInstance : public SvpSalInstance
 {
-    void BlitFrameToWindow(ANativeWindow *pWindow,
+    void BlitFrameToWindow(ANativeWindow_Buffer *pOutBuffer,
                            const basebmp::BitmapDeviceSharedPtr& aDev);
 public:
     AndroidSalInstance( SalYieldMutex *pMutex );
@@ -58,6 +61,11 @@ protected:
     virtual void DoReleaseYield( int nTimeoutMS );
     struct android_app *mpApp;
     bool mbQueueReDraw;
+
+private:
+    EGLDisplay mxDisplay;
+    EGLSurface mxSurface;
+    EGLContext mxContext;
 };
 
 #endif // ANDROID_SALINST_H
commit 51741668593d23a1b35beb6971e92ba648974f31
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Fri Jan 27 14:50:21 2012 +0000

    android: attach as daemon with given JNI version, and don't exit.

diff --git a/sal/android/lo-bootstrap.c b/sal/android/lo-bootstrap.c
index 9c2c3da..eee5f1f 100644
--- a/sal/android/lo-bootstrap.c
+++ b/sal/android/lo-bootstrap.c
@@ -47,7 +47,7 @@
 #include <android/log.h>
 
 #include "uthash.h"
-
+#include <osl/thread.h>
 #include "osl/detail/android-bootstrap.h"
 
 #pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
@@ -1482,16 +1482,25 @@ __attribute__ ((visibility("default")))
 void
 android_main(struct android_app* state)
 {
-    JNIEnv *env;
+    jint nRet;
+    JNIEnv *pEnv = NULL;
     struct engine engine;
     Dl_info lo_main_info;
+    JavaVMAttachArgs aArgs = {
+        JNI_VERSION_1_2,
+        "LibreOfficeThread",
+        NULL
+    };
+
+    fprintf (stderr, "android_main in thread: %d\n", (int)pthread_self());
 
     if (sleep_time != 0) {
         LOGI("android_main: Sleeping for %d seconds, start ndk-gdb NOW if that is your intention", sleep_time);
         sleep(sleep_time);
     }
 
-    (*(*state->activity->vm)->AttachCurrentThread)(state->activity->vm, &env, 0);
+    nRet = (*(*state->activity->vm)->AttachCurrentThreadAsDaemon)(state->activity->vm, &pEnv, &aArgs);
+    fprintf (stderr, "attach thread returned %d %p\n", nRet, pEnv);
 
     app = state;
 
@@ -1508,8 +1517,7 @@ android_main(struct android_app* state)
     extract_files(UNPACK_TREE);
 
     lo_main(lo_main_argc, lo_main_argv);
-
-    exit(0);
+    fprintf (stderr, "exit android_main\n");
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 76bdcb53a57234cbd2d05acc557935e8175c7884
Author: Michael Meeks <michael.meeks at suse.com>
Date:   Fri Jan 27 14:48:55 2012 +0000

    android: push the redraw-needed command into the app thread & wait

diff --git a/sal/android/android_native_app_glue.c b/sal/android/android_native_app_glue.c
index cacc3bb..c01db3b 100644
--- a/sal/android/android_native_app_glue.c
+++ b/sal/android/android_native_app_glue.c
@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <sys/resource.h>
 
+#include "osl/detail/android-bootstrap.h"
 #include "osl/detail/android_native_app_glue.h"
 #include <android/log.h>
 
@@ -143,6 +144,12 @@ void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
             pthread_cond_broadcast(&android_app->cond);
             pthread_mutex_unlock(&android_app->mutex);
             break;
+        case APP_CMD_WINDOW_REDRAW_NEEDED:
+            LOGI("APP_CMD_WINDOW_REDRAW_NEEDED - post\n");
+            pthread_mutex_lock(&android_app->mutex);
+            pthread_cond_broadcast(&android_app->cond);
+            pthread_mutex_unlock(&android_app->mutex);
+	    break;
 
         case APP_CMD_SAVE_STATE:
             LOGI("APP_CMD_SAVE_STATE\n");
@@ -303,6 +310,17 @@ static void android_app_set_window(struct android_app* android_app, ANativeWindo
     pthread_mutex_unlock(&android_app->mutex);
 }
 
+static void android_app_window_redraw_needed(struct android_app* android_app, ANativeWindow* window) {
+    pthread_mutex_lock(&android_app->mutex);
+    if (window != NULL) {
+        android_app_write_cmd(android_app, APP_CMD_WINDOW_REDRAW_NEEDED);
+    }
+    while (android_app->window != android_app->pendingWindow) {
+        pthread_cond_wait(&android_app->cond, &android_app->mutex);
+    }
+    pthread_mutex_unlock(&android_app->mutex);
+}
+
 static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
     pthread_mutex_lock(&android_app->mutex);
     android_app_write_cmd(android_app, cmd);
@@ -404,6 +422,11 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
     android_app_set_window((struct android_app*)activity->instance, NULL);
 }
 
+static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
+    LOGI("onNativeWindowRedrawNeeded: %p -- %p\n", activity, window);
+    android_app_window_redraw_needed((struct android_app*)activity->instance, window);
+}
+
 static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
     LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
     android_app_set_input((struct android_app*)activity->instance, queue);
@@ -428,6 +451,7 @@ __attribute__ ((visibility("default"))) void ANativeActivity_onCreate(ANativeAct
     activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
     activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
     activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
+    activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
     activity->callbacks->onInputQueueCreated = onInputQueueCreated;
     activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
 


More information about the Libreoffice-commits mailing list