#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <SDL.h>
-#include <SDL_syswm.h>
#if CONF_XSP
+# include <SDL_syswm.h>
# include <X11/extensions/Xsp.h>
#endif
#if CONF_HD
-# include <X11/Xatom.h>
-# include <sys/ipc.h>
-# include <sys/shm.h>
+# include <SDL_haa.h>
#endif
#include "snes9x.h"
-#include "display.h"
#include "platform.h"
-#include "scaler.h"
#include "sdlv.h"
#define DIE(format, ...) do { \
x = m_area.x; y = m_area.y; w = m_area.w; h = m_area.h;
};
- virtual int getRatio() const
+ virtual void getRatio(float & x, float & y) const
{
- return 1;
+ x = 1.0f; y = 1.0f;
};
virtual void prepare() { };
virtual void pause() { };
virtual void resume() { };
+
+ virtual bool filter(const SDL_Event& event) { return false; };
};
const DummyScaler::Factory DummyScaler::factory;
x = m_area.x; y = m_area.y; w = m_area.w; h = m_area.h;
};
- int getRatio() const
+ void getRatio(float & x, float & y) const
{
- return 2;
+ x = 2.0f; y = 2.0f;
};
void prepare() { };
void pause() { };
void resume() { };
+
+ bool filter(const SDL_Event& event) { return false; };
};
const SWScaler::Factory SWScaler::factory;
uint8 * m_surface;
const int m_w, m_h, m_Bpp;
+protected:
ARMScaler(SDL_Surface* screen, int w, int h)
: m_screen(screen), m_w(w), m_h(h),
m_Bpp(m_screen->format->BitsPerPixel / 8)
x = m_area.x; y = m_area.y; w = m_area.w; h = m_area.h;
};
- int getRatio() const
+ void getRatio(float & x, float & y) const
{
- return 2;
+ x = 2.0f; y = 2.0f;
};
void prepare() { };
void pause() { };
void resume() { };
+ bool filter(const SDL_Event& event) { return false; };
};
const ARMScaler::Factory ARMScaler::factory;
#endif
#if CONF_HD
-
-enum hdAtoms {
- ATOM_HILDON_NON_COMPOSITED_WINDOW = 0,
- ATOM_NET_WM_STATE,
- ATOM_NET_WM_STATE_FULLSCREEN,
- ATOM_NET_WM_WINDOW_TYPE,
- ATOM_NET_WM_WINDOW_TYPE_NORMAL,
- ATOM_NET_WM_WINDOW_TYPE_DIALOG,
- ATOM_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR,
- ATOM_HILDON_ANIMATION_CLIENT_READY,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_POSITION,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_SCALE,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_ANCHOR,
- ATOM_HILDON_ANIMATION_CLIENT_MESSAGE_PARENT,
- ATOM_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_SHM,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE,
- ATOM_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT,
- ATOM_HILDON_TEXTURE_CLIENT_READY,
- ATOM_COUNT
-};
-
-static const char * hdAtomNames[] = {
- "_HILDON_NON_COMPOSITED_WINDOW",
- "_NET_WM_STATE",
- "_NET_WM_STATE_FULLSCREEN",
- "_NET_WM_WINDOW_TYPE",
- "_NET_WM_WINDOW_TYPE_NORMAL",
- "_NET_WM_WINDOW_TYPE_DIALOG",
- "_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR",
- "_HILDON_ANIMATION_CLIENT_READY",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_POSITION",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_SCALE",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_ANCHOR",
- "_HILDON_ANIMATION_CLIENT_MESSAGE_PARENT",
- "_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_SHM",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE",
- "_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT",
- "_HILDON_TEXTURE_CLIENT_READY",
- ""
-};
-
-static Atom hdAtomsValues[ATOM_COUNT];
-static bool hdAtomsLoaded = false;
-
-#define HDATOM(X) hdAtomsValues[ ATOM ## X ]
-
-static void hildon_load_atoms(Display* display)
+class HAAScalerBase : public Scaler
{
- if (hdAtomsLoaded) return;
-
- XInternAtoms(display, (char**)hdAtomNames, ATOM_COUNT, True, hdAtomsValues);
- hdAtomsLoaded = true;
-
- if (HDATOM(_HILDON_NON_COMPOSITED_WINDOW) == None) {
- DIE("Hildon Desktop seems not be loaded, since %s is not defined",
- "_HILDON_NON_COMPOSITED_WINDOW");
- return;
- }
-}
-
-/** Enables or disables the Hildon NonCompositedWindow property */
-static void hildon_set_non_compositing(bool enable)
-{
- SDL_SysWMinfo wminfo;
- Display *display;
- Window xwindow;
- XSetWindowAttributes xattr;
- Atom atom;
- int one = 1;
-
- SDL_VERSION(&wminfo.version);
- if (!SDL_GetWMInfo(&wminfo)) return;
-
- wminfo.info.x11.lock_func();
- display = wminfo.info.x11.display;
- xwindow = wminfo.info.x11.fswindow;
- hildon_load_atoms(display);
-
- if (enable) {
- /*
- * The basic idea behind this is to disable the override_redirect
- * window attribute, which SDL sets, and instead use _NET_WM_STATE
- * to tell hildon-desktop to fullscreen the app.
- * I am not really happy with this, which should ideally be fixed
- * at the libsdl level, but seems to work.
- * As soon as the window is managed by Hildon-Desktop again, set for it
- * not to be composited.
- */
- XUnmapWindow(display, xwindow);
- xattr.override_redirect = False;
- XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &xattr);
-
- atom = HDATOM(_NET_WM_STATE_FULLSCREEN);
- XChangeProperty(display, xwindow, HDATOM(_NET_WM_STATE),
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *) &atom, 1);
-
- XChangeProperty(display, xwindow, HDATOM(_HILDON_NON_COMPOSITED_WINDOW),
- XA_INTEGER, 32, PropModeReplace,
- (unsigned char *) &one, 1);
- XMapWindow(display, xwindow);
- } else {
- xattr.override_redirect = True;
- XDeleteProperty(display, xwindow,
- HDATOM(_HILDON_NON_COMPOSITED_WINDOW));
- XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &xattr);
- }
-
- wminfo.info.x11.unlock_func();
-}
-
-class HDScalerBase : public Scaler
-{
- SDL_Surface * m_screen;
+ SDL_Surface *m_screen;
SDL_Rect m_area;
+ HAA_Actor *actor;
const int m_w, m_h, m_Bpp;
const float ratio_x, ratio_y;
- // SDL/X11 stuff we save for faster access.
- SDL_SysWMinfo wminfo;
- Display* display;
- Window window;
-
- // Shared memory segment info.
- key_t shmkey;
- int shmid;
- void *shmaddr;
-
-private:
- /** Sends a message to hildon-desktop.
- * This function comes mostly straight from libhildon.
- */
- void sendMessage(Atom message_type,
- uint32 l0, uint32 l1, uint32 l2, uint32 l3, uint32 l4)
- {
- XEvent event = { 0 };
-
- event.xclient.type = ClientMessage;
- event.xclient.window = window;
- event.xclient.message_type = message_type;
- event.xclient.format = 32;
- event.xclient.data.l[0] = l0;
- event.xclient.data.l[1] = l1;
- event.xclient.data.l[2] = l2;
- event.xclient.data.l[3] = l3;
- event.xclient.data.l[4] = l4;
-
- XSendEvent (display, window, True,
- StructureNotifyMask,
- (XEvent *)&event);
- }
-
- /** Sends all configuration parameters for the remote texture. */
- void reconfigure()
- {
- SDL_VERSION(&wminfo.version);
- if (!SDL_GetWMInfo(&wminfo)) {
- DIE("Bad SDL version!");
- }
-
- Window parent;
- int yoffset = 0;
- if (Config.fullscreen) {
- parent = wminfo.info.x11.fswindow;
- } else {
- parent = wminfo.info.x11.wmwindow;
- yoffset = 60; // Hardcode the title bar size for now.
- }
-
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_SHM),
- (uint32) shmkey, m_w, m_h, m_Bpp, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT),
- (uint32) parent, 0, 0, 0, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION),
- m_area.x, yoffset + m_area.y, m_area.w, m_area.h, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE),
- ratio_x * (1 << 16), ratio_y * (1 << 16), 0, 0, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW),
- 1, 255, 0, 0, 0);
- }
+ static bool initialized;
protected:
- HDScalerBase(SDL_Surface* screen, int w, int h, float r_x, float r_y)
+ HAAScalerBase(SDL_Surface* screen, int w, int h, float r_x, float r_y)
: m_screen(screen), m_w(w), m_h(h),
m_Bpp(m_screen->format->BitsPerPixel / 8),
ratio_x(r_x), ratio_y(r_y)
{
+ const bool fullscreen = m_screen->flags & SDL_FULLSCREEN;
centerRectangle(m_area, GUI.Width, GUI.Height, w * r_x, h * r_y);
- // What we're going to do:
- // - Create a new window that we're going to manage
- // - Set up that window as a Hildon Remote Texture
- // - Render to that new window, instead of the SDL window ("screen").
- // Yet another load of uglyness, but hey.
-
- // Barf if this is not a known SDL version.
- SDL_VERSION(&wminfo.version);
- if (!SDL_GetWMInfo(&wminfo)) {
- DIE("Bad SDL version!");
- }
-
// Clear the SDL screen with black, just in case it gets drawn.
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
- // Get the SDL gfxdisplay (this is where events end up).
- display = wminfo.info.x11.display;
-
- // The parent window needs to be mapped, so we sync it.
- XSync(display, True);
-
- // Ensure hildon atoms are synced, and that hildon-desktop is up.
- hildon_load_atoms(display);
-
- // Create our alternative window.
- const int blackColor = BlackPixel(display, DefaultScreen(display));
- window = XCreateSimpleWindow(display, DefaultRootWindow(display),
- 0, 0, m_w, m_h, 0, blackColor, blackColor);
- XStoreName(display, window, "DrNokSnes Video output window");
- Atom atom = HDATOM(_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE);
- XChangeProperty(display, window, HDATOM(_NET_WM_WINDOW_TYPE),
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *) &atom, 1);
- XSelectInput(display, window, PropertyChangeMask | StructureNotifyMask);
- XMapWindow(display, window);
-
- // Wait for "ready" property, set up by hildon-desktop after a while
- // For now, loop here. In the future, merge with main event loop.
- bool ready = false;
- while (!ready) {
- XEvent e;
- XNextEvent(display, &e);
- switch(e.type) {
- case PropertyNotify:
- if (e.xproperty.atom ==
- HDATOM(_HILDON_TEXTURE_CLIENT_READY)) {
- ready = true;
- }
- break;
- default:
- break;
- }
- }
-
- // Create a shared memory segment with hildon-desktop
- shmkey = ftok("/usr/bin/drnoksnes", 'd'); // TODO Put rom file here
- shmid = shmget(shmkey, m_w * m_h * m_Bpp, IPC_CREAT | 0777);
- if (shmid < 0) {
- DIE("Failed to create shared memory");
- }
- shmaddr = shmat(shmid, 0, 0);
- if (shmaddr == (void*)-1) {
- DIE("Failed to attach shared memory");
+ if (!initialized) {
+ HAA_Init(0);
+ initialized = true;
+ } else {
+ HAA_SetVideoMode(); // Tell HAA we might have changed video mode
}
- // Send all configuration events to hildon-desktop
- reconfigure();
+ actor = HAA_CreateActor(0, m_w, m_h, m_screen->format->BitsPerPixel);
+ HAA_SetPosition(actor, m_area.x, m_area.y + (fullscreen ? 0 : 60));
+ // In windowed mode, take care of the title bar (xoffset = 60)
+ HAA_SetScale(actor, r_x, r_y);
+ HAA_Show(actor);
}
public:
- virtual ~HDScalerBase()
+ virtual ~HAAScalerBase()
{
- // Hide, unparent and deattach the remote texture
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW),
- 0, 255, 0, 0, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT),
- 0, 0, 0, 0, 0);
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_SHM),
- 0, 0, 0, 0, 0);
- XFlush(display);
- // Destroy our managed window and shared memory segment
- XDestroyWindow(display, window);
- XSync(display, True);
- shmdt(shmaddr);
- shmctl(shmid, IPC_RMID, 0);
+ HAA_FreeActor(actor);
};
- virtual uint8* getDrawBuffer() const
+ uint8* getDrawBuffer() const
{
- return reinterpret_cast<uint8*>(shmaddr);
+ return reinterpret_cast<uint8*>(actor->surface->pixels);
};
- virtual unsigned int getDrawBufferPitch() const
+ unsigned int getDrawBufferPitch() const
{
- return m_w * m_Bpp;
+ return actor->surface->pitch;
};
- virtual void getRenderedGUIArea(unsigned short & x, unsigned short & y,
+ void getRenderedGUIArea(unsigned short & x, unsigned short & y,
unsigned short & w, unsigned short & h) const
{
x = m_area.x; y = m_area.y; w = m_area.w; h = m_area.h;
};
- virtual int getRatio() const
+ void getRatio(float & x, float & y) const
{
- return ratio_y; // TODO
+ x = ratio_x; y = ratio_y;
};
- virtual void prepare()
+ void prepare()
{
};
- virtual void finish()
+ void finish()
{
- // Send a damage event to hildon-desktop.
- sendMessage(HDATOM(_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE),
- 0, 0, m_w, m_h, 0);
- XSync(display, False);
+ HAA_Flip(actor);
};
- virtual void pause() { };
- virtual void resume() { };
-};
+ void pause() { };
+ void resume() { };
-class HDFillScaler : public HDScalerBase
-{
- HDFillScaler(SDL_Surface* screen, int w, int h)
- : HDScalerBase(screen, w, h,
- GUI.Width / (float)w, GUI.Height / (float)h)
+ bool filter(const SDL_Event& event)
{
- }
-
-public:
- class Factory : public ScalerFactory
- {
- const char * getName() const
- {
- return "hdfill";
- }
-
- bool canEnable(int bpp, int w, int h) const
- {
- return true;
- }
-
- Scaler* instantiate(SDL_Surface* screen, int w, int h) const
- {
- return new HDFillScaler(screen, w, h-20);
- }
+ return HAA_FilterEvent(&event) == 0;
};
-
- static const Factory factory;
-
- virtual const char * getName() const
- {
- return "hildon-desktop fill screen scaling";
- }
};
-const HDFillScaler::Factory HDFillScaler::factory;
+bool HAAScalerBase::initialized = false;
-class HDSquareScaler : public HDScalerBase
+class HAAFillScaler : public HAAScalerBase
{
- HDSquareScaler(SDL_Surface* screen, int w, int h, float ratio)
- : HDScalerBase(screen, w, h, ratio, ratio)
+ HAAFillScaler(SDL_Surface* screen, int w, int h)
+ : HAAScalerBase(screen, w, h,
+ GUI.Width / (float)w, GUI.Height / (float)h)
{
}
{
const char * getName() const
{
- return "hdsq";
+ return "haafill";
}
bool canEnable(int bpp, int w, int h) const
Scaler* instantiate(SDL_Surface* screen, int w, int h) const
{
- return new HDSquareScaler(screen, w, h,
- fminf(GUI.Width / (float)w, GUI.Height / (float)h));
- }
- };
-
- static const Factory factory;
-
- virtual const char * getName() const
- {
- return "hildon-desktop square screen scaling";
- }
-};
-const HDSquareScaler::Factory HDSquareScaler::factory;
-
-class HDDummy : public DummyScaler
-{
- HDDummy(SDL_Surface* screen, int w, int h)
- : DummyScaler(screen, w, h)
- {
- hildon_set_non_compositing(true);
- }
-
-public:
- ~HDDummy()
- {
- hildon_set_non_compositing(false);
- };
-
- class Factory : public ScalerFactory
- {
- const char * getName() const
- {
- return "hddummy";
- }
-
- bool canEnable(int bpp, int w, int h) const
- {
- return Config.fullscreen; // This makes sense only in fullscreen
- }
-
- Scaler* instantiate(SDL_Surface* screen, int w, int h) const
- {
- return new HDDummy(screen, w, h);
+ return new HAAFillScaler(screen, w, h-20);
}
};
const char * getName() const
{
- return "compositor disabled and no scaling";
+ return "HAA fill screen scaling";
}
};
-const HDDummy::Factory HDDummy::factory;
+const HAAFillScaler::Factory HAAFillScaler::factory;
-class HDSW : public SWScaler
+class HAASquareScaler : public HAAScalerBase
{
- HDSW(SDL_Surface* screen, int w, int h)
- : SWScaler(screen, w, h)
+ HAASquareScaler(SDL_Surface* screen, int w, int h, float ratio)
+ : HAAScalerBase(screen, w, h, ratio, ratio)
{
- hildon_set_non_compositing(true);
}
-
-public:
- ~HDSW()
- {
- hildon_set_non_compositing(false);
- };
-
- class Factory : public ScalerFactory
- {
- const char * getName() const
- {
- return "hdsoft2x";
- }
- bool canEnable(int bpp, int w, int h) const
- {
- return Config.fullscreen; // This makes sense only in fullscreen
- }
-
- Scaler* instantiate(SDL_Surface* screen, int w, int h) const
- {
- return new HDSW(screen, w, h);
- }
- };
-
- static const Factory factory;
-
- const char * getName() const
- {
- return "compositor disabled and software 2x scaling";
- }
-};
-const HDSW::Factory HDSW::factory;
-
-#ifdef __arm__
-class HDARM : public ARMScaler
-{
- HDARM(SDL_Surface* screen, int w, int h)
- : SWScaler(screen, w, h)
- {
- hildon_set_non_compositing(true);
- }
-
public:
- ~HDARM()
- {
- hildon_set_non_compositing(false);
- };
-
class Factory : public ScalerFactory
{
const char * getName() const
{
- return "hdarm2x";
+ return "haasq";
}
bool canEnable(int bpp, int w, int h) const
{
- return Config.fullscreen; // This makes sense only in fullscreen
+ return true;
}
Scaler* instantiate(SDL_Surface* screen, int w, int h) const
{
- return new HDARM(screen, w, h);
+ return new HAASquareScaler(screen, w, h,
+ fminf(GUI.Width / (float)w, GUI.Height / (float)h));
}
};
const char * getName() const
{
- return "compositor disabled and software ARM 2x scaling";
+ return "HAA square screen scaling";
}
};
-const HDSW::Factory HDSW::factory;
-#endif /* __arm__ */
+const HAASquareScaler::Factory HAASquareScaler::factory;
+
#endif /* CONF_HD */
#if CONF_XSP
x = m_area.x; y = m_area.y; w = m_area.w; h = m_area.h;
};
- int getRatio() const
+ void getRatio(float & x, float & y) const
{
- return 2;
+ x = 2.0f; y = 2.0f;
};
void prepare()
{
m_should_enable = true; // Will enable later
};
+
+ bool filter(const SDL_Event& event)
+ {
+ if (event.type == SDL_ACTIVEEVENT &&
+ (event.active.state & SDL_APPINPUTFOCUS)) {
+ if (event.active.gain) {
+ resume();
+ } else {
+ pause();
+ }
+
+ return true;
+ }
+
+ return false;
+ };
};
const XSPScaler::Factory XSPScaler::factory;
#endif
static const ScalerFactory* scalers[] = {
/* More useful scalers come first */
-#if CONF_HD && defined(__arm__)
- &HDARM::factory, /* non-composited arm 2x scaling */
-#endif
-#if CONF_HD
- &HDSquareScaler::factory, /* h-d assisted square scaling */
- &HDSW::factory, /* non-composited soft 2x scaling */
-#endif
#if CONF_XSP
&XSPScaler::factory, /* n8x0 pixel doubling */
#endif
#ifdef __arm__
&ARMScaler::factory, /* arm 2x scaling */
#endif
- &SWScaler::factory, /* soft 2x scaling */
#if CONF_HD
- &HDDummy::factory, /* non composited */
+ &HAASquareScaler::factory, /* n900 animation actor scaling */
#endif
+ &SWScaler::factory, /* soft 2x scaling */
&DummyScaler::factory, /* failsafe */
/* The following scalers will not be automatically enabled, no matter what */
#if CONF_HD
- &HDFillScaler::factory,
+ &HAAFillScaler::factory,
#endif
};