te: Mon, 15 Dec 2003 08:25:14 -0800 PST
authorSam Lantinga <slouken@libsdl.org>
Tue, 16 Dec 2003 13:04:44 +0000
changeset 756 10332c6fad2e
parent 755 b1595db396a7
child 757 4f46fee887fe
te: Mon, 15 Dec 2003 08:25:14 -0800 PST From: "Andrew Bachmann" Subject: libSDL patches for beos video I created some patches to SDL: 1. YUV overlay support 2. maintain high refresh rate when changing resolutions to a lower resolution
src/video/bwindow/Makefile.am
src/video/bwindow/SDL_BView.h
src/video/bwindow/SDL_lowvideo.h
src/video/bwindow/SDL_sysvideo.cc
src/video/bwindow/SDL_sysyuv.cc
src/video/bwindow/SDL_sysyuv.h
--- a/src/video/bwindow/Makefile.am	Sun Dec 14 06:28:07 2003 +0000
+++ b/src/video/bwindow/Makefile.am	Tue Dec 16 13:04:44 2003 +0000
@@ -15,5 +15,7 @@
 	SDL_sysmouse_c.h	\
 	SDL_sysvideo.cc		\
 	SDL_syswm.cc		\
-	SDL_syswm_c.h
+	SDL_syswm_c.h		\
+	SDL_sysyuv.cc		\
+	SDL_sysyuv.h
 
--- a/src/video/bwindow/SDL_BView.h	Sun Dec 14 06:28:07 2003 +0000
+++ b/src/video/bwindow/SDL_BView.h	Tue Dec 16 13:04:44 2003 +0000
@@ -20,6 +20,9 @@
     slouken@libsdl.org
 */
 
+#ifndef _SDL_BView_h
+#define _SDL_BView_h
+
 #ifdef SAVE_RCSID
 static char rcsid =
  "@(#) $Id$";
@@ -109,3 +112,5 @@
 	BBitmap *image;
 	int xoff, yoff;
 };
+
+#endif /* _SDL_BView_h */
--- a/src/video/bwindow/SDL_lowvideo.h	Sun Dec 14 06:28:07 2003 +0000
+++ b/src/video/bwindow/SDL_lowvideo.h	Tue Dec 16 13:04:44 2003 +0000
@@ -28,6 +28,7 @@
 #ifndef _SDL_lowvideo_h
 #define _SDL_lowvideo_h
 
+#include "SDL_BWin.h"
 #include "SDL_mouse.h"
 #include "SDL_sysvideo.h"
 
@@ -55,6 +56,8 @@
 	/* Keyboard state variables */
 	int key_flip;
 	struct key_info keyinfo[2];
+	
+	SDL_Overlay *overlay;
 };
 /* Old variable names */
 #define SDL_Win		(_this->hidden->SDL_Win)
@@ -66,5 +69,6 @@
 #define last_point	(_this->hidden->last_point)
 #define key_flip	(_this->hidden->key_flip)
 #define keyinfo		(_this->hidden->keyinfo)
+#define current_overlay (_this->hidden->overlay)
 
 #endif /* _SDL_lowvideo_h */
--- a/src/video/bwindow/SDL_sysvideo.cc	Sun Dec 14 06:28:07 2003 +0000
+++ b/src/video/bwindow/SDL_sysvideo.cc	Tue Dec 16 13:04:44 2003 +0000
@@ -47,6 +47,8 @@
 #include "SDL_events_c.h"
 #include "SDL_syswm_c.h"
 #include "SDL_lowvideo.h"
+#include "SDL_yuvfuncs.h"
+#include "SDL_sysyuv.h"
 
 #define BEOS_HIDDEN_SIZE	32	/* starting hidden window size */
 
@@ -65,6 +67,7 @@
 static void BE_FreeHWSurface(_THIS, SDL_Surface *surface);
 
 static int BE_ToggleFullScreen(_THIS, int fullscreen);
+static SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display);
 
 /* OpenGL functions */
 #ifdef HAVE_OPENGL
