Android: drawing behaves nice enough. Fl::flush seems to bring the expected results, although optimization is required at some point.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12710 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-05 22:57:33 +00:00
parent 8c51282770
commit b47db80af3
6 changed files with 63 additions and 39 deletions

View File

@ -146,6 +146,8 @@ int main(int argc, char **argv)
btn = new Fl_Button(190, 200, 280, 35, "Hello, Android!");
btn->color(FL_LIGHT2);
win->show();
Fl::damage(FL_DAMAGE_ALL);
win->redraw();
// loop waiting for stuff to do.
@ -174,11 +176,7 @@ int main(int argc, char **argv)
return 0;
}
}
//Fl::flush();
if (engine.animating) {
engine_draw_frame();
}
Fl::flush();
}
return 0;
}

View File

@ -121,14 +121,12 @@ public:
static void post_exec_cmd(int8_t cmd);
static inline ANativeWindow *native_window() { return pNativeWindow; }
static inline ANativeWindow_Buffer &graphics_buffer() { return pNativeWindowBuffer; }
static inline ANativeWindow_Buffer &graphics_buffer() { return pApplicationWindowBuffer; }
static int destroy_requested() { return pDestroyRequested; }
static void set_on_app_cmd(void (*cmd)(int32_t cmd)) { pOnAppCmd = cmd; }
static void set_on_input_event(int32_t (*cmd)(AInputEvent* event)) { pOnInputEvent = cmd; }
static bool lock_screen();
static void unlock_and_post_screen();
static bool screen_is_locked();
static void copy_screen();
protected:
static void free_saved_state();
@ -138,6 +136,11 @@ protected:
static void process_cmd(struct android_poll_source* source);
static void* thread_entry(void* param);
static void allocate_screen();
static bool lock_screen();
static void unlock_and_post_screen();
static bool screen_is_locked();
static ANativeActivity *pActivity;
static AConfiguration *pConfig;
static void *pSavedState;
@ -146,6 +149,7 @@ protected:
static AInputQueue *pInputQueue;
static ANativeWindow *pNativeWindow;
static ANativeWindow_Buffer pNativeWindowBuffer;
static ANativeWindow_Buffer pApplicationWindowBuffer;
static int pActivityState;
static int pDestroyRequested;
static void (*pOnAppCmd)(int32_t cmd);

View File

@ -70,6 +70,7 @@ ANativeWindow* Fl_Android_Application::pNativeWindow = 0;
// Use this buffer for direct drawing access
ANativeWindow_Buffer Fl_Android_Application::pNativeWindowBuffer = { 0 };
ANativeWindow_Buffer Fl_Android_Application::pApplicationWindowBuffer = { 0 };
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
@ -366,6 +367,43 @@ void *Fl_Android_Application::thread_entry(void* param)
return NULL;
}
/**
* Allocate memory for our internal screen buffer.
*
* FIXME: everything is currently hardcoded to an 600x800 resolution
* TODO: react to screen changes
*/
void Fl_Android_Application::allocate_screen() {
pApplicationWindowBuffer.bits = calloc(600*800, 2); // one uint16_t per pixel
pApplicationWindowBuffer.width = 600;
pApplicationWindowBuffer.height = 800;
pApplicationWindowBuffer.stride = 600;
pApplicationWindowBuffer.format = WINDOW_FORMAT_RGB_565;
}
#include <FL/fl_draw.H>
void Fl_Android_Application::copy_screen()
{
if (lock_screen()) {
static int i = 0;
fl_color( (i&1) ? FL_RED : FL_GREEN);
fl_rectf(i*10, 600+i*10, 50, 50);
i++;
if (i>10) i = 0;
// TODO: there are endless possibilities to optimize the following code
// We can identify previously written buffers and copy only those pixels
// that actually changed.
memcpy(pNativeWindowBuffer.bits,
pApplicationWindowBuffer.bits,
600*800*2);
unlock_and_post_screen();
}
}
/**
* Take ownership of screen memory for gaining write access.
*
@ -386,25 +424,13 @@ bool Fl_Android_Application::lock_screen()
return false;
}
// 190, 200, 280, 35
ARect dirty = { .left=190, .top = 200, .right = 290, .bottom = 235 };
if (ANativeWindow_lock(pNativeWindow, &pNativeWindowBuffer, &dirty) < 0) {
if (ANativeWindow_lock(pNativeWindow, &pNativeWindowBuffer, 0L) < 0) {
log_w("Unable to lock window buffer: Android won't lock.");
return false;
}
log_w("Dirty rect is %d %d %d %d", dirty.left, dirty.top, dirty.right, dirty.bottom);
ANativeWindow_Buffer buf;
if (ANativeWindow_lock(pNativeWindow, &buf, &dirty) < 0) {
log_w("Unable to lock 2nd window buffer: Android won't lock.");
return false;
}
return true;
}
#include <FL/fl_draw.H>
/**
* Release screen memory ownership and give it back to the system.
*
@ -416,12 +442,6 @@ void Fl_Android_Application::unlock_and_post_screen()
if (!screen_is_locked())
return;
static int i = 0;
fl_color( (i&1) ? FL_RED : FL_GREEN);
fl_rectf(i*10, 700, 50, 50);
i++;
if (i>10) i = 0;
ANativeWindow_unlockAndPost(pNativeWindow);
pNativeWindowBuffer.bits = 0L; // avoid any misunderstandings...
}
@ -679,12 +699,14 @@ void Fl_Android_Activity::onInputQueueDestroyed(ANativeActivity* activity, AInpu
void Fl_Android_Activity::create(ANativeActivity* activity, void* savedState,
size_t savedStateSize)
{
static char *FLTK = "FLTK";
static const char *FLTK = "FLTK";
activity->instance = (void*)FLTK;
set_activity(activity);
set_callbacks();
allocate_screen(); // TODO: we may need to change this to when the actual screen is allocated
pthread_mutex_init(&pMutex, NULL);
pthread_cond_init(&pCond, NULL);

View File

@ -58,7 +58,7 @@ protected:
#endif
public:
Fl_Android_Screen_Driver() : Fl_Screen_Driver() { }
Fl_Android_Screen_Driver() : Fl_Screen_Driver(), pScreenContentChanged(false) { }
#if 0
Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
@ -118,6 +118,7 @@ public:
virtual float desktop_scale_factor();
#endif
bool pScreenContentChanged;
};

View File

@ -372,17 +372,16 @@ void Fl_WinAPI_Screen_Driver::beep(int type)
#endif
/**
* On Android, get access to screen memory, then flush(), then
* release screen memory and post it to the physicla screen.
*
* Don't do anything if the screen wasn't previously locked by
* any Fl_Window_Driver. We would just needlessly repost the same screen.
* On Android, we currently write into a memory buffer and copy
* the content to the screen.
*/
void Fl_Android_Screen_Driver::flush()
{
if (Fl_Android_Application::screen_is_locked()) {
Fl_Screen_Driver::flush();
Fl_Android_Application::unlock_and_post_screen();
Fl_Screen_Driver::flush();
// FIXME: do this only if anything actually changed on screen!
if (pScreenContentChanged) {
Fl_Android_Application::copy_screen();
pScreenContentChanged = false;
}
}

View File

@ -77,7 +77,7 @@ void Fl_Android_Window_Driver::show()
void Fl_Android_Window_Driver::make_current()
{
Fl_Android_Application::lock_screen();
((Fl_Android_Screen_Driver*)Fl::screen_driver())->pScreenContentChanged = true;
}