April 06, 2011
On 2011-04-06 10:25:42 -0400, Matthias Pleh <jens@konrad.net> said:

> Am 06.04.2011 14:49, schrieb Michel Fortin:
>>      final class Bitmap(Color) : Image {
>>          void opIndexAssign(int x, int y, Color color) {
>>              pixels[y * width + x] = Color(color);
>>          }
>> 
>>          size_t width, height;
>>          Color[] pixels;
>>      }
> 
> Yep, exactly. I would implement it as template.
> 
> About the render backend, Nick mentioned.
> In the first step, I would just draw all objects (lines, boxes, circles) to the buffer and then render it as image per gdi/xlib.
> 
> this render should ideally be in a single file, so other backends can be implemented (gdi/direct2d/cairo/xcb/cocoa/..)

Since you're at it, have you considered making the API flexible enough so it could support vector images too?

	// return an object derived from image depending on the actual file type
	Image im = loadImage("filename");

	// creating a bitmap for on-screen rendering
	auto bitmap = new Bitmap!RGBColor(im.width, im.height);

	// base image class has a virtual function to draw itself on a bitmap at
	// a given location, so it's easy to draw it on screen
	im.draw(10, 10, bitmap);

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

April 06, 2011
Nick Sabalausky wrote:
> Of course, if you see any fundamental
> problems with this, feel free to let me know :)

I'm pretty sure your plan would work and would provide a boost, but I'm not sure if it's worth the extra time.

I think the best thing to do will be to partially implement it, write a little program with both methods and run some speed tests. See if it's still easy to use and how big the difference really is.

I'm actually already almost to the point where the simple event loop / gdi implementation works, so won't take long to finish that off. Then we'll go back and see what to do with speed with the simple base to compare against.

> It's good enough for desktop applications, and it's fine if you're just going to draw something once and display it.

Heh, that /was/ my original intention! But now, I think we can go so much further.

> And even then, things like line drawing, fills and image blitting are still better off skipping the individual-pixel-access routines

Aye, even my homegrown DOS would always write them separately. Horrible waste of instructions doing another y << 8 + y << 6 when a simple "inc ax" would suffice!

> But anyway, I don't know exactly how you were going about it, but the way to do this in OpenGL or DirectX would be to do all your drawing to a texture buffer

I at first just used a SetPixel function in opengl, but when it
was unacceptable, I simply abandoned the idea of drawing pixels
to the screen. Instead, I started focusing on polygons and textures -
a rectangle with a bitmap attached as a texture makes an excellent
sprite that draws very very quickly, even if rotated or misshapen.

Once I realized that works so well, pixels weren't important anymore so I just stopped using the old functions entirely. They're still in the code, still godawfully slow, but I don't care enough to change it.

> I'd love to do some of this.

Excellent!

> You were using getch() in a game?

Not literally, no, but this was quicker to write up in a post than to dig up the old assembly and keymaps to paste it all in, while still hopefully showing the same basic idea behind it. (specifically that it was a simple loop rather than a callback or virtual function system like most events nowadays)

> BTW, this is something I'd use DirectInput for. The Win32 event system is about as suitable for game input as the GDI is for game graphics.

All right. If you have the time to write that up too, I'd appreciate it. I'll keep it simple now due to my lack of experience with it. The one rule though is it needs to remain easy to use. One idea here is that newbies can run with it quickly.

> Don't want to join one of the established companies though.

Oh, hell no. Especially since my preferred style is more NES than XBox - I like the simple 2d, low resolution look. I like the relatively low frame rate. There's a lot less pressure to code it perfectly too (meaning I can just whip stuff out and it's good enough as long as its fun).


> Interesting. I've had a lot of thoughts about game loops flying around in the back of my mind too, but talking about any of it will have to wait for another time, gotta get back to some other stuff right now

Yea, me too... I did start that eventLoop function last night though. So far just tied in WM_KEYDOWN to a delegate, but it works and it's easy, so I figure I'll continue to flesh it out for the basic operations. This way, we can play with it soon and can go back and switch to a better system later.
April 06, 2011
Michel Fortin wrote:
> I played with it yesterday and never found why the blue channel didn't work!

Yeah, I noticed that too after posting it. Here's the problem:

this(int a, int b, int c) {
    r = cast(ubyte) a;
    g = cast(ubyte) b;
    b = cast(ubyte) c;
}

Those quick one letter variable names in a barely necessary constructor ended up shadowing each other - that last line wrote to the local parameter instead of to the struct member like I meant...

Stupid me. Make it this.b = ... and it works.


> I also made a working OS X implementation (Cocoa).

Cool!

> Can't we make things flexible enough for [different colorspaces] by using a template?

Yeah, probably.

