This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_DirectFB_yuv.c
289 lines (235 loc) · 7.59 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
73
74
static DFBResult
CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata,
int width, int height, Uint32 format)
75
{
76
77
78
79
80
81
82
83
84
DFBResult ret;
IDirectFB *dfb = HIDDEN->dfb;
IDirectFBDisplayLayer *layer;
DFBDisplayLayerConfig conf;
ret = dfb->EnumDisplayLayers(dfb, enum_layers_callback, hwdata);
if (ret) {
SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret);
return ret;
85
86
}
87
88
if (!hwdata->layer_id)
return DFB_UNSUPPORTED;
89
90
91
92
93
ret = dfb->GetDisplayLayer(dfb, hwdata->layer_id, &layer);
if (ret) {
SetDirectFBerror("IDirectFB::GetDisplayLayer", ret);
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
116
fprintf(stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n",
format);
break;
117
118
}
119
120
121
122
123
124
125
126
/* Need to set coop level or newer DirectFB versions will fail here. */
ret = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if (ret) {
SetDirectFBError("IDirectFBDisplayLayer::SetCooperativeLevel() failed", ret);
layer->Release(layer);
return ret;
}
127
128
129
130
131
ret = layer->SetConfiguration(layer, &conf);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret);
layer->Release(layer);
return ret;
132
133
}
134
135
136
137
138
ret = layer->GetSurface(layer, &hwdata->surface);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret);
layer->Release(layer);
return ret;
139
140
}
141
hwdata->layer = layer;
142
143
return DFB_OK;
144
145
}
146
147
148
SDL_Overlay *
DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
SDL_Surface * display)
149
{
150
151
152
153
154
155
156
157
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
/* Create the overlay structure */
overlay = SDL_calloc(1, sizeof(SDL_Overlay));
if (!overlay) {
SDL_OutOfMemory();
return NULL;
158
}
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* 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 */
hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
overlay->hwdata = hwdata;
if (!hwdata) {
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
return NULL;
175
176
}
177
178
179
if (CreateYUVSurface(this, hwdata, width, height, format)) {
SDL_FreeYUVOverlay(overlay);
return NULL;
180
181
}
182
overlay->hw_overlay = 1;
183
184
185
186
187
/* Set up the plane pointers */
overlay->pitches = hwdata->pitches;
overlay->pixels = hwdata->planes;
switch (format) {
188
189
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
190
191
overlay->planes = 3;
break;
192
default:
193
194
overlay->planes = 1;
break;
195
196
}
197
198
/* We're all done.. */
return overlay;
199
200
}
201
202
int
DirectFB_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
203
{
204
205
206
207
208
209
210
211
212
DFBResult ret;
void *data;
int pitch;
IDirectFBSurface *surface = overlay->hwdata->surface;
ret = surface->Lock(surface, DSLF_READ | DSLF_WRITE, &data, &pitch);
if (ret) {
SetDirectFBerror("IDirectFBSurface::Lock", ret);
return -1;
213
214
}
215
216
217
/* Find the pitch and offset values for the overlay */
overlay->pitches[0] = (Uint16) pitch;
overlay->pixels[0] = (Uint8 *) data;
218
219
switch (overlay->format) {
220
221
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
222
223
224
225
226
227
228
229
/* 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;
230
default:
231
232
/* Only one plane, no worries */
break;
233
234
}
235
return 0;
236
237
}
238
239
void
DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
240
{
241
IDirectFBSurface *surface = overlay->hwdata->surface;
242
243
overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL;
244
245
surface->Unlock(surface);
246
247
}
248
249
250
int
DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
SDL_Rect * dst)
251
{
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
DFBResult ret;
DFBDisplayLayerConfig conf;
IDirectFBDisplayLayer *primary = HIDDEN->layer;
IDirectFBDisplayLayer *layer = overlay->hwdata->layer;
primary->GetConfiguration(primary, &conf);
ret = layer->SetScreenLocation(layer,
dst->x / (float) conf.width,
dst->y / (float) conf.height,
dst->w / (float) conf.width,
dst->h / (float) conf.height);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret);
return -1;
267
268
}
269
return 0;
270
271
}
272
273
void
DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
274
{
275
struct private_yuvhwdata *hwdata;
276
277
278
279
280
hwdata = overlay->hwdata;
if (hwdata) {
if (hwdata->surface)
hwdata->surface->Release(hwdata->surface);
281
282
283
if (hwdata->layer)
hwdata->layer->Release(hwdata->layer);
284
285
free(hwdata);
286
287
288
}
}
289
/* vi: set ts=4 sw=4 expandtab: */