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