File: sdl.cpp

package info (click to toggle)
higan 094-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,780 kB
  • ctags: 15,643
  • sloc: cpp: 103,963; ansic: 659; makefile: 531; sh: 25
file content (141 lines) | stat: -rwxr-xr-x 3,505 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <X11/extensions/XShm.h>
#include <SDL/SDL.h>

namespace ruby {

struct pVideoSDL {
  Display* display;
  SDL_Surface* screen;
  SDL_Surface* buffer;
  unsigned iwidth, iheight;

  struct {
    uintptr_t handle;

    unsigned width;
    unsigned height;
  } settings;

  bool cap(const string& name) {
    if(name == Video::Handle) return true;
    return false;
  }

  any get(const string& name) {
    if(name == Video::Handle) return settings.handle;
    return false;
  }

  bool set(const string& name, const any& value) {
    if(name == Video::Handle) {
      settings.handle = any_cast<uintptr_t>(value);
      return true;
    }

    return false;
  }

  void resize(unsigned width, unsigned height) {
    if(iwidth >= width && iheight >= height) return;

    iwidth  = max(width,  iwidth);
    iheight = max(height, iheight);

    if(buffer) SDL_FreeSurface(buffer);
    buffer = SDL_CreateRGBSurface(
      SDL_SWSURFACE, iwidth, iheight, 32,
      0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
    );
  }

  bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) {
    if(width != settings.width || height != settings.height) {
      resize(settings.width = width, settings.height = height);
    }

    if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
    pitch = buffer->pitch;
    return data = (uint32_t*)buffer->pixels;
  }

  void unlock() {
    if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);
  }

  void clear() {
    if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
    for(unsigned y = 0; y < iheight; y++) {
      uint32_t* data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2);
      for(unsigned x = 0; x < iwidth; x++) *data++ = 0xff000000;
    }
    if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);
    refresh();
  }

  void refresh() {
    //ruby input is X8R8G8B8, top 8-bits are ignored.
    //as SDL forces us to use a 32-bit buffer, we must set alpha to 255 (full opacity)
    //to prevent blending against the window beneath when X window visual is 32-bits.
    if(SDL_MUSTLOCK(buffer)) SDL_LockSurface(buffer);
    for(unsigned y = 0; y < settings.height; y++) {
      uint32_t *data = (uint32_t*)buffer->pixels + y * (buffer->pitch >> 2);
      for(unsigned x = 0; x < settings.width; x++) *data++ |= 0xff000000;
    }
    if(SDL_MUSTLOCK(buffer)) SDL_UnlockSurface(buffer);

    XWindowAttributes attributes;
    XGetWindowAttributes(display, settings.handle, &attributes);

    SDL_Rect src, dest;

    src.x = 0;
    src.y = 0;
    src.w = settings.width;
    src.h = settings.height;

    dest.x = 0;
    dest.y = 0;
    dest.w = attributes.width;
    dest.h = attributes.height;

    SDL_SoftStretch(buffer, &src, screen, &dest);
    SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
  }

  bool init() {
    display = XOpenDisplay(0);

    char env[512];
    sprintf(env, "SDL_WINDOWID=%ld", (long int)settings.handle);
    putenv(env);

    SDL_InitSubSystem(SDL_INIT_VIDEO);
    screen = SDL_SetVideoMode(2560, 1600, 32, SDL_HWSURFACE);
    XUndefineCursor(display, settings.handle);

    buffer  = 0;
    iwidth  = 0;
    iheight = 0;
    resize(settings.width = 256, settings.height = 256);

    return true;
  }

  void term() {
    XCloseDisplay(display);
    SDL_FreeSurface(buffer);
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
  }

  pVideoSDL() {
    settings.handle = 0;
  }
};

DeclareVideo(SDL)

};