1*ee44f668SStefano Ceccherini /* 2*ee44f668SStefano Ceccherini Copyright 1999, Be Incorporated. All Rights Reserved. 3*ee44f668SStefano Ceccherini This file may be used under the terms of the Be Sample Code License. 4*ee44f668SStefano Ceccherini */ 5*ee44f668SStefano Ceccherini 6*ee44f668SStefano Ceccherini #include <Application.h> 7*ee44f668SStefano Ceccherini #include <WindowScreen.h> 8*ee44f668SStefano Ceccherini #include <Screen.h> 9*ee44f668SStefano Ceccherini #include <string.h> 10*ee44f668SStefano Ceccherini 11*ee44f668SStefano Ceccherini typedef long (*blit_hook)(long,long,long,long,long,long); 12*ee44f668SStefano Ceccherini typedef long (*sync_hook)(); 13*ee44f668SStefano Ceccherini 14*ee44f668SStefano Ceccherini class NApplication:public BApplication { 15*ee44f668SStefano Ceccherini public: 16*ee44f668SStefano Ceccherini NApplication(); 17*ee44f668SStefano Ceccherini bool is_quitting; // So that the WindowScreen knows what 18*ee44f668SStefano Ceccherini // to do when disconnected. 19*ee44f668SStefano Ceccherini private: 20*ee44f668SStefano Ceccherini bool QuitRequested(); 21*ee44f668SStefano Ceccherini void ReadyToRun(); 22*ee44f668SStefano Ceccherini }; 23*ee44f668SStefano Ceccherini 24*ee44f668SStefano Ceccherini class NWindowScreen:public BWindowScreen { 25*ee44f668SStefano Ceccherini public: 26*ee44f668SStefano Ceccherini NWindowScreen(status_t*); 27*ee44f668SStefano Ceccherini private: 28*ee44f668SStefano Ceccherini void ScreenConnected(bool); 29*ee44f668SStefano Ceccherini long MyCode(); 30*ee44f668SStefano Ceccherini static long Entry(void*); 31*ee44f668SStefano Ceccherini thread_id tid; 32*ee44f668SStefano Ceccherini sem_id sem; 33*ee44f668SStefano Ceccherini area_id area; 34*ee44f668SStefano Ceccherini uint8* save_buffer; 35*ee44f668SStefano Ceccherini uint8* frame_buffer; 36*ee44f668SStefano Ceccherini ulong line_length; 37*ee44f668SStefano Ceccherini bool thread_is_locked; // small hack to allow to quit the 38*ee44f668SStefano Ceccherini // app from ScreenConnected() 39*ee44f668SStefano Ceccherini blit_hook blit; // hooks to the graphics driver functions 40*ee44f668SStefano Ceccherini sync_hook sync; 41*ee44f668SStefano Ceccherini }; 42*ee44f668SStefano Ceccherini 43*ee44f668SStefano Ceccherini int main(int, char**) { 44*ee44f668SStefano Ceccherini NApplication app; 45*ee44f668SStefano Ceccherini } 46*ee44f668SStefano Ceccherini 47*ee44f668SStefano Ceccherini NApplication::NApplication() 48*ee44f668SStefano Ceccherini :BApplication("application/x-vnd.Be-sample-jbq1") { 49*ee44f668SStefano Ceccherini Run(); // see you in ReadyToRun() 50*ee44f668SStefano Ceccherini } 51*ee44f668SStefano Ceccherini 52*ee44f668SStefano Ceccherini void NApplication::ReadyToRun() { 53*ee44f668SStefano Ceccherini status_t ret=B_ERROR; 54*ee44f668SStefano Ceccherini is_quitting=false; 55*ee44f668SStefano Ceccherini NWindowScreen* ws=new NWindowScreen(&ret); 56*ee44f668SStefano Ceccherini // exit if constructing the WindowScreen failed. 57*ee44f668SStefano Ceccherini if ((ws==NULL)||(ret<B_OK)) 58*ee44f668SStefano Ceccherini PostMessage(B_QUIT_REQUESTED); 59*ee44f668SStefano Ceccherini } 60*ee44f668SStefano Ceccherini 61*ee44f668SStefano Ceccherini bool NApplication::QuitRequested() { 62*ee44f668SStefano Ceccherini is_quitting=true; 63*ee44f668SStefano Ceccherini return true; 64*ee44f668SStefano Ceccherini } 65*ee44f668SStefano Ceccherini 66*ee44f668SStefano Ceccherini NWindowScreen::NWindowScreen(status_t* ret) 67*ee44f668SStefano Ceccherini :BWindowScreen("Example",B_8_BIT_640x480,ret) { 68*ee44f668SStefano Ceccherini thread_is_locked=true; 69*ee44f668SStefano Ceccherini tid=0; 70*ee44f668SStefano Ceccherini if (*ret==B_OK) { 71*ee44f668SStefano Ceccherini // this semaphore controls the access to the WindowScreen 72*ee44f668SStefano Ceccherini sem=create_sem(0,"WindowScreen Access"); 73*ee44f668SStefano Ceccherini // this area is used to save the whole framebuffer when 74*ee44f668SStefano Ceccherini // switching workspaces. (better than malloc()). 75*ee44f668SStefano Ceccherini area=create_area("save",(void**)&save_buffer,B_ANY_ADDRESS 76*ee44f668SStefano Ceccherini ,640*2048,B_NO_LOCK,B_READ_AREA|B_WRITE_AREA); 77*ee44f668SStefano Ceccherini // exit if an error occured. 78*ee44f668SStefano Ceccherini if ((sem<B_OK)||(area<B_OK)) *ret=B_ERROR; 79*ee44f668SStefano Ceccherini else Show(); // let's go. See you in ScreenConnected. 80*ee44f668SStefano Ceccherini } 81*ee44f668SStefano Ceccherini } 82*ee44f668SStefano Ceccherini 83*ee44f668SStefano Ceccherini void NWindowScreen::ScreenConnected(bool connected) { 84*ee44f668SStefano Ceccherini if (connected) { 85*ee44f668SStefano Ceccherini if ((SetSpace(B_8_BIT_640x480)<B_OK) 86*ee44f668SStefano Ceccherini ||(SetFrameBuffer(640,2048)<B_OK)) { 87*ee44f668SStefano Ceccherini // properly set the framebuffer. exit if an error occurs. 88*ee44f668SStefano Ceccherini be_app->PostMessage(B_QUIT_REQUESTED); 89*ee44f668SStefano Ceccherini return; 90*ee44f668SStefano Ceccherini } 91*ee44f668SStefano Ceccherini // get the hardware acceleration hooks. get them each time 92*ee44f668SStefano Ceccherini // the WindowScreen is connected, because of multiple 93*ee44f668SStefano Ceccherini // monitor support 94*ee44f668SStefano Ceccherini blit=(blit_hook)CardHookAt(7); 95*ee44f668SStefano Ceccherini sync=(sync_hook)CardHookAt(10); 96*ee44f668SStefano Ceccherini // cannot work with no hardware blitting 97*ee44f668SStefano Ceccherini if (blit==NULL) { 98*ee44f668SStefano Ceccherini be_app->PostMessage(B_QUIT_REQUESTED); 99*ee44f668SStefano Ceccherini return; 100*ee44f668SStefano Ceccherini } 101*ee44f668SStefano Ceccherini // get the framebuffer-related info, each time the 102*ee44f668SStefano Ceccherini // WindowScreen is connected (multiple monitor) 103*ee44f668SStefano Ceccherini frame_buffer=(uint8*)(CardInfo()->frame_buffer); 104*ee44f668SStefano Ceccherini line_length=FrameBufferInfo()->bytes_per_row; 105*ee44f668SStefano Ceccherini if (tid==0) { 106*ee44f668SStefano Ceccherini // clean the framebuffer 107*ee44f668SStefano Ceccherini memset(frame_buffer,0,2048*line_length); 108*ee44f668SStefano Ceccherini // spawn the rendering thread. exit if an error occurs. 109*ee44f668SStefano Ceccherini if (((tid=spawn_thread(Entry,"rendering thread", 110*ee44f668SStefano Ceccherini B_URGENT_DISPLAY_PRIORITY,this))<B_OK) 111*ee44f668SStefano Ceccherini ||(resume_thread(tid)<B_OK)) 112*ee44f668SStefano Ceccherini be_app->PostMessage(B_QUIT_REQUESTED); 113*ee44f668SStefano Ceccherini } else for (int y=0;y<2048;y++) 114*ee44f668SStefano Ceccherini // restore the framebuffer when switching back from 115*ee44f668SStefano Ceccherini // another workspace. 116*ee44f668SStefano Ceccherini memcpy(frame_buffer+y*line_length, 117*ee44f668SStefano Ceccherini save_buffer+640*y,640); 118*ee44f668SStefano Ceccherini // set our color list. 119*ee44f668SStefano Ceccherini rgb_color palette[256]; 120*ee44f668SStefano Ceccherini for (int i=0;i<128;i++) { 121*ee44f668SStefano Ceccherini rgb_color c1={i*2,i*2,i*2}; 122*ee44f668SStefano Ceccherini rgb_color c2={127+i,2*i,254}; 123*ee44f668SStefano Ceccherini palette[i]=c1; 124*ee44f668SStefano Ceccherini palette[i+128]=c2; 125*ee44f668SStefano Ceccherini } 126*ee44f668SStefano Ceccherini SetColorList(palette); 127*ee44f668SStefano Ceccherini // allow the rendering thread to run. 128*ee44f668SStefano Ceccherini thread_is_locked=false; 129*ee44f668SStefano Ceccherini release_sem(sem); 130*ee44f668SStefano Ceccherini } else { 131*ee44f668SStefano Ceccherini // block the rendering thread. 132*ee44f668SStefano Ceccherini if (!thread_is_locked) { 133*ee44f668SStefano Ceccherini acquire_sem(sem); 134*ee44f668SStefano Ceccherini thread_is_locked=true; 135*ee44f668SStefano Ceccherini } 136*ee44f668SStefano Ceccherini // kill the rendering and clean up when quitting 137*ee44f668SStefano Ceccherini if ((((NApplication*)be_app)->is_quitting)) { 138*ee44f668SStefano Ceccherini status_t ret; 139*ee44f668SStefano Ceccherini kill_thread(tid); 140*ee44f668SStefano Ceccherini wait_for_thread(tid,&ret); 141*ee44f668SStefano Ceccherini delete_sem(sem); 142*ee44f668SStefano Ceccherini delete_area(area); 143*ee44f668SStefano Ceccherini } else { 144*ee44f668SStefano Ceccherini // set the color list black so that the screen doesn't seem 145*ee44f668SStefano Ceccherini // to freeze while saving the framebuffer 146*ee44f668SStefano Ceccherini rgb_color c={0,0,0}; 147*ee44f668SStefano Ceccherini rgb_color palette[256]; 148*ee44f668SStefano Ceccherini for (int i=0;i<256;i++) 149*ee44f668SStefano Ceccherini palette[i]=c; 150*ee44f668SStefano Ceccherini SetColorList(palette); 151*ee44f668SStefano Ceccherini 152*ee44f668SStefano Ceccherini // save the framebuffer 153*ee44f668SStefano Ceccherini for (int y=0;y<2048;y++) 154*ee44f668SStefano Ceccherini memcpy(save_buffer+640*y, 155*ee44f668SStefano Ceccherini frame_buffer+y*line_length,640); 156*ee44f668SStefano Ceccherini } 157*ee44f668SStefano Ceccherini } 158*ee44f668SStefano Ceccherini } 159*ee44f668SStefano Ceccherini 160*ee44f668SStefano Ceccherini long NWindowScreen::Entry(void* p) { 161*ee44f668SStefano Ceccherini return ((NWindowScreen*)p)->MyCode(); 162*ee44f668SStefano Ceccherini } 163*ee44f668SStefano Ceccherini 164*ee44f668SStefano Ceccherini long NWindowScreen::MyCode() { 165*ee44f668SStefano Ceccherini // gain access to the framebuffer before writing to it. 166*ee44f668SStefano Ceccherini 167*ee44f668SStefano Ceccherini acquire_sem(sem); 168*ee44f668SStefano Ceccherini 169*ee44f668SStefano Ceccherini for (int j=1440;j<2048;j++) { 170*ee44f668SStefano Ceccherini for (int i=0;i<640;i++) { 171*ee44f668SStefano Ceccherini // draw the backgroud ripple pattern 172*ee44f668SStefano Ceccherini float val=63.99*(1+cos(2*M_PI*((i-320)*(i-320) 173*ee44f668SStefano Ceccherini +(j-1744)*(j-1744))/1216)); 174*ee44f668SStefano Ceccherini frame_buffer[i+line_length*j]=int(val); 175*ee44f668SStefano Ceccherini } 176*ee44f668SStefano Ceccherini } 177*ee44f668SStefano Ceccherini ulong numframe=0; 178*ee44f668SStefano Ceccherini bigtime_t trgt=0; 179*ee44f668SStefano Ceccherini ulong y_origin; 180*ee44f668SStefano Ceccherini uint8* current_frame; 181*ee44f668SStefano Ceccherini while(true) { 182*ee44f668SStefano Ceccherini // the framebuffer coordinates of the next frame 183*ee44f668SStefano Ceccherini y_origin=480*(numframe%3); 184*ee44f668SStefano Ceccherini // and a pointer to it 185*ee44f668SStefano Ceccherini current_frame=frame_buffer+y_origin*line_length; 186*ee44f668SStefano Ceccherini // copy the background 187*ee44f668SStefano Ceccherini int ytop=numframe%608,ybot=ytop+479; 188*ee44f668SStefano Ceccherini if (ybot<608) { 189*ee44f668SStefano Ceccherini blit(0,1440+ytop,0,y_origin,639,479); 190*ee44f668SStefano Ceccherini } else { 191*ee44f668SStefano Ceccherini blit(0,1440+ytop,0,y_origin,639,1086-ybot); 192*ee44f668SStefano Ceccherini blit(0,1440,0,y_origin+1087-ybot,639,ybot-608); 193*ee44f668SStefano Ceccherini } 194*ee44f668SStefano Ceccherini // calculate the circle position. doing such calculations 195*ee44f668SStefano Ceccherini // between blit() and sync() is a good idea. 196*ee44f668SStefano Ceccherini uint32 x=(uint32)(287.99*(1+sin(numframe/72.))); 197*ee44f668SStefano Ceccherini uint32 y=(uint32)(207.99*(1+sin(numframe/52.))); 198*ee44f668SStefano Ceccherini if (sync) sync(); 199*ee44f668SStefano Ceccherini // draw the circle 200*ee44f668SStefano Ceccherini for (int j=0;j<64;j++) { 201*ee44f668SStefano Ceccherini for (int i=0;i<64;i++) { 202*ee44f668SStefano Ceccherini if ((i-31)*(i-32)+(j-31)*(j-32)<=1024) 203*ee44f668SStefano Ceccherini current_frame[x+i+line_length*(y+j)]+=128; 204*ee44f668SStefano Ceccherini } 205*ee44f668SStefano Ceccherini } 206*ee44f668SStefano Ceccherini // release the semaphore while waiting. gotta release it 207*ee44f668SStefano Ceccherini // at some point or nasty things will happen! 208*ee44f668SStefano Ceccherini release_sem(sem); 209*ee44f668SStefano Ceccherini // try to sync with the vertical retrace 210*ee44f668SStefano Ceccherini if (BScreen(this).WaitForRetrace()!=B_OK) { 211*ee44f668SStefano Ceccherini // we're doing some triple buffering. unwanted things would 212*ee44f668SStefano Ceccherini // happen if we rendered more pictures than the card can 213*ee44f668SStefano Ceccherini // display. we here make sure not to render more than 55.5 214*ee44f668SStefano Ceccherini // pictures per second if the card does not support retrace 215*ee44f668SStefano Ceccherini // syncing 216*ee44f668SStefano Ceccherini if (system_time()<trgt) snooze(trgt-system_time()); 217*ee44f668SStefano Ceccherini trgt=system_time()+18000; 218*ee44f668SStefano Ceccherini } 219*ee44f668SStefano Ceccherini // acquire the semaphore back before talking to the driver 220*ee44f668SStefano Ceccherini acquire_sem(sem); 221*ee44f668SStefano Ceccherini // do the page-flipping 222*ee44f668SStefano Ceccherini MoveDisplayArea(0,y_origin); 223*ee44f668SStefano Ceccherini // and go to the next frame! 224*ee44f668SStefano Ceccherini numframe++; 225*ee44f668SStefano Ceccherini } 226*ee44f668SStefano Ceccherini return 0; 227*ee44f668SStefano Ceccherini } 228