> I'd like it better if image.display(win) was replaced with
> "window.image = image" however.

Hmm, maybe. I'm thinking image.display(win) could be some kind of rendering function that then calls out to bitblt or whatever to draw in any location though, offering some flexibility that the property wouldn't provide.

So it's more like image.drawAt(drawable_surface, x, y);

Where the drawable_surface could be a window or another image, and the image renders itself to that destination. Default parameters would tell it to assume upper left of a new window, keeping the simple display() call just working.
April 06, 2011
On 2011-04-06 17:34, Matthias Pleh wrote:
>
>>
>> Yes that's true. I don't know how much different it would be compared to
>> a non-native framework since there you have all the different themes to
>> maintain.
>>
>
> Maybe, the best aproach would be, when you implement the basic framework
> flexible. E.g. a default rendering engine, where you can
> draw you own controls, but keep it possible to add native controls.
> So you always choose the best way, if a platform bring out a new control
> or a new look. But I down't know, if such different approaches
> cann merged together?

I don't know. It sounds like it could get really complicated.

> BTW: under what license is DWT?
> Can part of it relicensed under boost? (e.g. if we would reuse part of it)

It's licensed under the EPL license since that's the license used by SWT. So no. I don't know if you could do some kind of deal with the Eclipse foundation.

> °Matthias


-- 
/Jacob Carlborg
April 06, 2011
Am 06.04.2011 17:35, schrieb Michel Fortin:
> On 2011-04-06 10:25:42 -0400, Matthias Pleh <jens@konrad.net> said:
>
>> Am 06.04.2011 14:49, schrieb Michel Fortin:
>>> final class Bitmap(Color) : Image {
>>> void opIndexAssign(int x, int y, Color color) {
>>> pixels[y * width + x] = Color(color);
>>> }
>>>
>>> size_t width, height;
>>> Color[] pixels;
>>> }
>>
>> Yep, exactly. I would implement it as template.
>>
>> About the render backend, Nick mentioned.
>> In the first step, I would just draw all objects (lines, boxes,
>> circles) to the buffer and then render it as image per gdi/xlib.
>>
>> this render should ideally be in a single file, so other backends can
>> be implemented (gdi/direct2d/cairo/xcb/cocoa/..)
>
> Since you're at it, have you considered making the API flexible enough
> so it could support vector images too?
>
> // return an object derived from image depending on the actual file type
> Image im = loadImage("filename");
>
> // creating a bitmap for on-screen rendering
> auto bitmap = new Bitmap!RGBColor(im.width, im.height);
>
> // base image class has a virtual function to draw itself on a bitmap at
> // a given location, so it's easy to draw it on screen
> im.draw(10, 10, bitmap);
>


Yep, definitley this would be an issue to place on the todo-list.
But let's just start with a basic implementation with simple raster graphics, but always in mind to extand it in the future.
BTW: to implement the whole SVG specification, that would be a huge project, but basic vector drawings would be definitive a nice thing to have.

°Matthias
April 06, 2011
"Lutger Blijdestijn" <lutger.blijdestijn@gmail.com> wrote in message news:inhp3g$25jq$1@digitalmars.com...
> Nick Sabalausky wrote:
>
>>
>> Ha! I may not need to do much after all: I was just looking through Wikipedia's giant list of browsers, found a few that looked potentially promising, tried them all and...well, was mostly disappointed. But the *last* one I had left to try I've been really impressed with so far:
>>
>> Arora (Qt/WebKit)
>> http://code.google.com/p/arora/
>>
>> I've only tried it breifly, but the UI is *actually nice*! Only modern browser out there with a UI that isn't absolutely horrid. I didn't even see *one* instance of invisible-text on my light-on-dark system, which is unbeleivavly rare among all software these days.
>>
>> And it has a lot of essential stuff built in, like ad blocking,
>> disableable JS, and a "ClickToFlash" which I haven't tried out yet.
>> There's still a few things it seems like it might be missing, like
>> equivalents to NoScript, BetterPrivacy and maybe DownloadHelper and
>> DownThemAll, but most of those are less important to me, and even as it
>> is
>> right now it's a damn good start. Maybe I could add some of that
>> remaining
>> stuff, or heck, maybe even port the whole thing to D ;)
>
> Even it it would involve looking at C++ code?
>

Heh :) Yea, well, versus coding a whole browser from scratch that included all the features I'd want... Even using premade rendering and JS engines (which I definitely would have done), that still leaves a lot of work.

> Did you know Arora *is* the Qt webbrowser example that got out of control and became a real browser? (it uses webkit)
>

Yea, I noticed that on Arora's project page. Pretty cool.

> iirc QtD has a sizeable chunk of that example already ported to D.

