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