Mercurial > sdl-ios-xcode
comparison src/video/directfb/SDL_DirectFB_yuv.c @ 478:f8482d7c9595
Date: Tue, 27 Aug 2002 19:07:38 +0200
From: Denis Oliver Kropp
Subject: YUV support
I just added YUV overlay support to the DirectFB backend.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 31 Aug 2002 04:13:28 +0000 |
parents | |
children | b8d311d90021 |
comparison
equal
deleted
inserted
replaced
477:22581630aab7 | 478:f8482d7c9595 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* This is the DirectFB implementation of YUV video overlays */ | |
29 | |
30 #include <stdlib.h> | |
31 #include <string.h> | |
32 | |
33 #include "SDL_error.h" | |
34 #include "SDL_video.h" | |
35 #include "SDL_DirectFB_yuv.h" | |
36 #include "SDL_yuvfuncs.h" | |
37 | |
38 | |
39 /* The functions used to manipulate software video overlays */ | |
40 static struct private_yuvhwfuncs directfb_yuvfuncs = { | |
41 DirectFB_LockYUVOverlay, | |
42 DirectFB_UnlockYUVOverlay, | |
43 DirectFB_DisplayYUVOverlay, | |
44 DirectFB_FreeYUVOverlay | |
45 }; | |
46 | |
47 struct private_yuvhwdata { | |
48 DFBDisplayLayerID layer_id; | |
49 | |
50 IDirectFBDisplayLayer *layer; | |
51 IDirectFBSurface *surface; | |
52 | |
53 /* These are just so we don't have to allocate them separately */ | |
54 Uint16 pitches[3]; | |
55 Uint8 *planes[3]; | |
56 }; | |
57 | |
58 static DFBEnumerationResult | |
59 enum_layers_callback( DFBDisplayLayerID id, | |
60 DFBDisplayLayerDescription desc, | |
61 void *data ) | |
62 { | |
63 struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data; | |
64 | |
65 /* we don't want the primary */ | |
66 if (id == DLID_PRIMARY) | |
67 return DFENUM_OK; | |
68 | |
69 /* take the one with a surface for video */ | |
70 if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) | |
71 { | |
72 hwdata->layer_id = id; | |
73 | |
74 return DFENUM_CANCEL; | |
75 } | |
76 | |
77 return DFENUM_OK; | |
78 } | |
79 | |
80 | |
81 static DFBResult CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata, | |
82 int width, int height, Uint32 format) | |
83 { | |
84 DFBResult ret; | |
85 IDirectFB *dfb = HIDDEN->dfb; | |
86 IDirectFBDisplayLayer *layer; | |
87 DFBDisplayLayerConfig conf; | |
88 | |
89 ret = dfb->EnumDisplayLayers (dfb, enum_layers_callback, hwdata); | |
90 if (ret) | |
91 { | |
92 SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret); | |
93 return ret; | |
94 } | |
95 | |
96 if (!hwdata->layer_id) | |
97 return DFB_UNSUPPORTED; | |
98 | |
99 ret = dfb->GetDisplayLayer (dfb, hwdata->layer_id, &layer); | |
100 if (ret) | |
101 { | |
102 SetDirectFBerror("IDirectFB::GetDisplayLayer", ret); | |
103 return ret; | |
104 } | |
105 | |
106 conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; | |
107 conf.width = width; | |
108 conf.height = height; | |
109 | |
110 switch (format) | |
111 { | |
112 case SDL_YV12_OVERLAY: | |
113 conf.pixelformat = DSPF_YV12; | |
114 break; | |
115 case SDL_IYUV_OVERLAY: | |
116 conf.pixelformat = DSPF_I420; | |
117 break; | |
118 case SDL_YUY2_OVERLAY: | |
119 conf.pixelformat = DSPF_YUY2; | |
120 break; | |
121 case SDL_UYVY_OVERLAY: | |
122 conf.pixelformat = DSPF_UYVY; | |
123 break; | |
124 default: | |
125 fprintf (stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n", format); | |
126 break; | |
127 } | |
128 | |
129 ret = layer->SetConfiguration (layer, &conf); | |
130 if (ret) | |
131 { | |
132 SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret); | |
133 layer->Release (layer); | |
134 return ret; | |
135 } | |
136 | |
137 ret = layer->GetSurface (layer, &hwdata->surface); | |
138 if (ret) | |
139 { | |
140 SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret); | |
141 layer->Release (layer); | |
142 return ret; | |
143 } | |
144 | |
145 hwdata->layer = layer; | |
146 | |
147 return DFB_OK; | |
148 } | |
149 | |
150 SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | |
151 { | |
152 SDL_Overlay *overlay; | |
153 struct private_yuvhwdata *hwdata; | |
154 | |
155 /* Create the overlay structure */ | |
156 overlay = calloc (1, sizeof(SDL_Overlay)); | |
157 if (!overlay) | |
158 { | |
159 SDL_OutOfMemory(); | |
160 return NULL; | |
161 } | |
162 | |
163 /* Fill in the basic members */ | |
164 overlay->format = format; | |
165 overlay->w = width; | |
166 overlay->h = height; | |
167 | |
168 /* Set up the YUV surface function structure */ | |
169 overlay->hwfuncs = &directfb_yuvfuncs; | |
170 | |
171 /* Create the pixel data and lookup tables */ | |
172 hwdata = calloc(1, sizeof(struct private_yuvhwdata)); | |
173 overlay->hwdata = hwdata; | |
174 if (!hwdata) | |
175 { | |
176 SDL_OutOfMemory(); | |
177 SDL_FreeYUVOverlay (overlay); | |
178 return NULL; | |
179 } | |
180 | |
181 if (CreateYUVSurface (this, hwdata, width, height, format)) | |
182 { | |
183 SDL_FreeYUVOverlay (overlay); | |
184 return NULL; | |
185 } | |
186 | |
187 overlay->hw_overlay = 1; | |
188 | |
189 /* Set up the plane pointers */ | |
190 overlay->pitches = hwdata->pitches; | |
191 overlay->pixels = hwdata->planes; | |
192 switch (format) | |
193 { | |
194 case SDL_YV12_OVERLAY: | |
195 case SDL_IYUV_OVERLAY: | |
196 overlay->planes = 3; | |
197 break; | |
198 default: | |
199 overlay->planes = 1; | |
200 break; | |
201 } | |
202 | |
203 /* We're all done.. */ | |
204 return overlay; | |
205 } | |
206 | |
207 int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
208 { | |
209 DFBResult ret; | |
210 void *data; | |
211 unsigned int pitch; | |
212 IDirectFBSurface *surface = overlay->hwdata->surface; | |
213 | |
214 ret = surface->Lock (surface, DSLF_READ | DSLF_WRITE, &data, &pitch); | |
215 if (ret) | |
216 { | |
217 SetDirectFBerror("IDirectFBSurface::Lock", ret); | |
218 return -1; | |
219 } | |
220 | |
221 /* Find the pitch and offset values for the overlay */ | |
222 overlay->pitches[0] = (Uint16) pitch; | |
223 overlay->pixels[0] = (Uint8*) data; | |
224 | |
225 switch (overlay->format) | |
226 { | |
227 case SDL_YV12_OVERLAY: | |
228 case SDL_IYUV_OVERLAY: | |
229 /* Add the two extra planes */ | |
230 overlay->pitches[1] = overlay->pitches[0] / 2; | |
231 overlay->pitches[2] = overlay->pitches[0] / 2; | |
232 overlay->pixels[1] = overlay->pixels[0] + overlay->pitches[0] * overlay->h; | |
233 overlay->pixels[2] = overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2; | |
234 break; | |
235 default: | |
236 /* Only one plane, no worries */ | |
237 break; | |
238 } | |
239 | |
240 return 0; | |
241 } | |
242 | |
243 void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
244 { | |
245 IDirectFBSurface *surface = overlay->hwdata->surface; | |
246 | |
247 overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL; | |
248 | |
249 surface->Unlock (surface); | |
250 } | |
251 | |
252 int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dst) | |
253 { | |
254 DFBResult ret; | |
255 DFBDisplayLayerConfig conf; | |
256 IDirectFBDisplayLayer *primary = HIDDEN->layer; | |
257 IDirectFBDisplayLayer *layer = overlay->hwdata->layer; | |
258 | |
259 primary->GetConfiguration (primary, &conf); | |
260 | |
261 ret = layer->SetScreenLocation (layer, | |
262 dst->x / (float) conf.width, dst->y / (float) conf.height, | |
263 dst->w / (float) conf.width, dst->h / (float) conf.height ); | |
264 if (ret) | |
265 { | |
266 SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret); | |
267 return -1; | |
268 } | |
269 | |
270 return 0; | |
271 } | |
272 | |
273 void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) | |
274 { | |
275 struct private_yuvhwdata *hwdata; | |
276 | |
277 hwdata = overlay->hwdata; | |
278 if (hwdata) | |
279 { | |
280 if (hwdata->surface) | |
281 hwdata->surface->Release (hwdata->surface); | |
282 | |
283 if (hwdata->layer) | |
284 hwdata->layer->Release (hwdata->layer); | |
285 | |
286 free (hwdata); | |
287 } | |
288 } | |
289 |