Mercurial > sdl-ios-xcode
view src/video/bwindow/SDL_sysyuv.cc @ 4504:9faebccfefb3
Amazingly the Windows code is almost identical to the Mac OS X code. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 08 Jul 2010 23:07:34 -0700 |
parents | 99210400e8b9 |
children | b530ef003506 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2009 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* This is the BeOS version of SDL YUV video overlays */ #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 *) SDL_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 *) SDL_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 *) SDL_calloc(overlay->planes, sizeof(Uint16)); overlay->pixels = (Uint8 **) SDL_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 * src, SDL_Rect * dst) { 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 + dst->x, top + dst->y); } else { bview->MoveTo(dst->x, dst->y); } bview->ResizeTo(dst->w, dst->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; SDL_free(overlay->hwdata); } }; // extern "C" /* vi: set ts=4 sw=4 expandtab: */