OpenVG- baremetal VG

Anything and everything about programming graphics with Ultibo
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Tue Sep 26, 2017 1:08 pm

Getting the hang of this VG and object coding stuff.
Turned the clock into a unit and then had multiple clocks different sizes.
Made a typo and ended up with a giant clock :lol:
Interestingly the giant clock extended off screen and I got no errors :D

Flying clocks instead of toasters next?
Really need to sort out a RTC for Zero's, then I can have real time on the clocks.
Getting too used to using Zero's for development via USB booting ;)

I guess it could make a multi timezone clock display, London, Tokyo, LA, NY times etc.
Probably best to use a networked B/B+ to get accurate time.
More timezones by having wider framebuffer than the display screen and it scrolls?

Need RTC for time stamping jpgs etc for remote camera use too.

Wonder how many a Zero can handle? A glass cockpit for a Boeing NG uses 5 displays.
Many more on a A380. If i use a wide screen I could emulate two of the portrait main screens?

What car cluster could I emulate?
The kid's favorite Nismo R34 performance cluster only has 4 dials, easy, ho hum :D

This Ultibo stuff is much easier and faster than JavaFX :ugeek:

Need to check if background can be transparent?
https://www.raspberrypi.org/forums/view ... 9&t=190936

Code: Select all

program IndustrialClock;

{$mode objfpc}{$H+}

{ VideoCore IV example - OpenVG Shapes Demo                                           }

uses
  RaspberryPi, {Include RaspberryPi2 to make sure all standard functions are included}
  GlobalConst,
  GlobalTypes,
  Threads,
  Console,
  SysUtils,
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4,          {Include the VC4 unit to enable access to the GPU}
  iClock;

var
 Width:Integer;  {A few variables used by our shapes example}
 Height:Integer;

 posx:Integer;
 posy:Integer;
 dial:Integer;

 WindowHandle:TWindowHandle;
 

begin
 {Create a console window as usual}
 WindowHandle:=ConsoleWindowCreate(ConsoleDeviceGetDefault,CONSOLE_POSITION_FULL,True);

 ConsoleWindowWriteLn(WindowHandle,'Starting VGShapes Demo');

 {Initialize OpenVG and the VGShapes unit}
 VGShapesInit(Width,Height);

 
 {Start a picture the full width and height of the screen}
 VGShapesStart(Width,Height);

 {Make the background black}
 VGShapesBackground(153,204,255);


 for clkSeconds:= 0 to 60 do
     begin
       posx:=700;
       posy:=500;
       dial:=300;
       clock(posx,posy,dial);

       posx:=200;
       posy:=200;
       dial:=200;
       clock(posx,posy,dial);

       posx:=900;
       posy:=700;
       dial:=150;
       clock(posx,posy,dial);

       posx:=100;
       posy:=900;
       dial:=700;
       clock(posx,posy,dial);


     Sleep(1000);


   {End our picture and render it to the screen}
   VGShapesEnd;
   end;


 {Sleep for 10 seconds}
 Sleep(20000);
 
 {Clear our screen, cleanup OpenVG and deinitialize VGShapes}
 VGShapesFinish;
 
 {VGShapes calls BCMHostInit during initialization, we should also call BCMHostDeinit to cleanup}
 BCMHostDeinit;
 
 ConsoleWindowWriteLn(WindowHandle,'Completed VGShapes Demo');
 
 {Halt the main thread here}
 ThreadHalt(0);
end.



Code: Select all

unit iClock;

{$mode objfpc}{$H+}

interface

uses
  Threads,
  Console,
  Classes,
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4,
  SysUtils;

var
 CenterX:VGfloat;
 CenterY:VGfloat;
 Dialsize:VGfloat;

 dialrim:VGfloat;

 startickX:VGfloat;
 startickY:VGfloat;
 stoptickX:VGfloat;
 stoptickY:VGfloat;

 min5stroke:VGfloat;
 minstroke:VGfloat;

 handOffsetX:VGfloat;
 handOffsetY:VGfloat;
 secOffsetX:VGfloat;
 secOffsetY:VGfloat;

 secDotsize:VGfloat;
 minDotsize:VGfloat;

 sechandwidth:VGfloat;
 minhandwidth:VGfloat;
 hourhandwidth:VGfloat;

 Count:Integer;
 Countmin:Integer;

 clkHours:Integer;
 clkMinutes:Integer;
 clkSeconds:Integer;

 Fontsize:Integer;

