1 /*
2 (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 All rights reserved.
14
15 This file is subject to the terms and conditions of the MIT License:
16
17 Permission is hereby granted, free of charge, to any person
18 obtaining a copy of this software and associated documentation
19 files (the "Software"), to deal in the Software without restriction,
20 including without limitation the rights to use, copy, modify, merge,
21 publish, distribute, sublicense, and/or sell copies of the Software,
22 and to permit persons to whom the Software is furnished to do so,
23 subject to the following conditions:
24
25 The above copyright notice and this permission notice shall be
26 included in all copies or substantial portions of the Software.
27
28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
32 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
33 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
34 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 */
36
37 #include <config.h>
38
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <sys/mman.h>
42 #include <sys/stat.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <stdarg.h>
46
47 #include <directfb.h>
48
49 #include <direct/debug.h>
50 #include <direct/interface.h>
51 #include <direct/messages.h>
52 #include <direct/util.h>
53
54 #include <idirectfb.h>
55
56 #include <display/idirectfbsurface.h>
57
58 #include <misc/gfx_util.h>
59
60 #include <media/idirectfbdatabuffer.h>
61 #include <media/idirectfbimageprovider.h>
62
63 #include <dfiff.h>
64
65 static DFBResult
66 Probe( IDirectFBImageProvider_ProbeContext *ctx );
67
68 static DFBResult
69 Construct( IDirectFBImageProvider *thiz,
70 ... );
71
72 #include <direct/interface_implementation.h>
73
74 DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, DFIFF )
75
76
77 /*
78 * private data struct of IDirectFBImageProvider_DFIFF
79 */
80 typedef struct {
81 IDirectFBImageProvider_data base;
82
83 void *ptr; /* pointer to raw file data (mapped) */
84 int len; /* data length, i.e. file size */
85 } IDirectFBImageProvider_DFIFF_data;
86
87
88
89
90
91 static void
IDirectFBImageProvider_DFIFF_Destruct(IDirectFBImageProvider * thiz)92 IDirectFBImageProvider_DFIFF_Destruct( IDirectFBImageProvider *thiz )
93 {
94 IDirectFBImageProvider_DFIFF_data *data = thiz->priv;
95
96 munmap( data->ptr, data->len );
97 }
98
99 static DFBResult
IDirectFBImageProvider_DFIFF_RenderTo(IDirectFBImageProvider * thiz,IDirectFBSurface * destination,const DFBRectangle * dest_rect)100 IDirectFBImageProvider_DFIFF_RenderTo( IDirectFBImageProvider *thiz,
101 IDirectFBSurface *destination,
102 const DFBRectangle *dest_rect )
103 {
104 DFBResult ret;
105 IDirectFBSurface_data *dst_data;
106 CoreSurface *dst_surface;
107 const DFIFFHeader *header;
108 DFBRectangle rect;
109 DFBRectangle clipped;
110
111 DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_DFIFF)
112
113 if (!destination)
114 return DFB_INVARG;
115
116 DIRECT_INTERFACE_GET_DATA_FROM (destination, dst_data, IDirectFBSurface);
117
118 dst_surface = dst_data->surface;
119 if (!dst_surface)
120 return DFB_DEAD;
121
122 if (dest_rect) {
123 rect.x = dest_rect->x + dst_data->area.wanted.x;
124 rect.y = dest_rect->y + dst_data->area.wanted.y;
125 rect.w = dest_rect->w;
126 rect.h = dest_rect->h;
127 }
128 else
129 rect = dst_data->area.wanted;
130
131 if (rect.w < 1 || rect.h < 1)
132 return DFB_INVAREA;
133
134 clipped = rect;
135
136 if (!dfb_rectangle_intersect( &clipped, &dst_data->area.current ))
137 return DFB_INVAREA;
138
139 header = data->ptr;
140
141 if (DFB_RECTANGLE_EQUAL( rect, clipped ) &&
142 (unsigned)rect.w == header->width && (unsigned)rect.h == header->height &&
143 dst_surface->config.format == header->format)
144 {
145 ret = dfb_surface_write_buffer( dst_surface, CSBR_BACK,
146 (u8*)data->ptr + sizeof(DFIFFHeader), header->pitch, &rect );
147 if (ret)
148 return ret;
149 }
150 else {
151 IDirectFBSurface *source;
152 DFBSurfaceDescription desc;
153 DFBSurfaceCapabilities caps;
154 DFBRegion clip = DFB_REGION_INIT_FROM_RECTANGLE( &clipped );
155 DFBRegion old_clip;
156
157 thiz->GetSurfaceDescription( thiz, &desc );
158
159 desc.flags |= DSDESC_PREALLOCATED;
160 desc.preallocated[0].data = (u8*)data->ptr + sizeof(DFIFFHeader);
161 desc.preallocated[0].pitch = header->pitch;
162
163 ret = idirectfb_singleton->CreateSurface( idirectfb_singleton, &desc, &source );
164 if (ret)
165 return ret;
166
167 destination->GetCapabilities( destination, &caps );
168
169 if (caps & DSCAPS_PREMULTIPLIED && DFB_PIXELFORMAT_HAS_ALPHA(desc.pixelformat))
170 destination->SetBlittingFlags( destination, DSBLIT_SRC_PREMULTIPLY );
171 else
172 destination->SetBlittingFlags( destination, DSBLIT_NOFX );
173
174 destination->GetClip( destination, &old_clip );
175 destination->SetClip( destination, &clip );
176
177 destination->StretchBlit( destination, source, NULL, &rect );
178
179 destination->SetClip( destination, &old_clip );
180
181 destination->SetBlittingFlags( destination, DSBLIT_NOFX );
182
183 destination->ReleaseSource( destination );
184
185 source->Release( source );
186 }
187
188 if (data->base.render_callback) {
189 DFBRectangle rect = { 0, 0, clipped.w, clipped.h };
190 data->base.render_callback( &rect,
191 data->base.render_callback_context );
192 }
193
194 return DFB_OK;
195 }
196
197 /* Loading routines */
198
199 static DFBResult
IDirectFBImageProvider_DFIFF_GetSurfaceDescription(IDirectFBImageProvider * thiz,DFBSurfaceDescription * dsc)200 IDirectFBImageProvider_DFIFF_GetSurfaceDescription( IDirectFBImageProvider *thiz,
201 DFBSurfaceDescription *dsc )
202 {
203 const DFIFFHeader *header;
204
205 DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_DFIFF)
206
207 header = data->ptr;
208
209 dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
210 dsc->width = header->width;
211 dsc->height = header->height;
212 dsc->pixelformat = header->format;
213
214 return DFB_OK;
215 }
216
217 static DFBResult
IDirectFBImageProvider_DFIFF_GetImageDescription(IDirectFBImageProvider * thiz,DFBImageDescription * desc)218 IDirectFBImageProvider_DFIFF_GetImageDescription( IDirectFBImageProvider *thiz,
219 DFBImageDescription *desc )
220 {
221 const DFIFFHeader *header;
222
223 DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_DFIFF)
224
225 if (!desc)
226 return DFB_INVARG;
227
228 header = data->ptr;
229
230 desc->caps = DICAPS_NONE;
231
232 if (DFB_PIXELFORMAT_HAS_ALPHA( header->format ))
233 desc->caps |= DICAPS_ALPHACHANNEL;
234
235 return DFB_OK;
236 }
237
238
239
240 static DFBResult
Probe(IDirectFBImageProvider_ProbeContext * ctx)241 Probe( IDirectFBImageProvider_ProbeContext *ctx )
242 {
243 if (!strncmp( (const char*) ctx->header, "DFIFF", 5 ))
244 return DFB_OK;
245
246 return DFB_UNSUPPORTED;
247 }
248
249 static DFBResult
Construct(IDirectFBImageProvider * thiz,...)250 Construct( IDirectFBImageProvider *thiz,
251 ... )
252 {
253 DFBResult ret;
254 struct stat stat;
255 void *ptr;
256 int fd = -1;
257 IDirectFBDataBuffer_data *buffer_data;
258
259 IDirectFBDataBuffer *buffer;
260 CoreDFB *core;
261 va_list tag;
262
263 DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBImageProvider_DFIFF)
264
265 va_start( tag, thiz );
266 buffer = va_arg( tag, IDirectFBDataBuffer * );
267 core = va_arg( tag, CoreDFB * );
268 va_end( tag );
269
270 D_MAGIC_ASSERT( (IAny*) buffer, DirectInterface );
271
272 /* Get the buffer's private data. */
273 buffer_data = buffer->priv;
274 if (!buffer_data) {
275 ret = DFB_DEAD;
276 goto error;
277 }
278
279 /* Check for valid filename. */
280 if (!buffer_data->filename) {
281 ret = DFB_UNSUPPORTED;
282 goto error;
283 }
284
285 /* Open the file. */
286 fd = open( buffer_data->filename, O_RDONLY );
287 if (fd < 0) {
288 ret = errno2result( errno );
289 D_PERROR( "ImageProvider/DFIFF: Failure during open() of '%s'!\n", buffer_data->filename );
290 goto error;
291 }
292
293 /* Query file size etc. */
294 if (fstat( fd, &stat ) < 0) {
295 ret = errno2result( errno );
296 D_PERROR( "ImageProvider/DFIFF: Failure during fstat() of '%s'!\n", buffer_data->filename );
297 goto error;
298 }
299
300 /* Memory map the file. */
301 ptr = mmap( NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0 );
302 if (ptr == MAP_FAILED) {
303 ret = errno2result( errno );
304 D_PERROR( "ImageProvider/DFIFF: Failure during mmap() of '%s'!\n", buffer_data->filename );
305 goto error;
306 }
307
308 /* Already close, we still have the map. */
309 close( fd );
310
311 data->base.ref = 1;
312 data->base.core = core;
313
314 data->ptr = ptr;
315 data->len = stat.st_size;
316
317 data->base.Destruct = IDirectFBImageProvider_DFIFF_Destruct;
318
319 thiz->RenderTo = IDirectFBImageProvider_DFIFF_RenderTo;
320 thiz->GetImageDescription = IDirectFBImageProvider_DFIFF_GetImageDescription;
321 thiz->GetSurfaceDescription = IDirectFBImageProvider_DFIFF_GetSurfaceDescription;
322
323 return DFB_OK;
324
325 error:
326 if (fd != -1)
327 close( fd );
328
329 DIRECT_DEALLOCATE_INTERFACE(thiz);
330
331 return ret;
332 }
333
334