2 Copyright 1999, Be Incorporated. All Rights Reserved.
3 This file may be used under the terms of the Be Sample Code License.
6 #include <Application.h>
7 #include <WindowScreen.h>
11 typedef long (*blit_hook
)(long,long,long,long,long,long);
12 typedef long (*sync_hook
)();
14 class NApplication
:public BApplication
{
17 bool is_quitting
; // So that the WindowScreen knows what
18 // to do when disconnected.
24 class NWindowScreen
:public BWindowScreen
{
26 NWindowScreen(status_t
*);
28 void ScreenConnected(bool);
31 static int32
Entry(void*);
39 bool fThreadIsLocked
; // small hack to allow to quit the
40 // app from ScreenConnected()
41 blit_hook fBlitHook
; // hooks to the graphics driver functions
53 NApplication::NApplication()
54 :BApplication("application/x-vnd.Be-sample-jbq1")
56 Run(); // see you in ReadyToRun()
61 NApplication::ReadyToRun()
63 status_t ret
= B_ERROR
;
65 NWindowScreen
* windowScreen
= new NWindowScreen(&ret
);
66 // exit if constructing the WindowScreen failed.
67 if (windowScreen
== NULL
|| ret
< B_OK
)
68 PostMessage(B_QUIT_REQUESTED
);
73 NApplication::QuitRequested()
80 NWindowScreen::NWindowScreen(status_t
* ret
)
82 BWindowScreen("Example", B_8_BIT_640x480
, ret
),
89 fThreadIsLocked(true),
96 // this semaphore controls the access to the WindowScreen
97 fSem
= create_sem(0, "WindowScreen Access");
103 // this area is used to save the whole framebuffer when
104 // switching workspaces. (better than malloc()).
105 fArea
= create_area("save", (void**)&fSaveBuffer
, B_ANY_ADDRESS
,
106 640 * 2048, B_NO_LOCK
, B_READ_AREA
|B_WRITE_AREA
);
114 Show(); // let's go. See you in ScreenConnected.
119 NWindowScreen::ScreenConnected(bool connected
)
122 if (SetSpace(B_8_BIT_640x480
) < B_OK
|| SetFrameBuffer(640, 2048) < B_OK
) {
123 // properly set the framebuffer. exit if an error occurs.
124 be_app
->PostMessage(B_QUIT_REQUESTED
);
128 // get the hardware acceleration hooks. get them each time
129 // the WindowScreen is connected, because of multiple
131 fBlitHook
= (blit_hook
)CardHookAt(7);
132 fSyncHook
= (sync_hook
)CardHookAt(10);
134 // cannot work with no hardware blitting
135 if (fBlitHook
== NULL
) {
136 be_app
->PostMessage(B_QUIT_REQUESTED
);
139 // get the framebuffer-related info, each time the
140 // WindowScreen is connected (multiple monitor)
141 fFrameBuffer
= (uint8
*)(CardInfo()->frame_buffer
);
142 fLineLength
= FrameBufferInfo()->bytes_per_row
;
143 if (fThreadId
== 0) {
144 // clean the framebuffer
145 memset(fFrameBuffer
, 0, 2048 * fLineLength
);
146 // spawn the rendering thread. exit if an error occurs.
147 fThreadId
= spawn_thread(Entry
, "rendering thread", B_URGENT_DISPLAY_PRIORITY
, this);
148 if (fThreadId
< B_OK
|| resume_thread(fThreadId
) < B_OK
)
149 be_app
->PostMessage(B_QUIT_REQUESTED
);
151 for (int y
= 0; y
< 2048; y
++) {
152 // restore the framebuffer when switching back from
153 // another workspace.
154 memcpy(fFrameBuffer
+ y
* fLineLength
, fSaveBuffer
+ 640 * y
, 640);
158 // set our color list.
159 rgb_color palette
[256];
160 for (int i
= 0; i
< 128; i
++) {
161 rgb_color c1
= {i
* 2, i
* 2, i
* 2};
162 rgb_color c2
= {127 + i
, 2 * i
, 254};
164 palette
[i
+ 128] = c2
;
166 SetColorList(palette
);
167 // allow the rendering thread to run.
168 fThreadIsLocked
= false;
171 // block the rendering thread.
172 if (!fThreadIsLocked
) {
174 fThreadIsLocked
= true;
177 // kill the rendering and clean up when quitting
178 if ((((NApplication
*)be_app
)->is_quitting
)) {
180 kill_thread(fThreadId
);
181 wait_for_thread(fThreadId
, &ret
);
185 // set the color list black so that the screen doesn't seem
186 // to freeze while saving the framebuffer
187 rgb_color c
= { 0, 0, 0 };
188 rgb_color palette
[256];
189 for (int i
= 0; i
< 256; i
++)
191 SetColorList(palette
);
193 // save the framebuffer
194 for (int y
= 0; y
< 2048; y
++)
195 memcpy(fSaveBuffer
+ 640 * y
, fFrameBuffer
+ y
* fLineLength
, 640);
202 NWindowScreen::Entry(void* castToThis
)
204 return ((NWindowScreen
*)castToThis
)->DrawingCode();
209 NWindowScreen::DrawingCode()
211 // gain access to the framebuffer before writing to it.
215 for (int j
= 1440; j
< 2048; j
++) {
216 for (int i
; i
< 640; i
++) {
217 // draw the backgroud ripple pattern
218 float val
=63.99*(1+cos(2*M_PI
*((i
-320)*(i
-320)+(j
-1744)*(j
-1744))/1216));
219 fFrameBuffer
[i
+ fLineLength
*j
]=int(val
);
226 uint8
* current_frame
;
228 // the framebuffer coordinates of the next frame
229 y_origin
= 480 * (numframe
% 3);
230 // and a pointer to it
231 current_frame
= fFrameBuffer
+ y_origin
* fLineLength
;
232 // copy the background
233 int ytop
= numframe
% 608, ybot
= ytop
+ 479;
235 fBlitHook(0,1440+ytop
,0,y_origin
,639,479);
237 fBlitHook(0,1440+ytop
,0,y_origin
,639,1086-ybot
);
238 fBlitHook(0,1440,0,y_origin
+1087-ybot
,639,ybot
-608);
240 // calculate the circle position. doing such calculations
241 // between blit() and sync() is a good idea.
242 uint32 x
=(uint32
)(287.99*(1+sin(numframe
/72.)));
243 uint32 y
=(uint32
)(207.99*(1+sin(numframe
/52.)));
247 for (int j
= 0; j
< 64; j
++) {
248 for (int i
= 0; i
< 64; i
++) {
249 if ((i
-31)*(i
-32)+(j
-31)*(j
-32)<=1024)
250 current_frame
[x
+ i
+ fLineLength
* (y
+ j
)] += 128;
253 // release the semaphore while waiting. gotta release it
254 // at some point or nasty things will happen!
256 // try to sync with the vertical retrace
257 if (BScreen(this).WaitForRetrace() != B_OK
) {
258 // we're doing some triple buffering. unwanted things would
259 // happen if we rendered more pictures than the card can
260 // display. we here make sure not to render more than 55.5
261 // pictures per second if the card does not support retrace
263 if (system_time() < trgt
)
264 snooze(trgt
- system_time());
265 trgt
= system_time() + 18000;
267 // acquire the semaphore back before talking to the driver
269 // do the page-flipping
270 MoveDisplayArea(0, y_origin
);
271 // and go to the next frame!