02-15-2010, 04:45 PM | #1 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Code to accelerate FBReader page-flip on iLiad
This my current work on preloading next-page in FBReader. The idea starts here:https://www.mobileread.com/forums/sho...&postcount=167
Thanx for Antartica's xepdmgr and OpenInkpot project's previous efforts. Basically, it works. The page-flip is really fast. It's even more fast (slightly) than I thought. I thought this idea will improve page-flip from 5-6 secs to 3 secs, but I estimate that page-flip is completed in 2-3 secs. Still, some finetune is needed. To make it work with xepdmgr, I have to make FBReader sleep and yield priority to xepdmgr after calling EpdRefreshAuto(). Without the sleep() function call, xepdmgr's auto-refresh ability will be disabled before it starts and finishes the desired refresh job. The result will be no screen refresh at all. It took me some time to figure out this solution. However, using sleep function is not elegant, and sometimes unwanted result may occur. That is, due to the un-anticipatability of multi-process environment, xepdmgr may not have enough time to finish a screen refresh before its auto-refresh ability got disabled. One of the solution is to increase sleep time. I wonder if I can get some feedback about its executing status from xepdmgr. Is there a way to ensure xepdmgr's auto-refresh is disabled only after the desired screen refresh is done? The mod is simple. It's displayed below. Any comments or suggestions are welcome. In ScrollingAction.cpp of FBReader-0.12.2 Code:
#include "xepdmgr-1.9-iliad/xepdmgrclient.h" extern sEpd *Epd; bool preloaded = false; void ScrollingAction::run() { /* //original code FBReader &fbreader = FBReader::Instance(); shared_ptr<ZLView> view = fbreader.currentView(); int delay = fbreader.myLastScrollingTime.millisecondsTo(ZLTime()); if (view.isNull() || (delay >= 0 && delay < scrollingDelay())) { return; } if (view->typeId() == ZLTextView::TYPE_ID) { ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); FBReader::Instance().refreshWindow(); } else if (view->typeId() == ZLBlockTreeView::TYPE_ID) { ((ZLBlockTreeView&)*view).scroll(myBlockScrollingMode, !myForward); } fbreader.myLastScrollingTime = ZLTime();*/ //added for iLiad FBReader &fbreader = FBReader::Instance(); shared_ptr<ZLView> view = fbreader.currentView(); int delay = fbreader.myLastScrollingTime.millisecondsTo(ZLTime()); if (view.isNull() || (delay >= 0 && delay < scrollingDelay())) { return; } if (view->typeId() == ZLTextView::TYPE_ID) { if(preloaded){ if(myForward){ //use preloaded page EpdRefreshAuto(Epd,1); sleep(2); }else{ //reverse page-scroll ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); } }else{ ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); FBReader::Instance().refreshWindow(); fbreader.myLastScrollingTime = ZLTime(); EpdRefreshAuto(Epd,1); sleep(2); } preloaded = false; //do the preloading job EpdRefreshAuto(Epd,0); sleep(0); ((ZLTextView&)*view).scrollPage(true, myTextScrollingMode, textOptionValue()); FBReader::Instance().refreshWindow(); preloaded = true; } else if (view->typeId() == ZLBlockTreeView::TYPE_ID) { ((ZLBlockTreeView&)*view).scroll(myBlockScrollingMode, !myForward); fbreader.myLastScrollingTime = ZLTime(); EpdRefreshAuto(Epd,1); sleep(2); } } In main.cpp Code:
#include "xepdmgr-1.9-iliad/xepdmgrclient.c" sEpd *Epd = NULL; int main(int argc, char **argv) { //added for iLiad if((Epd=EpdInit(NULL))==NULL) return(1); /*ERROR */ if (!ZLibrary::init(argc, argv)) { return 1; } ZLibrary::run(new FBReader(argc == 1 ? std::string() : argv[1])); ZLibrary::shutdown(); EpdFini(Epd);//added for iLiad return 0; } Some note: 1. FBreader is comprised by one executable (FBReader) and three libs (zltext, zlcore, zl-ui). The above mod only affect the file "FBReader", and libs will stay the same. 2. Page-flip is only accelerated for next-page. Besides, the effect of acceleration will not be noticed at the first time when next-page button is pushed. Users will notice the effect after that. It's because preloading only starts after the first page-flip event. A demonstrative video is uploaded. Last edited by ericshliao; 02-15-2010 at 07:09 PM. |
02-16-2010, 11:00 AM | #2 |
Member
Posts: 22
Karma: 328
Join Date: Jul 2008
Device: iliad
|
I am not 100% sure if my understanding is correct so help me out if I am wrong.
You are loading the next page's content in buffer when you are loading the current page. When you hit next button you simply refresh the screen and it shows what is in the buffer. Then you load the next page into buffer. Repeat. Correct? |
Advert | |
|
02-16-2010, 11:35 AM | #3 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Based on my very limited knowledge, there are two way to implement preloading on iLiad. One is based on multi-thread to load next page in background, and the other is based on the slow refresh of EINK screen. The first one can be applied to all devices, and the second can only apply on EINK devices.
What you are refferring should be the first one. What I showed in this discussing-thread is the second one. I have been working on modding FBReader with preloading next page in thread, but I haven't made it successful. So I tried the second way. Last edited by ericshliao; 02-16-2010 at 11:43 AM. |
02-17-2010, 08:59 AM | #4 |
Member
Posts: 22
Karma: 328
Join Date: Jul 2008
Device: iliad
|
I see that makes sense.
Does the line FBReader::Instance().refreshWindow(); cause the refresh of the page? |
02-17-2010, 03:45 PM | #5 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
|
Advert | |
|
02-17-2010, 10:13 PM | #6 |
Member
Posts: 22
Karma: 328
Join Date: Jul 2008
Device: iliad
|
Try this one
I looked at your other posts regarding this and you are using xepdmgr to manage screen updates. Wouldn't you be better of going directly to the driver to perform the update since for FBReader it will always be a full screen update?
Also I would just update in the .refreshWindow(); method instead of putting refresh code in the scroll action class. Hope this can help a bit. Updated scrollingaction.cpp below Code:
if (view->typeId() == ZLTextView::TYPE_ID) { //if button press is forward and I have a page preloaded refresh the screen now if(myForward && preload) { FBReader::Instance().refreshWindow(); } //load the page regardless of forward or back press ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); //if back is clicked turn off preload if(!myForward) { //if a page is already preloaded we must go back one more page to get to the last page if(preload) { ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); } preload = false } //refresh if nothing has been preloaded if(!preload) { FBReader::Instance().refreshWindow(); //preload next page ((ZLTextView&)*view).scrollPage(myForward, myTextScrollingMode, textOptionValue()); preload = true; } } else if (view->typeId() == ZLBlockTreeView::TYPE_ID) { ((ZLBlockTreeView&)*view).scroll(myBlockScrollingMode, !myForward); } Last edited by joelypolly; 02-17-2010 at 10:17 PM. Reason: spelling |
02-17-2010, 10:58 PM | #7 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
That's exactly the way OpenInkpot project mods FBReader. It should be working for FBReader on iLiad. However, since I am not familiar with calling driver function, and xepdmgr can do the task for me, it's quite convenient to use xepdmgr in the mean time.
|
02-17-2010, 11:10 PM | #8 | |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Quote:
I want to minimize modification to original FBReader. Doing this in ScrollingAction (as OpenInkpot project did) should be an satisfactory simple way. I don't know if doing this in .refreshWindow() is more simple, but I think I don't have the energy to investigate it right now. |
|
02-18-2010, 10:00 AM | #9 |
Member
Posts: 22
Karma: 328
Join Date: Jul 2008
Device: iliad
|
Might not be too hard...
I found the code to update the screen. It is in the ZLApplication.cpp in the /zlibrary/core/src/application folder. I think you will only need to add the xepdmgrclient.h to this base class and call the correct screen update methods. I believe in this case it may be the EpdRefreshFull() method.
I don't have a working dev environment so if you can test this along with the scrollingaction.cpp updates it would be great. Code:
void ZLApplication::refreshWindow() { if (!myViewWidget.isNull()) { myViewWidget->repaint(); } if (!myWindow.isNull()) { myWindow->refresh(); //code to update screen should go here } } |
03-15-2010, 09:07 PM | #10 |
Connoisseur
Posts: 95
Karma: 186186
Join Date: May 2009
Location: Canberra, Australia
Device: Irex Iliad (Dead), EcoReader (Smashed screen), Kobo Touch
|
The refreshWindow() function calls doPaint() from zlibrary/ui/src/gtk/ZLGtkViewWidget.cpp, which is where the actual drawing takes place.
Code:
//added for iliad #include <gtk/gtk.h> #include <gdk/gdkx.h> #include <liberdm/erdm.h> #include <liberipc/eripcviewer.h> #include <liberipc/eripcbusyd.h> erClientChannel_t erbusyChannel; erClientChannel_t ertoolbarChannel; Display * display; //snip static void doPaint(GtkWidget*, GdkEventExpose*, ZLGtkViewWidget *data) { // Turn on the busy LED busySetBusy(erbusyChannel, ccBusyState_Blink); data->doPaint(); // update eInk display display = gdk_x11_display_get_xdisplay(gdk_display_get_default()); XSync(display, 1); dmDisplay(dmCmdPriorUrgent, dmQFull); //Turn off the busy LED busySetBusy(erbusyChannel, ccBusyState_Off) |
03-15-2010, 10:16 PM | #11 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Calling dmDisplay(dmCmdPriorUrgent, dmQFull) is a good idea to control screen update manually.
However, if we do the acutal screen upate in refreshWindow(), how can we achieve preloading? Added: With calling dmDisplay() directly and poreloading, the speed of page-flip on FBReader is approaching DR800. (I didn't touch refreshWindow(). All the preloading task is done in ScrollingAction::run().) Added 2: Since "display = gdk_x11_display_get_xdisplay(gdk_display_get_defau lt());" is always the same, I think it's better to make display a global variable and set it once in main(). Then it's not needed any more in doPaint(). Last edited by ericshliao; 03-15-2010 at 11:36 PM. |
03-16-2010, 03:35 AM | #12 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Now, I have implemented the "delayed refresh" idea without the assistance of xepdmgr.
IMHO, adding the eink update code in refreshWindow() on FBreader.cpp is preferred, because only the binary FBReader is affected, other zlcore, zltext and zlui will stay the same. The trade-off is to sacrifice fast typing refresh provided by xepdmgr. Added: The result of preloading without xepdmgr is not so satisfactory. I got redundant screen refresh sometimes. Maybe it the fault of my code. For now, the best reslut is the combination of dmDisplay() and xepdmgr. Last edited by ericshliao; 03-16-2010 at 04:34 AM. |
03-16-2010, 07:18 AM | #13 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
To avoid the flickering problem, replace
dmDisplay(dmCmdPriorUrgent, dmQFull); with dmDisplay(dmCmdPriorNormal, dmQFull); Last edited by ericshliao; 03-16-2010 at 09:02 AM. |
03-16-2010, 07:35 AM | #14 |
Guru
Posts: 976
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
|
Use the following code to ensure (not guaranteed) framebuffer is updated:
XSync(display, 1); sleep(0); dmDisplay(dmCmdPriorNormal, dmQFull); |
03-16-2010, 09:13 PM | #15 |
Connoisseur
Posts: 95
Karma: 186186
Join Date: May 2009
Location: Canberra, Australia
Device: Irex Iliad (Dead), EcoReader (Smashed screen), Kobo Touch
|
I can't get it all to work within FBReader.cpp::refreshWindow()
the Code:
#include <gtk/gtk.h> #include <gdk/gdkx.h> Is there something funky going on because they're C includes rather than C++? I'm not entirely familiar with C++. Any chance you can post a patch with working dmDisplay() style updates within FBReader.cpp? |
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Personal Code Page after power on? | T.W.G | Sony Reader Dev Corner | 3 | 07-24-2009 07:50 PM |
PRS-505: Page flip keys in landscape mode? | Juggle4Evr | Sony Reader | 4 | 01-19-2009 06:51 PM |
Change code page | mota | Bookeen | 7 | 11-10-2007 05:51 AM |
PRS-500 Joystick page flip and history hack | diabloNL | Sony Reader Dev Corner | 12 | 08-10-2007 02:32 PM |
Can Plucker flip a full page? | Muximori | Reading and Management | 4 | 12-26-2005 10:22 PM |