const
 {The names of dial text}
 Dialnames:array[0..11] of String = (
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '10',
  '11',
  '12');

procedure clock(var CenterX, CenterY, Dialsize: Integer);


implementation


procedure clock(var CenterX, CenterY, Dialsize: Integer);
begin

 dialrim:= Trunc(Dialsize * 0.02);
 min5stroke:= Trunc(Dialsize * 0.02);
 minstroke:= Trunc(Dialsize * 0.01);

 secDotsize:=Trunc(Dialsize * 0.01);
 minDotsize:=Trunc(Dialsize * 0.07);

 sechandwidth:=Trunc(Dialsize * 0.01);
 minhandwidth:=Trunc(Dialsize * 0.03);
 hourhandwidth:=Trunc(Dialsize * 0.03);

 Fontsize:=Trunc(Dialsize * 0.02);


       {Circle}
       VGShapesStrokeWidth(dialrim);
       VGShapesStroke(0,0,0,1);
       VGShapesFill(255,255,255,1);
       VGShapesCircle(CenterX,CenterY,Dialsize);

       VGShapesFill(0,0,0,1);
       VGShapesStroke(0,0,0,1);
       VGShapesStrokeWidth(minstroke);

       for Countmin:= 0 to 60 do
        begin

         startickX:= Dialsize / 2.4 * sin((Countmin * 6) * pi / 180 + pi / 6);
         startickY:= Dialsize / 2.4 * cos((Countmin * 6) * pi / 180 + pi / 6 ) ;

         stoptickX:= Dialsize / 2.1 * sin((Countmin * 6) * pi / 180 + pi / 6);
         stoptickY:= Dialsize / 2.1 * cos((Countmin * 6) * pi / 180 + pi / 6 ) ;

         VGShapesLine(CenterX  + startickX, CenterY + startickY,CenterX + stoptickX, CenterY + stoptickY);

        end;


       for Count:= 0 to 11 do
        begin

         startickX:= Dialsize / 2.8 * sin((Count * 30) * pi / 180 + pi / 6);
         startickY:= Dialsize / 2.8 * cos((Count * 30) * pi / 180 + pi / 6 ) ;
         stoptickX:= Dialsize / 2.1 * sin((Count * 30) * pi / 180 + pi / 6);
         stoptickY:= Dialsize / 2.1 * cos((Count * 30) * pi / 180 + pi / 6 ) ;

         VGShapesStrokeWidth(min5stroke);
         VGShapesLine(CenterX  + startickX, CenterY + startickY,CenterX + stoptickX , CenterY + stoptickY);

        end;

       vgSeti(VG_STROKE_CAP_STYLE,VG_CAP_ROUND);
       VGShapesStroke(0,0,0,1);
       VGShapesFill(0,0,0,1);
       VGShapesCircle(CenterX,CenterY,minDotsize);

       //hours
       clkHours:= 1;
       VGShapesStrokeWidth(hourhandwidth);
       VGShapesStroke(0,0,0,1);
       handOffsetX:= Dialsize / 4 * sin((clkHours * 30) * pi / 180 );
       handOffsetY:= Dialsize / 4 * cos((clkHours * 30) * pi / 180 );
       VGShapesLine(CenterX , CenterY, CenterX + handOffsetX, CenterY + handOffsetY);

       //minutes
       clkMinutes:= 1;
       VGShapesStrokeWidth(minhandwidth);
       VGShapesStroke(0,0,0,1);
       handOffsetX:= Dialsize / 3 * sin((clkMinutes * 6) * pi / 180 );
       handOffsetY:= Dialsize / 3 * cos((clkMinutes * 6) * pi / 180 );
       VGShapesLine(CenterX , CenterY, CenterX + handOffsetX, CenterY + handOffsetY);

       //Seconds:= 0 ;

       VGShapesStroke(200,0,0,1);
       VGShapesFill(200,0,0,1);
       VGShapesCircle(CenterX,CenterY,secDotsize);

       VGShapesStrokeWidth(sechandwidth);

       secOffsetX:= Dialsize / 3 * sin((clkSeconds * 6) * pi / 180 );
       secOffsetY:= Dialsize / 3 * cos((clkSeconds * 6) * pi / 180 );
       handOffsetX:= Dialsize / 12 * sin((clkSeconds * 6) * pi / 180 );
       handOffsetY:= Dialsize / 12 * cos((clkSeconds * 6) * pi / 180 );

       VGShapesLine(CenterX , CenterY, CenterX + secOffsetX, CenterY + secOffsetY);
       VGShapesLine(CenterX, CenterY, CenterX - handOffsetX, CenterY - handOffsetY);



 end;

