Android: improvements to Fl:flush() implementation. Initial draw, no wasted draw cycles.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12717 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-07 16:29:31 +00:00
parent 2df5cb850a
commit dcc10a6a0a
5 changed files with 46 additions and 30 deletions

View File

@ -52,15 +52,17 @@ struct engine {
struct engine engine = { 0 }; struct engine engine = { 0 };
#if 0
static void engine_draw_frame() static void engine_draw_frame()
{ {
//if (Fl_Android_Application::lock_screen()) { //if (Fl_Android_Application::lock_screen()) {
Fl::damage(FL_DAMAGE_ALL); //Fl::damage(FL_DAMAGE_ALL);
win->redraw(); //win->redraw();
Fl::flush(); Fl::flush();
// Fl_Android_Application::unlock_and_post_screen(); // Fl_Android_Application::unlock_and_post_screen();
//} //}
} }
#endif
static void engine_term_display() { static void engine_term_display() {
engine.animating = 0; engine.animating = 0;
@ -110,7 +112,7 @@ static void engine_handle_cmd(int32_t cmd) {
ANativeWindow_getHeight(app->window), ANativeWindow_getHeight(app->window),
#endif #endif
WINDOW_FORMAT_RGB_565); WINDOW_FORMAT_RGB_565);
engine_draw_frame(); Fl::damage(FL_DAMAGE_EXPOSE);
} }
break; break;
case APP_CMD_TERM_WINDOW: case APP_CMD_TERM_WINDOW:
@ -127,7 +129,7 @@ static void engine_handle_cmd(int32_t cmd) {
break; break;
case APP_CMD_LOST_FOCUS: case APP_CMD_LOST_FOCUS:
engine.animating = 0; engine.animating = 0;
engine_draw_frame(); //engine_draw_frame();
break; break;
default: break; default: break;
} }
@ -145,9 +147,14 @@ int main(int argc, char **argv)
win = new Fl_Window(10, 10, 600, 400, "Hallo"); win = new Fl_Window(10, 10, 600, 400, "Hallo");
btn = new Fl_Button(190, 200, 280, 35, "Hello, Android!"); btn = new Fl_Button(190, 200, 280, 35, "Hello, Android!");
btn->color(FL_LIGHT2); btn->color(FL_LIGHT2);
win->show(); win->show(argc, argv);
Fl::damage(FL_DAMAGE_ALL); int x;
win->redraw(); if (Fl::damage())
x = 0;
if (win->damage())
x = 2;
//Fl::damage(FL_DAMAGE_ALL);
//win->redraw();
// loop waiting for stuff to do. // loop waiting for stuff to do.
@ -161,7 +168,7 @@ int main(int argc, char **argv)
// If not animating, we will block forever waiting for events. // If not animating, we will block forever waiting for events.
// If animating, we loop until all events are read, then continue // If animating, we loop until all events are read, then continue
// to draw the next frame of animation. // to draw the next frame of animation.
while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, while ((ident=ALooper_pollAll(Fl::damage() ? 0 : -1, NULL, &events,
(void**)&source)) >= 0) { (void**)&source)) >= 0) {
// Process this event. // Process this event.

View File

@ -126,7 +126,7 @@ public:
static void set_on_app_cmd(void (*cmd)(int32_t cmd)) { pOnAppCmd = cmd; } 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 void set_on_input_event(int32_t (*cmd)(AInputEvent* event)) { pOnInputEvent = cmd; }
static void copy_screen(); static bool copy_screen();
protected: protected:
static void free_saved_state(); static void free_saved_state();
@ -145,7 +145,8 @@ protected:
static AConfiguration *pConfig; static AConfiguration *pConfig;
static void *pSavedState; static void *pSavedState;
static size_t pSavedStateSize; static size_t pSavedStateSize;
static ALooper *pLooper; static ALooper *pMsgPipeLooper;
static ALooper *pRedrawLooper;
static AInputQueue *pInputQueue; static AInputQueue *pInputQueue;
static ANativeWindow *pNativeWindow; static ANativeWindow *pNativeWindow;
static ANativeWindow_Buffer pNativeWindowBuffer; static ANativeWindow_Buffer pNativeWindowBuffer;
@ -155,12 +156,11 @@ protected:
static void (*pOnAppCmd)(int32_t cmd); static void (*pOnAppCmd)(int32_t cmd);
static int32_t (*pOnInputEvent)(AInputEvent* event); static int32_t (*pOnInputEvent)(AInputEvent* event);
// ---- no need to make these visible to the outside ---- // ---- no need to make these visible to the outside ----
static pthread_mutex_t pMutex; static pthread_mutex_t pMutex;
static pthread_cond_t pCond; static pthread_cond_t pCond;
static int pMsgRead; static int pMsgReadPipe;
static int pMsgWrite; static int pMsgWritePipe;
static pthread_t pThread; static pthread_t pThread;
static struct android_poll_source pCmdPollSource; static struct android_poll_source pCmdPollSource;
static struct android_poll_source pInputPollSource; static struct android_poll_source pInputPollSource;

View File

@ -59,7 +59,10 @@ void* Fl_Android_Application::pSavedState = 0;
size_t Fl_Android_Application::pSavedStateSize = 0; size_t Fl_Android_Application::pSavedStateSize = 0;
// The ALooper associated with the app's thread. // The ALooper associated with the app's thread.
ALooper* Fl_Android_Application::pLooper = 0; ALooper* Fl_Android_Application::pMsgPipeLooper = 0;
// The ALooper tht interrupts the main loop when FLTK requests a redraw.
ALooper* Fl_Android_Application::pRedrawLooper = 0;
// When non-NULL, this is the input queue from which the app will // When non-NULL, this is the input queue from which the app will
// receive user input events. // receive user input events.
@ -91,8 +94,8 @@ int32_t (*Fl_Android_Application::pOnInputEvent)(AInputEvent* event) = 0;
pthread_mutex_t Fl_Android_Application::pMutex = { 0 }; pthread_mutex_t Fl_Android_Application::pMutex = { 0 };
pthread_cond_t Fl_Android_Application::pCond = { 0 }; pthread_cond_t Fl_Android_Application::pCond = { 0 };
int Fl_Android_Application::pMsgRead = 0; int Fl_Android_Application::pMsgReadPipe = 0;
int Fl_Android_Application::pMsgWrite = 0; int Fl_Android_Application::pMsgWritePipe = 0;
pthread_t Fl_Android_Application::pThread = 0; pthread_t Fl_Android_Application::pThread = 0;
struct android_poll_source Fl_Android_Application::pCmdPollSource = { 0 }; struct android_poll_source Fl_Android_Application::pCmdPollSource = { 0 };
struct android_poll_source Fl_Android_Application::pInputPollSource = { 0 }; struct android_poll_source Fl_Android_Application::pInputPollSource = { 0 };
@ -164,7 +167,7 @@ void Fl_Android_Application::free_saved_state()
int8_t Fl_Android_Application::read_cmd() int8_t Fl_Android_Application::read_cmd()
{ {
int8_t cmd; int8_t cmd;
if (read(pMsgRead, &cmd, sizeof(cmd)) == sizeof(cmd)) { if (read(pMsgReadPipe, &cmd, sizeof(cmd)) == sizeof(cmd)) {
switch (cmd) { switch (cmd) {
case APP_CMD_SAVE_STATE: case APP_CMD_SAVE_STATE:
free_saved_state(); free_saved_state();
@ -222,7 +225,7 @@ void Fl_Android_Application::pre_exec_cmd(int8_t cmd)
if (pInputQueue != NULL) { if (pInputQueue != NULL) {
LOGV("Attaching input queue to looper"); LOGV("Attaching input queue to looper");
AInputQueue_attachLooper(pInputQueue, AInputQueue_attachLooper(pInputQueue,
pLooper, LOOPER_ID_INPUT, NULL, pMsgPipeLooper, LOOPER_ID_INPUT, NULL,
&pInputPollSource); &pInputPollSource);
} }
pthread_cond_broadcast(&pCond); pthread_cond_broadcast(&pCond);
@ -350,10 +353,10 @@ void *Fl_Android_Application::thread_entry(void* param)
pInputPollSource.id = LOOPER_ID_INPUT; pInputPollSource.id = LOOPER_ID_INPUT;
pInputPollSource.process = process_input; pInputPollSource.process = process_input;
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper *looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
ALooper_addFd(looper, pMsgRead, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, ALooper_addFd(looper, pMsgReadPipe, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
&pCmdPollSource); &pCmdPollSource);
pLooper = looper; pMsgPipeLooper = looper;
pthread_mutex_lock(&pMutex); pthread_mutex_lock(&pMutex);
pRunning = 1; pRunning = 1;
@ -384,8 +387,9 @@ void Fl_Android_Application::allocate_screen() {
#include <FL/fl_draw.H> #include <FL/fl_draw.H>
void Fl_Android_Application::copy_screen() bool Fl_Android_Application::copy_screen()
{ {
bool ret = false;
if (lock_screen()) { if (lock_screen()) {
static int i = 0; static int i = 0;
@ -413,7 +417,11 @@ void Fl_Android_Application::copy_screen()
dst += dstStride; dst += dstStride;
} }
unlock_and_post_screen(); unlock_and_post_screen();
ret = true;
} else {
Fl::damage(FL_DAMAGE_EXPOSE);
} }
return ret;
} }
/** /**
@ -475,7 +483,7 @@ bool Fl_Android_Application::screen_is_locked()
void Fl_Android_Activity::write_cmd(int8_t cmd) void Fl_Android_Activity::write_cmd(int8_t cmd)
{ {
if (write(pMsgWrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { if (write(pMsgWritePipe, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
} }
} }
@ -530,8 +538,8 @@ void Fl_Android_Activity::free()
} }
pthread_mutex_unlock(&pMutex); pthread_mutex_unlock(&pMutex);
close(pMsgRead); close(pMsgReadPipe);
close(pMsgWrite); close(pMsgWritePipe);
pthread_cond_destroy(&pCond); pthread_cond_destroy(&pCond);
pthread_mutex_destroy(&pMutex); pthread_mutex_destroy(&pMutex);
} }
@ -733,8 +741,8 @@ void Fl_Android_Activity::create(ANativeActivity* activity, void* savedState,
LOGE("could not create pipe: %s", strerror(errno)); LOGE("could not create pipe: %s", strerror(errno));
return; return;
} }
pMsgRead = msgpipe[0]; pMsgReadPipe = msgpipe[0];
pMsgWrite = msgpipe[1]; pMsgWritePipe = msgpipe[1];
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);

View File

@ -378,9 +378,9 @@ void Fl_WinAPI_Screen_Driver::beep(int type)
void Fl_Android_Screen_Driver::flush() void Fl_Android_Screen_Driver::flush()
{ {
Fl_Screen_Driver::flush(); Fl_Screen_Driver::flush();
// FIXME: do this only if anything actually changed on screen! // FIXME: do this only if anything actually changed on screen (need to optimize)!
if (pScreenContentChanged) { if (pScreenContentChanged) {
Fl_Android_Application::copy_screen(); if (Fl_Android_Application::copy_screen())
pScreenContentChanged = false; pScreenContentChanged = false;
} }
} }

View File

@ -69,6 +69,7 @@ void Fl_Android_Window_Driver::show()
i(x); i(x);
x->next = Fl_X::first; x->next = Fl_X::first;
Fl_X::first = x; Fl_X::first = x;
pWindow->redraw();
} else { } else {
// bring window to front // bring window to front
} }