2 // Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
31 #include <boost/assign/list_of.hpp>
32 #include <boost/date_time/date.hpp>
33 #include <boost/date_time/posix_time/posix_time.hpp>
34 #include <sys/types.h>
40 #include "SWFMatrix.h"
42 #include "Transform.h"
43 #include "ShapeRecord.h"
44 #include "CachedBitmap.h"
45 #include "GnashVaapiImage.h"
46 #include "GnashVaapiImageProxy.h"
47 #include "boost/date_time/posix_time/posix_time.hpp"
50 #include "agg/Renderer_agg.h"
52 #ifdef RENDERER_OPENGL
53 #include "opengl/Renderer_ogl.h"
55 #ifdef RENDERER_OPENVG
56 #include "openvg/OpenVGRenderer.h"
58 #ifdef HAVE_VG_VGEXT_H
59 # include <VG/vgext.h>
65 #include "opengles1/Renderer_gles1.h"
68 #include "opengles2/Renderer_gles2.h"
71 #include "cairo/Renderer_cairo.h"
76 # error "This file needs EGL"
79 #ifdef BUILD_EGL_DEVICE
80 # include <egl/eglDevice.h>
82 #ifdef BUILD_DIRECTFB_DEVICE
83 # include <directfb/directfb.h>
85 #ifdef BUILD_X11_DEVICE
86 # include <x11/X11Device.h>
91 using namespace gnash
;
92 using namespace renderer
;
94 using namespace boost::posix_time
;
96 void test_device(Renderer
*renderer
, const std::string
&type
);
97 void test_renderer(Renderer
*renderer
, const std::string
&type
);
98 void test_geometry(Renderer
*renderer
, const std::string
&type
);
99 void test_iterators(Renderer
*renderer
, const std::string
&type
);
101 // The debug log used by all the gnash libraries.
102 static LogFile
& dbglogfile
= LogFile::getDefaultInstance();
104 //------------------------------------------------------------
106 // Simple class to do nanosecond based timing for performance analysis
109 Timer(const std::string
&name
, bool flag
)
115 Timer(const std::string
&name
) : _print(false) { _name
= name
; start(); }
116 Timer() : _print(false) { start(); }
121 cerr
<< "Total time for " << _name
<< " was: " << elapsed() << endl
;
126 _starttime
= boost::posix_time::microsec_clock::local_time();
130 _stoptime
= boost::posix_time::microsec_clock::local_time();
133 std::string
elapsed() {
135 time_duration td
= _stoptime
- _starttime
;
136 ss
<< td
.total_nanoseconds() << "ns elapsed";
139 void setName(const std::string
&name
) { _name
= name
; };
140 std::string
&getName() { return _name
; };
145 boost::posix_time::ptime _starttime
;
146 boost::posix_time::ptime _stoptime
;
150 main(int argc
, char *argv
[])
152 // FIXME: for now, always run verbose till this supports command line args
153 dbglogfile
.setVerbosity();
155 const char *pixelformat
= "RGB24";
158 #ifdef BUILD_RAWFB_DEVICE_XXX
159 rawfb::RawFBDevice
rawfb(argc
, argv
);
160 fd
= rawfb
.getHandle();
161 #endif // BUILD_RAWFB_DEVICE
163 #if defined(BUILD_EGL_DEVICE) && !defined(BUILD_X11_DEVICE)
164 // Setup EGL, OpenVG needs it
165 EGLDevice
egl(argc
, argv
);
166 egl
.bindClient(GnashDevice::OPENVG
);
167 fd
= open("/dev/fb0", O_RDWR
);
168 egl
.attachWindow(fd
);
169 #endif // BUILD_EGL_DEVICE
171 #ifdef BUILD_X11_DEVICE
172 // Setup EGL, OpenVG needs it
175 egl
.initDevice(argc
, argv
);
176 int vid
= egl
.getNativeVisual();
177 egl
.bindClient(GnashDevice::OPENVG
);
179 // Create an X11 device for the display. This is for libMesa
180 // where we can also run OpenVG on the desktop.
181 x11::X11Device
x11(vid
);
182 //x11.initDevice(argc, argv);
183 x11
.createWindow("TestR", 0, 0, 640, 480);
185 // This is the window that gets rendered in
186 Window win
= x11
.getHandle();
188 egl
.attachWindow(win
);
190 log_error(_("Couldn't get Drawable window from X11"));
193 // Set initial projection/viewing transformation.
194 // We can't be sure we'll get a ConfigureNotify event when the window
202 std::cerr
<< "Hello World!" << std::endl
;
208 Renderer
*renderer1
= create_Renderer_agg(pixelformat
);
209 // The methods were moved to the glue API
211 // test_device(renderer1, "EGL");
212 // test_device(renderer1, "DIRECTFB");
213 // test_device(renderer1, "X11");
216 test_renderer(renderer1
, "AGG");
217 test_geometry(renderer1
, "AGG");
218 test_iterators(renderer1
, "AGG");
221 cerr
<< "AGG tests took " << tagg
.elapsed() << endl
<< endl
;
224 #ifdef RENDERER_OPENVG
225 Timer
tovg("OpenVG");
226 Renderer
*renderer2
= renderer::openvg::create_handler(pixelformat
);
227 // EGLDevice *ovg = dynamic_cast<EGLDevice *>(renderer2);
229 // ovg->initDevice(0, 0);
230 // // ovg->attachWindow(*(reinterpret_cast<EGLNativeWindowType *>(canvas)));
231 // ovg->attachWindow(0);
233 test_renderer(renderer2
, "OpenVG");
234 test_geometry(renderer2
, "OpenVG");
235 test_iterators(renderer2
, "OpenVG");
237 cerr
<< "ERROR: No OpenVG renderer to test!" << endl
;
240 cerr
<< "OpenVG tests took " << tovg
.elapsed() << endl
;
244 #ifdef RENDERER_GLES1
245 Timer
tgles1("OpenGLES1");
246 Renderer
*renderer3
= renderer::gles1::create_handler(pixelformat
);
248 test_renderer(renderer3
, "OpenGLES1");
249 test_geometry(renderer3
, "OpenGLES1");
250 test_iterators(renderer3
, "OpenGLES1");
252 cerr
<< "ERROR: No OpenGLES1 renderer to test!" << endl
;
255 cerr
<< "OpenGLES1 tests took " << tgles1
.elapsed() << endl
;
258 #ifdef RENDERER_GLES2
259 Timer
tgles2("OpenGLES2");
260 Renderer
*renderer4
= renderer::gles2::create_handler(pixelformat
);
262 test_renderer(renderer4
, "OpenGLES2");
263 test_geometry(renderer4
, "OpenGLES2");
264 test_iterators(renderer4
, "OpenGLES2");
266 cerr
<< "ERROR: No OpenGLES2 renderer to test!" << endl
;
269 cerr
<< "OpenGLES2 tests took " << tgles2
.elapsed() << endl
;
272 #ifdef RENDERER_CAIRO
273 Timer
tcairo("Cairo");
274 Renderer
*renderer5
= renderer::cairo::create_handler();
276 test_renderer(renderer5
, "Cairo");
277 test_geometry(renderer5
, "Cairo");
278 test_iterators(renderer5
, "Cairo");
280 cerr
<< "ERROR: No Cairo renderer to test!" << endl
;
283 cerr
<< "Cairo tests took " << tcairo
.elapsed() << endl
;
286 #ifdef RENDERER_OPENGL
288 Renderer
*renderer6
= renderer::opengl::create_handler(true);
290 test_renderer(renderer6
, "OpenGL");
291 test_geometry(renderer6
, "OpenGL");
292 test_iterators(renderer6
, "OpenGL");
294 cerr
<< "ERROR: No OpenGL renderer to test!" << endl
;
297 cerr
<< "OpenGL tests took " << tgl
.elapsed() << endl
;
302 // Each Renderer has an associated display device, currently EGL
303 // for OpenVG, OpenGLES1, and OpenGLES2. The DirectFB device is
304 // also available for these three renderers. The EGL device can
305 // also be run under X11 using the Mesa libraries. Both EGL and
306 // DirectFB are primarily for framebuffers. While all of the methods
307 // of each device class are available to the Renderer, most aren't
308 // exposed with more accesors beyond these for manipulating the
309 // device setting itself.
311 test_device(Renderer
*renderer
, const std::string
&type
)
313 cout
<< endl
<< "Testing " << type
<< " Device" << endl
;
316 std::unique_ptr
<renderer::GnashDevice::dtype_t
[]> devs
= renderer
->probeDevices();
318 runtest
.pass("Renderer::probeDevices()");
320 runtest
.fail("Renderer::probeDevices()");
322 // Be default, there should be no device associated with this
324 if (renderer
->getDevice() == GnashDevice::GNASH_NODEV
) {
325 runtest
.pass("Renderer::getDevice()");
327 runtest
.fail("Renderer::getDevice()");
330 // Set to a device and see if it's axctually set
331 renderer
->setDevice(GnashDevice::X11
);
332 if (renderer
->getDevice() == GnashDevice::X11
) {
333 runtest
.pass("Renderer::setDevice()");
335 runtest
.fail("Renderer::setDevice()");
338 // reset to the original value so we don't screw up future tests
339 renderer
->resetDevice();
344 test_renderer(Renderer
*renderer
, const std::string
&type
)
346 cout
<< "Testing " << type
<< " Renderer" << endl
;
347 // Timer trend("Renderer Tests", true);
350 runtest
.unresolved("No renderer to test!");
355 runtest
.pass("Got Renderer");
357 runtest
.fail("Couldn't get Renderer");
360 if (!renderer
->description().empty()) {
361 if (renderer
->description() == type
) {
362 runtest
.pass("description is correct");
364 runtest
.fail("description is wrong");
367 runtest
.fail("Couldn't get description!");
371 if (renderer
->getBitsPerPixel()) {
372 runtest
.pass("getBitsPerPixel()");
374 runtest
.fail("getBitsPerPixel()");
378 image::GnashImage
*frame1
= new image::ImageRGBA(10, 12);
379 std::unique_ptr
<image::GnashImage
> im1(frame1
);
380 CachedBitmap
*cb
= renderer
->createCachedBitmap(im1
);
382 image::GnashImage
&gi
= cb
->image();
383 if ((gi
.width() == 10) && (gi
.height() == 12)) {
384 runtest
.pass("createCachedBitmap()");
386 runtest
.fail("createCachedBitmap()");
389 runtest
.unresolved("createCachedBitmap()");
393 // FIXME: initTestBuffer() is going away, replaced by the fake
395 // Initializes the renderer for off-screen rendering used by the testsuite.
396 if (renderer
->initTestBuffer(10, 10)) {
397 runtest
.pass("initTestBuffer()");
399 runtest
.fail("initTestBuffer()");
403 /// @coords an array of 16-bit signed integer coordinates. Even indices
404 /// (and 0) are x coordinates, while uneven ones are y coordinates.
405 /// @vertex_count the number of x-y coordinates (vertices).
406 /// @color the color to be used to draw the line strip.
407 /// @mat the SWFMatrix to be used to transform the vertices.
408 std::uint16_t x
= 10;
409 std::uint16_t y
= 10;
410 std::uint16_t h
= 10;
411 std::vector
<point
> box
= boost::assign::list_of
415 rgba
color(0, 0, 0, 255);
417 mat
.set_scale_rotation(1, 3, 0);
419 Timer
tdrawline("drawline");
420 renderer
->drawLine(box
, color
, mat
);
424 // runtest.pass("drawLine()");
426 // runtest.fail("drawLine()");
428 runtest
.unresolved(std::string("drawLine() ") + tdrawline
.elapsed());
430 //drawVideoFrame(image::GnashImage* frame, const Transform& xform, const SWFRect* bounds, bool smooth);
432 image::GnashImage
*frame
;
433 const Transform xform
;
434 const SWFRect bounds
;
436 Timer
tdrawvideo("drawVideoFrame");
437 renderer
->drawVideoFrame(frame
, xform
, bounds
, smooth
);
440 runtest
.untested("drawVideoFrame()");
443 size_t corner_count
= 0;
444 rgba
fill(0, 0, 0, 255);;
445 rgba
outline(0, 0, 0, 255);;
447 Timer
tdrawpoly("drawPoly");
448 renderer
->draw_poly(corners
, corner_count
, fill
, outline
, mat
, masked
);
450 runtest
.unresolved(std::string("drawPoly() ") + tdrawpoly
.elapsed());
452 // SWF::ShapeRecord shape;
453 SWFMatrix
mat2(0x10000, 0x0, 0x0, 0x10000, 0x0, 0x0);
455 //(0x100, 0x100, 0x100, 0x100, 0x0, 0x0, 0x0, 0x0);
456 Transform
xform(mat2
, cxform
);
457 SWF::ShapeRecord shape
;
458 // _bounds = {0x80000000, 0x7fffffff,
459 // 0x80000000, 0x80000000,
460 // 0x80000000, 0x80000000}}
461 Timer
drawshape("drawShape");
462 renderer
->drawShape(shape
, xform
);
463 runtest
.unresolved("drawShape()");
466 // SWF::ShapeRecord rec;
469 // Timer drawGlyph("drawGlyph");
470 // renderer->drawGlyph(rec, color, mat);
471 runtest
.untested("drawGlyph()");
475 std::unique_ptr
<IOChannel
> io
;
477 Timer
renderi("renderToImage");
478 renderer
->renderToImage(io
, ftype
);
481 runtest
.untested("renderToImage()");
483 CachedBitmap
*bitmap
= 0;
484 image::GnashImage
*frame2
= new image::ImageRGBA(10, 10);
485 std::unique_ptr
<image::GnashImage
> im(frame2
);
486 Timer
cbit("createCachedBitmap");
487 bitmap
= renderer
->createCachedBitmap(im
);
490 runtest
.pass(std::string("createCachedBitmap() ") + cbit
.elapsed());
492 runtest
.fail(std::string("createCachedBitmap() ") + cbit
.elapsed());
497 test_geometry(Renderer
*renderer
, const std::string
&type
)
499 cout
<< "\t" << type
<< " geometry tests" << endl
;
502 runtest
.unresolved("No renderer to test!");
508 geometry::Point2d
nz(200, 0);
509 geometry::Point2d
z(x
, y
);
510 geometry::Range2d
<int> pixelbounds
;
511 geometry::Range2d
<int> worldbounds
;
512 Timer
tpixtow("pixel_to_world(int, int)");
513 z
= renderer
->pixel_to_world(x
, y
);
516 if ((z
.x
>= 199) || (z
.y
>= 199)) {
517 runtest
.pass(std::string("pixel_to_world(int, int) ") + tpixtow
.elapsed());
519 runtest
.fail(std::string("pixel_to_world(int, int) ") + tpixtow
.elapsed());
523 Timer
tpixtow2("pixel_to_world(pixelbounds)");
524 worldbounds
= renderer
->pixel_to_world(pixelbounds
);
526 if (worldbounds
.isNull()) {
527 runtest
.pass(std::string("pixel_to_world(geometry::Range2d<int>) ") + tpixtow2
.elapsed());
529 runtest
.fail(std::string("pixel_to_world(geometry::Range2d<int>) ") + tpixtow2
.elapsed());
532 runtest
.untested("pixel_to_world(geometry::Range2d<int>)");
535 Timer
twtop("world_to_pixel(geometry::Range2d<int>)");
536 pixelbounds
= renderer
->world_to_pixel(worldbounds
);
538 if (pixelbounds
.isNull()) {
539 runtest
.pass(std::string("world_to_pixel(geometry::Range2d<int>) ") + twtop
.elapsed());
541 runtest
.fail(std::string("world_to_pixel(geometry::Range2d<int>) ") + twtop
.elapsed());
545 Timer
tbounds1("bounds_in_clipping_area(SWFRect)");
546 bool ret
= renderer
->bounds_in_clipping_area(bounds
);
549 runtest
.pass(std::string("bounds_in_clipping_area(SWFRect) ") + tbounds1
.elapsed());
551 runtest
.fail(std::string("bounds_in_clipping_area(SWFRect) ") + tbounds1
.elapsed());
554 InvalidatedRanges ranges
;
555 Timer
tbounds2("bounds_in_clipping_area(InvalidatedRanges)");
556 ret
= renderer
->bounds_in_clipping_area(ranges
);
559 runtest
.pass(std::string("bounds_in_clipping_area(InvalidatedRanges) ") + tbounds2
.elapsed());
561 runtest
.fail(std::string("bounds_in_clipping_area(InvalidatedRanges) ") + tbounds2
.elapsed());
564 Timer
tbounds3("bounds_in_clipping_area(geometry::Range2d<int>)");
565 ret
= renderer
->bounds_in_clipping_area(pixelbounds
);
568 runtest
.pass(std::string("bounds_in_clipping_area(geometry::Range2d<int>) ") + tbounds3
.elapsed());
570 runtest
.fail(std::string("bounds_in_clipping_area(geometry::Range2d<int>) ") + tbounds3
.elapsed());
575 // Machinery for delayed images rendering (e.g. Xv with YV12 or VAAPI)
578 test_iterators(Renderer
*renderer
, const std::string
&type
)
580 cout
<< "\t"<< type
<< " iterator tests" << endl
;
583 runtest
.unresolved("No renderer to test!");
587 Renderer::RenderImages::iterator fit
= renderer
->getFirstRenderImage();
588 Renderer::RenderImages::iterator lit
= renderer
->getLastRenderImage();
589 // When there are no images, the first and last are the same obviously
591 runtest
.pass("getFirstRenderImage()");
593 runtest
.fail("getFirstRenderImage()");
597 geometry::Point2d
a(1, 2);
598 geometry::Point2d
c(3, 4);
599 Renderer::RenderImage image
;
600 image::GnashImage
*frame
= new image::ImageRGBA(10, 10);
601 // gnash::GnashVaapiImage *foo = static_cast<gnash::GnashVaapiImage *>(frame);
602 // gnash::GnashVaapiImageProxy *bar = new gnash::GnashVaapiImageProxy(foo, a.x, a.y, c.x - a.x, c.y - a.y);
603 std::unique_ptr
<image::GnashImage
> rgba(frame
);
604 // image.reset(new gnash::GnashVaapiImageProxy(foo, a.x, a.y, c.x - a.x, c.y - a.y));
606 renderer
->addRenderImage(image
);
607 // image.reset(new gnash::GnashVaapiImageProxy(foo, a.x, a.y, c.x - a.x, c.y - a.y));
608 renderer
->addRenderImage(image
);
611 fit
= renderer
->getFirstRenderImage();
612 lit
= renderer
->getLastRenderImage();
613 // When there are no images, the first and last are the same obviously
615 runtest
.pass("addRenderImage()");
617 runtest
.fail("addRenderImage()");
621 typedef std::shared_ptr
<GnashVaapiImageProxy
> RenderImage
;
622 typedef std::vector
<RenderImage
> RenderImages
;
624 // Get first render image
625 virtual RenderImages::iterator
getFirstRenderImage()
626 { return _render_images
.begin(); }
627 virtual RenderImages::const_iterator
getFirstRenderImage() const
628 { return _render_images
.begin(); }
630 // Get last render image
631 virtual RenderImages::iterator
getLastRenderImage()
632 { return _render_images
.end(); }
633 virtual RenderImages::const_iterator
getLastRenderImage() const
634 { return _render_images
.end(); }
641 Renderer_ovg::createBitmapInfo(std::unique_ptr
<GnashImage
> im
)
646 // indent-tabs-mode: nil