This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_DirectFB_yuv.c
281 lines (228 loc) · 7.29 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 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
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
Sam Lantinga
slouken@libsdl.org
*/
22
#include "SDL_config.h"
23
24
25
26
27
/* This is the DirectFB implementation of YUV video overlays */
#include "SDL_video.h"
#include "SDL_DirectFB_yuv.h"
28
#include "../SDL_yuvfuncs.h"
29
30
31
32
/* The functions used to manipulate software video overlays */
static struct private_yuvhwfuncs directfb_yuvfuncs = {
33
34
35
36
DirectFB_LockYUVOverlay,
DirectFB_UnlockYUVOverlay,
DirectFB_DisplayYUVOverlay,
DirectFB_FreeYUVOverlay
37
38
};
39
40
41
struct private_yuvhwdata
{
DFBDisplayLayerID layer_id;
42
43
44
IDirectFBDisplayLayer *layer;
IDirectFBSurface *surface;
45
46
47
48
/* These are just so we don't have to allocate them separately */
Uint16 pitches[3];
Uint8 *planes[3];
49
50
51
};
static DFBEnumerationResult
52
53
enum_layers_callback(DFBDisplayLayerID id,
DFBDisplayLayerDescription desc, void *data)
54
{
55
struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data;
56
57
58
59
/* we don't want the primary */
if (id == DLID_PRIMARY)
return DFENUM_OK;
60
61
62
63
/* take the one with a surface for video */
if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) {
hwdata->layer_id = id;
64
65
return DFENUM_CANCEL;
66
67
}
68
return DFENUM_OK;
69
70
71
}
72
static DFBResult
73
74
CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata,
int width, int height, Uint32 format)
75
{
76
77
78
79
80
DFBResult ret;
IDirectFB *dfb = HIDDEN->dfb;
IDirectFBDisplayLayer *layer;
DFBDisplayLayerConfig conf;
81
ret = dfb->EnumDisplayLayers(dfb, enum_layers_callback, hwdata);
82
if (ret) {
83
SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret);
84
return ret;
85
86
}
87
88
if (!hwdata->layer_id)
return DFB_UNSUPPORTED;
89
90
ret = dfb->GetDisplayLayer(dfb, hwdata->layer_id, &layer);
91
if (ret) {
92
SetDirectFBerror("IDirectFB::GetDisplayLayer", ret);
93
return ret;
94
95
}
96
97
98
conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
conf.width = width;
conf.height = height;
99
100
switch (format) {
101
case SDL_YV12_OVERLAY:
102
103
conf.pixelformat = DSPF_YV12;
break;
104
case SDL_IYUV_OVERLAY:
105
106
conf.pixelformat = DSPF_I420;
break;
107
case SDL_YUY2_OVERLAY:
108
109
conf.pixelformat = DSPF_YUY2;
break;
110
case SDL_UYVY_OVERLAY:
111
112
conf.pixelformat = DSPF_UYVY;
break;
113
default:
114
115
fprintf(stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n",
format);
116
break;
117
118
}
119
ret = layer->SetConfiguration(layer, &conf);
120
if (ret) {
121
122
SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret);
layer->Release(layer);
123
return ret;
124
125
}
126
ret = layer->GetSurface(layer, &hwdata->surface);
127
if (ret) {
128
129
SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret);
layer->Release(layer);
130
return ret;
131
132
}
133
hwdata->layer = layer;
134
135
return DFB_OK;
136
137
}
138
SDL_Overlay *
139
140
DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
SDL_Surface * display)
141
{
142
143
144
145
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
/* Create the overlay structure */
146
overlay = SDL_calloc(1, sizeof(SDL_Overlay));
147
if (!overlay) {
148
SDL_OutOfMemory();
149
return NULL;
150
}
151
152
153
154
155
156
157
158
159
160
/* Fill in the basic members */
overlay->format = format;
overlay->w = width;
overlay->h = height;
/* Set up the YUV surface function structure */
overlay->hwfuncs = &directfb_yuvfuncs;
/* Create the pixel data and lookup tables */
161
hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
162
163
overlay->hwdata = hwdata;
if (!hwdata) {
164
165
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
166
return NULL;
167
168
}
169
170
if (CreateYUVSurface(this, hwdata, width, height, format)) {
SDL_FreeYUVOverlay(overlay);
171
return NULL;
172
173
}
174
overlay->hw_overlay = 1;
175
176
177
178
179
/* Set up the plane pointers */
overlay->pitches = hwdata->pitches;
overlay->pixels = hwdata->planes;
switch (format) {
180
181
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
182
183
overlay->planes = 3;
break;
184
default:
185
186
overlay->planes = 1;
break;
187
188
}
189
190
/* We're all done.. */
return overlay;
191
192
}
193
int
194
DirectFB_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
195
{
196
197
198
199
200
DFBResult ret;
void *data;
int pitch;
IDirectFBSurface *surface = overlay->hwdata->surface;
201
ret = surface->Lock(surface, DSLF_READ | DSLF_WRITE, &data, &pitch);
202
if (ret) {
203
SetDirectFBerror("IDirectFBSurface::Lock", ret);
204
return -1;
205
206
}
207
208
209
/* Find the pitch and offset values for the overlay */
overlay->pitches[0] = (Uint16) pitch;
overlay->pixels[0] = (Uint8 *) data;
210
211
switch (overlay->format) {
212
213
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
214
215
216
217
218
219
220
221
/* Add the two extra planes */
overlay->pitches[1] = overlay->pitches[0] / 2;
overlay->pitches[2] = overlay->pitches[0] / 2;
overlay->pixels[1] =
overlay->pixels[0] + overlay->pitches[0] * overlay->h;
overlay->pixels[2] =
overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
break;
222
default:
223
224
/* Only one plane, no worries */
break;
225
226
}
227
return 0;
228
229
}
230
void
231
DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
232
{
233
IDirectFBSurface *surface = overlay->hwdata->surface;
234
235
overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL;
236
237
surface->Unlock(surface);
238
239
}
240
int
241
242
DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
SDL_Rect * dst)
243
{
244
245
246
247
248
DFBResult ret;
DFBDisplayLayerConfig conf;
IDirectFBDisplayLayer *primary = HIDDEN->layer;
IDirectFBDisplayLayer *layer = overlay->hwdata->layer;
249
primary->GetConfiguration(primary, &conf);
250
251
252
253
254
255
ret = layer->SetScreenLocation(layer,
dst->x / (float) conf.width,
dst->y / (float) conf.height,
dst->w / (float) conf.width,
dst->h / (float) conf.height);
256
if (ret) {
257
SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret);
258
return -1;
259
260
}
261
return 0;
262
263
}
264
void
265
DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
266
{
267
struct private_yuvhwdata *hwdata;
268
269
270
271
hwdata = overlay->hwdata;
if (hwdata) {
if (hwdata->surface)
272
hwdata->surface->Release(hwdata->surface);
273
274
if (hwdata->layer)
275
hwdata->layer->Release(hwdata->layer);
276
277
free(hwdata);
278
279
280
}
}
281
/* vi: set ts=4 sw=4 expandtab: */