SDL-1.2.14
[sdl_omap.git] / src / video / bwindow / SDL_sysyuv.cc
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"