I'm really interestng in looking at that now. I wonder how much of a split there is between that and the current Arora.



April 06, 2011
"Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:ini1jr$2lj3$1@digitalmars.com...
> Nick Sabalausky wrote:
>> Of course, if you see any fundamental
>> problems with this, feel free to let me know :)
>
> I'm pretty sure your plan would work and would provide a boost, but I'm not sure if it's worth the extra time.
>
> I think the best thing to do will be to partially implement it, write a little program with both methods and run some speed tests. See if it's still easy to use and how big the difference really is.
>


Yea, sounds like a good plan. Although, my design is heavily dependent on inlining working, so that may be a problem until DMD issue #5708 gets fixed: http://d.puremagic.com/issues/show_bug.cgi?id=5708

There another similar -inline related bug in there too, but I don't remember offhand what it is.

>> And even then, things like line drawing, fills and image blitting are still better off skipping the individual-pixel-access routines
>
> Aye, even my homegrown DOS would always write them separately. Horrible waste of instructions doing another y << 8 + y << 6 when a simple "inc ax" would suffice!
>

Yup, exactly. Which reminds me, I've always wanted to actually check to see if modern compilers (or at least DMD) would be smart enough to optimize something like:

for(i in 128...256)
    arr[i] = ...;

Into something like:

auto ptr = arr.ptr + 128;
auto ptrEnd = arr.ptr + 256;
for(; ptr < ptrEnd; ptr++)
    *ptr = ...;

My guess is no (and I'm fairly certain it was "no" back in my DOS days: that was the sort of manual optimization I remember doing all the time), but with all the improvements that optimizers keep making, I'm not really sure anymore.

Of course, even if the compiler can optimize that, I still doubt it would be able to automatically do an equivalent optimization to effectively create, for example, Bresenham's algorithm (ie, straight diagonal lines between two arbitrary points).

>> But anyway, I don't know exactly how you were going about it, but the way to do this in OpenGL or DirectX would be to do all your drawing to a texture buffer
>
> I at first just used a SetPixel function in opengl, but when it
> was unacceptable, I simply abandoned the idea of drawing pixels
> to the screen. Instead, I started focusing on polygons and textures -
> a rectangle with a bitmap attached as a texture makes an excellent
> sprite that draws very very quickly, even if rotated or misshapen.
>
> Once I realized that works so well, pixels weren't important anymore so I just stopped using the old functions entirely. They're still in the code, still godawfully slow, but I don't care enough to change it.
>

Yea. I see. I wonder if OpenGL's SetPixel was inlined. If not, I bet we could do better (as long as we had direct access to the texture's buffer).

>> You were using getch() in a game?
>
> Not literally, no, but this was quicker to write up in a post than to dig up the old assembly and keymaps to paste it all in, while still hopefully showing the same basic idea behind it. (specifically that it was a simple loop rather than a callback or virtual function system like most events nowadays)
>

Ahh, I see :)

>> BTW, this is something I'd use DirectInput for. The Win32 event system is about as suitable for game input as the GDI is for game graphics.
>
> All right. If you have the time to write that up too, I'd appreciate it. I'll keep it simple now due to my lack of experience with it. The one rule though is it needs to remain easy to use. One idea here is that newbies can run with it quickly.
>

Yea. Actually, I think I'll need to take look at Derelict again. I know that project already has a lot of these game-appropriate APIs wrapped for D (or at least bindings). I don't remember: Did you say this would ideally be something for Phobos? If so, I wonder if requiring Derelict would be a problem. If it is, then maybe I could just borrow the appropriate code from Derelict, depending on the licenses involved (I don't remember what Derelict's license is).

>> Don't want to join one of the established companies though.
>
> Oh, hell no. Especially since my preferred style is more NES than XBox - I like the simple 2d, low resolution look. I like the relatively low frame rate. There's a lot less pressure to code it perfectly too (meaning I can just whip stuff out and it's good enough as long as its fun).
>

