Cleaned up a bit PageFlipper sources.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19112 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2006-10-24 15:56:32 +00:00
parent 6b375f2ef3
commit 743fe40eba
2 changed files with 233 additions and 185 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
SubDir HAIKU_TOP src tests kits game page_flipper ; SubDir HAIKU_TOP src tests kits game page_flipper ;
SimpleTest page_flipper SimpleTest PageFlipper
: page_flip.cpp : page_flip.cpp
: game be root : game be root
; ;
+184 -136
View File
@@ -26,201 +26,249 @@ public:
NWindowScreen(status_t*); NWindowScreen(status_t*);
private: private:
void ScreenConnected(bool); void ScreenConnected(bool);
long MyCode(); int32 DrawingCode();
static long Entry(void*);
thread_id tid; static int32 Entry(void*);
sem_id sem;
area_id area; thread_id fThreadId;
uint8* save_buffer; sem_id fSem;
uint8* frame_buffer; area_id fArea;
ulong line_length; uint8* fSaveBuffer;
bool thread_is_locked; // small hack to allow to quit the uint8* fFrameBuffer;
ulong fLineLength;
bool fThreadIsLocked; // small hack to allow to quit the
// app from ScreenConnected() // app from ScreenConnected()
blit_hook blit; // hooks to the graphics driver functions blit_hook fBlitHook; // hooks to the graphics driver functions
sync_hook sync; sync_hook fSyncHook;
}; };
int main(int, char**) {
int
main()
{
NApplication app; NApplication app;
} }
NApplication::NApplication() NApplication::NApplication()
:BApplication("application/x-vnd.Be-sample-jbq1") { :BApplication("application/x-vnd.Be-sample-jbq1")
{
Run(); // see you in ReadyToRun() Run(); // see you in ReadyToRun()
} }
void NApplication::ReadyToRun() {
status_t ret=B_ERROR; void
is_quitting=false; NApplication::ReadyToRun()
NWindowScreen* ws=new NWindowScreen(&ret); {
// exit if constructing the WindowScreen failed. status_t ret = B_ERROR;
if ((ws==NULL)||(ret<B_OK)) is_quitting = false;
NWindowScreen* windowScreen = new NWindowScreen(&ret);
// exit if constructing the WindowScreen failed.
if (windowScreen == NULL || ret < B_OK)
PostMessage(B_QUIT_REQUESTED); PostMessage(B_QUIT_REQUESTED);
} }
bool NApplication::QuitRequested() {
is_quitting=true; bool
NApplication::QuitRequested()
{
is_quitting = true;
return true; return true;
} }
NWindowScreen::NWindowScreen(status_t* ret) NWindowScreen::NWindowScreen(status_t* ret)
:BWindowScreen("Example",B_8_BIT_640x480,ret) { :
thread_is_locked=true; BWindowScreen("Example", B_8_BIT_640x480, ret),
tid=0; fThreadId(-1),
if (*ret==B_OK) { fSem(-1),
// this semaphore controls the access to the WindowScreen fArea(-1),
sem=create_sem(0,"WindowScreen Access"); fSaveBuffer(NULL),
// this area is used to save the whole framebuffer when fFrameBuffer(NULL),
// switching workspaces. (better than malloc()). fLineLength(0),
area=create_area("save",(void**)&save_buffer,B_ANY_ADDRESS fThreadIsLocked(true),
,640*2048,B_NO_LOCK,B_READ_AREA|B_WRITE_AREA); fBlitHook(NULL),
// exit if an error occured. fSyncHook(NULL)
if ((sem<B_OK)||(area<B_OK)) *ret=B_ERROR; {
else Show(); // let's go. See you in ScreenConnected. if (*ret < B_OK)
return;
// this semaphore controls the access to the WindowScreen
fSem = create_sem(0, "WindowScreen Access");
if (fSem < B_OK) {
*ret = fSem;
return;
} }
// this area is used to save the whole framebuffer when
// switching workspaces. (better than malloc()).
fArea = create_area("save", (void**)&fSaveBuffer, B_ANY_ADDRESS,
640 * 2048, B_NO_LOCK, B_READ_AREA|B_WRITE_AREA);
if (fArea < B_OK) {
*ret = fArea;
delete_sem(fSem);
fSem = -1;
return;
}
Show(); // let's go. See you in ScreenConnected.
} }
void NWindowScreen::ScreenConnected(bool connected) {
void
NWindowScreen::ScreenConnected(bool connected)
{
if (connected) { if (connected) {
if ((SetSpace(B_8_BIT_640x480)<B_OK) if (SetSpace(B_8_BIT_640x480) < B_OK || SetFrameBuffer(640, 2048) < B_OK) {
||(SetFrameBuffer(640,2048)<B_OK)) { // properly set the framebuffer. exit if an error occurs.
// properly set the framebuffer. exit if an error occurs.
be_app->PostMessage(B_QUIT_REQUESTED); be_app->PostMessage(B_QUIT_REQUESTED);
return; return;
} }
// get the hardware acceleration hooks. get them each time
// the WindowScreen is connected, because of multiple // get the hardware acceleration hooks. get them each time
// monitor support // the WindowScreen is connected, because of multiple
blit=(blit_hook)CardHookAt(7); // monitor support
sync=(sync_hook)CardHookAt(10); fBlitHook = (blit_hook)CardHookAt(7);
// cannot work with no hardware blitting fSyncHook = (sync_hook)CardHookAt(10);
if (blit==NULL) {
// cannot work with no hardware blitting
if (fBlitHook == NULL) {
be_app->PostMessage(B_QUIT_REQUESTED); be_app->PostMessage(B_QUIT_REQUESTED);
return; return;
} }
// get the framebuffer-related info, each time the // get the framebuffer-related info, each time the
// WindowScreen is connected (multiple monitor) // WindowScreen is connected (multiple monitor)
frame_buffer=(uint8*)(CardInfo()->frame_buffer); fFrameBuffer = (uint8 *)(CardInfo()->frame_buffer);
line_length=FrameBufferInfo()->bytes_per_row; fLineLength = FrameBufferInfo()->bytes_per_row;
if (tid==0) { if (fThreadId == 0) {
// clean the framebuffer // clean the framebuffer
memset(frame_buffer,0,2048*line_length); memset(fFrameBuffer, 0, 2048 * fLineLength);
// spawn the rendering thread. exit if an error occurs. // spawn the rendering thread. exit if an error occurs.
if (((tid=spawn_thread(Entry,"rendering thread", fThreadId = spawn_thread(Entry, "rendering thread", B_URGENT_DISPLAY_PRIORITY, this);
B_URGENT_DISPLAY_PRIORITY,this))<B_OK) if (fThreadId < B_OK || resume_thread(fThreadId) < B_OK)
||(resume_thread(tid)<B_OK))
be_app->PostMessage(B_QUIT_REQUESTED); be_app->PostMessage(B_QUIT_REQUESTED);
} else for (int y=0;y<2048;y++) } else {
// restore the framebuffer when switching back from for (int y = 0; y < 2048; y++) {
// another workspace. // restore the framebuffer when switching back from
memcpy(frame_buffer+y*line_length, // another workspace.
save_buffer+640*y,640); memcpy(fFrameBuffer + y * fLineLength, fSaveBuffer + 640 * y, 640);
// set our color list. }
}
// set our color list.
rgb_color palette[256]; rgb_color palette[256];
for (int i=0;i<128;i++) { for (int i = 0; i < 128; i++) {
rgb_color c1={i*2,i*2,i*2}; rgb_color c1 = {i * 2, i * 2, i * 2};
rgb_color c2={127+i,2*i,254}; rgb_color c2 = {127 + i, 2 * i, 254};
palette[i]=c1; palette[i] = c1;
palette[i+128]=c2; palette[i + 128] = c2;
} }
SetColorList(palette); SetColorList(palette);
// allow the rendering thread to run. // allow the rendering thread to run.
thread_is_locked=false; fThreadIsLocked = false;
release_sem(sem); release_sem(fSem);
} else { } else {
// block the rendering thread. // block the rendering thread.
if (!thread_is_locked) { if (!fThreadIsLocked) {
acquire_sem(sem); acquire_sem(fSem);
thread_is_locked=true; fThreadIsLocked = true;
} }
// kill the rendering and clean up when quitting
// kill the rendering and clean up when quitting
if ((((NApplication*)be_app)->is_quitting)) { if ((((NApplication*)be_app)->is_quitting)) {
status_t ret; status_t ret;
kill_thread(tid); kill_thread(fThreadId);
wait_for_thread(tid,&ret); wait_for_thread(fThreadId, &ret);
delete_sem(sem); delete_sem(fSem);
delete_area(area); delete_area(fArea);
} else { } else {
// set the color list black so that the screen doesn't seem // set the color list black so that the screen doesn't seem
// to freeze while saving the framebuffer // to freeze while saving the framebuffer
rgb_color c={0,0,0}; rgb_color c = { 0, 0, 0 };
rgb_color palette[256]; rgb_color palette[256];
for (int i=0;i<256;i++) for (int i = 0; i < 256; i++)
palette[i]=c; palette[i] = c;
SetColorList(palette); SetColorList(palette);
// save the framebuffer // save the framebuffer
for (int y=0;y<2048;y++) for (int y = 0; y < 2048; y++)
memcpy(save_buffer+640*y, memcpy(fSaveBuffer + 640 * y, fFrameBuffer + y * fLineLength, 640);
frame_buffer+y*line_length,640);
} }
} }
} }
long NWindowScreen::Entry(void* p) {
return ((NWindowScreen*)p)->MyCode(); int32
NWindowScreen::Entry(void* castToThis)
{
return ((NWindowScreen *)castToThis)->DrawingCode();
} }
long NWindowScreen::MyCode() {
// gain access to the framebuffer before writing to it.
acquire_sem(sem); int32
NWindowScreen::DrawingCode()
{
// gain access to the framebuffer before writing to it.
for (int j=1440;j<2048;j++) { acquire_sem(fSem);
for (int i=0;i<640;i++) {
// draw the backgroud ripple pattern for (int j = 1440; j < 2048; j++) {
float val=63.99*(1+cos(2*M_PI*((i-320)*(i-320) for (int i; i < 640; i++) {
+(j-1744)*(j-1744))/1216)); // draw the backgroud ripple pattern
frame_buffer[i+line_length*j]=int(val); float val=63.99*(1+cos(2*M_PI*((i-320)*(i-320)+(j-1744)*(j-1744))/1216));
fFrameBuffer[i + fLineLength*j]=int(val);
} }
} }
ulong numframe=0;
bigtime_t trgt=0; ulong numframe = 0;
bigtime_t trgt = 0;
ulong y_origin; ulong y_origin;
uint8* current_frame; uint8* current_frame;
while(true) { while (true) {
// the framebuffer coordinates of the next frame // the framebuffer coordinates of the next frame
y_origin=480*(numframe%3); y_origin = 480 * (numframe % 3);
// and a pointer to it // and a pointer to it
current_frame=frame_buffer+y_origin*line_length; current_frame = fFrameBuffer + y_origin * fLineLength;
// copy the background // copy the background
int ytop=numframe%608,ybot=ytop+479; int ytop = numframe % 608, ybot = ytop + 479;
if (ybot<608) { if (ybot < 608) {
blit(0,1440+ytop,0,y_origin,639,479); fBlitHook(0,1440+ytop,0,y_origin,639,479);
} else { } else {
blit(0,1440+ytop,0,y_origin,639,1086-ybot); fBlitHook(0,1440+ytop,0,y_origin,639,1086-ybot);
blit(0,1440,0,y_origin+1087-ybot,639,ybot-608); fBlitHook(0,1440,0,y_origin+1087-ybot,639,ybot-608);
} }
// calculate the circle position. doing such calculations // calculate the circle position. doing such calculations
// between blit() and sync() is a good idea. // between blit() and sync() is a good idea.
uint32 x=(uint32)(287.99*(1+sin(numframe/72.))); uint32 x=(uint32)(287.99*(1+sin(numframe/72.)));
uint32 y=(uint32)(207.99*(1+sin(numframe/52.))); uint32 y=(uint32)(207.99*(1+sin(numframe/52.)));
if (sync) sync(); if (fSyncHook)
// draw the circle fSyncHook();
for (int j=0;j<64;j++) { // draw the circle
for (int i=0;i<64;i++) { for (int j = 0; j < 64; j++) {
for (int i = 0; i < 64; i++) {
if ((i-31)*(i-32)+(j-31)*(j-32)<=1024) if ((i-31)*(i-32)+(j-31)*(j-32)<=1024)
current_frame[x+i+line_length*(y+j)]+=128; current_frame[x + i + fLineLength * (y + j)] += 128;
} }
} }
// release the semaphore while waiting. gotta release it // release the semaphore while waiting. gotta release it
// at some point or nasty things will happen! // at some point or nasty things will happen!
release_sem(sem); release_sem(fSem);
// try to sync with the vertical retrace // try to sync with the vertical retrace
if (BScreen(this).WaitForRetrace()!=B_OK) { if (BScreen(this).WaitForRetrace() != B_OK) {
// we're doing some triple buffering. unwanted things would // we're doing some triple buffering. unwanted things would
// happen if we rendered more pictures than the card can // happen if we rendered more pictures than the card can
// display. we here make sure not to render more than 55.5 // display. we here make sure not to render more than 55.5
// pictures per second if the card does not support retrace // pictures per second if the card does not support retrace
// syncing // syncing
if (system_time()<trgt) snooze(trgt-system_time()); if (system_time() < trgt)
trgt=system_time()+18000; snooze(trgt - system_time());
trgt = system_time() + 18000;
} }
// acquire the semaphore back before talking to the driver // acquire the semaphore back before talking to the driver
acquire_sem(sem); acquire_sem(fSem);
// do the page-flipping // do the page-flipping
MoveDisplayArea(0,y_origin); MoveDisplayArea(0, y_origin);
// and go to the next frame! // and go to the next frame!
numframe++; numframe++;
} }
return 0; return 0;