瀏覽代碼

Added raspberry pi fullscreen mode switch flag.

woollybah 10 年之前
父節點
當前提交
15d70a2a8d
共有 5 個文件被更改,包括 285 次插入5 次删除
  1. 12 0
      sdl.mod/SDL/raspberrypi_build_notes.txt
  2. 10 0
      sdlgraphics.mod/common.bmx
  3. 29 1
      sdlgraphics.mod/glue.c
  4. 194 0
      sdlgraphics.mod/rpi_glue.c
  5. 40 4
      sdlgraphics.mod/sdlgraphics.bmx

+ 12 - 0
sdl.mod/SDL/raspberrypi_build_notes.txt

@@ -0,0 +1,12 @@
+sudo apt-get install libgtkhtml3.14-dev
+sudo apt-get install libgtk2.0-dev
+sudo apt-get install libgdk-pixbuf2.0-dev
+
+sudo apt-get install libudev-dev
+
+sudo usermod -aG video pi
+
+
+CC="gcc -I/opt/vc/include -L/opt/vc/lib -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux" ../configure --disable-pulseaudio --disable-esd --disable-video-mir --disable-video-wayland --disable-video-x11 --disable-video-opengl --host=arm-raspberry-linux-gnueabihf
+
+

+ 10 - 0
sdlgraphics.mod/common.bmx

@@ -54,6 +54,9 @@ Import "../../sdl.mod/sdl.mod/include/*.h"
 '?
 
 Import "glue.c"
+?raspberrypi
+Import "rpi_glue.c"
+?
 
 Extern
 
@@ -74,6 +77,12 @@ Extern
 '	Function SDL_ShowCursor(visible:Int)
 	Function bmx_SDL_WarpMouseInWindow(x:Int, y:Int)
 	
+?raspberrypi
+	Function bmx_tvservice_init()
+	Function bmx_tvservice_modes:Int(modes:Byte Ptr, maxcount:Int, withMode:Int)
+	Function bmx_reset_screen()
+?
+	
 '	Function bmx_SDL_GetDisplayWidth:Int(display:Int)
 '	Function bmx_SDL_GetDisplayHeight:Int(display:Int)
 '	Function bmx_SDL_GetDisplayDepth:Int(display:Int)
@@ -99,3 +108,4 @@ Const SDL_WINDOW_FULLSCREEN_DESKTOP:Int = SDL_WINDOW_FULLSCREEN | $00001000
 Const SDL_WINDOW_FOREIGN:Int = $00000800            ' window Not created by SDL
 Const SDL_WINDOW_ALLOW_HIGHDPI:Int = $00002000       ' window should be created in high-DPI Mode If supported
 
+Const GRAPHICS_RPI_TV_FULLSCREEN:Int = $1000

+ 29 - 1
sdlgraphics.mod/glue.c

@@ -40,6 +40,7 @@ enum{
 	FLAGS_STENCILBUFFER = 0x10,
 	FLAGS_ACCUMBUFFER   = 0x20,
 	FLAGS_BORDERLESS    = 0x40,
+	FLAGS_RPI_TV_FULLSCREEN = 0x1000,
 	FLAGS_FULLSCREEN    = 0x80000000
 };
 
@@ -60,6 +61,11 @@ void bbSDLGraphicsClose( BBSDLContext *context );
 void bmx_SDL_Poll();
 void bmx_SDL_WaitEvent();
 
