Added split screen functionality, for showing up to four groups at a time.
authorSteinar H. Gunderson <sesse@samfundet.no>
Sun, 20 Feb 2005 00:51:39 +0000 (00:51 +0000)
committerSteinar H. Gunderson <sesse@samfundet.no>
Sun, 20 Feb 2005 00:51:39 +0000 (00:51 +0000)
bigscreen/Makefile
bigscreen/ccbs_bigscreen.cpp
bigscreen/splitscreen.cpp [new file with mode: 0644]
bigscreen/splitscreen.h [new file with mode: 0644]

index 2303ff9..2afcd30 100644 (file)
@@ -4,7 +4,7 @@ CPPFLAGS=-I/usr/include/postgresql $(shell freetype-config --cflags) -Itinyptc/
 CXXFLAGS=-g -Wall
 LDFLAGS=-L/usr/X11R6/lib
 LIBS=$(shell freetype-config --libs) $(shell libpq3-config) -lpqxx tinyptc/libtinyptc.a -lX11
-CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o flagtrigger.o widestring.o fetch_current_tournament.o fetch_list_of_active_groups.o fetch_max_score_for_song.o fetch_max_score_for_player.o fetch_group.o fonts.o groupscreen.o screen.o
+CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o flagtrigger.o widestring.o fetch_current_tournament.o fetch_list_of_active_groups.o fetch_max_score_for_song.o fetch_max_score_for_player.o fetch_group.o fonts.o groupscreen.o splitscreen.o screen.o
 
 all: ccbs-bigscreen
 
index fbbc0aa..2114093 100644 (file)
 #include "fetch_group.h"
 #include "fonts.h"
 #include "groupscreen.h"
+#include "splitscreen.h"
 
 Tournament active_tournament;
 std::vector<SkeletonGroup> active_groups;
 std::vector<GenericScreen *> screens;
+SplitScreen *mainscreen = NULL;
 unsigned char framebuf[800 * 600 * 4], screenbuf[800 * 600 * 4];
 
 void init(pqxx::connection &conn)
@@ -24,6 +26,8 @@ void init(pqxx::connection &conn)
        }
        screens.erase(screens.begin(), screens.end());
        
+       delete mainscreen;
+       
        conn.perform(FetchCurrentTournament(&active_tournament));
        conn.perform(FetchListOfActiveGroups(&active_groups));
 
@@ -39,6 +43,14 @@ void init(pqxx::connection &conn)
                        screens.push_back(new GroupScreen(conn, i->tournament, i->round, i->parallel));
                }
        }
+
+       // hack
+       screens.push_back(NULL);
+       screens.push_back(NULL);
+       screens.push_back(NULL);
+       screens.push_back(NULL);
+
+       mainscreen = new SplitScreen(screens[0], screens[1], screens[2], screens[3]);
 }
 
 void main_loop(pqxx::connection &conn)
@@ -49,17 +61,11 @@ void main_loop(pqxx::connection &conn)
                return;
        }
 
-       memset(framebuf, 0, 800*600*4);
-       
-       if (screens.size() > 0) {
-               if (screens[0]->check_invalidated()) {
-                       screens[0]->draw(screenbuf);
-               }
-
-               memcpy(framebuf, screenbuf, 800*600*4);
+       if (mainscreen->check_invalidated()) {
+               mainscreen->draw(framebuf);
        }
-
        ptc_update(framebuf);
+
        conn.await_notification(0, 50000);
 }
 
diff --git a/bigscreen/splitscreen.cpp b/bigscreen/splitscreen.cpp
new file mode 100644 (file)
index 0000000..a322fec
--- /dev/null
@@ -0,0 +1,70 @@
+#include <cstring>
+#include "splitscreen.h"
+
+SplitScreen::SplitScreen(GenericScreen *s1, GenericScreen *s2, GenericScreen *s3, GenericScreen *s4)
+       : valid(false)
+{
+       subscreens[0] = s1;
+       subscreens[1] = s2;
+       subscreens[2] = s3;
+       subscreens[3] = s4;
+
+       memset(subbufs[0], 0, 800*600*4);
+       memset(subbufs[1], 0, 800*600*4);
+       memset(subbufs[2], 0, 800*600*4);
+       memset(subbufs[3], 0, 800*600*4);
+}
+
+SplitScreen::~SplitScreen()
+{
+}
+
+bool SplitScreen::check_invalidated()
+{
+       if (!valid)
+               return true;
+       
+       for (unsigned i = 0; i < 4; ++i) {
+               if (subscreens[i] && subscreens[i]->check_invalidated())
+                       return true;
+       }
+
+       return false;
+}
+
+void SplitScreen::draw(unsigned char *buf)
+{
+       for (unsigned i = 0; i < 4; ++i) {
+               if (subscreens[i] && subscreens[i]->check_invalidated()) {
+                       subscreens[i]->draw(subbufs[i]);
+               }
+       }
+       
+       downscale_2x2(buf, subbufs[0]);
+       downscale_2x2(buf + 400 * 4, subbufs[1]);
+       downscale_2x2(buf + 800 * 300 * 4, subbufs[2]);
+       downscale_2x2(buf + 800 * 300 * 4 + 400 * 4, subbufs[3]); 
+
+       valid = true;
+}
+       
+// simple box filter (blah)
+void SplitScreen::downscale_2x2(unsigned char *dst, unsigned char *src)
+{
+       for (unsigned y = 0; y < 300; ++y) {
+               unsigned char *sptr1 = src + (y*2) * 800 * 4;
+               unsigned char *sptr2 = src + (y*2+1) * 800 * 4;
+               unsigned char *dptr = dst + y * 800 * 4;
+               
+               for (unsigned x = 0; x < 400; ++x) {
+                       *dptr++ = (sptr1[0] + sptr1[4] + sptr2[0] + sptr2[4]) >> 2;  // red
+                       *dptr++ = (sptr1[1] + sptr1[5] + sptr2[1] + sptr2[5]) >> 2;  // green
+                       *dptr++ = (sptr1[2] + sptr1[6] + sptr2[2] + sptr2[6]) >> 2;  // blue
+                       *dptr++ = (sptr1[3] + sptr1[7] + sptr2[3] + sptr2[7]) >> 2;  // alpha
+
+                       sptr1 += 8;
+                       sptr2 += 8;
+               }
+       }
+}
+
diff --git a/bigscreen/splitscreen.h b/bigscreen/splitscreen.h
new file mode 100644 (file)
index 0000000..3b0616c
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _SPLITSCREEN_H
+#define _SPLITSCREEN_H 1
+
+#include "screen.h"
+
+/* A 4x4 split class */
+class SplitScreen : public GenericScreen {
+private:
+       unsigned char subbufs[4][800 * 600 * 4];
+       GenericScreen *subscreens[4];
+       bool valid;
+
+       void downscale_2x2(unsigned char *dst, unsigned char *src);
+       
+public:
+       SplitScreen(GenericScreen *s1, GenericScreen *s2, GenericScreen *s3, GenericScreen *s4);
+       virtual ~SplitScreen();
+
+       bool check_invalidated();
+       void draw(unsigned char *buf);
+};
+
+#endif /* !defined(_SPLITSCREEN_H) */