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:
parent
8c51282770
commit
b47db80af3
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
// FIXME: do this only if anything actually changed on screen!
|
||||
if (pScreenContentChanged) {
|
||||
Fl_Android_Application::copy_screen();
|
||||
pScreenContentChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user