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:
@@ -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
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -26,95 +26,135 @@ 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() {
|
|
||||||
|
void
|
||||||
|
NApplication::ReadyToRun()
|
||||||
|
{
|
||||||
status_t ret = B_ERROR;
|
status_t ret = B_ERROR;
|
||||||
is_quitting = false;
|
is_quitting = false;
|
||||||
NWindowScreen* ws=new NWindowScreen(&ret);
|
NWindowScreen* windowScreen = new NWindowScreen(&ret);
|
||||||
// exit if constructing the WindowScreen failed.
|
// exit if constructing the WindowScreen failed.
|
||||||
if ((ws==NULL)||(ret<B_OK))
|
if (windowScreen == NULL || ret < B_OK)
|
||||||
PostMessage(B_QUIT_REQUESTED);
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NApplication::QuitRequested() {
|
|
||||||
|
bool
|
||||||
|
NApplication::QuitRequested()
|
||||||
|
{
|
||||||
is_quitting = true;
|
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),
|
||||||
|
fArea(-1),
|
||||||
|
fSaveBuffer(NULL),
|
||||||
|
fFrameBuffer(NULL),
|
||||||
|
fLineLength(0),
|
||||||
|
fThreadIsLocked(true),
|
||||||
|
fBlitHook(NULL),
|
||||||
|
fSyncHook(NULL)
|
||||||
|
{
|
||||||
|
if (*ret < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
// this semaphore controls the access to the WindowScreen
|
// this semaphore controls the access to the WindowScreen
|
||||||
sem=create_sem(0,"WindowScreen Access");
|
fSem = create_sem(0, "WindowScreen Access");
|
||||||
// this area is used to save the whole framebuffer when
|
if (fSem < B_OK) {
|
||||||
// switching workspaces. (better than malloc()).
|
*ret = fSem;
|
||||||
area=create_area("save",(void**)&save_buffer,B_ANY_ADDRESS
|
return;
|
||||||
,640*2048,B_NO_LOCK,B_READ_AREA|B_WRITE_AREA);
|
|
||||||
// exit if an error occured.
|
|
||||||
if ((sem<B_OK)||(area<B_OK)) *ret=B_ERROR;
|
|
||||||
else Show(); // let's go. See you in ScreenConnected.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NWindowScreen::ScreenConnected(bool connected) {
|
// 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)
|
||||||
|
{
|
||||||
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
|
// get the hardware acceleration hooks. get them each time
|
||||||
// the WindowScreen is connected, because of multiple
|
// the WindowScreen is connected, because of multiple
|
||||||
// monitor support
|
// monitor support
|
||||||
blit=(blit_hook)CardHookAt(7);
|
fBlitHook = (blit_hook)CardHookAt(7);
|
||||||
sync=(sync_hook)CardHookAt(10);
|
fSyncHook = (sync_hook)CardHookAt(10);
|
||||||
|
|
||||||
// cannot work with no hardware blitting
|
// cannot work with no hardware blitting
|
||||||
if (blit==NULL) {
|
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 {
|
||||||
|
for (int y = 0; y < 2048; y++) {
|
||||||
// restore the framebuffer when switching back from
|
// restore the framebuffer when switching back from
|
||||||
// another workspace.
|
// another workspace.
|
||||||
memcpy(frame_buffer+y*line_length,
|
memcpy(fFrameBuffer + y * fLineLength, fSaveBuffer + 640 * y, 640);
|
||||||
save_buffer+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++) {
|
||||||
@@ -125,21 +165,22 @@ void NWindowScreen::ScreenConnected(bool connected) {
|
|||||||
}
|
}
|
||||||
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
|
||||||
@@ -151,29 +192,34 @@ void NWindowScreen::ScreenConnected(bool connected) {
|
|||||||
|
|
||||||
// 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() {
|
|
||||||
|
int32
|
||||||
|
NWindowScreen::DrawingCode()
|
||||||
|
{
|
||||||
// gain access to the framebuffer before writing to it.
|
// gain access to the framebuffer before writing to it.
|
||||||
|
|
||||||
acquire_sem(sem);
|
acquire_sem(fSem);
|
||||||
|
|
||||||
for (int j = 1440; j < 2048; j++) {
|
for (int j = 1440; j < 2048; j++) {
|
||||||
for (int i=0;i<640;i++) {
|
for (int i; i < 640; i++) {
|
||||||
// draw the backgroud ripple pattern
|
// draw the backgroud ripple pattern
|
||||||
float val=63.99*(1+cos(2*M_PI*((i-320)*(i-320)
|
float val=63.99*(1+cos(2*M_PI*((i-320)*(i-320)+(j-1744)*(j-1744))/1216));
|
||||||
+(j-1744)*(j-1744))/1216));
|
fFrameBuffer[i + fLineLength*j]=int(val);
|
||||||
frame_buffer[i+line_length*j]=int(val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong numframe = 0;
|
ulong numframe = 0;
|
||||||
bigtime_t trgt = 0;
|
bigtime_t trgt = 0;
|
||||||
ulong y_origin;
|
ulong y_origin;
|
||||||
@@ -182,30 +228,31 @@ long NWindowScreen::MyCode() {
|
|||||||
// 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)
|
||||||
|
fSyncHook();
|
||||||
// draw the circle
|
// draw the circle
|
||||||
for (int j = 0; j < 64; j++) {
|
for (int j = 0; j < 64; j++) {
|
||||||
for (int i = 0; i < 64; i++) {
|
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
|
||||||
@@ -213,11 +260,12 @@ long NWindowScreen::MyCode() {
|
|||||||
// 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)
|
||||||
|
snooze(trgt - system_time());
|
||||||
trgt = system_time() + 18000;
|
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!
|
||||||
|
|||||||
Reference in New Issue
Block a user