Home | History | Annotate | Download | only in bwindow
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 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 (at) 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 enum 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"
    315