1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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 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