src/video/bwindow/SDL_sysyuv.cc
author Sam Lantinga <slouken@libsdl.org>
Tue, 17 Mar 2009 03:58:53 +0000
branchSDL-1.2
changeset 4164 7a4c511c980a
parent 4159 a1b03ba2fcd0
child 6137 4720145f848b
permissions -rw-r--r--
Date: Fri, 6 Mar 2009 12:41:17 -0800
From: scott mc
Subject: Re: [SDL] patch for building on haiku

Ok. I've combined the various Haiku patches for the SDL-1.2 branch
into one .diff file
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* This is the BeOS version of SDL YUV video overlays */
    25 
    26 #include "SDL_video.h"
    27 #include "SDL_sysyuv.h"
    28 #include "../SDL_yuvfuncs.h"
    29 
    30 extern "C" {
    31 
    32 /* The functions used to manipulate software video overlays */
    33 static struct private_yuvhwfuncs be_yuvfuncs =
    34 {
    35     BE_LockYUVOverlay,
    36     BE_UnlockYUVOverlay,
    37     BE_DisplayYUVOverlay,
    38     BE_FreeYUVOverlay
    39 };
    40 
    41 BBitmap * BE_GetOverlayBitmap(BRect bounds, color_space cs) {
    42 	BBitmap *bbitmap;
    43 	bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs);
    44 	if (!bbitmap || bbitmap->InitCheck() != B_OK) {
    45 		delete bbitmap;
    46 		return 0;
    47 	}
    48 	overlay_restrictions r;
    49 	bbitmap->GetOverlayRestrictions(&r);
    50 	uint32 width = bounds.IntegerWidth() + 1;
    51 	uint32 height = bounds.IntegerHeight() + 1;
    52 	uint32 width_padding = 0;
    53 	uint32 height_padding = 0;
    54 	if ((r.source.horizontal_alignment != 0) ||
    55 	    (r.source.vertical_alignment != 0)) {
    56 		delete bbitmap;
    57 		return 0;
    58 	}
    59 	if (r.source.width_alignment != 0) {
    60 		uint32 aligned_width = r.source.width_alignment + 1;
    61 		if (width % aligned_width > 0) {
    62 			width_padding = aligned_width - width % aligned_width;
    63 		}
    64 	}
    65 	if (r.source.height_alignment != 0) {
    66 		uint32 aligned_height = r.source.height_alignment + 1;
    67 		if (height % aligned_height > 0) {
    68 			fprintf(stderr,"GetOverlayBitmap failed height alignment\n");
    69 			fprintf(stderr,"- height = %lu, aligned_height = %lu\n",height,aligned_height);
    70 			delete bbitmap;
    71 			return 0;
    72 		}
    73 	}
    74 	if ((r.source.min_width > width) ||
    75 	    (r.source.min_height > height) ||
    76 	    (r.source.max_width < width) ||
    77 	    (r.source.max_height < height)) {
    78 		fprintf(stderr,"GetOverlayBitmap failed bounds tests\n");
    79 	    delete bbitmap;
    80 	    return 0;
    81 	}
    82 	if ((width_padding != 0) || (height_padding != 0)) {
    83 		delete bbitmap;
    84 		bounds.Set(bounds.left,bounds.top,bounds.right+width_padding,bounds.bottom+height_padding);
    85 		bbitmap = new BBitmap(bounds,B_BITMAP_WILL_OVERLAY,cs);
    86 		if (!bbitmap || bbitmap->InitCheck() != B_OK) {
    87 			fprintf(stderr,"GetOverlayBitmap failed late\n");
    88 			delete bbitmap;
    89 			return 0;
    90 		}
    91 	}		
    92 	return bbitmap;	    
    93 }
    94 
    95 // See <GraphicsDefs.h> [btw: Cb=U, Cr=V]
    96 // See also http://www.fourcc.org/indexyuv.htm
    97 color_space convert_color_space(Uint32 format) {
    98 	switch (format) {
    99 	case SDL_YV12_OVERLAY:
   100 		return B_YUV9;
   101 	case SDL_IYUV_OVERLAY:
   102 		return B_YUV12;
   103 	case SDL_YUY2_OVERLAY:
   104 		return B_YCbCr422;
   105 	case SDL_UYVY_OVERLAY:
   106 		return B_YUV422;
   107 	case SDL_YVYU_OVERLAY: // not supported on beos?
   108 		return B_NO_COLOR_SPACE;
   109 	default:
   110 		return B_NO_COLOR_SPACE;
   111 	}
   112 }
   113 
   114 // See SDL_video.h
   115 int count_planes(Uint32 format) {
   116 	switch (format) {
   117 	case SDL_YV12_OVERLAY:
   118 	case SDL_IYUV_OVERLAY:
   119 		return 3;
   120 	case SDL_YUY2_OVERLAY:
   121 	case SDL_UYVY_OVERLAY:
   122 	case SDL_YVYU_OVERLAY:
   123 		return 1;
   124 	default:
   125 		return 0;
   126 	}
   127 }		
   128 
   129 SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) {
   130 	SDL_Overlay* overlay;
   131 	struct private_yuvhwdata* hwdata;
   132 	BBitmap *bbitmap;
   133 	int planes;
   134 	BRect bounds;
   135 	color_space cs;
   136 	
   137 	/* find the appropriate BeOS colorspace descriptor */
   138 	cs = convert_color_space(format);
   139 	if (cs == B_NO_COLOR_SPACE)
   140 	{
   141 		return NULL;
   142 	}
   143 	
   144 	/* count planes */
   145 	planes = count_planes(format);
   146 	if (planes == 0)
   147 	{
   148 		return NULL;
   149 	}
   150 	/* TODO: figure out planar modes, if anyone cares */
   151 	if (planes == 3)
   152 	{
   153 		return NULL;
   154 	}
   155 
   156     /* Create the overlay structure */
   157     overlay = (SDL_Overlay*)SDL_calloc(1, sizeof(SDL_Overlay));
   158 
   159     if (overlay == NULL)
   160     {
   161         SDL_OutOfMemory();
   162         return NULL;
   163     }
   164 
   165     /* Fill in the basic members */
   166     overlay->format = format;
   167     overlay->w = width;
   168     overlay->h = height;
   169     overlay->hwdata = NULL;
   170 	
   171     /* Set up the YUV surface function structure */
   172     overlay->hwfuncs = &be_yuvfuncs;
   173 
   174     /* Create the pixel data and lookup tables */
   175     hwdata = (struct private_yuvhwdata*)SDL_calloc(1, sizeof(struct private_yuvhwdata));
   176 
   177     if (hwdata == NULL)
   178     {
   179         SDL_OutOfMemory();
   180         SDL_FreeYUVOverlay(overlay);
   181         return NULL;
   182     }
   183 
   184     overlay->hwdata = hwdata;
   185 	overlay->hwdata->display = display;
   186 	overlay->hwdata->bview = NULL;
   187 	overlay->hwdata->bbitmap = NULL;
   188 	overlay->hwdata->locked = 0;
   189 
   190 	/* Create the BBitmap framebuffer */
   191 	bounds.top = 0;	bounds.left = 0;
   192 	bounds.right = width-1;
   193 	bounds.bottom = height-1;
   194 	
   195 	BView * bview = new BView(bounds,"overlay",B_FOLLOW_NONE,B_WILL_DRAW); 
   196 	if (!bview) {
   197 		SDL_OutOfMemory();
   198         SDL_FreeYUVOverlay(overlay);
   199         return NULL;
   200 	}
   201 	overlay->hwdata->bview = bview;
   202 	overlay->hwdata->first_display = true;
   203 	bview->Hide();
   204 	
   205 	bbitmap = BE_GetOverlayBitmap(bounds,cs);
   206 	if (!bbitmap) {
   207 		overlay->hwdata->bbitmap = NULL;
   208 		SDL_FreeYUVOverlay(overlay);
   209 		return NULL;
   210 	}
   211 	overlay->hwdata->bbitmap = bbitmap;
   212 	
   213 	overlay->planes = planes;
   214 	overlay->pitches = (Uint16*)SDL_calloc(overlay->planes, sizeof(Uint16));
   215 	overlay->pixels  = (Uint8**)SDL_calloc(overlay->planes, sizeof(Uint8*));
   216 	if (!overlay->pitches || !overlay->pixels)
   217 	{
   218         SDL_OutOfMemory();
   219         SDL_FreeYUVOverlay(overlay);
   220         return(NULL);
   221     }
   222 
   223    	overlay->pitches[0] = bbitmap->BytesPerRow();
   224    	overlay->pixels[0]  = (Uint8 *)bbitmap->Bits();
   225 	overlay->hw_overlay = 1;
   226 	
   227 	if (SDL_Win->LockWithTimeout(1000000) != B_OK) {
   228         SDL_FreeYUVOverlay(overlay);
   229         return(NULL);
   230     }
   231 	BView * view = SDL_Win->View();
   232     view->AddChild(bview);
   233     rgb_color key;
   234     bview->SetViewOverlay(bbitmap,bounds,bview->Bounds(),&key,B_FOLLOW_ALL,
   235                          B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
   236     bview->SetViewColor(key);
   237     bview->Flush();
   238 	SDL_Win->Unlock();
   239 	
   240 	current_overlay=overlay;
   241         
   242 	return overlay;
   243 }
   244 
   245 int BE_LockYUVOverlay(_THIS, SDL_Overlay* overlay)
   246 {
   247     if (overlay == NULL)
   248     {
   249         return 0;
   250     }
   251 
   252     overlay->hwdata->locked = 1;
   253     return 0;
   254 }
   255 
   256 void BE_UnlockYUVOverlay(_THIS, SDL_Overlay* overlay)
   257 {
   258     if (overlay == NULL)
   259     {
   260          return;
   261     }
   262 
   263     overlay->hwdata->locked = 0;
   264 }
   265 
   266 int BE_DisplayYUVOverlay(_THIS, SDL_Overlay* overlay, SDL_Rect* src, SDL_Rect *dst)
   267 {
   268     if ((overlay == NULL) || (overlay->hwdata==NULL)
   269         || (overlay->hwdata->bview==NULL) || (SDL_Win->View() == NULL))
   270     {
   271         return -1;
   272     }
   273     if (SDL_Win->LockWithTimeout(50000) != B_OK) {
   274         return 0;
   275     }
   276     BView * bview = overlay->hwdata->bview;
   277     if (SDL_Win->IsFullScreen()) {
   278     	int left,top;
   279     	SDL_Win->GetXYOffset(left,top);
   280 	    bview->MoveTo(left+dst->x,top+dst->y);
   281     } else {
   282 	    bview->MoveTo(dst->x,dst->y);
   283     }
   284     bview->ResizeTo(dst->w,dst->h);
   285     bview->Flush();
   286 	if (overlay->hwdata->first_display) {
   287 		bview->Show();
   288 		overlay->hwdata->first_display = false;
   289 	}
   290     SDL_Win->Unlock();
   291     
   292 	return 0;
   293 }
   294 
   295 void BE_FreeYUVOverlay(_THIS, SDL_Overlay *overlay)
   296 {
   297     if (overlay == NULL)
   298     {
   299         return;
   300     }
   301 
   302     if (overlay->hwdata == NULL)
   303     {
   304         return;
   305     }
   306 
   307     current_overlay=NULL;
   308 
   309 	delete overlay->hwdata->bbitmap;
   310 
   311     SDL_free(overlay->hwdata);
   312 }
   313 
   314 }; // extern "C"