• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
BE_GetOverlayBitmap(BRect bounds,color_space cs)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
convert_color_space(Uint32 format)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
count_planes(Uint32 format)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 
BE_CreateYUVOverlay(_THIS,int width,int height,Uint32 format,SDL_Surface * display)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 
BE_LockYUVOverlay(_THIS,SDL_Overlay * overlay)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 
BE_UnlockYUVOverlay(_THIS,SDL_Overlay * overlay)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 
BE_DisplayYUVOverlay(_THIS,SDL_Overlay * overlay,SDL_Rect * src,SDL_Rect * dst)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 
BE_FreeYUVOverlay(_THIS,SDL_Overlay * overlay)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