Mercurial > sdl-ios-xcode
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"