Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#include <Application.h>
#include <WindowScreen.h>
#include <Screen.h>
#include <string.h>
typedef long (*blit_hook)(long,long,long,long,long,long);
typedef long (*sync_hook)();
class NApplication:public BApplication {
public:
NApplication();
bool is_quitting;
private:
bool QuitRequested();
void ReadyToRun();
};
class NWindowScreen:public BWindowScreen {
public:
NWindowScreen(status_t*);
private:
void ScreenConnected(bool);
int32 DrawingCode();
static int32 Entry(void*);
thread_id fThreadId;
sem_id fSem;
area_id fArea;
uint8* fSaveBuffer;
uint8* fFrameBuffer;
ulong fLineLength;
bool fThreadIsLocked;
blit_hook fBlitHook;
sync_hook fSyncHook;
};
int
main()
{
NApplication app;
}
NApplication::NApplication()
:BApplication("application/x-vnd.Be-sample-jbq1")
{
Run();
}
void
NApplication::ReadyToRun()
{
status_t ret = B_ERROR;
is_quitting = false;
NWindowScreen* windowScreen = new NWindowScreen(&ret);
if (windowScreen == NULL || ret < B_OK)
PostMessage(B_QUIT_REQUESTED);
}
bool
NApplication::QuitRequested()
{
is_quitting = true;
return true;
}
NWindowScreen::NWindowScreen(status_t* ret)
:
BWindowScreen("Example", B_8_BIT_640x480, ret),
fThreadId(-1),
fSem(-1),
fArea(-1),
fSaveBuffer(NULL),
fFrameBuffer(NULL),
fLineLength(0),
fThreadIsLocked(true),
fBlitHook(NULL),
fSyncHook(NULL)
{
if (*ret < B_OK)
return;
fSem = create_sem(0, "WindowScreen Access");
if (fSem < B_OK) {
*ret = fSem;
return;
}
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();
}
void
NWindowScreen::ScreenConnected(bool connected)
{
if (connected) {
if (SetSpace(B_8_BIT_640x480) < B_OK || SetFrameBuffer(640, 2048) < B_OK) {
be_app->PostMessage(B_QUIT_REQUESTED);
return;
}
fBlitHook = (blit_hook)CardHookAt(7);
fSyncHook = (sync_hook)CardHookAt(10);
if (fBlitHook == NULL) {
be_app->PostMessage(B_QUIT_REQUESTED);
return;
}
fFrameBuffer = (uint8 *)(CardInfo()->frame_buffer);
fLineLength = FrameBufferInfo()->bytes_per_row;
if (fThreadId == 0) {
memset(fFrameBuffer, 0, 2048 * fLineLength);
fThreadId = spawn_thread(Entry, "rendering thread", B_URGENT_DISPLAY_PRIORITY, this);
if (fThreadId < B_OK || resume_thread(fThreadId) < B_OK)
be_app->PostMessage(B_QUIT_REQUESTED);
} else {
for (int y = 0; y < 2048; y++) {
memcpy(fFrameBuffer + y * fLineLength, fSaveBuffer + 640 * y, 640);
}
}
rgb_color palette[256];
for (int i = 0; i < 128; i++) {
rgb_color c1 = {i * 2, i * 2, i * 2};
rgb_color c2 = {127 + i, 2 * i, 254};
palette[i] = c1;
palette[i + 128] = c2;
}
SetColorList(palette);
fThreadIsLocked = false;
release_sem(fSem);
} else {
if (!fThreadIsLocked) {
acquire_sem(fSem);
fThreadIsLocked = true;
}
if ((((NApplication*)be_app)->is_quitting)) {
status_t ret;
kill_thread(fThreadId);
wait_for_thread(fThreadId, &ret);
delete_sem(fSem);
delete_area(fArea);
} else {
rgb_color c = { 0, 0, 0 };
rgb_color palette[256];
for (int i = 0; i < 256; i++)
palette[i] = c;
SetColorList(palette);
for (int y = 0; y < 2048; y++)
memcpy(fSaveBuffer + 640 * y, fFrameBuffer + y * fLineLength, 640);
}
}
}
int32
NWindowScreen::Entry(void* castToThis)
{
return ((NWindowScreen *)castToThis)->DrawingCode();
}
int32
NWindowScreen::DrawingCode()
{
acquire_sem(fSem);
for (int j = 1440; j < 2048; j++) {
for (int i; i < 640; i++) {
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 y_origin;
uint8* current_frame;
while (true) {
y_origin = 480 * (numframe % 3);
current_frame = fFrameBuffer + y_origin * fLineLength;
int ytop = numframe % 608, ybot = ytop + 479;
if (ybot < 608) {
fBlitHook(0,1440+ytop,0,y_origin,639,479);
} else {
fBlitHook(0,1440+ytop,0,y_origin,639,1086-ybot);
fBlitHook(0,1440,0,y_origin+1087-ybot,639,ybot-608);
}
uint32 x=(uint32)(287.99*(1+sin(numframe/72.)));
uint32 y=(uint32)(207.99*(1+sin(numframe/52.)));
if (fSyncHook)
fSyncHook();
for (int j = 0; j < 64; j++) {
for (int i = 0; i < 64; i++) {
if ((i-31)*(i-32)+(j-31)*(j-32)<=1024)
current_frame[x + i + fLineLength * (y + j)] += 128;
}
}
release_sem(fSem);
if (BScreen(this).WaitForRetrace() != B_OK) {
if (system_time() < trgt)
snooze(trgt - system_time());
trgt = system_time() + 18000;
}
acquire_sem(fSem);
MoveDisplayArea(0, y_origin);
numframe++;
}
return 0;
}