Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » DirectX VRAM-VRAM accelerated stretch blit

This thread is locked; no one can reply to it. rss feed Print
DirectX VRAM-VRAM accelerated stretch blit
A J
Member #3,025
December 2002
avatar

The most useful feature i want from Allegro is VRAM to VRAM accelerated stretch blit. I dont think the current DirectX driver has this feature as its using dx3.

What versions of DirectX contain this feature ?
When would allegro get this DirectX version ?

if this is not likely to occur any time soon, does anyone know of other allegro-like libs that can do it ?

___________________________
The more you talk, the more AJ is right. - ML

HoHo
Member #4,534
April 2004
avatar

Quote:

When would allegro get this DirectX version ?

when someone implements it.

I personally think there is little point in improving current drivers. The main energy should go into developing a decent OpenGL driver. With that it would be possible to accelerate almost anything and it would be portable.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Evert
Member #794
November 2000
avatar

As HoHo said, it'll be there when someone writes the code. I'm sure you're aware of the number of active Windows developers we have right now, so if you care to implement it that would be welcome.

Regarding OpenGL to do this, it's possible that AllegroGL already implements this functionality. I don't know for sure that it does, but it would be possible for it to support it. If it doesn't, I'm sure some help there is also appreciated.

Richard Phipps
Member #1,632
November 2001
avatar

AJ: If you use OpenLayer you can effectively do this already (and with blending, roatation, etc..)

Elias
Member #358
May 2000

Quote:

What versions of DirectX contain this feature ?

No DirectDraw version has this, so upgrading Allegro's code to DirectDraw 7 would have no effect. The only way would be to replace the "DirectDraw" interface based driver by a "Direct3D" interface based one, which is the equivalent of OpenGL. Probably it would make most sense to use DX9. But it means, a complete driver rewrite is necessary. (Someone started such a driver once I think.. not sure what happened to it.)

--
"Either help out or stop whining" - Evert

Dennis
Member #1,090
July 2003
avatar

The problem with DX9 is, we would lose "ddraw.h", because the last directX version supporting standard 2D interfaces is DirectX8. DX9 is 3D interfaces only and that would require to emulate 2D through 3D interfaces. Another point for not using DX9 would be that there are a lot of video cards out there, who simply can not run DX9 games in hardware, so there would be a need for fallback drivers to DX8 and DX7 to support the most common video cards in use. (Otherwise those unsupported cards would use DX9 software interfaces, which would slow everything down and not utilize the acceleration potential of those cards.)

Sounds all nice and easy in theory. In practice that means a huge workload and i don't know if that's worth the trouble in the current Allegro version(which sources are horrible). Goes without saying that, if i knew HOW to do all of the above, i would long have started to implement it, but since i don't know anything about Direct3D and don't have the time to learn it, i have not.;D

HoHo
Member #4,534
April 2004
avatar

Quote:

The problem with DX9 is, ...

Or in other words, doing the same with OpenGL would be much simplier and would work cross-platform everywhere :)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Thomas Harte
Member #33
April 2000
avatar

Quote:

No DirectDraw version has this

With all due respect, every version of DirectDraw has this. It's the reason IDirectDrawSurface::Blt has a source RECT and a dest RECT. Microsoft aren't in the habit of keeping around old documentation, but I can still find IDirectDrawSurface5::Blt in MSDN and note particularly from the comments (emphasis added):

MSDN said:

This method is capable of synchronous or asynchronous blits (the default behavior), either display memory to display memory, display memory to system memory, system memory to display memory, or system memory to system memory. The blits can be performed by using source color keys, and destination color keys. Arbitrary stretching or shrinking will be performed if the source and destination rectangles are not the same size.

I can't find an MSDN source for it, but I can assert that this method was not changed as DirectDraw advanced. The ability to scale is what differentiates Blt from BltFast. Of course DirectDraw is able to use either of its blit functions for the equivalent of Allegro _blit and _sprite functionality.