+#ifdef __RASPBERRYPI__
+void bmx_tvservice_get_closest_mode(int width, int height, int framerate, int * mode, int * group);
+void bmx_tvservice_setmode(int mode, int group, int width, int height);
+#endif
+
 static BBSDLContext *_currentContext;
 
 int bbSDLGraphicsGraphicsModes( int display, int *imodes,int maxcount ) {
@@ -102,9 +108,24 @@ BBSDLContext *bbSDLGraphicsCreateGraphics( int width,int height,int depth,int hz
 	if (flags & FLAGS_ALPHABUFFER) SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
 	if (flags & FLAGS_DEPTHBUFFER) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
 	if (flags & FLAGS_STENCILBUFFER) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
+
+#ifdef __RASPBERRYPI__
+	int rpi_mode;
+	int rpi_group;
 	
+	if (depth && (flags & FLAGS_RPI_TV_FULLSCREEN)) {
+		bmx_tvservice_get_closest_mode(width, height, hz, &rpi_mode, &rpi_group);
+		bmx_tvservice_setmode(rpi_mode, rpi_group, width, height);
+	}
+	SDL_VideoInit(NULL);
+#endif
 	SDL_Window *window = SDL_CreateWindow(appTitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 		width, height, windowFlags);
+		
+	if (window == NULL) {
+printf("error... %s\n", SDL_GetError());fflush(stdout);
+		return;
+	}
 
 	SDL_GL_SetSwapInterval(-1);
 	
@@ -114,8 +135,12 @@ BBSDLContext *bbSDLGraphicsCreateGraphics( int width,int height,int depth,int hz
 	memset( bbcontext,0,sizeof(BBSDLContext) );
 	bbcontext->mode=mode;	
 	bbcontext->width=width;	
-	bbcontext->height=height;	
+	bbcontext->height=height;
+#ifdef __RASPBERRYPI__
+	bbcontext->depth=16;
+#else
 	bbcontext->depth=24;	
+#endif
 	bbcontext->hertz=hz;
 	bbcontext->flags=flags;
 	bbcontext->sync=-1;	
@@ -184,5 +209,8 @@ void bbSDLGraphicsGetSettings( BBSDLContext *context, int * width,int * height,i
 void bbSDLExit(){
 	bbSDLGraphicsClose( _currentContext );
 	_currentContext=0;
+#ifdef __RASPBERRYPI__
+	SDL_VideoQuit();
+#endif
 }
 

+ 194 - 0
sdlgraphics.mod/rpi_glue.c

@@ -0,0 +1,194 @@
+#include <stdio.h>
+#include <math.h>
+#include "interface/vmcs_host/vc_tvservice.h"
+
+static int start_mode;
+static int start_group;
+static int start_width;
+static int start_height;
+
+void bmx_tvservice_init() {
+	int w, h, f, m, g;
+
+	vcos_init();
+	
+	VCHI_INSTANCE_T instance;
+	VCHI_CONNECTION_T connection;
+	
+	vchi_initialise(&instance);
+	
+	vchi_connect(NULL, 0, instance);
+	
+	vc_vchi_tv_init(instance, &connection, 1);
+	
+	
+	bmx_tvservice_currentres(&w, &h, &f, &m, &g);
+	start_mode = m;
+	start_group = g;
+	start_width = w;
+	start_height = h;
+}
+
+
+void bmx_tvservice_currentres(int * width, int * height, float * framerate, int * mode, int * group) {
+	TV_DISPLAY_STATE_T state;
+	
+	if (vc_tv_get_display_state(&state) == 0) {
+	
+		HDMI_PROPERTY_PARAM_T property;
+		property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
+		
+		vc_tv_hdmi_get_property(&property);
+		
+		//float framerate;
+		
+		if (property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC) {
+			*framerate = state.display.hdmi.frame_rate * (1000.0f / 1001.0f);
+		} else {
+			*framerate = state.display.hdmi.frame_rate;
+		}
+		
+		*width = state.display.hdmi.width;
+		*height = state.display.hdmi.height;
+		*mode = state.display.hdmi.mode;
+		*group = state.display.hdmi.group;
+	
+	}
+	
+}
+
+int bmx_tvservice_modes(int * imodes, int maxcount, int with_mode) {
+	TV_SUPPORTED_MODE_NEW_T supported_modes[127];
+	HDMI_RES_GROUP_T group, preferred_group;
+	uint32_t preferred_mode;
+	int count, mode_count, i, n;
+	
+	count = 0;
+	
+	for (i = 0; i < 2; i++) {
+
+		memset(supported_modes, 0, sizeof(supported_modes));
+	
+		switch (i) {
+			case 0:
+				group = HDMI_RES_GROUP_CEA;
+				break;
+			case 1:
+				group = HDMI_RES_GROUP_DMT;
+				break;
+		}
+	
+		mode_count = vc_tv_hdmi_get_supported_modes_new(group, supported_modes, vcos_countof(supported_modes),
+				&preferred_group, &preferred_mode);
+		
+		for (n = 0; n < mode_count; n++) {
+			*imodes++ = supported_modes[n].width;
+			*imodes++ = supported_modes[n].height;
+			*imodes++ = 16;
+			*imodes++ = supported_modes[n].frame_rate;
+			
+			if (with_mode) {
+				*imodes++ = supported_modes[n].code;
+				*imodes++ = group;
+			}
+			
+			count++;
+			
+			if (maxcount < count) {
+				break;
+			}
+		}
+	}
+	
+	return count;
+}
+
+void bmx_tvservice_get_closest_mode(int width, int height, int framerate, int * mode, int * group) {
+	int modes[127 * 6];
+	int count, i;
+	*mode = -1;
+	*group = -1;
+	int * p;
+	int closest_prod = -1;
+	int closest_hz = -1;
+	int closest_mode = -1;
+	int closest_group = -1;
+	int product = width * height;
+	int better_match;
+	
+	count = bmx_tvservice_modes(&modes, 127, 1);
+	
+	p = &modes;
+	
+	for (i = 0; i < count; i++) {
+		
+		better_match = 0;
+		
+		if (width <= p[0] && height <= p[1]) {
+			
+			// found a closer res?
+			if (abs(p[0] * p[1] - product) <= abs(closest_prod - product)) {
+				
+				// an exact match?
+				if ((p[0] * p[1] == product) && framerate == p[3]) {
+					*mode = p[4];
+					*group = p[5];
+					break;
+				}
+
+				if (p[0] * p[1] == closest_prod) {
+					
+					// is hz a better match?
+					if (p[3] > closest_hz) {
+						if (abs(framerate-p[3]) < abs(framerate-closest_hz)) {
+							better_match = 1;
+						}
+					}
+					
+				} else {
+					better_match = 1;
+				}
+				
+				if (better_match) {
+					closest_prod = p[0] * p[1];
+					closest_hz = p[3];
+					closest_mode = p[4];
+					closest_group = p[5];
+				}
+
+			}
+		}
+		
+		p += 6;
+	}
+	
+	// did we already find an exact match?
+	// no
+	if (*mode < 0) {
+		// pick the closest
+		*mode = closest_mode;
+		*group = closest_group;
+	}
+}
+
+void bmx_tvservice_setmode(int mode, int group, int width, int height) {
+	// set the tv mode
+	//vc_tv_hdmi_power_on_explicit_new(((group==0) || (group == HDMI_RES_GROUP_CEA))?HDMI_RES_GROUP_CEA:HDMI_RES_GROUP_DMT, mode, HDMI_MODE_HDMI);
+	char buf[255];
+
+	snprintf(buf, 255, "tvservice -e \"%s %d %s\"",((group==0) || (group == HDMI_RES_GROUP_CEA))? "CEA":"DMT", mode, "HDMI");
+	system(buf);
+	
+	sleep(1);
+	
+	// reset the framebuffer
+	//system("fbset -depth 8 && fbset -depth 16");
+	//snprintf(buf, 255, "fbset -xres %d -yres %d -depth 8 && fbset -depth 16", width, height);
+//printf("%s\n", buf);fflush(stdout);
+//	system(buf);
+}
+
+void bmx_reset_screen() {
+	bmx_tvservice_setmode(start_mode, start_group, start_width, start_height);
+	system("fbset -depth 8 && fbset -depth 16");
+}

+ 40 - 4
sdlgraphics.mod/sdlgraphics.bmx

@@ -24,7 +24,14 @@ Strict
 Module SDL.SDLGraphics
 
 ?raspberrypi
+ModuleInfo "CC_OPTS: -D__RASPBERRYPI__"
+ModuleInfo "CC_OPTS: -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads"
 ModuleInfo "LD_OPTS: -L/opt/vc/lib"
+
+Import "-lvcos"
+Import "-lvchostif"
+Import "-lvchiq_arm"
+Import "-lbcm_host"
 ?
 
 Import SDL.SDLSystem
@@ -60,20 +67,42 @@ Type TSDLGraphics Extends TGraphics
 	
 End Type
 
+Type TSDLGraphicsMode Extends TGraphicsMode
+?raspberrypi
+	Field mode:Int
+	Field group:Int
+?
+End Type
+
 Type TSDLGraphicsDriver Extends TGraphicsDriver
+?Not raspberrypi
+	Const MODE_SIZE:Int = 4
+?raspberrypi
+	Const MODE_SIZE:Int = 6
+?
 
 	Method GraphicsModes:TGraphicsMode[]()
-		Local buf:Int[1024*4]
+		Local buf:Int[1024*MODE_SIZE]
+?Not raspberrypi
 		Local count:Int=bbSDLGraphicsGraphicsModes( 0, buf,1024 )
+?raspberrypi
+		Local count:Int = bmx_tvservice_modes(buf, 1024, True)
+?
 		Local modes:TGraphicsMode[count],p:Int Ptr=buf
 		For Local i:Int=0 Until count
-			Local t:TGraphicsMode=New TGraphicsMode
+			Local t:TSDLGraphicsMode=New TSDLGraphicsMode
 			t.width=p[0]
 			t.height=p[1]
 			t.depth=p[2]
 			t.hertz=p[3]
+?raspberrypi
+			t.mode=p[4]
+			t.group=p[5]
+?
 			modes[i]=t
-			p:+4
+
+			p :+ MODE_SIZE
+
 		Next
 		Return modes
 	End Method
@@ -124,11 +153,18 @@ Function SDLGraphics:TGraphics( width:Int,height:Int,depth:Int=0,hertz:Int=60,fl
 	SetGraphicsDriver SDLGraphicsDriver()
 	Return Graphics( width,height,depth,hertz,flags )
 End Function
-	
+
+?Not raspberrypi
 SDL_Init(SDL_INIT_VIDEO)
+?raspberrypi
+bmx_tvservice_init()
+?
 
 ' cleanup context on exit
 OnEnd(bbSDLExit)
+?raspberrypi
+OnEnd(bmx_reset_screen)
+?
 ' set mouse warp function
 _sdl_WarpMouse = bmx_SDL_WarpMouseInWindow