/*
- * (C) Gražvydas "notaz" Ignotas, 2010
+ * (C) Gražvydas "notaz" Ignotas, 2010-2012
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING file in the top-level directory.
#include <stdio.h>
#include <stdlib.h>
+#include <X11/XF86keysym.h>
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "linux/xenv.h"
-#include "omapsdl.h"
+#include "osdl.h"
static int omap_available(void)
struct SDL_PrivateVideoData *pdata = this->hidden;
SDL_PixelFormat *format;
Uint32 unhandled_flags;
+ int doublebuf;
void *fbmem;
trace("%d, %d, %d, %08x", width, height, bpp, flags);
format = SDL_ReallocFormat(current, 24, 0xff0000, 0xff00, 0xff, 0);
break;
case 32:
- format = SDL_ReallocFormat(current, 32, 0xff0000, 0xff00, 0xff, 0xff000000);
+ format = SDL_ReallocFormat(current, 32, 0xff0000, 0xff00, 0xff, 0);
break;
default:
err("SetVideoMode: bpp %d not supported", bpp);
}
}
+ /* always use doublebuf, when SDL_DOUBLEBUF is not set,
+ * we'll have to blit manually on UpdateRects() */
+ doublebuf = 1;
+
fbmem = osdl_video_set_mode(pdata,
pdata->border_l, pdata->border_r, pdata->border_t, pdata->border_b,
- width, height, bpp, (flags & SDL_DOUBLEBUF) ? 1 : 0);
+ width, height, bpp, &doublebuf, this->wm_title);
if (fbmem == NULL) {
- log("failing on mode %dx%d@%d, doublebuf %s",
- width, height, bpp, (flags & SDL_DOUBLEBUF) ? "on" : "off");
+ err("failing on mode %dx%d@%d, doublebuf %s, border %d,%d,%d,%d",
+ width, height, bpp, (flags & SDL_DOUBLEBUF) ? "on" : "off",
+ pdata->border_l, pdata->border_r, pdata->border_t, pdata->border_b);
+ return NULL;
+ }
+ pdata->front_buffer = osdl_video_get_active_buffer(pdata);
+ if (pdata->front_buffer == NULL) {
+ err("osdl_video_get_active_buffer failed\n");
return NULL;
}
+ if (!doublebuf) {
+ if (flags & SDL_DOUBLEBUF) {
+ log("doublebuffering could not be set\n");
+ flags &= ~SDL_DOUBLEBUF;
+ }
+ /* XXX: could just malloc a back buffer here instead */
+ pdata->cfg_force_directbuf = 1;
+ }
+
+ if (!(flags & SDL_DOUBLEBUF) && pdata->cfg_force_directbuf)
+ fbmem = pdata->front_buffer;
+
flags |= SDL_FULLSCREEN | SDL_HWSURFACE;
unhandled_flags = flags & ~(SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);
if (unhandled_flags != 0) {
static int omap_FlipHWSurface(SDL_VideoDevice *this, SDL_Surface *surface)
{
struct SDL_PrivateVideoData *pdata = this->hidden;
+ static int warned;
trace("%p", surface);
- surface->pixels = osdl_video_flip(pdata);
+ if (surface != this->screen) {
+ if (!warned) {
+ err("flip surface %p which is not screen %p?\n",
+ surface, this->screen);
+ warned = 1;
+ }
+ return;
+ }
+
+ if (surface->flags & SDL_DOUBLEBUF)
+ surface->pixels = osdl_video_flip(pdata);
+ else {
+ if (surface->pixels != pdata->front_buffer)
+ memcpy(surface->pixels, pdata->front_buffer,
+ surface->pitch * surface->h);
+ }
+
pdata->app_uses_flip = 1;
return 0;
static void omap_UpdateRects(SDL_VideoDevice *this, int nrects, SDL_Rect *rects)
{
struct SDL_PrivateVideoData *pdata = this->hidden;
+ SDL_Surface *screen = this->screen;
+ int fullscreen_blit = 0;
+ int i, Bpp, x, y, w, h;
+ char *src, *dst;
trace("%d, %p", nrects, rects);
- /* for doublebuf forcing on apps */
- if (nrects == 1 && rects->x == 0 && rects->y == 0
- && !pdata->app_uses_flip && (this->screen->flags & SDL_DOUBLEBUF)
- && rects->w == this->screen->w && rects->h == this->screen->h)
- {
- this->screen->pixels = osdl_video_flip(pdata);
+ fullscreen_blit =
+ nrects == 1 && rects->x == 0 && rects->y == 0
+ && (rects->w == screen->w || rects->w == 0)
+ && (rects->h == screen->h || rects->h == 0);
+
+ if (screen->flags & SDL_DOUBLEBUF) {
+ if (fullscreen_blit && !pdata->app_uses_flip)
+ screen->pixels = osdl_video_flip(pdata);
+ return;
+ }
+
+ src = screen->pixels;
+ dst = pdata->front_buffer;
+ if (src == dst)
+ return;
+
+ if (fullscreen_blit) {
+ memcpy(dst, src, screen->pitch * screen->h);
+ return;
+ }
+
+ for (i = 0, Bpp = screen->format->BytesPerPixel; i < nrects; i++) {
+ /* this supposedly has no clipping, but we'll do it anyway */
+ x = rects[i].x, y = rects[i].y, w = rects[i].w, h = rects[i].h;
+ if (x < 0)
+ w += x, x = 0;
+ else if (x + w > screen->w)
+ w = screen->w - x;
+ if (w <= 0)
+ continue;
+
+ if (y < 0)
+ h += y, y = 0;
+ else if (y + h > screen->h)
+ h = screen->h - y;
+
+ for (; h > 0; y++, h--)
+ memcpy(dst + y * screen->pitch + x * Bpp,
+ src + y * screen->pitch + x * Bpp,
+ w * Bpp);
}
}
trace();
}
-static int key_event_cb(void *cb_arg, int sdl_kc, int is_pressed)
+static int key_event_cb(void *cb_arg, int sdl_kc, int sdl_sc, int is_pressed)
{
SDL_keysym keysym = { 0, };
+ int shift = 0;
+ SDLMod mod;
+ int ret;
keysym.sym = sdl_kc;
+ keysym.scancode = sdl_sc;
+
+ /* 0xff if pandora's Fn, so we exclude it too.. */
+ if (is_pressed && sdl_kc < 0xff && SDL_TranslateUNICODE) {
+ mod = SDL_GetModState();
+ if (!(mod & KMOD_CTRL) && (!!(mod & KMOD_SHIFT) ^ !!(mod & KMOD_CAPS)))
+ shift = 1;
+
+ /* prefer X mapping, if that doesn't work use hardcoded one */
+ ret = xenv_keycode_to_keysym(sdl_sc, shift);
+ if (ret >= 0) {
+ keysym.unicode = ret;
+ if ((mod & KMOD_CTRL)
+ && 0x60 <= keysym.unicode && keysym.unicode <= 0x7f)
+ {
+ keysym.unicode -= 0x60;
+ }
+ /* hmh.. */
+ if ((keysym.unicode & 0xff00) == 0xff00)
+ keysym.unicode &= ~0xff00;
+ }
+ else {
+ keysym.unicode = sdl_kc;
+ if ((mod & KMOD_CTRL) && 0x60 <= sdl_kc && sdl_kc <= 0x7f)
+ {
+ keysym.unicode = sdl_kc - 0x60;
+ }
+ else if (shift && 'a' <= sdl_kc && sdl_kc <= 'z')
+ {
+ keysym.unicode = sdl_kc - 'a' + 'A';
+ }
+ }
+ }
+
SDL_PrivateKeyboard(is_pressed, &keysym);
}
if (x < (min)) x = min; \
if (x >= (max)) x = max
-static int ts_event_cb(void *cb_arg, int x, int y, unsigned int pressure)
+static void translate_mouse(SDL_VideoDevice *this, int *x, int *y)
{
- static int was_pressed;
- SDL_VideoDevice *this = cb_arg;
struct SDL_PrivateVideoData *pdata = this->hidden;
- int xoffs;
if (!pdata->cfg_no_ts_translate && pdata->layer_w != 0 && pdata->layer_h != 0) {
- x = pdata->border_l + ((x - pdata->layer_x) * pdata->ts_xmul >> 16);
- y = pdata->border_t + ((y - pdata->layer_y) * pdata->ts_ymul >> 16);
- clamp(x, 0, this->screen->w);
- clamp(y, 0, this->screen->h);
+ *x = pdata->border_l + ((*x - pdata->layer_x) * pdata->ts_xmul >> 16);
+ *y = pdata->border_t + ((*y - pdata->layer_y) * pdata->ts_ymul >> 16);
+ clamp(*x, 0, this->screen->w);
+ clamp(*y, 0, this->screen->h);
}
+}
- SDL_PrivateMouseMotion(0, 0, x, y);
+static int ts_event_cb(void *cb_arg, int x, int y, unsigned int pressure)
+{
+ static int was_pressed;
+ SDL_VideoDevice *this = cb_arg;
+ struct SDL_PrivateVideoData *pdata = this->hidden;
+
+ translate_mouse(this, &x, &y);
pressure = !!pressure;
if (pressure != was_pressed) {
- SDL_PrivateMouseButton(pressure ? SDL_PRESSED : SDL_RELEASED, 1, 0, 0);
+ SDL_PrivateMouseButton(pressure ? SDL_PRESSED : SDL_RELEASED, 1, x, y);
was_pressed = pressure;
}
+ else
+ SDL_PrivateMouseMotion(0, 0, x, y);
+}
+
+static int xmouseb_event_cb(void *cb_arg, int x, int y, int button, int is_pressed)
+{
+ SDL_VideoDevice *this = cb_arg;
+ struct SDL_PrivateVideoData *pdata = this->hidden;
+
+ translate_mouse(this, &x, &y);
+ SDL_PrivateMouseButton(is_pressed ? SDL_PRESSED : SDL_RELEASED, button, x, y);
+}
+
+static int xmousem_event_cb(void *cb_arg, int x, int y)
+{
+ SDL_VideoDevice *this = cb_arg;
+ struct SDL_PrivateVideoData *pdata = this->hidden;
+
+ translate_mouse(this, &x, &y);
+ SDL_PrivateMouseMotion(0, 0, x, y);
+}
+
+static int xkey_cb(void *cb_arg, int kc, int is_pressed)
+{
+ SDL_VideoDevice *this = cb_arg;
+ struct SDL_PrivateVideoData *pdata = this->hidden;
+ int ret;
+
+ if (kc == XF86XK_MenuKB && is_pressed) {
+ ret = osdl_video_pause(pdata, 1);
+ if (ret == 0) {
+ xenv_minimize();
+ osdl_video_pause(pdata, 0);
+ omapsdl_input_get_events(0, NULL, NULL, NULL);
+ }
+ }
}
static void omap_PumpEvents(SDL_VideoDevice *this)
{
struct SDL_PrivateVideoData *pdata = this->hidden;
- int dummy;
+ int read_tslib = 1;
trace();
- omapsdl_input_get_events(0, key_event_cb, ts_event_cb, this);
+ if (pdata->xenv_up) {
+ if (!pdata->cfg_ts_force_tslib) {
+ xenv_update(xkey_cb, xmouseb_event_cb, xmousem_event_cb, this);
+ if (pdata->xenv_mouse)
+ read_tslib = 0;
+ }
+ else {
+ /* just flush X event queue */
+ xenv_update(NULL, NULL, NULL, NULL);
+ }
+ }
- // XXX: we might want to process some X events too
- if (pdata->xenv_up)
- xenv_update(&dummy);
+ omapsdl_input_get_events(0, key_event_cb,
+ read_tslib ? ts_event_cb : NULL, this);
}
static SDL_VideoDevice *omap_create(int devindex)