To implement an accelerated stretch on Windows should be as simple as duplicating the hardware non-scaled blitter, changing the (hopefully) BltFast to a Blt and independently building a destination rectangle. It should be a quick enough modification. Although I don't have a suitable build chain, I'll go glance at the source.

EDIT:

Having found the non-accelerated version (src/win/wddaccel.c, line 88 onwards), what is the purpose of this clause at line 139:

   else {
      /* have to use the original software version */
      _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height);
   }
}

I cannot imagine that the Allegro developers think they have implemented a faster software blit than that provided by DirectDraw? Perhaps it is to mask Allegro's continuing deficiencies with locking and unlocking?

EDIT2:
The following code should do:

1static void ddraw_masked_stretch_blit(BITMAP * source, BITMAP * dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height)
2{
3 RECT dest_rect, source_rect;
4 DDCOLORKEY src_key;
5 HRESULT hr;
6 BITMAP *dest_parent;
7 BITMAP *source_parent;
8 
9 dest_rect.left = dest_x + dest->x_ofs;
10 dest_rect.top = dest_y + dest->y_ofs;
11 dest_rect.right = dest_x + dest->x_ofs + dest_width;
12 dest_rect.bottom = dest_y + dest->y_ofs + dest_height;
13 
14 source_rect.left = source_x + source->x_ofs;
15 source_rect.top = source_y + source->y_ofs;
16 source_rect.right = source_x + source->x_ofs + dest_width;
17 source_rect.bottom = source_y + source->y_ofs + dest_height;
18 
19 src_key.dwColorSpaceLowValue = source->vtable->mask_color;
20 src_key.dwColorSpaceHighValue = source->vtable->mask_color;
21 
22 if (is_video_bitmap(source) || is_system_bitmap(source)) {
23 
24 /* find parents */
25 dest_parent = dest;
26 while (dest_parent->id & BMP_ID_SUB)
27 dest_parent = (BITMAP *)dest_parent->extra;
28 
29 source_parent = source;
30 while (source_parent->id & BMP_ID_SUB)
31 source_parent = (BITMAP *)source_parent->extra;
32 
33 _enter_gfx_critical();
34 gfx_directx_release_lock(dest);
35 gfx_directx_release_lock(source);
36 
37 IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id,
38 DDCKEY_SRCBLT, &src_key);
39 
40 hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
41 DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
42 DDBLT_KEYSRC | DDBLT_WAIT, NULL);
43 _exit_gfx_critical();
44 
45 if (FAILED(hr))
46 _TRACE(PREFIX_E "Blt failed (%x)\n", hr);
47 
48 /* only for windowed mode */
49 if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap))
50 win_gfx_driver->paint(&dest_rect);
51 }
52 else {
53 /* have to use the original software version */
54 _orig_masked_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height);
55 }
56}

Plus something analogous to ddraw_draw_sprite to map from stretch_sprite to masked_stretch_blit, and the flagging of this as an available accelerated routine at wherever that should be done (which I haven't quite found yet...)

EDIT3:
And why not use BltFast in masked blit? It is rarely faster, but it may be depending on driver and hardware, etc. i.e.

1static void ddraw_masked_blit(BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
2{
3 RECT source_rect;
4 DDCOLORKEY src_key;
5 HRESULT hr;
6 BITMAP *dest_parent;
7 BITMAP *source_parent;
8 
9 source_rect.left = source_x + source->x_ofs;
10 source_rect.top = source_y + source->y_ofs;
11 source_rect.right = source_x + source->x_ofs + width;
12 source_rect.bottom = source_y + source->y_ofs + height;
13 
14 src_key.dwColorSpaceLowValue = source->vtable->mask_color;
15 src_key.dwColorSpaceHighValue = source->vtable->mask_color;
16 
17 if (is_video_bitmap(source) || is_system_bitmap(source)) {
18 
19 /* find parents */
20 dest_parent = dest;
21 while (dest_parent->id & BMP_ID_SUB)
22 dest_parent = (BITMAP *)dest_parent->extra;
23 
24 source_parent = source;
25 while (source_parent->id & BMP_ID_SUB)
26 source_parent = (BITMAP *)source_parent->extra;
27 
28 _enter_gfx_critical();
29 gfx_directx_release_lock(dest);
30 gfx_directx_release_lock(source);
31 
32 IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id,
33 DDCKEY_SRCBLT, &src_key);
34 
35 hr = IDirectDrawSurface2_BltFast(DDRAW_SURFACE_OF(dest_parent)->id, dest_x + dest->x_ofs, dest_y + dest->y_ofs,
36 DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
37 DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT, NULL);
38 _exit_gfx_critical();
39 
40 if (FAILED(hr))
41 _TRACE(PREFIX_E "Blt failed (%x)\n", hr);
42 
43 /* only for windowed mode */
44 if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap))
45 win_gfx_driver->paint(&dest_rect);
46 }
47 else {
48 /* have to use the original software version */
49 _orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height);
50 }
51}

