diff src/video/bwindow/SDL_sysyuv.cc @ 756:10332c6fad2e

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
author Sam Lantinga <slouken@libsdl.org>
date Tue, 16 Dec 2003 13:04:44 +0000
parents
children b8d311d90021
line wrap: on
line diff
--- /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"