Yea, same here for the most part. Although I have fallen completely in love with the first three Splinter Cell games :) And Pikmin. And Moonbase Commander (Although that one's more SNES-style). Actually, there's a fair amount in both gaming eras I'm really into (and in-between stuff, like Doom 1/2/64 and the first two Quakes). But with the newer stuff it just seems to be getting harder and harder to find the gems, and even when you do, they're likely to have more problems than they used to (Like Sonic Unleashed: The daytime levels and puzzle areas were fantastic, but then they had to cram in reams of utterly pointless dialog, cutscenes and nighttime levels - and then Sonic Colors didn't *remotely* live up to the claims of "It's Sonic Unleashed's daytime!" Sonic Team really needs to just step aside and let Dimps handle everything...)

And along the NES/SNES lines, I've always been a huge sucker for DOS VGA/EGA gaming. Back when Epic put out good games, and Apogee was still relevent (and actualy existed). Three hidden gems of that era that I'd highly recommend are Capture The Flag (EGA, turn-based strategy), Space Chase (EGA, platformer), and God of Thunder (VGA, sort of a slightly linear SNES-Zelda). And, of course, almost any of Epic's, Apogee's and id's DOS games. You'd probably need DOSBox for all of them these days.


April 06, 2011
"Nick Sabalausky" <a@a.a> wrote in message news:inihjp$hnp$1@digitalmars.com...
> "Adam D. Ruppe" <destructionator@gmail.com> wrote in message news:ini1jr$2lj3$1@digitalmars.com...
>>
>> Aye, even my homegrown DOS would always write them separately. Horrible waste of instructions doing another y << 8 + y << 6 when a simple "inc ax" would suffice!
>>
>
> Yup, exactly. Which reminds me, I've always wanted to actually check to see if modern compilers (or at least DMD) would be smart enough to optimize something like:
>
> for(i in 128...256)
>    arr[i] = ...;
>
> Into something like:
>
> auto ptr = arr.ptr + 128;
> auto ptrEnd = arr.ptr + 256;
> for(; ptr < ptrEnd; ptr++)
>    *ptr = ...;
>

Actually, I meant more like this:

enum width = 512;
int x = 10;
for(y in 128...256)
   arr[y * width + x] = ...;

to this:

enum width = 512;
int x = 10;
auto ptr = arr.ptr + 128*width + x;
auto ptrEnd = arr.ptr + 256*width + x;
for(; ptr < ptrEnd; ptr += width)
   *ptr = ...;



April 06, 2011
"Michel Fortin" <michel.fortin@michelf.com> wrote in message news:inhnnn$236n$1@digitalmars.com...
>> Nick Sabalausky wrote:
>>> I haven't benchmarked or even tested this, and heck, maybe I'm just a dinosaur, but for better speed and flexibility I'd recommend something more like what I've attached.
>>
>> Yea, that does sound better. Though I have a few comments...
>>
>>> The width is statically-known, so the compiler can optimize the index calculation from multiplication to shifts when appropriate.
>>
>> One concern I have here is will it be an incompatible type with dynamic widths? i.e. an image loaded from a file? (I'll be hopefully cleaning up my png and bmp loaders in the near future to use with this.)
>
> I don't think having fixed-size image will be a useful optimization, except perhaps if you manipulate a lot of tiny images of the same size.
>

Manipulating images in software involves accessing a *lot* of pixels, so you have a very big "inner loop" situation. If the width isn't statically-known, then:

- Every arbitrary pixel access requires a multiply (instead of a shift or sum-of-shifts like you can do if the width is statically-known and a power of 2 or a sum of powers of 2).

- Every sequential non-horizontal pixel access requires an extra register to be used (to hold the pointer-increment value).

Over all the pixels in a scene, that can really add up. In fact, that's one of the reasons game engines traditionally have only supported very specific finite sets of fixed image sizes.

Of course, usually you'd avoid doing direct pixel access and use specially-optimized higher-level primitives instead (although even those can often benefit from a statically-known power-of-2 width). But since one of the goals behind this API is to be used as a "playground", we can expect that people are going to want to be doing a lot of direct pixel access.

Although, we'll certainly want to do some benchmarking to really know for sure.

>
> Don't forget that there's actually much more colorspaces than indexed and RGB. There's RGBA (when you need semi-transparency), there's CYMB (for print), there's grayscale. And in some cases HSV or XYZ could be useful too. And for each of these someone might want different bit depth. Can't we make things flexible enough for that by using a template?
>
> final class Bitmap(Color) : Image {
> void opIndexAssign(int x, int y, Color color) {
> pixels[y * width + x] = Color(color);
> }
>
> size_t width, height;
> Color[] pixels;
> }
>
> This way, you can have a bitmap of RGBColor, or RGBAColor (with an alpha mask), GrayColor, IndexedColor, or whatever color type you can come with, and algorithms can be reused.
>

Yea, that's probably a very good idea.



April 06, 2011
On 4/6/11 10:41 PM, Nick Sabalausky wrote:
>> I don't think having fixed-size image will be a useful optimization,
>> except perhaps if you manipulate a lot of tiny images of the same size.
>>
>
> Manipulating images in software involves accessing a *lot* of pixels, so you
> have a very big "inner loop" situation. If the width isn't statically-known,
> then:[…]

If you want to write something generic that actually performs well, the Adobe/Boost »Generic Image Library« might be an interesting example: www.boost.org/doc/libs/release/libs/gil/doc/index.html

David