June 09, 2013
On Saturday, 8 June 2013 at 22:45:36 UTC, maarten wrote:
> Very good news that I can now compile it on my 64 bit machine,
> because dmd not only refused to in the past but I couldn't even
> get -m32 working. (Probably installed something somewhere
> incorrectly?)

It should pretty much just work if you just grab simpledisplay.d and color.d and add both files to your dmd command to compile all at once.

If not though let me know and I can look into it.
June 09, 2013
On Sunday, 9 June 2013 at 05:53:40 UTC, Marco Leise wrote:
> Does that mirror XCB (independent of XCB, implements RPC) or
> add a wrapper layer around the C bindings? Because it would be
> kinda cool to have a real X sever binding in D and not just
> D bindings to the C bindings to the X server. :p

It is just bindings right not but it is built from the xml file so if I spent some time tweaking it and writing the 10 or so base functions it needs from the C library it should be good to go.

Though tweaking it is harder for me than it should be because I don't know xslt at all. I might just do my own thing anyway, I'm reading up on the x protocol myself so I know all the needed details.
June 09, 2013
Adam D. Ruppe:

> https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/simpledisplay.d

Time ago I tried simpledisplay (on 32 bit Windows) and I remember I had to make the class Image final to have some performance. I used it on Rosettacode too:

http://rosettacode.org/wiki/Forest_fire#Graphical_Version


I have tried that Forest fire code with your new version and it gives me a:
simpledisplay.d(676): Error: undefined identifier i, did you mean variable s?

The line is here:

void drawPixmap(Sprite s, int x, int y) {
    BITMAP bm;

    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hbmOld = SelectObject(hdcMem, s.handle);

    GetObject(i.handle, bm.sizeof, &bm); <<


Bye,
bearophile
June 09, 2013
On Sunday, 9 June 2013 at 12:09:03 UTC, bearophile wrote:
> Time ago I tried simpledisplay (on 32 bit Windows) and I remember I had to make the class Image final to have some performance. I used it on Rosettacode too:

Hmm probably putPixel and impl.putPixel is too slow, it is called a lot. I made the class final now and got a about 8% improvement, using linux right now.

Eliminating those calls entirely, writing straight to the private rawData pointer, gives about 12% improvement, since this would get rid of calculating pixel offsets too (we can just do ptr++). Maybe I'll expose that and try to make it somehow cross platform.

I got as high as 45 fps using that trick plus the dmd -inline -release -O -noboundscheck flags. (The original code without flags and without final gave me only 30 fps).

I compiled and ran on wine too and it seems to have worked. Here's the nextState function using a pointer:


void nextState(ref World world, ref World nextWorld,
               ref Xorshift rnd, Image img) {
  auto pixelPointer = img.getDataPointer();
  auto linePadding = img.bytesPerLine() - img.bytesPerPixel * img.width;
  auto pixelPadding = img.bytesPerPixel() - 3;
  enum double div = cast(double)typeof(rnd.front()).max;
  immutable nr = world.length;
  immutable nc = world[0].length;
  foreach (r, row; world) {
    foreach (c, elem; row) {
      final switch (elem) {
        case Cell.empty:
		*pixelPointer++ = 255;
		*pixelPointer++ = 255;
		*pixelPointer++ = 255;
          //img.putPixel(c, r, white);
          nextWorld[r][c] = (rnd.front()/div)<P_PROB ? Cell.tree : Cell.empty;
          rnd.popFront();
          break;

        case Cell.tree:
          //img.putPixel(c, r, green);
	  	*pixelPointer++ = 0;
	  	*pixelPointer++ = 255;
	  	*pixelPointer++ = 0;

          foreach (rowShift; sp)
            foreach (colShift; sp)
              if ((r + rowShift) >= 0 && (r + rowShift) < nr &&
                  (c + colShift) >= 0 && (c + colShift) < nc &&
                  world[r + rowShift][c + colShift] == Cell.burning) {
                nextWorld[r][c] = Cell.burning;
                goto END;
              }

          nextWorld[r][c]=(rnd.front()/div)<F_PROB ? Cell.burning : Cell.tree;
          rnd.popFront();
          END: break;

        case Cell.burning:
          //img.putPixel(c, r, red);
	  	*pixelPointer++ = 0;
	  	*pixelPointer++ = 0;
	  	*pixelPointer++ = 255;
          nextWorld[r][c] = Cell.empty;
          break;
      }

      pixelPointer += pixelPadding;
    }

    pixelPointer += linePadding;
  }

  swap(world, nextWorld);
}


> I have tried that Forest fire code with your new version and it gives me a:
> simpledisplay.d(676): Error: undefined identifier i, did you mean variable s?

oops fixed. I added a new function but didn't even compile the Windows version of this change (only tried linux) and made a typo there.
June 09, 2013
Adam D. Ruppe:

> I got as high as 45 fps using that trick plus the dmd -inline -release -O -noboundscheck flags. (The original code without flags and without final gave me only 30 fps).

Some people keep saying how much nice the F# language is, and indeed I like it and it's nice. But on that page the F# entry seems to be more than 10 times slower than D entry (the image says 2.9 FPS, but maybe it's in debug mode):
http://rosettacode.org/wiki/Forest_fire#F.23


> I compiled and ran on wine too and it seems to have worked.

thank you for your quick fixes and improvements :-)


