1 /*
2 (c) Copyright 2008 Denis Oliver Kropp
3
4 All rights reserved.
5
6 This file is subject to the terms and conditions of the MIT License:
7
8 Permission is hereby granted, free of charge, to any person
9 obtaining a copy of this software and associated documentation
10 files (the "Software"), to deal in the Software without restriction,
11 including without limitation the rights to use, copy, modify, merge,
12 publish, distribute, sublicense, and/or sell copies of the Software,
13 and to permit persons to whom the Software is furnished to do so,
14 subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 #include <config.h>
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include <direct/messages.h>
35
36 #include <directfb.h>
37 #include <directfb_strings.h>
38 #include <directfb_util.h>
39
40
41 static const s32 identity_matrix[9] = { 0x10000, 0x00000, 0x00000,
42 0x00000, 0x10000, 0x00000,
43 0x00000, 0x00000, 0x10000 };
44
45 static const s32 rotate_matrix[9] = { 0x0DDB3, -0x08000, 0x00000,
46 0x08000, 0x0DDB3, 0x00000,
47 0x00000, 0x00000, 0x10000 };
48
49 static const s32 translate_matrix[9] = { 0x10000, 0x00000, 0x80000,
50 0x00000, 0x10000, 0xF0000,
51 0x00000, 0x00000, 0x10000 };
52
53 static const s32 shear_matrix[9] = { 0x10000, 0x14000, 0x00000,
54 0x00000, 0x10000, 0x00000,
55 0x00000, 0x00000, 0x10000 };
56
57 static const DirectFBPixelFormatNames( format_names );
58
59 /**********************************************************************************************************************/
60
61 static DFBBoolean
parse_format(const char * arg,DFBSurfacePixelFormat * _f)62 parse_format( const char *arg, DFBSurfacePixelFormat *_f )
63 {
64 int i = 0;
65
66 while (format_names[i].format != DSPF_UNKNOWN) {
67 if (!strcasecmp( arg, format_names[i].name )) {
68 *_f = format_names[i].format;
69 return DFB_TRUE;
70 }
71
72 ++i;
73 }
74
75 fprintf (stderr, "\nInvalid format specified!\n\n" );
76
77 return DFB_FALSE;
78 }
79
80 static int
print_usage(const char * prg)81 print_usage( const char *prg )
82 {
83 int i = 0;
84
85 fprintf (stderr, "\n");
86 fprintf (stderr, "== DirectFB Blitting Test (version %s) ==\n", DIRECTFB_VERSION);
87 fprintf (stderr, "\n");
88 fprintf (stderr, "Known pixel formats:\n");
89
90 while (format_names[i].format != DSPF_UNKNOWN) {
91 DFBSurfacePixelFormat format = format_names[i].format;
92
93 fprintf (stderr, " %-10s %2d bits, %d bytes",
94 format_names[i].name, DFB_BITS_PER_PIXEL(format),
95 DFB_BYTES_PER_PIXEL(format));
96
97 if (DFB_PIXELFORMAT_HAS_ALPHA(format))
98 fprintf (stderr, " ALPHA");
99
100 if (DFB_PIXELFORMAT_IS_INDEXED(format))
101 fprintf (stderr, " INDEXED");
102
103 if (DFB_PLANAR_PIXELFORMAT(format)) {
104 int planes = DFB_PLANE_MULTIPLY(format, 1000);
105
106 fprintf (stderr, " PLANAR (x%d.%03d)",
107 planes / 1000, planes % 1000);
108 }
109
110 fprintf (stderr, "\n");
111
112 ++i;
113 }
114
115 fprintf (stderr, "\n");
116
117 fprintf (stderr, "\n");
118 fprintf (stderr, "Usage: %s [options]\n", prg);
119 fprintf (stderr, "\n");
120 fprintf (stderr, "Options:\n");
121 fprintf (stderr, " -h, --help Show this help message\n");
122 fprintf (stderr, " -v, --version Print version information\n");
123 fprintf (stderr, " -s, --source <pixelformat> Source pixel format\n");
124 fprintf (stderr, " -d, --dest <pixelformat> Destination pixel format\n");
125 fprintf (stderr, " -r, --resize Set destination from source size\n");
126 fprintf (stderr, " -x, --scale Scale from source to destination\n");
127 fprintf (stderr, " -b, --benchmark Enable benchmarking mode\n");
128 fprintf (stderr, " -R, --rerender Rerender before every blit (benchmark)\n");
129 fprintf (stderr, " -t, --tile Perform a tile blit\n");
130 fprintf (stderr, " -X, --matrix-translate Enable Matrix translation during blit\n");
131 fprintf (stderr, " -O, --matrix-rotate Enable Matrix rotation during blit\n");
132 fprintf (stderr, " -S, --matrix-shear Enable Matrix shear during blit\n");
133
134 return -1;
135 }
136
137 /**********************************************************************************************************************/
138
139 int
main(int argc,char * argv[])140 main( int argc, char *argv[] )
141 {
142 int i;
143 DFBResult ret;
144 DFBSurfaceDescription desc;
145 IDirectFB *dfb;
146 IDirectFBImageProvider *provider = NULL;
147 IDirectFBSurface *source = NULL;
148 IDirectFBSurface *dest = NULL;
149 const char *url = NULL;
150 DFBSurfacePixelFormat source_format = DSPF_UNKNOWN;
151 DFBSurfacePixelFormat dest_format = DSPF_UNKNOWN;
152 bool dest_resize = false;
153 bool benchmark = false;
154 bool rerender = false;
155 bool scale_enable = false;
156 bool tile = false;
157 bool matrix_translate = false;
158 bool matrix_rotate = false;
159 bool matrix_shear = false;
160
161 /* Initialize DirectFB. */
162 ret = DirectFBInit( &argc, &argv );
163 if (ret) {
164 D_DERROR( ret, "DFBTest/Blit: DirectFBInit() failed!\n" );
165 return ret;
166 }
167
168 /* Parse arguments. */
169 for (i=1; i<argc; i++) {
170 const char *arg = argv[i];
171
172 if (strcmp( arg, "-h" ) == 0 || strcmp (arg, "--help") == 0)
173 return print_usage( argv[0] );
174 else if (strcmp (arg, "-v") == 0 || strcmp (arg, "--version") == 0) {
175 fprintf (stderr, "dfbtest_blit version %s\n", DIRECTFB_VERSION);
176 return false;
177 }
178 else if (strcmp (arg, "-s") == 0 || strcmp (arg, "--source") == 0) {
179 if (++i == argc) {
180 print_usage (argv[0]);
181 return false;
182 }
183
184 if (!parse_format( argv[i], &source_format ))
185 return false;
186 }
187 else if (strcmp (arg, "-d") == 0 || strcmp (arg, "--dest") == 0) {
188 if (++i == argc) {
189 print_usage (argv[0]);
190 return false;
191 }
192
193 if (!parse_format( argv[i], &dest_format ))
194 return false;
195 }
196 else if (strcmp (arg, "-r") == 0 || strcmp (arg, "--resize") == 0)
197 dest_resize = true;
198 else if (strcmp (arg, "-b") == 0 || strcmp (arg, "--benchmark") == 0)
199 benchmark = true;
200 else if (strcmp (arg, "-R") == 0 || strcmp (arg, "--rerender") == 0)
201 rerender = true;
202 else if (strcmp (arg, "-x") == 0 || strcmp (arg, "--scale") == 0)
203 scale_enable = true;
204 else if (strcmp (arg, "-t") == 0 || strcmp (arg, "--tile") == 0)
205 tile = true;
206 else if (strcmp (arg, "-X") == 0 || strcmp (arg, "--matrix-translate") == 0)
207 matrix_translate = true;
208 else if (strcmp (arg, "-O") == 0 || strcmp (arg, "--matrix-rotate") == 0)
209 matrix_rotate = true;
210 else if (strcmp (arg, "-S") == 0 || strcmp (arg, "--matrix-shear") == 0)
211 matrix_shear = true;
212 else if (!url)
213 url = arg;
214 else
215 return print_usage( argv[0] );
216 }
217
218 /* Check if we got an URL. */
219 if (!url)
220 return print_usage( argv[0] );
221
222 /* Create super interface. */
223 ret = DirectFBCreate( &dfb );
224 if (ret) {
225 D_DERROR( ret, "DFBTest/Blit: DirectFBCreate() failed!\n" );
226 return ret;
227 }
228
229 /* Create an image provider for the image to be loaded. */
230 ret = dfb->CreateImageProvider( dfb, url, &provider );
231 if (ret) {
232 D_DERROR( ret, "DFBTest/Blit: IDirectFB::CreateImageProvider( '%s' ) failed!\n", url );
233 goto out;
234 }
235
236 /* Get the surface description. */
237 ret = provider->GetSurfaceDescription( provider, &desc );
238 if (ret) {
239 D_DERROR( ret, "DFBTest/Blit: IDirectFBImageProvider::GetSurfaceDescription() failed!\n" );
240 goto out;
241 }
242
243 if (source_format != DSPF_UNKNOWN)
244 desc.pixelformat = source_format;
245
246 D_INFO( "DFBTest/Blit: Source is %dx%d using %s\n",
247 desc.width, desc.height, dfb_pixelformat_name(desc.pixelformat) );
248
249 /* Create a surface for the image. */
250 ret = dfb->CreateSurface( dfb, &desc, &source );
251 if (ret) {
252 D_DERROR( ret, "DFBTest/Blit: IDirectFB::CreateSurface() failed!\n" );
253 goto out;
254 }
255
256 ret = provider->RenderTo( provider, source, NULL );
257 if (ret) {
258 D_DERROR( ret, "DFBTest/Blit: IDirectFBImageProvider::RenderTo() failed!\n" );
259 goto out;
260 }
261
262 /* Fill description for a primary surface. */
263 desc.flags = DSDESC_CAPS;
264 desc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;
265
266 if (dest_format != DSPF_UNKNOWN) {
267 desc.flags |= DSDESC_PIXELFORMAT;
268 desc.pixelformat = dest_format;
269 }
270
271 if (dest_resize)
272 desc.flags |= DSDESC_WIDTH | DSDESC_HEIGHT;
273
274 dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN );
275
276 /* Create a primary surface. */
277 ret = dfb->CreateSurface( dfb, &desc, &dest );
278 if (ret) {
279 D_DERROR( ret, "DFBTest/Blit: IDirectFB::CreateSurface() failed!\n" );
280 goto out;
281 }
282
283 dest->GetSize( dest, &desc.width, &desc.height );
284 dest->GetPixelFormat( dest, &desc.pixelformat );
285
286 D_INFO( "DFBTest/Blit: Destination is %dx%d using %s\n",
287 desc.width, desc.height, dfb_pixelformat_name(desc.pixelformat) );
288
289 dest->SetRenderOptions( dest, DSRO_MATRIX );
290
291 if (matrix_rotate) {
292 dest->SetMatrix( dest, rotate_matrix );
293 } else if (matrix_translate) {
294 dest->SetMatrix( dest, translate_matrix );
295 } else if (matrix_shear) {
296 dest->SetMatrix( dest, shear_matrix );
297 } else {
298 dest->SetMatrix( dest, identity_matrix );
299 }
300
301 if (tile)
302 dest->TileBlit( dest, source, NULL, 0, 0 );
303 else if (scale_enable)
304 dest->StretchBlit( dest, source, NULL, NULL );
305 else
306 dest->Blit( dest, source, NULL, 0, 0 );
307
308 dest->Flip( dest, NULL, DSFLIP_NONE );
309
310 if (benchmark) {
311 int num = 0;
312 long long start, diff = 0, speed;
313
314 sync();
315
316 sleep( 1 );
317
318 dest->StretchBlit( dest, source, NULL, NULL );
319
320 D_INFO( "DFBTest/Blit: Benchmarking...\n" );
321
322 dfb->WaitIdle( dfb );
323
324 start = direct_clock_get_millis();
325
326 do {
327 if (rerender) {
328 ret = provider->RenderTo( provider, source, NULL );
329 if (ret) {
330 D_DERROR( ret, "DFBTest/Blit: IDirectFBImageProvider::RenderTo() failed!\n" );
331 goto out;
332 }
333 }
334
335 dest->StretchBlit( dest, source, NULL, NULL );
336
337 if ((num & 7) == 7)
338 diff = direct_clock_get_millis() - start;
339
340 num++;
341 } while (diff < 2300);
342
343 dfb->WaitIdle( dfb );
344
345 diff = direct_clock_get_millis() - start;
346
347 speed = (long long) num * desc.width * desc.height / diff;
348
349 D_INFO( "DFBTest/Blit: Speed is %lld.%03lld MPixel/sec (%dx%d x %d in %lld.%03lld sec)\n",
350 speed / 1000LL, speed % 1000LL, desc.width, desc.height, num, diff / 1000LL, diff % 1000LL );
351 }
352 else
353 sleep( 2 );
354
355
356 sleep(10);
357
358 out:
359 if (dest)
360 dest->Release( dest );
361
362 if (source)
363 source->Release( source );
364
365 if (provider)
366 provider->Release( provider );
367
368 /* Shutdown DirectFB. */
369 dfb->Release( dfb );
370
371 return ret;
372 }
373
374