Elias
Member #358
May 2000

Quote:

To implement an accelerated stretch on Windows should be as simple as duplicating the hardware non-scaled blitter, changing the (hopefully) BltFast to a Blt and independently building a destination rectangle. It should be a quick enough modification. Although I don't have a suitable build chain, I'll go glance at the source.

Oh, very nice, I didn't know that.

Quote:

I cannot imagine that the Allegro developers think they have implemented a faster software blit than that provided by DirectDraw?

That's simply the case for memory bitmaps.. there is no DX function (well, again, to my knowledge) to blit a memory rectangle to a DX surface.

--
"Either help out or stop whining" - Evert

Thomas Harte
Member #33
April 2000
avatar

Quote:

That's simply the case for memory bitmaps..

Oh, Allegro is maintaining it's own internal format for memory bitmaps? I'm curious - why would does it not just use DirectDraw memory surfaces?

GullRaDriel
Member #3,861
September 2003
avatar

Quote:

Oh, Allegro is maintaining it's own internal format for memory bitmaps? I'm curious - why would does it not just use DirectDraw memory surfaces?

CrossPlatform Issues ?

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Thomas Harte
Member #33
April 2000
avatar

Quote:

CrossPlatform Issues ?

I can't see how, if Allegro is flexible enough to be able to handle DirectDraw surfaces as BITMAPS where they are system/video resident, it could not handle DirectDraw surfaces as memory BITMAPS.

