1 #include <sys/ipc.h>
2 #include <sys/shm.h>
3 #include <X11/extensions/Xv.h>
4 #include <X11/extensions/Xvlib.h>
5 #include <X11/extensions/XShm.h>
6 #include <SDL/SDL.h>
7 
8 namespace ruby {
9 
10 class pVideoSDL {
11 public:
12   Display *display;
13   SDL_Surface *screen, *buffer;
14   unsigned iwidth, iheight;
15 
16   struct {
17     uintptr_t handle;
18 
19     unsigned width;
20     unsigned height;
21   } settings;
22 
cap(const string & name)23   bool cap(const string& name) {
24     if(name == Video::Handle) return true;
25     return false;
26   }
27 
get(const string & name)28   any get(const string& name) {
29     if(name == Video::Handle) return settings.handle;
30     return false;
31   }
32 
set(const string & name,const any & value)33   bool set(const string& name, const any& value) {
34     if(name == Video::Handle) {
35       settings.handle = any_cast<uintptr_t>(value);
36       return true;
37     }
38 
39     return false;
40   }
41 
resize(unsigned width,unsigned height)42   void resize(unsigned width, unsigned height) {
43     if(iwidth >= width && iheight >= height) return;
44 
45     iwidth  = max(width,  iwidth);
46     iheight = max(height, iheight);
47 
48     if(buffer) SDL_FreeSurface(buffer);
49     buffer = SDL_CreateRGBSurface(
50       SDL_SWSURFACE, iwidth, iheight, 32,
51       0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
52     );
53   }
54 
lock(uint32_t * & data,unsigned & pitch,unsigned width,unsigned height)55   bool lock(uint32_t *&data, unsigned &pitch, unsigned width, unsigned height) {
56     if(width != settings.width || height != settings.height) {
57       resize(settings.width = width, settings.height = height);
58     }
59 
60     if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
61     pitch = buffer->pitch;
62     return data = (uint32_t*)buffer->pixels;
63   }
64 
unlock()65   void unlock() {
66     if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);
67   }
68 
clear()69   void clear() {
70     if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
71     for(unsigned y = 0; y < iheight; y++) {
72       uint32_t *data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2);
73       for(unsigned x = 0; x < iwidth; x++) *data++ = 0xff000000;
74     }
75     if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);
76     refresh();
77   }
78 
refresh()79   void refresh() {
80     //ruby input is X8R8G8B8, top 8-bits are ignored.
81     //as SDL forces us to use a 32-bit buffer, we must set alpha to 255 (full opacity)
82     //to prevent blending against the window beneath when X window visual is 32-bits.
83     if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
84     for(unsigned y = 0; y < settings.height; y++) {
85       uint32_t *data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2);
86       for(unsigned x = 0; x < settings.width; x++) *data++ |= 0xff000000;
87     }
88     if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);
89 
90     XWindowAttributes attributes;
91     XGetWindowAttributes(display, settings.handle, &attributes);
92 
93     SDL_Rect src, dest;
94 
95     src.x = 0;
96     src.y = 0;
97     src.w = settings.width;
98     src.h = settings.height;
99 
100     dest.x = 0;
101     dest.y = 0;
102     dest.w = attributes.width;
103     dest.h = attributes.height;
104 
105     SDL_SoftStretch(buffer, &src, screen, &dest);
106     SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
107   }
108 
init()109   bool init() {
110     display = XOpenDisplay(0);
111 
112     char env[512];
113     sprintf(env, "SDL_WINDOWID=%ld", (long int)settings.handle);
114     putenv(env);
115 
116     SDL_InitSubSystem(SDL_INIT_VIDEO);
117     screen = SDL_SetVideoMode(2560, 1600, 32, SDL_HWSURFACE);
118 
119     buffer  = 0;
120     iwidth  = 0;
121     iheight = 0;
122     resize(settings.width = 256, settings.height = 256);
123 
124     return true;
125   }
126 
term()127   void term() {
128     XCloseDisplay(display);
129     SDL_FreeSurface(buffer);
130     SDL_QuitSubSystem(SDL_INIT_VIDEO);
131   }
132 
pVideoSDL()133   pVideoSDL() {
134     settings.handle = 0;
135   }
136 };
137 
138 DeclareVideo(SDL)
139 
140 };
141