end.

pik33
Posts: 767
Joined: Fri Sep 30, 2016 6:30 pm
Location: Poland
Contact:

Re: OpenVG- baremetal VG

Postby pik33 » Tue Sep 26, 2017 3:04 pm

Need to check if background can be transparent?


You can make a transparent layer using DispmanX. The alpha can be set constant for all pixels in the object, or every pixel can have its own alpha value (ARGB8888).
I don't know if there is possible to combine OpenVG with DispmanX - to be researched. The OpenVG can help me to draw window decoration, for example :)

Edit:

I think I got it. OpenVG uses EGL and EGL uses DispmanX surface. The result is: OpenVG draws on DispmanX element and not on the framebuffer (which is also (another) DispmanX element)

All the egl init stuff lays in VGShapes unit and I think it can be hacked to not create a new DispmanX element, but give the EGL an existing one (=window)

In line 322 of VGShapes unit you have State.Alpha.flags:=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
Then you have State.Alpha.opacity:=255; in line 323.

This means not transparent layer.

To be researched :)

Edit 2: I found a book "Raspberry Pi GPU Audio Video Programming" - Jan Newmarch - I don't know how good it is but then there is 450 pages about GPU programming on RPi. In C. Two foreign languages at once - C and English...
User avatar
Ultibo
Site Admin
Posts: 2040
Joined: Sat Dec 19, 2015 3:49 am
Location: Australia

Re: OpenVG- baremetal VG

Postby Ultibo » Wed Sep 27, 2017 12:37 am

Gavinmc42 wrote:Need to check if background can be transparent?
https://www.raspberrypi.org/forums/view ... 9&t=190936

As per that post, you have 2 options.

You can use VGShapesWindowOpacity() to make the entire window opaque so that the background shows through.

Of course you can modify the VGShapes.pas unit, find the function eglInit() and change this line:

Code: Select all

 State.Alpha.flags:=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;

to this:

Code: Select all

 State.Alpha.flags:=DISPMANX_FLAGS_ALPHA_FROM_SOURCE;

then rebuild your RTL.

That will allow you to set a transparent background by using the VGShapesBackgroundRGB() and passing something less than 1.0 for the alpha parameter (0 being fully transparent).

We might include a small modification in VGShapes to allow that to be done on the fly without rebuilding.
Ultibo.org | Make something amazing
https://ultibo.org
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Wed Sep 27, 2017 1:05 am

Thanks guys, changing the RTL for transparency - opaque as default would be great Garry.

Making UI's with VG seems to be the way to go now that acceleration works.
Not sure how fast it can be pushed but UI's that autoscale for the display make sense to me.
Been spending years tweaking things by pixel counts for each display.
Added advantage I see is VG lists take up much less memory than bitmaps and images.
This is good for embedded aps.

Most single purpose gadgets that I do, don't need high speed UI's.
That might change when I make a 100MHz Digital CRO with a Zero :lol:

Transparent backgrounds could do some multilayer effects, scrolling game backgrounds etc

EGL does seem to buried underneath everything, time to learn that too?
pik33
Posts: 767
Joined: Fri Sep 30, 2016 6:30 pm
Location: Poland
Contact:

Re: OpenVG- baremetal VG

Postby pik33 » Wed Sep 27, 2017 4:34 am

The order is: OpenSomething->EGL->DispmanX->GPU
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Wed Sep 27, 2017 6:12 am

Dispmanx - interface to ThreadX on the VC4?
Another wonderfully documented thing :D
Looks like Andrew and Jan in Melbourne are the guys who know this thing a little ;)

Transparent background and layers
http://www.raspberry-projects.com/pi/pr ... mx-pngview

