Register Guidelines E-Books Search Today's Posts Mark Forums Read

Go Back   MobileRead Forums > E-Book Readers > More E-Book Readers > iRex > iRex Developer's Corner

Notices

Reply
 
Thread Tools Search this Thread
Old 02-15-2010, 04:45 PM   #1
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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:http://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.
Attached Files
File Type: avi DSCN2221_xvid.avi (3.78 MB, 240 views)

Last edited by ericshliao; 02-15-2010 at 07:09 PM.
ericshliao is offline   Reply With Quote
Old 02-16-2010, 11:00 AM   #2
joelypolly
Member
joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.
 
Posts: 16
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?
joelypolly is offline   Reply With Quote
Old 02-16-2010, 11:35 AM   #3
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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.
ericshliao is offline   Reply With Quote
Old 02-17-2010, 08:59 AM   #4
joelypolly
Member
joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.
 
Posts: 16
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?
joelypolly is offline   Reply With Quote
Old 02-17-2010, 03:45 PM   #5
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
Quote:
Originally Posted by joelypolly View Post
Does the line FBReader::Instance().refreshWindow(); cause the refresh of the page?
Yes, it's the case for FBReader on most devices. For iLiad, however, we need to control screen refresh manually.
ericshliao is offline   Reply With Quote
Old 02-17-2010, 10:13 PM   #6
joelypolly
Member
joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.
 
Posts: 16
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
joelypolly is offline   Reply With Quote
Old 02-17-2010, 10:58 PM   #7
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
Quote:
Originally Posted by joelypolly View Post
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?
[/CODE]
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.
ericshliao is offline   Reply With Quote
Old 02-17-2010, 11:10 PM   #8
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
Karma: 687
Join Date: Nov 2007
Device: Dell X51v; iLiad v2
Quote:
Originally Posted by joelypolly View Post
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.
IMHO, calling driver function to refresh EINK screen in .refreshWindow() member function will need tremendous modification because of the compilcated class hierarchy of FBReader and its MVC architecture.

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.
ericshliao is offline   Reply With Quote
Old 02-18-2010, 10:00 AM   #9
joelypolly
Member
joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.joelypolly has a complete set of Star Wars action figures.
 
Posts: 16
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
	}
}
joelypolly is offline   Reply With Quote
Old 03-15-2010, 09:07 PM   #10
pwarren
Connoisseur
pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.
 
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)
That's what I used for the 0.10 binary I posted. Just now updating things for 0.12.7, hopefully will have a new binary to post soon, with pre-rendered pages
pwarren is offline   Reply With Quote
Old 03-15-2010, 10:16 PM   #11
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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.
ericshliao is offline   Reply With Quote
Old 03-16-2010, 03:35 AM   #12
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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.
ericshliao is offline   Reply With Quote
Old 03-16-2010, 07:18 AM   #13
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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.
ericshliao is offline   Reply With Quote
Old 03-16-2010, 07:35 AM   #14
ericshliao
Guru
ericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enoughericshliao will become famous soon enough
 
Posts: 973
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);
ericshliao is offline   Reply With Quote
Old 03-16-2010, 09:13 PM   #15
pwarren
Connoisseur
pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.pwarren can program the VCR without an owner's manual.
 
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>
lines produce pages and pages of errors when compiling, after modifying the makefiles so that gcc knows where to find them.

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?
pwarren is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Forum Jump

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


All times are GMT -4. The time now is 02:16 PM.


MobileRead.com is a privately owned, operated and funded community.