mirror of
https://github.com/MiyooCFW/buildroot.git
synced 2025-09-27 22:24:19 +03:00
293 lines
8.6 KiB
Diff
293 lines
8.6 KiB
Diff
diff --git a/include/SDL_video.h b/include/SDL_video.h
|
|
index f9c4e07..aa0459c 100644
|
|
--- a/include/SDL_video.h
|
|
+++ b/include/SDL_video.h
|
|
@@ -138,6 +138,7 @@ typedef struct SDL_Surface {
|
|
#define SDL_ANYFORMAT 0x10000000 /**< Allow any video depth/pixel-format */
|
|
#define SDL_HWPALETTE 0x20000000 /**< Surface has exclusive palette */
|
|
#define SDL_DOUBLEBUF 0x40000000 /**< Set up double-buffered video mode */
|
|
+#define SDL_TRIPLEBUF 0x40000100 /**< Set up triple-buffered video mode */
|
|
#define SDL_FULLSCREEN 0x80000000 /**< Surface is a full screen display */
|
|
#define SDL_OPENGL 0x00000002 /**< Create an OpenGL rendering context */
|
|
#define SDL_OPENGLBLIT 0x0000000A /**< Create an OpenGL rendering context and use it for blitting */
|
|
diff --git a/src/video/fbcon/SDL_fbvideo.c b/src/video/fbcon/SDL_fbvideo.c
|
|
index fec158f..21ee142 100644
|
|
--- a/src/video/fbcon/SDL_fbvideo.c
|
|
+++ b/src/video/fbcon/SDL_fbvideo.c
|
|
@@ -156,6 +156,12 @@ static void FB_FreeHWSurface(_THIS, SDL_Surface *surface);
|
|
static void FB_WaitVBL(_THIS);
|
|
static void FB_WaitIdle(_THIS);
|
|
static int FB_FlipHWSurface(_THIS, SDL_Surface *surface);
|
|
+#if !SDL_THREADS_DISABLED
|
|
+static int FB_TripleBufferingThread(void *d);
|
|
+static void FB_TripleBufferInit(_THIS);
|
|
+static void FB_TripleBufferStop(_THIS);
|
|
+static void FB_TripleBufferQuit(_THIS);
|
|
+#endif
|
|
|
|
/* Internal palette functions */
|
|
static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo,
|
|
@@ -812,6 +818,10 @@ static int FB_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
|
}
|
|
}
|
|
|
|
+#if !SDL_THREADS_DISABLED
|
|
+ FB_TripleBufferInit(this);
|
|
+#endif
|
|
+
|
|
/* We're done! */
|
|
return(0);
|
|
}
|
|
@@ -1028,6 +1038,14 @@ static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current,
|
|
fprintf(stderr, "Printing original vinfo:\n");
|
|
print_vinfo(&vinfo);
|
|
#endif
|
|
+
|
|
+#if SDL_THREADS_DISABLED
|
|
+ if ( (flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+ flags &= ~SDL_TRIPLEBUF;
|
|
+ flags |= SDL_DOUBLEBUF; /* Double buffering doesn't require threads */
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Do not use double buffering with shadow buffer */
|
|
if (shadow_fb) {
|
|
flags &= ~SDL_DOUBLEBUF;
|
|
@@ -1041,7 +1059,9 @@ static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current,
|
|
vinfo.xres = width;
|
|
vinfo.xres_virtual = width;
|
|
vinfo.yres = height;
|
|
- if ( flags & SDL_DOUBLEBUF ) {
|
|
+ if ( (flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+ vinfo.yres_virtual = height*3;
|
|
+ } else if ( flags & SDL_DOUBLEBUF ) {
|
|
vinfo.yres_virtual = height*2;
|
|
} else {
|
|
vinfo.yres_virtual = height;
|
|
@@ -1071,7 +1091,9 @@ static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current,
|
|
int maxheight;
|
|
|
|
/* Figure out how much video memory is available */
|
|
- if ( flags & SDL_DOUBLEBUF ) {
|
|
+ if ( (flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+ maxheight = height*3;
|
|
+ } else if ( flags & SDL_DOUBLEBUF ) {
|
|
maxheight = height*2;
|
|
} else {
|
|
maxheight = height;
|
|
@@ -1169,14 +1191,41 @@ static SDL_Surface *FB_SetVideoMode(_THIS, SDL_Surface *current,
|
|
break;
|
|
}
|
|
|
|
+#if !SDL_THREADS_DISABLED
|
|
+ if ( triplebuf_thread )
|
|
+ FB_TripleBufferStop(this);
|
|
+
|
|
+ if ( (flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+ current->flags |= SDL_TRIPLEBUF;
|
|
+ current_page = 0;
|
|
+ new_page = 2;
|
|
+ triplebuf_thread_stop = 0;
|
|
+
|
|
+ SDL_LockMutex(triplebuf_mutex);
|
|
+ triplebuf_thread = SDL_CreateThread(FB_TripleBufferingThread, this);
|
|
+
|
|
+ /* Wait until the triplebuf thread is ready */
|
|
+ SDL_CondWait(triplebuf_cond, triplebuf_mutex);
|
|
+ SDL_UnlockMutex(triplebuf_mutex);
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Update for double-buffering, if we can */
|
|
if ( flags & SDL_DOUBLEBUF ) {
|
|
- if ( vinfo.yres_virtual == (height*2) ) {
|
|
+ if ( vinfo.yres_virtual >= (height*2) ) {
|
|
current->flags |= SDL_DOUBLEBUF;
|
|
- flip_page = 0;
|
|
flip_address[0] = (char *)current->pixels;
|
|
flip_address[1] = (char *)current->pixels+
|
|
current->h*current->pitch;
|
|
+ flip_address[2] = (char *)current->pixels+
|
|
+ current->h*current->pitch*2;
|
|
+
|
|
+ if ( (flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+ flip_page = 1;
|
|
+ } else {
|
|
+ flip_page = 0;
|
|
+ }
|
|
+
|
|
this->screen = current;
|
|
FB_FlipHWSurface(this, current);
|
|
this->screen = NULL;
|
|
@@ -1425,26 +1474,106 @@ static void FB_WaitIdle(_THIS)
|
|
return;
|
|
}
|
|
|
|
+#if !SDL_THREADS_DISABLED
|
|
+static int FB_TripleBufferingThread(void *d)
|
|
+{
|
|
+ SDL_VideoDevice *this = d;
|
|
+
|
|
+ SDL_LockMutex(triplebuf_mutex);
|
|
+ SDL_CondSignal(triplebuf_cond);
|
|
+
|
|
+ for (;;) {
|
|
+ unsigned int page;
|
|
+
|
|
+ SDL_CondWait(triplebuf_cond, triplebuf_mutex);
|
|
+ if (triplebuf_thread_stop)
|
|
+ break;
|
|
+
|
|
+ /* Flip the most recent back buffer with the front buffer */
|
|
+ page = current_page;
|
|
+ current_page = new_page;
|
|
+ new_page = page;
|
|
+
|
|
+ /* flip display */
|
|
+ cache_vinfo.yoffset = current_page * cache_vinfo.yres;
|
|
+
|
|
+ // The GCW Zero kernel waits for vsync as part of the pan ioctl.
|
|
+ //wait_vbl(this);
|
|
+ if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) {
|
|
+ SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed");
|
|
+ return(-1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ SDL_UnlockMutex(triplebuf_mutex);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void FB_TripleBufferInit(_THIS)
|
|
+{
|
|
+ triplebuf_mutex = SDL_CreateMutex();
|
|
+ triplebuf_cond = SDL_CreateCond();
|
|
+ triplebuf_thread = NULL;
|
|
+}
|
|
+
|
|
+static void FB_TripleBufferStop(_THIS)
|
|
+{
|
|
+ SDL_LockMutex(triplebuf_mutex);
|
|
+ triplebuf_thread_stop = 1;
|
|
+ SDL_CondSignal(triplebuf_cond);
|
|
+ SDL_UnlockMutex(triplebuf_mutex);
|
|
+
|
|
+ SDL_WaitThread(triplebuf_thread, NULL);
|
|
+ triplebuf_thread = NULL;
|
|
+}
|
|
+
|
|
+static void FB_TripleBufferQuit(_THIS)
|
|
+{
|
|
+ if (triplebuf_thread)
|
|
+ FB_TripleBufferStop(this);
|
|
+ SDL_DestroyMutex(triplebuf_mutex);
|
|
+ SDL_DestroyCond(triplebuf_cond);
|
|
+}
|
|
+#endif
|
|
+
|
|
static int FB_FlipHWSurface(_THIS, SDL_Surface *surface)
|
|
{
|
|
if ( switched_away ) {
|
|
return -2; /* no hardware access */
|
|
}
|
|
|
|
- /* Wait for vertical retrace and then flip display */
|
|
- cache_vinfo.yoffset = flip_page * cache_vinfo.yres;
|
|
if ( FB_IsSurfaceBusy(this->screen) ) {
|
|
FB_WaitBusySurfaces(this);
|
|
}
|
|
- // The GCW Zero kernel waits for vsync as part of the pan ioctl.
|
|
- //wait_vbl(this);
|
|
- if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) {
|
|
- SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed");
|
|
- return(-1);
|
|
+
|
|
+ if ( (surface->flags & SDL_TRIPLEBUF) == SDL_TRIPLEBUF ) {
|
|
+#if !SDL_THREADS_DISABLED
|
|
+ unsigned int page;
|
|
+
|
|
+ /* Flip the two back buffers */
|
|
+ SDL_LockMutex(triplebuf_mutex);
|
|
+ page = new_page;
|
|
+ new_page = flip_page;
|
|
+ flip_page = page;
|
|
+
|
|
+ surface->pixels = flip_address[flip_page];
|
|
+ SDL_CondSignal(triplebuf_cond);
|
|
+ SDL_UnlockMutex(triplebuf_mutex);
|
|
+#endif
|
|
+ } else {
|
|
+ /* Wait for vertical retrace and then flip display */
|
|
+ cache_vinfo.yoffset = flip_page * cache_vinfo.yres;
|
|
+ // The GCW Zero kernel waits for vsync as part of the pan ioctl.
|
|
+ //wait_vbl(this);
|
|
+ if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) {
|
|
+ SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed");
|
|
+ return(-1);
|
|
+ }
|
|
+ flip_page = !flip_page;
|
|
+
|
|
+ surface->pixels = flip_address[flip_page];
|
|
}
|
|
- flip_page = !flip_page;
|
|
|
|
- surface->pixels = flip_address[flip_page];
|
|
return(0);
|
|
}
|
|
|
|
@@ -1915,6 +2044,10 @@ static void FB_VideoQuit(_THIS)
|
|
int i, j;
|
|
const char *dontClearPixels = SDL_getenv("SDL_FBCON_DONT_CLEAR");
|
|
|
|
+#if !SDL_THREADS_DISABLED
|
|
+ FB_TripleBufferQuit(this);
|
|
+#endif
|
|
+
|
|
if ( this->screen ) {
|
|
/* Clear screen and tell SDL not to free the pixels */
|
|
|
|
diff --git a/src/video/fbcon/SDL_fbvideo.h b/src/video/fbcon/SDL_fbvideo.h
|
|
index 1443d2b..3efbd3a 100644
|
|
--- a/src/video/fbcon/SDL_fbvideo.h
|
|
+++ b/src/video/fbcon/SDL_fbvideo.h
|
|
@@ -30,6 +30,7 @@
|
|
|
|
#include "SDL_mouse.h"
|
|
#include "SDL_mutex.h"
|
|
+#include "SDL_thread.h"
|
|
#include "../SDL_sysvideo.h"
|
|
#if SDL_INPUT_TSLIB
|
|
#include "tslib.h"
|
|
@@ -83,7 +84,15 @@ struct SDL_PrivateVideoData {
|
|
char *mapped_io;
|
|
long mapped_iolen;
|
|
int flip_page;
|
|
- char *flip_address[2];
|
|
+ char *flip_address[3];
|
|
+#if !SDL_THREADS_DISABLED
|
|
+ int current_page;
|
|
+ int new_page;
|
|
+ SDL_mutex *triplebuf_mutex;
|
|
+ SDL_cond *triplebuf_cond;
|
|
+ SDL_Thread *triplebuf_thread;
|
|
+ int triplebuf_thread_stop;
|
|
+#endif
|
|
int rotate;
|
|
int shadow_fb; /* Tells whether a shadow is being used. */
|
|
FB_bitBlit *blitFunc;
|
|
@@ -130,6 +139,14 @@ struct SDL_PrivateVideoData {
|
|
#define mapped_iolen (this->hidden->mapped_iolen)
|
|
#define flip_page (this->hidden->flip_page)
|
|
#define flip_address (this->hidden->flip_address)
|
|
+#if !SDL_THREADS_DISABLED
|
|
+#define current_page (this->hidden->current_page)
|
|
+#define new_page (this->hidden->new_page)
|
|
+#define triplebuf_mutex (this->hidden->triplebuf_mutex)
|
|
+#define triplebuf_cond (this->hidden->triplebuf_cond)
|
|
+#define triplebuf_thread (this->hidden->triplebuf_thread)
|
|
+#define triplebuf_thread_stop (this->hidden->triplebuf_thread_stop)
|
|
+#endif
|
|
#define rotate (this->hidden->rotate)
|
|
#define shadow_fb (this->hidden->shadow_fb)
|
|
#define blitFunc (this->hidden->blitFunc)
|