> oops fixed.

After this you will probably be more careful in future, to avoid similar bugs :-)

Bye and thank you,
bearophile
June 09, 2013
Adam D. Ruppe:

> I got as high as 45 fps using that trick plus the dmd -inline -release -O -noboundscheck flags. (The original code without flags and without final gave me only 30 fps).

Compiled with dmd, on my slower PC I see about 37 fps on the original code. Using ldc2 on the same code I see 53 fps. Using the pointers with ldc2 I see 68 fps.

And with a bit more cache-friendly data structure:
alias World = Cell[worldSide][];
I see 74 fps with ldc2 with pointers.

On Windows Vista the the window close X button on the top right doesn't work, and I have to use the close from the window menu on the top left.

Bye,
bearophile
June 09, 2013
On Sunday, 9 June 2013 at 14:00:20 UTC, bearophile wrote:
> But on that page the F# entry seems to be more than 10 times slower than D entry (the image says 2.9 FPS, but maybe it's in debug mode):

They could have ran it on a slow computer too, only way to be fair with these kind of comparisons is to it yourself.

> After this you will probably be more careful in future, to avoid similar bugs :-)

Yeah, I just made a new script on my linux computer called dmdw that calls the Windows version of dmd (through wine) for easy testing. Now I don't have to get out my laptop just to make sure changes still compile.
June 09, 2013
On Sunday, 9 June 2013 at 20:22:24 UTC, bearophile wrote:
> Using the pointers with ldc2 I see 68 fps.

Good speed there. Another problem I just realized though: on Windows, bitmaps are stored upside down so you'd have to draw y-inverted too. Didn't make a difference here because the image doesn't care about orientation but it would be visible with a lot of other programs.

Maybe simple functions or mixins (if inlining isn't reliable) could be used to hide this detail. Though for max performance you might have to know some platform specific details anyway. (and this library isn't really made for max performance, instead preferring simplicity of use and implementation. but still no need to be pointlessly slow)

> On Windows Vista the the window close X button on the top right doesn't work, and I have to use the close from the window menu on the top left.

OK I'll check that from my laptop tomorrow.
June 09, 2013
Adam D. Ruppe:

> Another problem I just realized though: on Windows, bitmaps are stored upside down so you'd have to draw y-inverted too. Didn't make a difference here because the image doesn't care about orientation but it would be visible with a lot of other programs.
>
> Maybe simple functions or mixins (if inlining isn't reliable) could be used to hide this detail.

This high level library should generate the same image output on all systems it compiles on.


> (and this library isn't really made for max performance, instead preferring simplicity of use and implementation.

A small, basic and simple to use graphics library has its usages. For small single-module (or few modules) programs like the one I have linked in Rosettacode you don't want to import a large GUI library.

Eventually I think such simple simpledisplay.d and color.d modules should go in Phobos, after some cleaning, ddoc string, a heavy cycle of review and improvements, API design, etc. It's a battery worth putting in the standard library. So people can write portable and very easy to use little graphical programs in D.

Delphi has a large and efficient GUI toolkit in the standard library, but I think it's not a good idea to put a GUI toolkit in Phobos. But a little library as simpledisplay is OK.

Maybe for Phobos simpledisplay.d could be renamed just graphicdisplay.d or something like that.

Regarding color, I think it will enjoy few more color-related functions, like a function to generate a rainbow given the temperature of a black body, few more greying functions, a bit more colorimetry, etc.

A color.d module for Phobos should not import simpledisplay.d. And it should be a top-level module (unlike now, that's inside a package).

Even the Python standard library has a very minimal color module:
http://docs.python.org/2/library/colorsys.html

A third small module (less than 15-30 KB of code) worth adding to Phobos, that builds on graphicdisplay.d and color.d, could generate basic data plots (scatter plots and line plots). It's not meant to replace a complete library for graphing. It's meant for a quick and very simple display of all kind of data during development or for quick D script-like programs.

When I program in Python I often use the good http://matplotlib.org/ . It's a large plotting library that allows me to plot data with few lines of code. This allows me to visualize intermediate data during debugging, like arrays, so it improves my understanding of data and such data.

Bye,
bearophile
June 09, 2013
W dniu 10.06.2013 00:09, bearophile pisze:
> Delphi has a large and efficient GUI toolkit in the standard library,
> but I think it's not a good idea to put a GUI toolkit in Phobos. But a
> little library as simpledisplay is OK.

Hmm... What if Lazarus GUI code and/or LCL could be ported to D? I've seen full featured Object Pascal parser in their repository. Maybe it's possible to transcode the source to D ;) Just thinking loud.