Looks like pngview with layers and x,y offsets could be used for simple scrolling games.

Max 3 layers?
https://www.raspberrypi.org/forums/view ... 5&t=113240

The HVS has a limit of being about to composite about three 1080p images that involve vertical resizing.
This is because images are fetched from sdram, format converted, resized and alpha blended in real time.
Any vertical resize requires a number of lines of context - too many and we exceed the LBM memory (48K).


More layers on lower res screens? More if no vertical sizing?
More stuff to learn but now we have pretty pictures to play with :D
pik33
Posts: 767
Joined: Fri Sep 30, 2016 6:30 pm
Location: Poland
Contact:

Re: OpenVG- baremetal VG

Postby pik33 » Wed Sep 27, 2017 8:00 am

The HVS uses its internal memory for vertical resizing. The memory amount is small (48k, some sources tells 96k). This limits the number of high resolution vertical layers. The full horizontal line of all these layers has to fit in this buffer and then it is also used for another tasks.

Don't do vertical resize and you will get much more layers.

The game elements like sprites and playfields can be resized once to the screen resolution while game starts. The sprites may need resizing while playing ( see Mario Bros ) but this can be achieved by defining these sprites in different sizes, and then these sprites are small so its resizing via hvs is cheap.

Then there is config.txt setting:

scaling_kernel=8