EDIT:
it seems the place to notify Allegro of a new accelerated function is in gfx_directx_enable_acceleration at line 453 of the same file as above - src/win/wddaccel.c. I haven't found the definition of _screen_vtable yet but at a guess you'd change the final if clause, currently:

   if ((ddcaps.dwCaps & DDCAPS_COLORKEY) &&
       (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) {
      _screen_vtable.masked_blit = ddraw_masked_blit;
      _screen_vtable.draw_sprite = ddraw_draw_sprite;

      if (_screen_vtable.color_depth == 8)
   _screen_vtable.draw_256_sprite = ddraw_draw_sprite;

      gfx_capabilities |= (GFX_HW_VRAM_BLIT_MASKED | GFX_HW_SYS_TO_VRAM_BLIT_MASKED);
   }

To:

   if ((ddcaps.dwCaps & DDCAPS_COLORKEY) &&
       (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) {
      _screen_vtable.masked_blit = ddraw_masked_blit;
      _screen_vtable.draw_sprite = ddraw_draw_sprite;

      /* new entry */
      _screen_vtable.masked_stretch_blit = ddraw_masked_stretch_blit

      if (_screen_vtable.color_depth == 8)
   _screen_vtable.draw_256_sprite = ddraw_draw_sprite;

      gfx_capabilities |= (GFX_HW_VRAM_BLIT_MASKED | GFX_HW_SYS_TO_VRAM_BLIT_MASKED);
   }

Does anybody have a Windows/GCC toolchain to try some of this stuff out?

Elias
Member #358
May 2000

Probably the original idea was to avoid overhead in the case where you do lots of direct manipulations on the memory bitmap. I think in the new API, we won't have the separation into "memory", "system" and "video" bitmaps.. it will all be managed internally. Probably with the possibility to set some extra flag if you want to override the default behavior.

[Edit:] And in my understanding, you get DX memory bitmaps as "system" bitmaps currently.

--
"Either help out or stop whining" - Evert

GullRaDriel
Member #3,861
September 2003
avatar

i'm trying it ...

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

A J
Member #3,025
December 2002
avatar

GullRaDriel, have any luck ?

___________________________
The more you talk, the more AJ is right. - ML

GullRaDriel
Member #3,861
September 2003
avatar

ddraw_masked_stretch_blit isn't declared.

Quote:

C:\PROG\LIBRARY_IDE\Allegro\Copy of allegro>make
Compiling Allegro for MinGW32, optimised. Please wait...
gcc -DALLEGRO_SRC -DALLEGRO_LIB_BUILD -Wall -Wno-unused -mtune=i586 -O2 -funroll
-loops -ffast-math -fomit-frame-pointer -I. -I./include -o obj/mingw32/alleg/wd
daccel.o -c src/win/wddaccel.c
src/win/wddaccel.c: In function `gfx_directx_enable_acceleration':
src/win/wddaccel.c:468: error: structure has no member named `masked_stretch_blit'
src/win/wddaccel.c:470: error: `ddraw_masked_stretch_blit' undeclared (first use
in this function)
src/win/wddaccel.c:470: error: (Each undeclared identifier is reported only once

src/win/wddaccel.c:470: error: for each function it appears in.)
src/win/wddaccel.c:470: error: syntax error before "if"
make: *** [obj/mingw32/alleg/wddaccel.o] Error 1

i'm trying to use the Thomas's ddraw_masked_strech_blit.
I'm currently including it to fix the gcc issue (i'm dumb, i know)

EDIT: currently compiling... with no warning or error, i follow the AL_FUNC(...) and other allegro's specific way of implementing.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Evert
Member #794
November 2000
avatar

Quote:

I haven't found the definition of _screen_vtable yet

It's just a global variable of type GFX_VTABLE. The element you'll want to change is
AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked));
masked is a flag (true or false) that determines wether or not to do a masked blit or a normal blit.

GullRaDriel
Member #3,861
September 2003
avatar

I'm leaving work but will try to to this when at home.
I'll keep you informed.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Thomas Harte
Member #33
April 2000
avatar

Quote:

... masked is a flag (true or false) that determines wether or not to do a masked blit or a normal blit.

Well in that case the code above won't work properly, but it should be easy to make something that does. This Sunday I'll try and get a working Windows/GCC install so that I can look into that + the clipping topics Neil Walker raised in the other thread. It seems that time I spent learning Windows/DirectDraw will not have been wasted.

GullRaDriel
Member #3,861
September 2003
avatar

i'm back

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Richard Phipps
Member #1,632
November 2001
avatar

GullRaDriel
Member #3,861
September 2003
avatar

i'm currently here:

Quote:

C:\PROG\LIBRARY_IDE\Allegro\Copy of allegro>make
Compiling Allegro for MinGW32, optimised. Please wait...
gcc -DALLEGRO_SRC -DALLEGRO_LIB_BUILD -Wall -Wno-unused -mtune=i586 -O2 -funroll-loops -ffast-math -fomit-frame-pointer -I. -I./include -o obj/mingw32/alleg/wddaccel.o -c src/win/wddaccel.c
src/win/wddaccel.c: In function `gfx_directx_enable_acceleration':
src/win/wddaccel.c:467: error: structure has no member named `masked_stretch_blit'
src/win/wddaccel.c: In function `ddraw_masked_stretch_blit':
src/win/wddaccel.c:572: warning: implicit declaration of function `_orig_masked_stretch_blit'
make: *** [obj/mingw32/alleg/wddaccel.o] Error 1

any idea?

PS: if a someone is good at allegro-updating, i can provide a 'fast' vnc connection for him.

Also a ftp.

PM me !

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Evert
Member #794
November 2000
avatar

Quote:

any idea?

See my above post.

Thomas Harte
Member #33
April 2000
avatar

Dump ddraw_masked_stretch_blit as suggested above and try the following:

1static void ddraw_do_stretch_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)
2{
3 RECT dest_rect, source_rect;
4 DDCOLORKEY src_key;
5 HRESULT hr;
6 BITMAP *dest_parent;
7 BITMAP *source_parent;
8 
9 dest_rect.left = dest_x + dest->x_ofs;
10 dest_rect.top = dest_y + dest->y_ofs;
11 dest_rect.right = dest_x + dest->x_ofs + dest_width;
12 dest_rect.bottom = dest_y + dest->y_ofs + dest_height;
13 
14 source_rect.left = source_x + source->x_ofs;
15 source_rect.top = source_y + source->y_ofs;
16 source_rect.right = source_x + source->x_ofs + dest_width;
17 source_rect.bottom = source_y + source->y_ofs + dest_height;
18 
19 src_key.dwColorSpaceLowValue = source->vtable->mask_color;
20 src_key.dwColorSpaceHighValue = source->vtable->mask_color;
21 
22 if (is_video_bitmap(source) || is_system_bitmap(source)) {
23 
24 /* find parents */
25 dest_parent = dest;
26 while (dest_parent->id & BMP_ID_SUB)
27 dest_parent = (BITMAP *)dest_parent->extra;
28 
29 source_parent = source;
30 while (source_parent->id & BMP_ID_SUB)
31 source_parent = (BITMAP *)source_parent->extra;
32 
33 _enter_gfx_critical();
34 gfx_directx_release_lock(dest);
35 gfx_directx_release_lock(source);
36 
37 IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id,
38 DDCKEY_SRCBLT, &src_key);
39 
40 hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
41 DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
42 (masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL);
43 _exit_gfx_critical();
44 
45 if (FAILED(hr))
46 _TRACE(PREFIX_E "Blt failed (%x)\n", hr);
47 
48 /* only for windowed mode */
49 if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap))
50 win_gfx_driver->paint(&dest_rect);
51 }
52 else {
53 /* have to use the original software version */
54 _orig_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked);
55 }
56}

And then bin:
_screen_vtable.masked_stretch_blit = ddraw_masked_stretch_blit;
For:
_screen_vtable.do_stretch_blit = ddraw_do_stretch_blit;
Note that this should only accelerate stretch_blit and masked_stretch_blit (or wherever masked is added to make that an Allegro function) - if it works then a simple thing to convert accelerated stretch_sprites to stretch_blits can be added.

Evert
Member #794
November 2000
avatar

Quote:

Note that this should only accelerate stretch_blit and masked_stretch_blit (or wherever masked is added to make that an Allegro function) - if it works then a simple thing to convert accelerated stretch_sprites to stretch_blits can be added.

Actually, stretch_blit, masked_stretch_blit and stretch_sprite all call the same do_stretch_blit(), which is actually called that in the asm version of the code; it's the infamous self-modifying code in Allegro; it's called _al_stretch_blit in the C version of the code. Neither function is exposed through the API and they're static to their respective sourcefiles (allegro/src/i386/istretch.c and allegro/src/c/cstretch.c). Pretty confusing, isn't it?
Anyway, do_stretch_blit() and _al_stretch_blit() both have

   /* vtable hook */   
   if (source->vtable->do_stretch_blit) {
      source->vtable->do_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked);
      return;
   }

So bottom line: they should all work.

EDIT: do we need a GFX_HW_STRETCH_BLIT flag for gfx_capabilities now?



Go to: