Note that if app isn't updating whole buffer each frame, it will glitch.
This is the same as specifying SDL_DOUBLEBUF to SDL_SetVideoMode.
+SDL_OMAP_FORCE_DIRECTBUF:
+ When double buffering is not used, this option forces all blits to go
+ directly to the framebuffer (SDL_UpdateRect[s]() has no effect), which will
+ give speed but may cause flickering. Otherwise all blits will go to offscreen
+ buffer and SDL_UpdateRect[s]() is needed to update the screen (this is how
+ standard SDL works too).
+ When double buffering is used, this option has no effect (all blits always
+ go to back buffer that's displayed after flip).
+
SDL_OMAP_NO_TS_TRANSLATE:
Disable automatic touchscreen screen -> layer coordinate translation,
return real screen coordinates.
# same as SDL_OMAP_FORCE_DOUBLEBUF
force_doublebuf = 1/0
+# same as SDL_OMAP_FORCE_DIRECTBUF
+force_directbuf = 1/0
+
# same as SDL_OMAP_NO_TS_TRANSLATE
no_ts_translate = 1/0
pdata->cfg_force_doublebuf = !!strtol(p, NULL, 0);
continue;
}
+ else if (check_token_eq(&p, "force_directbuf")) {
+ pdata->cfg_force_directbuf = !!strtol(p, NULL, 0);
+ continue;
+ }
else if (check_token_eq(&p, "no_ts_translate")) {
pdata->cfg_no_ts_translate = !!strtol(p, NULL, 0);
continue;
tmp = getenv("SDL_OMAP_FORCE_DOUBLEBUF");
if (tmp != NULL)
pdata->cfg_force_doublebuf = !!strtol(tmp, NULL, 0);
+ tmp = getenv("SDL_OMAP_FORCE_DIRECTBUF");
+ if (tmp != NULL)
+ pdata->cfg_force_directbuf = !!strtol(tmp, NULL, 0);
tmp = getenv("SDL_OMAP_NO_TS_TRANSLATE");
if (tmp != NULL)
pdata->cfg_no_ts_translate = !!strtol(tmp, NULL, 0);
struct SDL_PrivateVideoData {
struct vout_fbdev *fbdev;
+ void *front_buffer;
void *saved_layer;
/* physical screen size, should match touchscreen */
int phys_w, phys_h;
unsigned int app_uses_flip:1;
unsigned int cfg_force_vsync:1;
unsigned int cfg_force_doublebuf:1;
+ unsigned int cfg_force_directbuf:1;
unsigned int cfg_no_ts_translate:1;
unsigned int cfg_ts_force_tslib:1;
};
int width, int height, int bpp, int *doublebuf,
const char *wm_title);
void *osdl_video_flip(struct SDL_PrivateVideoData *pdata);
+void *osdl_video_get_active_buffer(struct SDL_PrivateVideoData *pdata);
int osdl_video_detect_screen(struct SDL_PrivateVideoData *pdata);
int osdl_video_pause(struct SDL_PrivateVideoData *pdata, int is_pause);
void osdl_video_finish(struct SDL_PrivateVideoData *pdata);
}
}
- doublebuf = (flags & SDL_DOUBLEBUF) ? 1 : 0;
+ /* 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, &doublebuf, this->wm_title);
pdata->border_l, pdata->border_r, pdata->border_t, pdata->border_b);
return NULL;
}
- if ((flags & SDL_DOUBLEBUF) && !doublebuf) {
- log("doublebuffering could not be set\n");
- flags &= ~SDL_DOUBLEBUF;
+ 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;
+ Uint16 *src, *dst;
+ int i, x, y, w, h;
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);
+ if (screen->flags & SDL_DOUBLEBUF) {
+ if (nrects == 1 && rects->x == 0 && rects->y == 0
+ && (rects->w == screen->w || rects->w == 0)
+ && (rects->h == screen->h || rects->h == 0)
+ && !pdata->app_uses_flip)
+ {
+ screen->pixels = osdl_video_flip(pdata);
+ }
+ return;
+ }
+
+ src = screen->pixels;
+ dst = pdata->front_buffer;
+ if (src == dst)
+ return;
+
+ for (i = 0; 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 / 2 + x,
+ src + y * screen->pitch / 2 + x,
+ w * 2);
}
}