@@ -136,6 +139,7 @@
 
 	device->free = BE_DeleteDevice;
 	device->ToggleFullScreen = BE_ToggleFullScreen;
+	device->CreateYUVOverlay = BE_CreateYUVOverlay;
 
 	/* Set the driver flags */
 	device->handles_any_size = 1;
@@ -330,6 +334,11 @@
 	uint32 i, nmodes;
 	SDL_Rect **modes;
 	display_mode *dmodes;
+	display_mode current;
+	float current_refresh;
+	bscreen.GetMode(&current);
+	current_refresh = (1000 * current.timing.pixel_clock) / 
+	                  (current.timing.h_total * current.timing.v_total);
 
 	modes = SDL_modelist[((bpp+7)/8)-1];
 	for ( i=0; modes[i] && (modes[i]->w > width) &&
@@ -351,6 +360,15 @@
 	}
 	if ( i != nmodes ) {
 		*mode = dmodes[i];
+		if ((mode->virtual_width <= current.virtual_width) &&
+		    (mode->virtual_height <= current.virtual_height)) {
+			float new_refresh = (1000 * mode->timing.pixel_clock) /
+			                    (mode->timing.h_total * mode->timing.v_total);
+			if (new_refresh < current_refresh) {
+				mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total)
+				                                    * current_refresh / 1000);
+			}
+		}
 		return true;
 	} else {
 		return false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/bwindow/SDL_sysyuv.cc	Tue Dec 16 13:04:44 2003 +0000
@@ -0,0 +1,323 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* This is the BeOS version of SDL YUV video overlays */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_sysyuv.h"
+#include "SDL_yuvfuncs.h"
+
+extern "C" {
+
+/* The functions used to manipulate software video overlays */
+static struct private_yuvhwfuncs be_yuvfuncs =
+{
+    BE_LockYUVOverlay,
+    BE_UnlockYUVOverlay,
+    BE_DisplayYUVOverlay,
+    BE_FreeYUVOverlay
+};
+
+BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs) {
+	BBitmap *bbitmap;
+	bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs);
+	if (!bbitmap || bbitmap->InitCheck() != B_OK) {
+		delete bbitmap;
+		return 0;
+	}
+	overlay_restrictions r;
+	bbitmap->GetOverlayRestrictions(&r);
+	uint32 width = bounds.IntegerWidth() + 1;
+	uint32 height = bounds.IntegerHeight() + 1;
+	uint32 width_padding = 0;
+	uint32 height_padding = 0;
+	if ((r.source.horizontal_alignment != 0) ||
+	    (r.source.vertical_alignment != 0)) {
+		delete bbitmap;
+		return 0;
+	}
+	if (r.source.width_alignment != 0) {
+		uint32 aligned_width = r.source.width_alignment + 1;
+		if (width % aligned_width > 0) {
+			width_padding = aligned_width - width % aligned_width;
+		}
+	}
+	if (r.source.height_alignment != 0) {
+		uint32 aligned_height = r.source.height_alignment + 1;
+		if (height % aligned_height > 0) {
+			fprintf(stderr,"GetOverlayBitmap failed height alignment\n");
+			fprintf(stderr,"- height = %lu, aligned_height = %lu\n",height,aligned_height);
+			delete bbitmap;
+			return 0;
+		}
+	}
+	if ((r.source.min_width > width) ||
+	    (r.source.min_height > height) ||
+	    (r.source.max_width < width) ||
+	    (r.source.max_height < height)) {
+		fprintf(stderr,"GetOverlayBitmap failed bounds tests\n");
+	    delete bbitmap;
+	    return 0;
+	}
+	if ((width_padding != 0) || (height_padding != 0)) {
+		delete bbitmap;
+		bounds.Set(bounds.left,bounds.top,bounds.right+width_padding,bounds.bottom+height_padding);
+		bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs);
+		if (!bbitmap || bbitmap->InitCheck() != B_OK) {
+			fprintf(stderr,"GetOverlayBitmap failed late\n");
+			delete bbitmap;
+			return 0;
+		}
+	}		
+	return bbitmap;	    
+}
+
+// See <GraphicsDefs.h> [btw: Cb=U, Cr=V]
+// See also http://www.fourcc.org/indexyuv.htm
+enum color_space convert_color_space(Uint32 format) {
+	switch (format) {
+	case SDL_YV12_OVERLAY:
+		return B_YUV9;
+	case SDL_IYUV_OVERLAY:
+		return B_YUV12;
+	case SDL_YUY2_OVERLAY:
+		return B_YCbCr422;
+	case SDL_UYVY_OVERLAY:
+		return B_YUV422;
+	case SDL_YVYU_OVERLAY: // not supported on beos?
+		return B_NO_COLOR_SPACE;
+	default:
+		return B_NO_COLOR_SPACE;
+	}
+}
+
+// See SDL_video.h
+int count_planes(Uint32 format) {
+	switch (format) {
+	case SDL_YV12_OVERLAY:
+	case SDL_IYUV_OVERLAY:
+		return 3;
+	case SDL_YUY2_OVERLAY:
+	case SDL_UYVY_OVERLAY:
+	case SDL_YVYU_OVERLAY:
+		return 1;
+	default:
+		return 0;
+	}
+}		
+
+SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) {
+	SDL_Overlay* overlay;
+	struct private_yuvhwdata* hwdata;
+	BBitmap *bbitmap;
+	int planes;
+	BRect bounds;
+	color_space cs;
+	
+	/* find the appropriate BeOS colorspace descriptor */
+	cs = convert_color_space(format);
+	if (cs == B_NO_COLOR_SPACE)
+	{
+		return NULL;
+	}
+	
+	/* count planes */
+	planes = count_planes(format);
+	if (planes == 0)
+	{
+		return NULL;
+	}
+	/* TODO: figure out planar modes, if anyone cares */
+	if (planes == 3)
+	{
+		return NULL;
+	}
+
+    /* Create the overlay structure */
+    overlay = (SDL_Overlay*)calloc(1, sizeof(SDL_Overlay));
+
+    if (overlay == NULL)
+    {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    /* Fill in the basic members */
+    overlay->format = format;
+    overlay->w = width;
+    overlay->h = height;
+    overlay->hwdata = NULL;
+	
+    /* Set up the YUV surface function structure */
+    overlay->hwfuncs = &be_yuvfuncs;
+
+    /* Create the pixel data and lookup tables */
+    hwdata = (struct private_yuvhwdata*)calloc(1, sizeof(struct private_yuvhwdata));
+
+    if (hwdata == NULL)
+    {
+        SDL_OutOfMemory();
+        SDL_FreeYUVOverlay(overlay);
+        return NULL;
+    }
+
+    overlay->hwdata = hwdata;
+	overlay->hwdata->display = display;
+	overlay->hwdata->bview = NULL;
+	overlay->hwdata->bbitmap = NULL;
+	overlay->hwdata->locked = 0;
+
+	/* Create the BBitmap framebuffer */
+	bounds.top = 0;	bounds.left = 0;
+	bounds.right = width-1;
+	bounds.bottom = height-1;
+	
+	BView * bview = new BView(bounds,"overlay",B_FOLLOW_NONE,B_WILL_DRAW); 
+	if (!bview) {
+		SDL_OutOfMemory();
+        SDL_FreeYUVOverlay(overlay);
+        return NULL;
+	}
+	overlay->hwdata->bview = bview;
+	overlay->hwdata->first_display = true;
+	bview->Hide();
+	
+	bbitmap = BE_GetOverlayBitmap(bounds,cs);
+	if (!bbitmap) {
+		overlay->hwdata->bbitmap = NULL;
+		SDL_FreeYUVOverlay(overlay);
+		return NULL;
+	}
+	overlay->hwdata->bbitmap = bbitmap;
+	
+	overlay->planes = planes;
+	overlay->pitches = (Uint16*)calloc(overlay->planes, sizeof(Uint16));
+	overlay->pixels  = (Uint8**)calloc(overlay->planes, sizeof(Uint8*));
+	if (!overlay->pitches || !overlay->pixels)
+	{
+        SDL_OutOfMemory();
+        SDL_FreeYUVOverlay(overlay);
+        return(NULL);
+    }
+
+   	overlay->pitches[0] = bbitmap->BytesPerRow();
+   	overlay->pixels[0]  = (Uint8 *)bbitmap->Bits();
+	overlay->hw_overlay = 1;
+	
+	if (SDL_Win->LockWithTimeout(1000000) != B_OK) {
+        SDL_FreeYUVOverlay(overlay);
+        return(NULL);
+    }
+	BView * view = SDL_Win->View();
+    view->AddChild(bview);
+    rgb_color key;
+    bview->SetViewOverlay(bbitmap,bounds,bview->Bounds(),&key,B_FOLLOW_ALL,
+                         B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
+    bview->SetViewColor(key);
+    bview->Flush();
+	SDL_Win->Unlock();
+	
+	current_overlay=overlay;
+        
+	return overlay;
+}
+
+int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay)
+{
+    if (overlay == NULL)
+    {
+        return 0;
+    }
+
+    overlay->hwdata->locked = 1;
+    return 0;
+}
+
+void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay)
+{
+    if (overlay == NULL)
+    {
+         return;
+    }
+
+    overlay->hwdata->locked = 0;
+}
+
+int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* dstrect)
+{
+    if ((overlay == NULL) || (overlay->hwdata==NULL)
+        || (overlay->hwdata->bview==NULL) || (SDL_Win->View() == NULL))
+    {
+        return -1;
+    }
+    if (SDL_Win->LockWithTimeout(50000) != B_OK) {
+        return 0;
+    }
+    BView * bview = overlay->hwdata->bview;
+    if (SDL_Win->IsFullScreen()) {
+    	int left,top;
+    	SDL_Win->GetXYOffset(left,top);
+	    bview->MoveTo(left+dstrect->x,top+dstrect->y);
+    } else {
+	    bview->MoveTo(dstrect->x,dstrect->y);
+    }
+    bview->ResizeTo(dstrect->w,dstrect->h);
+    bview->Flush();
+	if (overlay->hwdata->first_display) {
+		bview->Show();
+		overlay->hwdata->first_display = false;
+	}
+    SDL_Win->Unlock();
+    
+	return 0;
+}
+
+void BE_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
+{
+    if (overlay == NULL)
+    {
+        return;
+    }
+
+    if (overlay->hwdata == NULL)
+    {
+        return;
+    }
+
+    current_overlay=NULL;
+
+	delete overlay->hwdata->bbitmap;
+
+    free(overlay->hwdata);
+}
+
+}; // extern "C"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/bwindow/SDL_sysyuv.h	Tue Dec 16 13:04:44 2003 +0000
@@ -0,0 +1,77 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+
+#ifndef __SDL_SYS_YUV_H__
+#define __SDL_SYS_YUV_H__
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif /* SAVE_RCSID */
+
+/* This is the BeOS implementation of YUV video overlays */
+
+#include "SDL_video.h"
+#include "SDL_lowvideo.h"
+
+extern "C" {
+
+struct private_yuvhwdata
+{
+/*  FRAMEDATA* CurrentFrameData;
+    FRAMEDATA* FrameData0;
+    FRAMEDATA* FrameData1;
+    PgScalerProps_t   props;
+    PgScalerCaps_t    caps;
+    PgVideoChannel_t* channel;
+    PhArea_t CurrentViewPort;
+    PhPoint_t CurrentWindowPos;
+    long format;
+    int scaler_on;
+    int current;
+    long YStride;
+    long VStride;
+    long UStride;
+    int ischromakey;
+    long chromakey;
+    int forcedredraw;
+    unsigned long State;
+    long flags;
+*/
+	SDL_Surface *display;
+	BView *bview;
+	bool first_display;
+	BBitmap *bbitmap;
+    int locked;
+};
+
+extern BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs);
+extern SDL_Overlay* BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface* display);
+extern int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay);
+extern void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay);
+extern int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* dstrect);
+extern void BE_FreeYUVOverlay(_THIS, SDL_Overlay* overlay);
+
+};
+
+#endif /* __SDL_PH_YUV_H__ */