It causes scaling will use nearest neighbor instead of bicubic. May be good for 8-bit style sprites rescaling, they are not smeared, when enlarged. The scaling filter is system wide :( and I don't know how to temporary change it while in program. Linux users use vcgencmd for this task.
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Mon Oct 02, 2017 7:43 am

PFD- Primary Flight Display
I did attempt to do this in 3D, but i don't know enough OpenGS EL2 yet ;)
But even aircraft glass cockpit displays are going flat designs :D
This is about as basic as it gets and is just an experiment and starting point for me.
Starting to do enough little things like this I probably should github them, if i knew how :oops: .

Code: Select all

program PFD;

{$mode objfpc}{$H+}

{ VideoCore IV example - OpenVG Demo                                           }

uses
  RaspberryPi, {Include RaspberryPi2 to make sure all standard functions are included}
  GlobalConst,
  GlobalTypes,
  Threads,
  Console,
  SysUtils,
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4,
  artihorizon;          {Include the VC4 unit to enable access to the GPU}

var
 Width:Integer;  {A few variables used by our shapes example}
 Height:Integer;
 

 ArtiHoriX:Integer;
 ArtiHoriY:Integer;
 ArtiHorisize:Integer;

 yawangle:Integer;
 rollangle:Integer;
 pitchangle:Integer;

 WindowHandle:TWindowHandle;

 
begin
 {Create a console window as usual}
 WindowHandle:=ConsoleWindowCreate(ConsoleDeviceGetDefault,CONSOLE_POSITION_FULL,True);

 ConsoleWindowWriteLn(WindowHandle,'Starting PFD Demo');

 Width:=ConsoleWindowGetWidth(WindowHandle);
 Height:=ConsoleWindowGetHeight(WindowHandle);

 {Initialize OpenVG and the VGShapes unit}
 VGShapesInit(Width,Height);
 
 {set some values for testing}

 ArtiHoriX:=500;
 ArtiHoriY:=500;
 ArtiHorisize:=300;
 yawangle:=0;
 rollangle:=10;
 pitchangle:=10;
 
 {Start a picture the full width and height of the screen}
 VGShapesStart(Width,Height);
 
 {Make the background black}
 VGShapesBackground(0,0,0);

 {add PFD instruments}

 while true do
   begin

     horizon(ArtiHoriX, ArtiHoriY, ArtiHorisize, yawangle, rollangle, pitchangle);
     rollangle:= rollangle + 1;
     {End our picture and render it to the screen}
     VGShapesEnd;
     Sleep(100);

   end;

 {Clear our screen, cleanup OpenVG and deinitialize VGShapes}
 VGShapesFinish;
 
 {VGShapes calls BCMHostInit during initialization, we should also call BCMHostDeinit to cleanup}
 BCMHostDeinit;
 
 ConsoleWindowWriteLn(WindowHandle,'Completed VGShapes Demo');
 
 {Halt the main thread here}
 ThreadHalt(0);
end.


The Artificial Horizon unit code

Code: Select all

unit artihorizon;

{$mode objfpc}{$H+}

interface

uses
  Threads,
  Console,
  SysUtils,
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4;          {Include the VC4 unit to enable access to the GPU}

var
 
 HoriX:VGfloat;
 HoriY:VGfloat;
 Horisize:VGfloat;

 HleftX:VGfloat;
 HrightX:VGfloat;

 HbottomY:VGfloat;
 HtopY:VGfloat;

 HoriLL:VGfloat;
 HoriLR:VGfloat;

 PolyX:array[0..3] of VGfloat;
 PolyY:array[0..3] of VGfloat;

procedure horizon(var HoriX, HoriY, Horisize, yaw, roll, pitch: Integer);

implementation

procedure horizon(var HoriX, HoriY, Horisize, yaw, roll, pitch: Integer);

   var rolloffset:VGfloat;
   var pitchoffset:VGfloat;
begin

   HleftX:= HoriX - Horisize /2;
   HrightX:= HoriX + Horisize /2;
   HtopY:= HoriY + Horisize /2;
   HbottomY:= HoriY - Horisize /2;

   rolloffset:= Horisize / 2 * sin(roll * pi / 180);
   pitchoffset:= Horisize / 2 * sin(pitch * pi / 180);

   HoriLR:=Horisize / 2 + rolloffset - pitchoffset;
   HoriLL:=Horisize / 2 - rolloffset - pitchoffset;

   {bluw sky}
   VGShapesFill(80,80,255,1.0);

   PolyX[0]:=HleftX;
   PolyX[1]:=HrightX;
   PolyX[2]:=HrightX;
   PolyX[3]:=HleftX;

   PolyY[0]:=HtopY;
   PolyY[1]:=HtopY;
   PolyY[2]:=HbottomY + HoriLR;
   PolyY[3]:=HbottomY + HoriLL;

   VGShapesPolygon(@PolyX,@PolyY,4);

   {brown ground   }
   VGShapesFill(128,80,20,1.0);

   PolyX[0]:=HleftX;
   PolyX[1]:=HrightX;
   PolyX[2]:=HrightX;
   PolyX[3]:=HleftX;

   PolyY[0]:=HbottomY;
   PolyY[1]:=HbottomY;
   PolyY[2]:=HbottomY + HoriLR;
   PolyY[3]:=HbottomY + HoriLL;

   VGShapesPolygon(@PolyX,@PolyY,4);

   {white markings}

   VGShapesStroke(255,255,255,1);
   VGShapesFill(255,255,255,1);
   VGShapesStrokeWidth(Horisize / 60);

   {left wing}
   VGShapesLine(HleftX + Horisize / 6 , HbottomY + Horisize / 2, HleftX + Horisize / 2.5 , HbottomY + Horisize / 2);
   VGShapesLine(HleftX + Horisize / 2.5 , HbottomY + Horisize / 2, HleftX + Horisize / 2.5 , HbottomY + Horisize / 2 - Horisize / 20);

   {right wing}
   VGShapesLine(HrightX - Horisize / 2.5 , HbottomY + Horisize / 2, HrightX - Horisize / 6 , HbottomY + Horisize / 2);
   VGShapesLine(HrightX - Horisize / 2.5 , HbottomY + Horisize / 2, HrightX - Horisize / 2.5 , HbottomY + Horisize / 2 - Horisize / 20);

   {Bezel, hides bad code output }
   VGShapesStrokeWidth(Horisize / 6);
   VGShapesStroke(60,60,60,1);
   VGShapesFill(0,0,0,0);
   VGShapesRoundrect(HoriX - (Horisize / 2 + Horisize / 12) , HoriY - (Horisize / 2 + Horisize / 12) , Horisize + Horisize / 6,  Horisize + Horisize / 6, Horisize / 4 , Horisize / 4 );

 end;
end.
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Mon Oct 02, 2017 7:58 am

Updated the Industrial clock code to get Internet time, so it is sort of accurate now.
None of this is optimised, if it works that's good enough for me.
It's not as if I don't have enough ram on the Pi.

If you are a clock watcher change Sleep(100); to a higher value like 1000, it will make you twitch :lol:
Drawing the OpenVG takes time and this sleep time causes jitter on the secondhand movement, watch for missing seconds.

Code: Select all

program IndustrialClock;

{$mode objfpc}{$H+}

{ VideoCore IV example - OpenVG Shapes Demo                                           }

uses
  RaspberryPi2, {Include RaspberryPi2 to make sure all standard functions are included}
  BCM2836,
  BCM2709,
  GlobalConst,
  GlobalTypes,
  Threads,
  Console,
  SysUtils,
  Timezone,
  FileSystem,
  HTTP,            {Include the HTTP unit for the server classes}
  Winsock2,        {Include the Winsock2 unit so we can get the IP address}
  Devices,
  Dos,
  DateUtils,
  DWCOTG,   {We need to include the USB host driver for the Raspberry Pi}
  SMSC95XX, {We also need to include the driver for the Raspberry Pi network adapter}
  Services, {The services unit includes the NTP client and will automatically include the network}
  UltiboUtils,  {Include Ultibo utils for some command line manipulation}
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4,          {Include the VC4 unit to enable access to the GPU}
  Ultibo,
  iClock;

var

 timehour:Integer;
 timemin:Integer;
 timesecs:Integer;

 Counter:LongWord;
 Width:Integer;  {A few variables used by our shapes example}
 Height:Integer;

 posx:Integer;
 posy:Integer;
 dial:Integer;

 WindowHandle:TWindowHandle;
 IPAddress:String;
 Winsock2TCPClient:TWinsock2TCPClient;

begin
 {Create a console window as usual}
 WindowHandle:=ConsoleWindowCreate(ConsoleDeviceGetDefault,CONSOLE_POSITION_FULL,True);

 {Print out the current time and date}
 {This will probably show 30-12-99 which is midnight on 30 December 1899, this is the default value of Free Pascal time}
 ConsoleWindowWriteLn(WindowHandle,'The current date and time is ' + DateTimeToStr(Now));

 {Initialize a variable so we can count how long we've been waiting}
 Counter:=0;

 {Create a Winsock2TCPClient so that we can get some local information}
 Winsock2TCPClient:=TWinsock2TCPClient.Create;

 {Print our host name on the screen}
 ConsoleWindowWriteLn(WindowHandle,'Host name is ' + Winsock2TCPClient.LocalHost);

 {Get our local IP address which may be invalid at this point}
 IPAddress:=Winsock2TCPClient.LocalAddress;

 {Check the local IP address}
 if (IPAddress = '') or (IPAddress = '0.0.0.0') or (IPAddress = '255.255.255.255') then
  begin
   ConsoleWindowWriteLn(WindowHandle,'IP address is ' + IPAddress);
   ConsoleWindowWriteLn(WindowHandle,'Waiting for a valid IP address, make sure the network is connected');

   {Wait until we have an IP address}
   while (IPAddress = '') or (IPAddress = '0.0.0.0') or (IPAddress = '255.255.255.255') do
     begin
      {Sleep a bit}
      Sleep(1000);
      {Get the address again}
      IPAddress:=Winsock2TCPClient.LocalAddress;
    end;
   end;

 {Print our IP address on the screen}
 ConsoleWindowWriteLn(WindowHandle,'IP address is ' + IPAddress);
 ConsoleWindowWriteLn(WindowHandle,'');

 {Initialize a variable so we can count how long we've been waiting}
 Counter:=0;

 {Let's wait for a while for the time to be updated}
 while YearOf(Now) < 2000 do
  begin
   {Sleep for a second}
   Sleep(1000);

   {Update our counter}
   Inc(Counter);

   {Check how long we have waited}
   if Counter > 90 then
    begin
     {Print a failure message on the console}
     ConsoleWindowWriteLn(WindowHandle,'Sorry, failed to get the time after 90 seconds. Is the network connected?');

     {Break out of the loop and continue}
     Break;
    end;
  end;

 {Check out counter to see if we got here by success of failure}
 if Counter <= 90 then
  begin
   {We must have been successful so let's print the date and time again}
   ConsoleWindowWriteLn(WindowHandle,'Success, time has been updated from the internet');
   ConsoleWindowWriteLn(WindowHandle,'The date and time is now ' + DateTimeToStr(Now));
  end;

 ConsoleWindowWriteLn(WindowHandle,'The current date and time is ' + DateTimeToStr(Now));

 {Now we can set the timezone to another place and see what the time is there}
   {Australia}
   ConsoleWindowWriteLn(WindowHandle,'Setting Timezone to "E. Australia Standard Time"');
   SetCurrentTimezone('E. Australia Standard Time');
   ConsoleWindowWriteLn(WindowHandle,'The date and time is now ' + FormatDateTime(DefaultFormatSettings.LongDateFormat + ' ' +       DefaultFormatSettings.LongTimeFormat,Now));
   ConsoleWindowWriteLn(WindowHandle,'');

 Sleep(5000);

 ConsoleWindowWriteLn(WindowHandle,'Starting VGShapes Demo');

 Width:=ConsoleWindowGetWidth(WindowHandle);
 Height:=ConsoleWindowGetHeight(WindowHandle);

 {Initialize OpenVG and the VGShapes unit}
 VGShapesInit(Width,Height);
 
 {Start a picture the full width and height of the screen}
 VGShapesStart(Width,Height);

 {Make the background black}
 VGShapesBackground(153,204,255);

 While true  do
     begin
       timehour:= HourOf(now);
       timemin:= MinuteOf(now);
       timesecs:= SecondOf(now);

       posx:=Width div 2;
       posy:=Height div 2;
       dial:=5 * Height div 6 ;
       clock(posx,posy,dial,timehour, timemin, timesecs);

     Sleep(100);

   {End our picture and render it to the screen}
   VGShapesEnd;
   end;

 {Sleep for 10 seconds}
 Sleep(20000);
 
 {Clear our screen, cleanup OpenVG and deinitialize VGShapes}
 VGShapesFinish;
 
 {VGShapes calls BCMHostInit during initialization, we should also call BCMHostDeinit to cleanup}
 BCMHostDeinit;
 
 ConsoleWindowWriteLn(WindowHandle,'Completed VGShapes Demo');
 
 {Halt the main thread here}
 ThreadHalt(0);
end.


The clock unit

Code: Select all

unit iClock;

{$mode objfpc}{$H+}

interface

uses
  Threads,
  Console,
  Classes,
  OpenVG,       {Include the OpenVG unit so we can use the various types and structures}
  VGShapes,     {Include the VGShapes unit to give us access to all the functions}
  VC4,
  SysUtils;

var
 CenterX:VGfloat;
 CenterY:VGfloat;
 Dialsize:VGfloat;

 dialrim:VGfloat;

 startickX:VGfloat;
 startickY:VGfloat;
 stoptickX:VGfloat;
 stoptickY:VGfloat;

 min5stroke:VGfloat;
 minstroke:VGfloat;

 handOffsetX:VGfloat;
 handOffsetY:VGfloat;
 secOffsetX:VGfloat;
 secOffsetY:VGfloat;

 secDotsize:VGfloat;
 minDotsize:VGfloat;

 sechandwidth:VGfloat;
 minhandwidth:VGfloat;
 hourhandwidth:VGfloat;

 Count:Integer;
 Countmin:Integer;

 clkHours:Integer;
 clkMinutes:Integer;
 clkSeconds:Integer;

 Fontsize:Integer;

const
 {The names of dial text}
 Dialnames:array[0..11] of String = (
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '10',
  '11',
  '12');

procedure clock(var CenterX, CenterY, Dialsize, clkHours,clkMinutes,clkSeconds: Integer);

implementation

procedure clock(var CenterX, CenterY, Dialsize, clkHours,clkMinutes,clkSeconds: Integer);
begin

 dialrim:= Trunc(Dialsize * 0.02);
 min5stroke:= Trunc(Dialsize * 0.02);
 minstroke:= Trunc(Dialsize * 0.01);

 secDotsize:=Trunc(Dialsize * 0.01);
 minDotsize:=Trunc(Dialsize * 0.07);

 sechandwidth:=Trunc(Dialsize * 0.01);
 minhandwidth:=Trunc(Dialsize * 0.022);
 hourhandwidth:=Trunc(Dialsize * 0.03);

 Fontsize:=Trunc(Dialsize * 0.02);

       {Circle}
       VGShapesStrokeWidth(dialrim);
       VGShapesStroke(0,0,0,1);
       VGShapesFill(255,255,255,1);
       VGShapesCircle(CenterX,CenterY,Dialsize);

       VGShapesFill(0,0,0,1);
       VGShapesStroke(0,0,0,1);
       VGShapesStrokeWidth(minstroke);

       for Countmin:= 0 to 59 do
        begin

         startickX:= Dialsize / 2.4 * sin((Countmin * 6) * pi / 180 + pi / 6);
         startickY:= Dialsize / 2.4 * cos((Countmin * 6) * pi / 180 + pi / 6 ) ;

         stoptickX:= Dialsize / 2.1 * sin((Countmin * 6) * pi / 180 + pi / 6);
         stoptickY:= Dialsize / 2.1 * cos((Countmin * 6) * pi / 180 + pi / 6 ) ;

         VGShapesLine(CenterX  + startickX, CenterY + startickY,CenterX + stoptickX, CenterY + stoptickY);

        end;

       for Count:= 0 to 11 do
        begin

         startickX:= Dialsize / 2.8 * sin((Count * 30) * pi / 180 + pi / 6);
         startickY:= Dialsize / 2.8 * cos((Count * 30) * pi / 180 + pi / 6 ) ;
         stoptickX:= Dialsize / 2.1 * sin((Count * 30) * pi / 180 + pi / 6);
         stoptickY:= Dialsize / 2.1 * cos((Count * 30) * pi / 180 + pi / 6 ) ;

         VGShapesStrokeWidth(min5stroke);
         VGShapesLine(CenterX  + startickX, CenterY + startickY,CenterX + stoptickX , CenterY + stoptickY);

        end;

       vgSeti(VG_STROKE_CAP_STYLE,VG_CAP_ROUND);
       VGShapesStroke(0,0,0,1);
       VGShapesFill(0,0,0,1);
       VGShapesCircle(CenterX,CenterY,minDotsize);

       //hours

       VGShapesStrokeWidth(hourhandwidth);
       VGShapesStroke(0,0,0,1);
       handOffsetX:= Dialsize / 4 * sin((clkHours * 30 + (clkMinutes / 2)) * pi / 180 );
       handOffsetY:= Dialsize / 4 * cos((clkHours * 30 + (clkMinutes / 2)) * pi / 180 );
       VGShapesLine(CenterX , CenterY, CenterX + handOffsetX, CenterY + handOffsetY);

       //minutes

       VGShapesStrokeWidth(minhandwidth);
       VGShapesStroke(0,0,0,1);
       handOffsetX:= Dialsize / 3 * sin((clkMinutes * 6) * pi / 180 );
       handOffsetY:= Dialsize / 3 * cos((clkMinutes * 6) * pi / 180 );
       VGShapesLine(CenterX , CenterY, CenterX + handOffsetX, CenterY + handOffsetY);

       //Seconds:= 0 ;

       VGShapesStroke(200,0,0,1);
       VGShapesFill(200,0,0,1);
       VGShapesCircle(CenterX,CenterY,secDotsize);

       VGShapesStrokeWidth(sechandwidth);

       secOffsetX:= Dialsize / 2.5 * sin((clkSeconds * 6) * pi / 180 );
       secOffsetY:= Dialsize / 2.5 * cos((clkSeconds * 6) * pi / 180 );
       handOffsetX:= Dialsize / 10 * sin((clkSeconds * 6) * pi / 180 );
       handOffsetY:= Dialsize / 10 * cos((clkSeconds * 6) * pi / 180 );

       VGShapesLine(CenterX , CenterY, CenterX + secOffsetX, CenterY + secOffsetY);
       VGShapesLine(CenterX, CenterY, CenterX - handOffsetX, CenterY - handOffsetY);

 end;

end.
Gavinmc42
Posts: 1399
Joined: Sun Jun 05, 2016 12:38 pm
Location: Brisbane, Australia

Re: OpenVG- baremetal VG

Postby Gavinmc42 » Mon Oct 02, 2017 10:17 am

Been learning github, if these two work then I have learned enough.
Otherwise more to learn :oops:
https://github.com/Gavinmc42

Return to “Graphics”

Who is online

Users browsing this forum: No registered users and 1 guest