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