|
|
@@ -64,7 +64,9 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, |
|
|
|
CConn* cc_) |
|
|
|
: Fl_Window(w, h), cc(cc_), offscreen(NULL), overlay(NULL), |
|
|
|
firstUpdate(true), |
|
|
|
delayedFullscreen(false), delayedDesktopSize(false) |
|
|
|
delayedFullscreen(false), delayedDesktopSize(false), |
|
|
|
statsLastFrame(0), statsLastPixels(0), statsLastPosition(0), |
|
|
|
statsGraph(NULL) |
|
|
|
{ |
|
|
|
Fl_Group* group; |
|
|
|
|
|
|
@@ -174,6 +176,12 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, |
|
|
|
fullscreen_on(); |
|
|
|
} |
|
|
|
|
|
|
|
// Throughput graph for debugging |
|
|
|
if (vlog.getLevel() >= LogWriter::LEVEL_DEBUG) { |
|
|
|
memset(&stats, 0, sizeof(stats)); |
|
|
|
Fl::add_timeout(0, handleStatsTimeout, this); |
|
|
|
} |
|
|
|
|
|
|
|
// Show hint about menu key |
|
|
|
Fl::add_timeout(0.5, menuOverlay, this); |
|
|
|
} |
|
|
@@ -187,6 +195,7 @@ DesktopWindow::~DesktopWindow() |
|
|
|
Fl::remove_timeout(handleResizeTimeout, this); |
|
|
|
Fl::remove_timeout(handleFullscreenTimeout, this); |
|
|
|
Fl::remove_timeout(handleEdgeScroll, this); |
|
|
|
Fl::remove_timeout(handleStatsTimeout, this); |
|
|
|
Fl::remove_timeout(menuOverlay, this); |
|
|
|
Fl::remove_timeout(updateOverlay, this); |
|
|
|
|
|
|
@@ -195,6 +204,8 @@ DesktopWindow::~DesktopWindow() |
|
|
|
delete overlay; |
|
|
|
delete offscreen; |
|
|
|
|
|
|
|
delete statsGraph; |
|
|
|
|
|
|
|
// FLTK automatically deletes all child widgets, so we shouldn't touch |
|
|
|
// them ourselves here |
|
|
|
} |
|
|
@@ -325,6 +336,23 @@ void DesktopWindow::draw() |
|
|
|
update_child(*viewport); |
|
|
|
} |
|
|
|
|
|
|
|
// Debug graph (if active) |
|
|
|
if (statsGraph) { |
|
|
|
int ox, oy, ow, oh; |
|
|
|
|
|
|
|
ox = X = w() - statsGraph->width() - 30; |
|
|
|
oy = Y = h() - statsGraph->height() - 30; |
|
|
|
ow = statsGraph->width(); |
|
|
|
oh = statsGraph->height(); |
|
|
|
|
|
|
|
fl_clip_box(ox, oy, ow, oh, ox, oy, ow, oh); |
|
|
|
|
|
|
|
if (offscreen) |
|
|
|
statsGraph->blend(offscreen, ox - X, oy - Y, ox, oy, ow, oh, 204); |
|
|
|
else |
|
|
|
statsGraph->blend(ox - X, oy - Y, ox, oy, ow, oh, 204); |
|
|
|
} |
|
|
|
|
|
|
|
// Overlay (if active) |
|
|
|
if (overlay) { |
|
|
|
int ox, oy, ow, oh; |
|
|
@@ -1161,3 +1189,128 @@ void DesktopWindow::handleEdgeScroll(void *data) |
|
|
|
|
|
|
|
Fl::repeat_timeout(0.1, handleEdgeScroll, data); |
|
|
|
} |
|
|
|
|
|
|
|
void DesktopWindow::handleStatsTimeout(void *data) |
|
|
|
{ |
|
|
|
DesktopWindow *self = (DesktopWindow*)data; |
|
|
|
|
|
|
|
const size_t statsCount = sizeof(stats)/sizeof(stats[0]); |
|
|
|
|
|
|
|
unsigned frame, pixels, pos; |
|
|
|
unsigned elapsed; |
|
|
|
|
|
|
|
const unsigned statsWidth = 200; |
|
|
|
const unsigned statsHeight = 100; |
|
|
|
const unsigned graphWidth = statsWidth - 10; |
|
|
|
const unsigned graphHeight = statsHeight - 25; |
|
|
|
|
|
|
|
Fl_Image_Surface *surface; |
|
|
|
Fl_RGB_Image *image; |
|
|
|
|
|
|
|
unsigned maxFPS, maxPPS, maxBPS; |
|
|
|
size_t i; |
|
|
|
|
|
|
|
char buffer[256]; |
|
|
|
|
|
|
|
frame = self->cc->getFrameCount(); |
|
|
|
pixels = self->cc->getPixelCount(); |
|
|
|
pos = self->cc->getPosition(); |
|
|
|
elapsed = msSince(&self->statsLastTime); |
|
|
|
if (elapsed < 1) |
|
|
|
elapsed = 1; |
|
|
|
|
|
|
|
memmove(&self->stats[0], &self->stats[1], sizeof(stats[0])*(statsCount-1)); |
|
|
|
|
|
|
|
self->stats[statsCount-1].fps = (frame - self->statsLastFrame) * 1000 / elapsed; |
|
|
|
self->stats[statsCount-1].pps = (pixels - self->statsLastPixels) * 1000 / elapsed; |
|
|
|
self->stats[statsCount-1].bps = (pos - self->statsLastPosition) * 1000 / elapsed; |
|
|
|
|
|
|
|
gettimeofday(&self->statsLastTime, NULL); |
|
|
|
self->statsLastFrame = frame; |
|
|
|
self->statsLastPixels = pixels; |
|
|
|
self->statsLastPosition = pos; |
|
|
|
|
|
|
|
#if !defined(WIN32) && !defined(__APPLE__) |
|
|
|
// FLTK < 1.3.5 crashes if fl_gc is unset |
|
|
|
if (!fl_gc) |
|
|
|
fl_gc = XDefaultGC(fl_display, 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
surface = new Fl_Image_Surface(statsWidth, statsHeight); |
|
|
|
surface->set_current(); |
|
|
|
|
|
|
|
fl_rectf(0, 0, statsWidth, statsHeight, FL_BLACK); |
|
|
|
|
|
|
|
fl_rect(5, 5, graphWidth, graphHeight, FL_WHITE); |
|
|
|
|
|
|
|
maxFPS = maxPPS = maxBPS = 0; |
|
|
|
for (i = 0;i < statsCount;i++) { |
|
|
|
if (self->stats[i].fps > maxFPS) |
|
|
|
maxFPS = self->stats[i].fps; |
|
|
|
if (self->stats[i].pps > maxPPS) |
|
|
|
maxPPS = self->stats[i].pps; |
|
|
|
if (self->stats[i].bps > maxBPS) |
|
|
|
maxBPS = self->stats[i].bps; |
|
|
|
} |
|
|
|
|
|
|
|
if (maxFPS != 0) { |
|
|
|
fl_color(FL_GREEN); |
|
|
|
for (i = 0;i < statsCount-1;i++) { |
|
|
|
fl_line(5 + i * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i].fps / maxFPS, |
|
|
|
5 + (i+1) * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i+1].fps / maxFPS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (maxPPS != 0) { |
|
|
|
fl_color(FL_YELLOW); |
|
|
|
for (i = 0;i < statsCount-1;i++) { |
|
|
|
fl_line(5 + i * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i].pps / maxPPS, |
|
|
|
5 + (i+1) * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i+1].pps / maxPPS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (maxBPS != 0) { |
|
|
|
fl_color(FL_RED); |
|
|
|
for (i = 0;i < statsCount-1;i++) { |
|
|
|
fl_line(5 + i * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i].bps / maxBPS, |
|
|
|
5 + (i+1) * graphWidth / statsCount, |
|
|
|
5 + graphHeight - graphHeight * self->stats[i+1].bps / maxBPS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fl_font(FL_HELVETICA, 10); |
|
|
|
|
|
|
|
fl_color(FL_GREEN); |
|
|
|
snprintf(buffer, sizeof(buffer), "%u fps", self->stats[statsCount-1].fps); |
|
|
|
fl_draw(buffer, 5, statsHeight - 5); |
|
|
|
|
|
|
|
fl_color(FL_YELLOW); |
|
|
|
siPrefix(self->stats[statsCount-1].pps * 8, "pix/s", |
|
|
|
buffer, sizeof(buffer), 3); |
|
|
|
fl_draw(buffer, 5 + (statsWidth-10)/3, statsHeight - 5); |
|
|
|
|
|
|
|
fl_color(FL_RED); |
|
|
|
iecPrefix(self->stats[statsCount-1].bps * 8, "Bps", |
|
|
|
buffer, sizeof(buffer), 3); |
|
|
|
fl_draw(buffer, 5 + (statsWidth-10)*2/3, statsHeight - 5); |
|
|
|
|
|
|
|
image = surface->image(); |
|
|
|
delete surface; |
|
|
|
|
|
|
|
Fl_Display_Device::display_device()->set_current(); |
|
|
|
|
|
|
|
delete self->statsGraph; |
|
|
|
self->statsGraph = new Surface(image); |
|
|
|
delete image; |
|
|
|
|
|
|
|
self->damage(FL_DAMAGE_CHILD, self->w() - statsWidth - 30, |
|
|
|
self->h() - statsHeight - 30, |
|
|
|
statsWidth, statsHeight); |
|
|
|
|
|
|
|
Fl::repeat_timeout(0.5, handleStatsTimeout, data); |
|
|
|
} |