e14743d1 |
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 DirectFB implementation of YUV video overlays */ |
25 | |
26 | #include "SDL_video.h" |
27 | #include "SDL_DirectFB_yuv.h" |
28 | #include "../SDL_yuvfuncs.h" |
29 | |
30 | |
31 | /* The functions used to manipulate software video overlays */ |
32 | static struct private_yuvhwfuncs directfb_yuvfuncs = { |
33 | DirectFB_LockYUVOverlay, |
34 | DirectFB_UnlockYUVOverlay, |
35 | DirectFB_DisplayYUVOverlay, |
36 | DirectFB_FreeYUVOverlay |
37 | }; |
38 | |
39 | struct private_yuvhwdata { |
40 | DFBDisplayLayerID layer_id; |
41 | |
42 | IDirectFBDisplayLayer *layer; |
43 | IDirectFBSurface *surface; |
44 | |
45 | /* These are just so we don't have to allocate them separately */ |
46 | Uint16 pitches[3]; |
47 | Uint8 *planes[3]; |
48 | }; |
49 | |
50 | static DFBEnumerationResult |
51 | enum_layers_callback( DFBDisplayLayerID id, |
52 | DFBDisplayLayerDescription desc, |
53 | void *data ) |
54 | { |
55 | struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data; |
56 | |
57 | /* we don't want the primary */ |
58 | if (id == DLID_PRIMARY) |
59 | return DFENUM_OK; |
60 | |
61 | /* take the one with a surface for video */ |
62 | if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) |
63 | { |
64 | hwdata->layer_id = id; |
65 | |
66 | return DFENUM_CANCEL; |
67 | } |
68 | |
69 | return DFENUM_OK; |
70 | } |
71 | |
72 | |
73 | static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata, |
74 | int width, int height, Uint32 format) |
75 | { |
76 | DFBResult ret; |
77 | IDirectFB *dfb = HIDDEN->dfb; |
78 | IDirectFBDisplayLayer *layer; |
79 | DFBDisplayLayerConfig conf; |
80 | |
81 | ret = dfb->EnumDisplayLayers (dfb, enum_layers_callback, hwdata); |
82 | if (ret) |
83 | { |
84 | SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret); |
85 | return ret; |
86 | } |
87 | |
88 | if (!hwdata->layer_id) |
89 | return DFB_UNSUPPORTED; |
90 | |
91 | ret = dfb->GetDisplayLayer (dfb, hwdata->layer_id, &layer); |
92 | if (ret) |
93 | { |
94 | SetDirectFBerror("IDirectFB::GetDisplayLayer", ret); |
95 | return ret; |
96 | } |
97 | |
98 | conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; |
99 | conf.width = width; |
100 | conf.height = height; |
101 | |
102 | switch (format) |
103 | { |
104 | case SDL_YV12_OVERLAY: |
105 | conf.pixelformat = DSPF_YV12; |
106 | break; |
107 | case SDL_IYUV_OVERLAY: |
108 | conf.pixelformat = DSPF_I420; |
109 | break; |
110 | case SDL_YUY2_OVERLAY: |
111 | conf.pixelformat = DSPF_YUY2; |
112 | break; |
113 | case SDL_UYVY_OVERLAY: |
114 | conf.pixelformat = DSPF_UYVY; |
115 | break; |
116 | default: |
117 | fprintf (stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format); |
118 | break; |
119 | } |
120 | |
121 | /* Need to set coop level or newer DirectFB versions will fail here. */ |
122 | ret = layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE); |
123 | if (ret) |
124 | { |
125 | SetDirectFBerror("IDirectFBDisplayLayer::SetCooperativeLevel() failed", ret); |
126 | layer->Release (layer); |
127 | return ret; |
128 | } |
129 | |
130 | ret = layer->SetConfiguration (layer, &conf); |
131 | if (ret) |
132 | { |
133 | SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret); |
134 | layer->Release (layer); |
135 | return ret; |
136 | } |
137 | |
138 | ret = layer->GetSurface (layer, &hwdata->surface); |
139 | if (ret) |
140 | { |
141 | SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret); |
142 | layer->Release (layer); |
143 | return ret; |
144 | } |
145 | |
146 | hwdata->layer = layer; |
147 | |
148 | return DFB_OK; |
149 | } |
150 | |
151 | SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) |
152 | { |
153 | SDL_Overlay *overlay; |
154 | struct private_yuvhwdata *hwdata; |
155 | |
156 | /* Create the overlay structure */ |
157 | overlay = SDL_calloc (1, sizeof(SDL_Overlay)); |
158 | if (!overlay) |
159 | { |
160 | SDL_OutOfMemory(); |
161 | return NULL; |
162 | } |
163 | |
164 | /* Fill in the basic members */ |
165 | overlay->format = format; |
166 | overlay->w = width; |
167 | overlay->h = height; |
168 | |
169 | /* Set up the YUV surface function structure */ |
170 | overlay->hwfuncs = &directfb_yuvfuncs; |
171 | |
172 | /* Create the pixel data and lookup tables */ |
173 | hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata)); |
174 | overlay->hwdata = hwdata; |
175 | if (!hwdata) |
176 | { |
177 | SDL_OutOfMemory(); |
178 | SDL_FreeYUVOverlay (overlay); |
179 | return NULL; |
180 | } |
181 | |
182 | if (CreateYUVSurface (this, hwdata, width, height, format)) |
183 | { |
184 | SDL_FreeYUVOverlay (overlay); |
185 | return NULL; |
186 | } |
187 | |
188 | overlay->hw_overlay = 1; |
189 | |
190 | /* Set up the plane pointers */ |
191 | overlay->pitches = hwdata->pitches; |
192 | overlay->pixels = hwdata->planes; |
193 | switch (format) |
194 | { |
195 | case SDL_YV12_OVERLAY: |
196 | case SDL_IYUV_OVERLAY: |
197 | overlay->planes = 3; |
198 | break; |
199 | default: |
200 | overlay->planes = 1; |
201 | break; |
202 | } |
203 | |
204 | /* We're all done.. */ |
205 | return overlay; |
206 | } |
207 | |
208 | int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay) |
209 | { |
210 | DFBResult ret; |
211 | void *data; |
212 | int pitch; |
213 | IDirectFBSurface *surface = overlay->hwdata->surface; |
214 | |
215 | ret = surface->Lock (surface, DSLF_READ | DSLF_WRITE, &data, &pitch); |
216 | if (ret) |
217 | { |
218 | SetDirectFBerror("IDirectFBSurface::Lock", ret); |
219 | return -1; |
220 | } |
221 | |
222 | /* Find the pitch and offset values for the overlay */ |
223 | overlay->pitches[0] = (Uint16) pitch; |
224 | overlay->pixels[0] = (Uint8*) data; |
225 | |
226 | switch (overlay->format) |
227 | { |
228 | case SDL_YV12_OVERLAY: |
229 | case SDL_IYUV_OVERLAY: |
230 | /* Add the two extra planes */ |
231 | overlay->pitches[1] = overlay->pitches[0] / 2; |
232 | overlay->pitches[2] = overlay->pitches[0] / 2; |
233 | overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; |
234 | overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; |
235 | break; |
236 | default: |
237 | /* Only one plane, no worries */ |
238 | break; |
239 | } |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) |
245 | { |
246 | IDirectFBSurface *surface = overlay->hwdata->surface; |
247 | |
248 | overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL; |
249 | |
250 | surface->Unlock (surface); |
251 | } |
252 | |
253 | int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) |
254 | { |
255 | DFBResult ret; |
256 | DFBDisplayLayerConfig conf; |
257 | IDirectFBDisplayLayer *primary = HIDDEN->layer; |
258 | IDirectFBDisplayLayer *layer = overlay->hwdata->layer; |
259 | |
260 | primary->GetConfiguration (primary, &conf); |
261 | |
262 | ret = layer->SetScreenLocation (layer, |
263 | dst->x / (float) conf.width, dst->y / (float) conf.height, |
264 | dst->w / (float) conf.width, dst->h / (float) conf.height ); |
265 | if (ret) |
266 | { |
267 | SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret); |
268 | return -1; |
269 | } |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) |
275 | { |
276 | struct private_yuvhwdata *hwdata; |
277 | |
278 | hwdata = overlay->hwdata; |
279 | if (hwdata) |
280 | { |
281 | if (hwdata->surface) |
282 | hwdata->surface->Release (hwdata->surface); |
283 | |
284 | if (hwdata->layer) |
285 | hwdata->layer->Release (hwdata->layer); |
286 | |
287 | free (hwdata); |
288 | } |
289 | } |
290 | |