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
Neil Walker
Member #210
April 2000
avatar

It's ok, I've done the change manually, the diff file is self-explanatory (btw, you haven't included the file anyway!) [edit]I see you now have. I'll recompile[/edit].

Before I do my tests, here are the results of the new test.exe, which I guess says my card is doing acceleration for video/system graphics.

vram->vram blit: yes
masked vram->vram blit: yes
mem->screen blit: no
masked mem->screen blit: no
system->screen blit: yes
masked system->screen blit: yes

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

(btw, you haven't included the file anyway!).

I hit add reply instead of browse by accident. I know, they're not even close. Don't ask.

Quote:

Before I do my tests, here are the results of the new test.exe, which I guess says my card is doing acceleration for video/system graphics.

It appears that I neglected to include the display code in teh relevant location! You'll only see it reported in the logfile with the version I attached. Try the one I attacehd to this post (untested).
What you posted only says if normal blits are accelerated. It doesn't say anything about stretch_blit().

Neil Walker
Member #210
April 2000
avatar

Ok, updated test as well and my system is fully hardware accelerated except for memory to screen blits and stretched vram-vram (though masked stretched vram-vram is), which I guess is fairly normal. Here are my results. I tested it with all permutations of video/system/memory bitmaps onto memory/system/video buffers using both single graphics and sub-bitmaps. I also tested them as a base with the original 4.2 DLL and the new changes:

Tests are :
A. draw buffer is memory. graphics are memory (normal, not sub-bitmap)
B. draw buffer is memory. graphics are system (normal, not sub-bitmap)
C. draw buffer is memory. graphics are video (normal, not sub-bitmap)
D. draw buffer is system. graphics are memory (normal, not sub-bitmap)
E. draw buffer is system. graphics are system (normal, not sub-bitmap)
F. draw buffer is system. graphics are video (normal, not sub-bitmap)
G. draw buffer is video. graphics are memory (normal, not sub-bitmap)
H. draw buffer is video. graphics are system (normal, not sub-bitmap)
I. draw buffer is video. graphics are video (normal, not sub-bitmap)

Firstly, as a base, I tested all the above using the standard allegro 4.2 dll. All the stretch functions works. draw_sprite is as my other emails so I won't mention it.

Using the new DLL the results are as follows,
Y - works fine
Nx - fails, number corresponds to the errors below the table.

test  stretch_blit  masked_stretch_blit  stretch_sprite  draw_sprite
A    Y    Y      Y    Y
B    N1    N1      N1    Y
C    N1    N1      N1    Y
D    Y    Y      Y    Y
E    N2    N2      N2    Y
F    N2    N2      N2    Y
G    Y    Y      Y    Y
H    N2    N2      N2    Y
I    N2    N2      N2    Y

Failure types
N1: crash on calling function
N2: sprite is not shown

Using the new code and single bitmaps it's pretty clear that stretch only works when the buffer being drawn onto is memory. Where it fails the majority must be failing to draw, but when you draw memory bitmaps onto accelerated buffer it crashes.

------------------------------------
I then repeated all the tests again, but this time the graphics being shown are sub-bitmaps of a master sheet. I will only show below the results that are different (i.e. a different result blitting sub-bitmaps rather than normal bitmaps)

test  stretch_blit  masked_stretch_blit  stretch_sprite  draw_sprite
B                  N3
E    N4    N4      N4    N3
F    N4    N4      N4    N3
H    N4    N4      N4    N3
I    N4    N4      N4    Y

Failure types
N3 Crashes on destroying the subbitmap (this is already documented by me earlier)
N4 This is a freaky error! instead of drawing the bitmap stretched it is increasing the size of the bitmap (i.e. if my sprite was 32x32, instead of stretching it to 64x64 as in the code, it actually simply changes the size of the sub-bitmap to 64x64 - showing simply a larger part of the master bitmap)

So it looks like when your graphic being drawn is a subbitmap and your drawing buffer is a system or video bitmap and your graphic is a system or video you get the bitmap being enlarged not stretched.

Hope this helps :)

btw, in the test code you popped up, you forgot a comma in this line and the one bwlow:
"stretch vram->vram blit:"

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

stretched vram-vram (though masked stretched vram-vram is)

That's just weird.

I'm not at all sure what to make of these results though. Someone with Windows should have a look and try to isolate the problem. I may check if my XP64 license hasn't expired yet (I think it has), in which case I might check for myself. No promises though.

Your test is fairly exhaustive, which I'm sure will help eventually. However, you could have left out the mem->* and draw_sprite() tests since they are (should) be unaffected by the patch in this thread.

Quote:

btw, in the test code you popped up, you forgot a comma in this line and the one bwlow:
"stretch vram->vram blit:"

I know. I fixed it a minute after posting that but neglectied to attach the updated file.

EDIT: For the `bitmap size is wrong', I think you need to have

source_rect.right = source_x + source->x_ofs + source_width;
   source_rect.bottom = source_y + source->y_ofs + source_height;

instead of

source_rect.right = source_x + source->x_ofs + dest_width;
   source_rect.bottom = source_y + source->y_ofs + dest_height;

Please try it out and see if that helps.

EDIT2: In the test programme, add
"Mouse pointer:",
at line 1752 (before "stretch vram->vram blit:").

EDIT3:
Ok, I managed to boot into Windows after some tinkering with grub (I added a harddisk a few weeks ago and had to change some settings because of that) and apparently my licesense hasn't expired yet.
Try the following patch:

1Index: src/win/wddaccel.c
2===================================================================
3--- src/win/wddaccel.c (revision 5662)
4+++ src/win/wddaccel.c (working copy)
5@@ -15,6 +15,7 @@
6 * Bugfixes by Isaac Cruz.
7 *
8 * Accelerated rectfill() and hline() added by Shawn Hargreaves.
9+ * Accelerated stretch_blit() and friends by Thomas Harte
10 *
11 * See readme.txt for copyright information.
12 */
13@@ -34,6 +35,7 @@
14 static void (*_orig_rectfill) (BITMAP * bmp, int x1, int y1, int x2, int y2, int color);
15 static void (*_orig_draw_sprite) (BITMAP * bmp, BITMAP * sprite, int x, int y);
16 static void (*_orig_masked_blit) (BITMAP * source, BITMAP * dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
17+static void (*_orig_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, int masked);
18
19
20
21@@ -193,6 +195,70 @@
22
23
24
25+/* ddraw_do_stretch_blit:
26+ * Accelerated stretch_blit, stretch_sprite, stretch_masked_blit
27+ */
28+static 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)
29+{
30+ RECT dest_rect, source_rect;
31+ DDCOLORKEY src_key;
32+ HRESULT hr;
33+ BITMAP *dest_parent;
34+ BITMAP *source_parent;
35+
36+ dest_rect.left = dest_x + dest->x_ofs;
37+ dest_rect.top = dest_y + dest->y_ofs;
38+ dest_rect.right = dest_x + dest->x_ofs + dest_width;
39+ dest_rect.bottom = dest_y + dest->y_ofs + dest_height;
40+
41+ source_rect.left = source_x + source->x_ofs;
42+ source_rect.top = source_y + source->y_ofs;
43+ source_rect.right = source_x + source->x_ofs + source_width;
44+ source_rect.bottom = source_y + source->y_ofs + source_height;
45+
46+ src_key.dwColorSpaceLowValue = source->vtable->mask_color;
47+ src_key.dwColorSpaceHighValue = source->vtable->mask_color;
48+
49+ if ( ( (masked && (gfx_capabilities & GFX_HW_STRETCH_BLIT_MASKED)) ||
50+ (!masked && (gfx_capabilities & GFX_HW_STRETCH_BLIT))
51+ ) && ( is_video_bitmap(source) || is_system_bitmap(source) ) ) {
52+
53+ /* find parents */
54+ dest_parent = dest;
55+ while (dest_parent->id & BMP_ID_SUB)
56+ dest_parent = (BITMAP *)dest_parent->extra;
57+
58+ source_parent = source;
59+ while (source_parent->id & BMP_ID_SUB)
60+ source_parent = (BITMAP *)source_parent->extra;
61+
62+ _enter_gfx_critical();
63+ gfx_directx_release_lock(dest);
64+ gfx_directx_release_lock(source);
65+
66+ IDirectDrawSurface2_SetColorKey(DDRAW_SURFACE_OF(source_parent)->id,
67+ DDCKEY_SRCBLT, &src_key);
68+
69+ hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
70+ DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
71+ (masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL);
72+ _exit_gfx_critical();
73+
74+ if (FAILED(hr))
75+ _TRACE(PREFIX_E "Blt failed (%x)\n", hr);
76+
77+ /* only for windowed mode */
78+ if ((gfx_driver->id == GFX_DIRECTX_WIN) && (dest_parent == gfx_directx_forefront_bitmap))
79+ win_gfx_driver->paint(&dest_rect);
80+ }
81+ else {
82+ /* have to use the original software version */
83+ _orig_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked);
84+ }
85+}
86+
87+
88+
89 /* ddraw_clear_to_color:
90 * Accelerated screen clear routine.
91 */
92@@ -458,6 +524,7 @@
93 _orig_rectfill = _screen_vtable.rectfill;
94 _orig_draw_sprite = _screen_vtable.draw_sprite;
95 _orig_masked_blit = _screen_vtable.masked_blit;
96+ _orig_stretch_blit = _screen_vtable.do_stretch_blit;
97
98 /* accelerated video to video blits? */
99 if (ddcaps.dwCaps & DDCAPS_BLT) {
100@@ -467,6 +534,11 @@
101 _screen_vtable.blit_from_system = ddraw_blit_to_self;
102 _screen_vtable.blit_to_system = ddraw_blit_to_self;
103
104+ if (ddcaps.dwCaps&DDCAPS_BLTSTRETCH) {
105+ _screen_vtable.do_stretch_blit = ddraw_do_stretch_blit;
106+ gfx_capabilities |= GFX_HW_STRETCH_BLIT;
107+ }
108+
109 gfx_capabilities |= (GFX_HW_VRAM_BLIT | GFX_HW_SYS_TO_VRAM_BLIT);
110 }
111
112@@ -486,6 +558,11 @@
113 _screen_vtable.masked_blit = ddraw_masked_blit;
114 _screen_vtable.draw_sprite = ddraw_draw_sprite;
115
116+ if (ddcaps.dwCaps&DDCAPS_BLTSTRETCH) {
117+ _screen_vtable.do_stretch_blit = ddraw_do_stretch_blit;
118+ gfx_capabilities |= GFX_HW_STRETCH_BLIT_MASKED;
119+ }
120+
121 if (_screen_vtable.color_depth == 8)
122 _screen_vtable.draw_256_sprite = ddraw_draw_sprite;
123
124Index: tests/test.c
125===================================================================
126--- tests/test.c (revision 5662)
127+++ tests/test.c (working copy)
128@@ -1748,6 +1748,9 @@
129 "masked mem->screen blit:",
130 "system->screen blit:",
131 "masked system->screen blit:",
132+ "Mouse pointer:",
133+ "stretch vram->vram blit:",
134+ "masked stretch vram->vram blit:",
135 NULL
136 };
137
138@@ -3385,6 +3388,8 @@
139 if (gfx_capabilities & GFX_HW_MEM_BLIT_MASKED) fprintf(f, " masked mem->vram blits\n");
140 if (gfx_capabilities & GFX_HW_SYS_TO_VRAM_BLIT) fprintf(f, " system->vram blits\n");
141 if (gfx_capabilities & GFX_HW_SYS_TO_VRAM_BLIT_MASKED) fprintf(f, " masked system->vram blits\n");
142+ if (gfx_capabilities & GFX_HW_STRETCH_BLIT) fprintf(f, " stretch blits\n");
143+ if (gfx_capabilities & GFX_HW_STRETCH_BLIT_MASKED) fprintf(f, " masked stretch blits\n");
144
145 if (!(gfx_capabilities & ~(GFX_CAN_SCROLL | GFX_CAN_TRIPLE_BUFFER | GFX_HW_CURSOR)))
146 fprintf(f, " <none>\n");
147Index: include/allegro/gfx.h
148===================================================================
149--- include/allegro/gfx.h (revision 5662)
150+++ include/allegro/gfx.h (working copy)
151@@ -142,6 +142,8 @@
152 #define GFX_HW_SYS_TO_VRAM_BLIT 0x00100000
153 #define GFX_HW_SYS_TO_VRAM_BLIT_MASKED 0x00200000
154 #define GFX_SYSTEM_CURSOR 0x00400000
155+#define GFX_HW_STRETCH_BLIT 0x00800000
156+#define GFX_HW_STRETCH_BLIT_MASKED 0x01000000
157
158
159 AL_VAR(int, gfx_capabilities); /* current driver capabilities */

With it, the test programme correctly reports all stretch_blit related operations as being hardware accelerated. Modifying exscale to use a video bitmap (be sure to allocate a dummy one the size of the screen first) also seems to work fine.
Curiously enough, it appears to be slower on my system than if I do a mem->vram blit, except if I remove the vsync() call. Perhaps that's normal, but it's not what I was expecting. shrugs
\begin[off-topic]{rant}
How do you Windows people manage, though? I can't believe how unresponsive and klunky the interface feels and how badly the terminal works. That and not being able to trace with printf() is a real pain too. Man, am I glad I never have to use that system for anything serious...
\end{rant} ;)

Thomas Harte
Member #33
April 2000
avatar

Can anyone confirm or deny that ddraw_do_stretch_blit obeys set_clip_rect? I can't think how it does and I'm particularly concerned that if DDCAPS_CANCLIPSTRETCHED is not set then some sort of memory overflow may occur. I have no idea what that would do in global terms but I'd imagine at least graphics corruption.

Quote:

How do you Windows people manage, though? I can't believe how unresponsive and klunky the interface feels and how badly the terminal works. That and not being able to trace with printf() is a real pain too. Man, am I glad I never have to use that system for anything serious...

Yes, I'm having a few issues with it. I'd definitely either GNUstep or ROX Desktop/Zero Install if I left the Mac world. Anyway can anyone recommend a Windows/GCC setup that includes a graphical debugger that could be used to trace into a (suitably built) version of the Allegro DLL?

Neil Walker
Member #210
April 2000
avatar

I've recompiled and done a few tests (not exhaustive, I'll do the grid later), however here are my findings with the new code posted above:

Things that work:
1. test.exe now works and shows the correct hardware acceleration flags
2. stretching of video/system bitmaps now shows the correct image rather than either nothing (for standard bitmaps) or simply resizing the bitmap (for sub-bitmaps)

So that's good.

However, the things that don't work:

1. When you are drawing stretched video/system bitmaps onto a memory buffer it still crashes
2. When you are drawing stretched single bitmaps (rather than sub-bitmaps) AND both your buffer and graphic are video (any other combination is ok, including system) it leaves a 1 pixel magenta (i.e. the mask colour) around the outline of the graphic (i.e. around the outermost pixels, not the rectangular border).

My only thought on (2) is it might be a bug in the dd function, e.g. stretching first and anti-aliasing the magenta edge? but then sub-bitmaps work ok.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

1. When you are drawing stretched video/system bitmaps onto a memory buffer it still crashes

I figured the other day that it might. I don't think there's a special check for that in the code. The fix is probably to only call the HW-accelerated version if the target is a video/system bitmap.
I'm curious now: does a normal blit from video->mem work if vid->vid is hardware accelerated or does that also crash?

Neil Walker
Member #210
April 2000
avatar

Quote:

I figured the other day that it might.

Maybe if you know the area of fault this might fix the problem of it crashing when destroying system bitmaps?

Quote:

does a normal blit from video->mem work if vid->vid is hardware accelerated or does that also crash

From memory all other permutations work, only vid->vid failed, but I'll check when I start up my laptop tonight as that's got the code on it, and do another grid.

I checked google for bugs on directdraw functions and blitting (for the magenta halo on stretching) but the only thing returned was Allegro.cc forum entries! I guess we must be the only people in the world still using DX3 ;)

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Thomas Harte
Member #33
April 2000
avatar

Quote:

My only thought on (2) is it might be a bug in the dd function, e.g. stretching first and anti-aliasing the magenta edge? but then sub-bitmaps work ok.

Without really being able to explain the sub-bitmap thing, I guess a relevant question is whether you see a "colour 0" border in 8bpp mode? Does generating a sub-bitmap that is actually exactly the same proportions as a parent bitmap fix the problem?

EDIT: Hmmm, it seems others have had the same problem and not found a solution. Do you see the main body of your sprite being filtered? I guess we need to play about with a DDBLTFX structure - in particular it seems to have stuff like dwAlphaEdgeBlend, although not particularly clear from a brief reading. It also allows flipped and mirrored blits, so things like draw_sprite_v_flip (or whatever Allegro calls it) could be accelerated if they aren't already (?)

Evert
Member #794
November 2000
avatar

Quote:

Maybe if you know the area of fault this might fix the problem of it crashing when destroying system bitmaps?

Eh? I don't see what the one has to do with the other, to be honest!
The reason I thought it might crash is this: the stretch_blit (et al) code checks if the source bitmap says it can be hardware accelerated and if it can be it calls the function, from allegro/src/c/cstretch.c:

   /* vtable hook */   
   if (src->vtable->do_stretch_blit) {
      src->vtable->do_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, masked);
      return;
   }

while ddraw_do_stretch_blit does not check what sort of bitmap the destination is. Which I figured might be a problem if it's not a video or system bitmap, since that's what it's supposed to work with.

So the questions I'd like to know the answer to (just yes or no) are:
1) Does normal blit frim vid->mem work, even if vid->vid is accelared? (Asking because the code should be similar)
2) Does the old non-accelerated stretch_blit work properly if you go from vid->mem? (Asking because it immediately highlights the problem and suggests a way to fix it)

Quote:

It also allows flipped and mirrored blits, so things like draw_sprite_v_flip (or whatever Allegro calls it) could be accelerated if they aren't already (?)

I don't think they are. If there's no function that does that in src/win/wddaccel.c then it isn't. If you need the vtable function name and prototype and haven't found where they're declared yet, they're in allegro/include/allegro/gfx.h in the GFX_VTABLE struct. If you want to take a shot at doing this, let me know. The plan is to release 4.2.1 soonish but I think we can puch it back a little for something like this.

Neil Walker
Member #210
April 2000
avatar

Gamasutra has this to say about this about stretching/mirroring/shrinking, 'These features, however, are often driver-dependent and are supported to different extents on different video hardware, providing inconsistent results if used.'

Perhaps to make it consistent in the case of vid->vid then do a fallback to the _orig_stretch_blit(...), e.g. in ddraw_do_stretch_blit():

   if ( ( (masked && (gfx_capabilities & GFX_HW_STRETCH_BLIT_MASKED)) ||
  (!masked && (gfx_capabilities & GFX_HW_STRETCH_BLIT)) 
) && ( (is_video_bitmap(source) && !is_video_bitmap(dest)) || is_system_bitmap(source) ) 
                                  ********************

If you look at the attached image you'll see it doing what we thought. It seems to be stretching then removing the mask, leaving an anti-aliased artifact.

Back to the tests, I've tested all the things as above and updated the table.

A. draw buffer is memory. graphics are memory (normal, not sub-bitmap)
B. draw buffer is memory. graphics are system (normal, not sub-bitmap)
C. draw buffer is memory. graphics are video (normal, not sub-bitmap)
D. draw buffer is system. graphics are memory (normal, not sub-bitmap)
E. draw buffer is system. graphics are system (normal, not sub-bitmap)
F. draw buffer is system. graphics are video (normal, not sub-bitmap)
G. draw buffer is video. graphics are memory (normal, not sub-bitmap)
H. draw buffer is video. graphics are system (normal, not sub-bitmap)
I. draw buffer is video. graphics are video (normal, not sub-bitmap)

1test stretch
2A Y
3B N1
4C N1
5D Y
6E Y
7F Y
8G Y
9H Y
10I N3
11 
12N1: crash on calling function
13N2: crash on destroying bitmap/subbitmap
14N3: 'single pixel halo'
15 
16with subbitmaps are the same as above, except:
17test stretch
18H N2

So it looks like things are almost there with the only fault now being drawing system/video bitmaps onto memory bitmaps. The other two faults are on destroying sub-bitmaps that are system bitmaps (but that isn't a stretch fault) and the odd halo fault that might be a ddraw bug.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Ok, so vid->mem stretch blits crash with the hardware accelerated code. Does it work without (ie, did it work properly with the software stretcher)?
Did you test regular blits?

Quote:

!is_video_bitmap(dest)

Shouldn't that lose the `!'?
You want to use that function if both source and dest are video surfaces (or possibly system bitmaps) and fall back on the original if they are not.

Neil Walker
Member #210
April 2000
avatar

to answer the questions:

Quote:

Shouldn't that lose the `!'?

No, that bit of code was to avoid vid->vid which is the only one which seems to be a ddraw bug and not a coding problem, so cannot be fixed, or made to work consistently in Windows. this isn't a big thing as it's currently software only anyway.

The software stretcher works fine (i.e. using the unchanged code).

Standard blits are fine, it is just any of the stretch functions.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

No, that bit of code was to avoid vid->vid which is the only one which seems to be a ddraw bug and not a coding problem, so cannot be fixed, or made to work consistently in Windows. this isn't a big thing as it's currently software only anyway.

Well, I'd prefer being able to detect it (somehow) and not report the accelerated blit as being possible, or work around it. What the code does with your change is always fall back on software stretching despite claiming that vid->vid is accelerated. This is worse than it is now.

Quote:

The software stretcher works fine (i.e. using the unchanged code).

Ok, so we can check if the destination bitmap is a video bitmap and use the software stretcher in that case?

Quote:

Standard blits are fine, it is just any of the stretch functions.

Ok, in that case I'll have a look at how standard blits deal with vid->mem blits. I'm assuming they do something special if the accelerated vid->mem stretch_blit crashes.

Neil Walker
Member #210
April 2000
avatar

As far as I can see there is hardly any difference between ddraw_masked_blit() and ddraw_do_stretch_blit(), nothing worth noting anyway. In order to state the obvious I debugged the stretch_blit at the point of crash and it fails on the draw:

hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
(masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL);

I can only summise that it must be a bug inside the _Blt function or perhaps my video card has a fault? If someone offers (they haven't the past few times I did) I'll post the exe for them to test.

Neil.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Thomas Harte
Member #33
April 2000
avatar

Quote:

I can only summise that it must be a bug inside the _Blt function or perhaps my video card has a fault?

There's the outside possibility of an issue with clipping, that I vaguely alluded to before. Did you make a note either of the values of dest_rect and source_rect or of the parameters you passed to stretch_blit to make it crash?

Quote:

If someone offers (they haven't the past few times I did) I'll post the exe for them to test.

You might as well post - I might get a go on a Windows machine later.

Neil Walker
Member #210
April 2000
avatar

I didn't check the data in the function (I'll do it tonight and update the post when done - I don't have a JIT debugger on this build) but for my source image I tried both 24x24 and 32x32, and tried doubling the size and keeping the same size.

So thinking about it, there is no difference between the standard masked_blit call and the stretched_mask_blit when your destination size is the same as the source as they both call the same IDirectDrawSurface2_Blt with the same parameters, don't they?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

As far as I can see there is hardly any difference between ddraw_masked_blit() and ddraw_do_stretch_blit(), nothing worth noting anyway. In order to state the obvious I debugged the stretch_blit at the point of crash and it fails on the draw:

hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(dest_parent)->id, &dest_rect,
DDRAW_SURFACE_OF(source_parent)->id, &source_rect,
(masked ? DDBLT_KEYSRC : 0) | DDBLT_WAIT, NULL);

I can only summise that it must be a bug inside the _Blt function or perhaps my video card has a fault?

Not nescessarily. To the best of my knowledge normal Allegro memory bitmaps don't have a DirectX drawing surface associated with them, so based on that idea (which I don't actually know if it's accurate or not) I would expect that code to crash if given a memory bitmap. I should have taken a little more time to explain what I was thinking when I asked if normal blits work.

The ddraw_stretch_blit and ddraw_blit functions are virtually identical, which suggests that the problem is not in there, but in blit() or stretch_blit() itself. What I was thinking is that maybe blit() checks if the destination surface is also a video bitmap before calling the hardware accelerated function. I know stretch_blit() does no such test and if that's the difference it can account for the one crashing and the other not.
Checking if this is really the difference is something I could do fairly quickly later on just by having a look at the source for blit().

Neil Walker
Member #210
April 2000
avatar

In blit.c in the src directory blit() does this:

      /* drawing onto memory bitmaps */
      if ((is_video_bitmap(src)) || (is_system_bitmap(src)))
         src->vtable->blit_to_memory(src, dest, s_x, s_y, d_x, d_y, w, h);
      else
         dest->vtable->blit_to_self(src, dest, s_x, s_y, d_x, d_y, w, h);

This is the code for blitting video/system onto memory, which is as you say, checks what to do, which I guess is why standard blit works.

I got a bit confused as to stretch_blit as the only obvious place was cstretch.c in src\c and istretch.c in the i386 directory. I don't know which is being called.

However, in istretch.c it does say that the code is a bit dodgy, but it does no checks on bitmap type, however if source->vtable->do_stretch_blit is set then it just calls do_stretch_blit() which doesn't have any checks either on whether the source/dest are video->memory.

In cstretch.c it does:

   #ifdef ALLEGRO_MPW
      if (is_system_bitmap(src) && is_system_bitmap(dst))
         system_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh);
      else
   #endif
         _al_stretch_blit(src, dst, sx, sy, sw, sh, dx, dy, dw, dh, 0);

I don't know what ALLEGRO_MPW is or whether either function does dst bitmap type checks.

Guessing I say it is calling the function in istretch.c because the vtable function is getting called and that does no checks?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Peter Hull
Member #1,136
March 2001

MPW is Macintosh Programmer's Workshop - it was Apple's IDE for development on Mac OS 'classic' i.e. version 9 and earlier. There was a partial Mac port but IIRC it was never complete. Any MPW code is obsolete now, of course.

Pete

Neil Walker
Member #210
April 2000
avatar

In that case, the function in istretch.c must be the fault like Evert said. I'll give the code a tweak tonight (unless Evert beats me to it) and see if it works.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

I got a bit confused as to stretch_blit as the only obvious place was cstretch.c in src\c and istretch.c in the i386 directory. I don't know which is being called.

It depends: the code on src/c is compiled if Allegro is compiled without ASM code (it's the code that's always used when not using an i386 or compatible computer), the code in src/i386 is used when Allegro is compiled with assmebler code. The stretch_blit code is a bit of self-modifying code, which is sortof neat but also quite evil.
Both need to be fixed, but see below.

Quote:

however if source->vtable->do_stretch_blit is set then it just calls do_stretch_blit()

Yes. Actually, when I think about it this is the proper way to do it: this bitmap type (each bitmap type, memory, system and video, has its own vtable) has a dedicated special-purpose function that knows how to do stretch_blit better than the general purpose code. I feel that stretch_blit() itself should not try to guess when the vtable function should or should not be used. Instead, the vtable function should fall back on the software blitter in case it decides that it cannot use hardware acceleration. In this sense, I think blit() is at fault from an object-oriented point of view, but we'll leave it as is for 4.2.
So I think the proper fix would be to add

if (is_memory_bitmap(dest)) {
   _orig_stretch_blit(source, dest, source_x, source_y, source_width, source_height, dest_x, dest_y, dest_width, dest_height, masked);
   return;
}

to ddraw_do_stretch_blit before the first check.
Alternatively, only call the vtable function when dest is not a memory bitmap, but as I said, I think the check should be in the special-purpose function.

Quote:

Any MPW code is obsolete now, of course.

Yeah, we should probably remove it as we go. I don't think it ever actually worked anyway.

Neil Walker
Member #210
April 2000
avatar

It still crashes. Even if I put the _orig function at the top of the do_stretch function and call it regardless. I can't really follow all the vtable stuff so I guess something is going wrong somewhere as it works with the non-accelerated code changes. I put the change in ddraw_do_stretch_blit.

btw, it isn't exactly a huge speed increase, but at the top of most of the ddraw blit functions there are about 10 lines of calculations for dest_rect and source_rect and src_key. They are only used when the acceleration check is made, so I guess it would make sense to move them into the statement to gain a teeny weeny increase in speed. I tried it and it works fine.

Is it possible to make unaccelerated calls to the blit, etc. functions when code would normally route it to the accelerated functions? is it just a matter of changing the gfx flag at runtime to disable the feature, or is this a bad thing to do?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Evert
Member #794
November 2000
avatar

Quote:

It still crashes. Even if I put the _orig function at the top of the do_stretch function and call it regardless.

That doesn't make sense if the original version worked. Does it also crash if you remove the vtable check and call?

Quote:

I can't really follow all the vtable stuff

The DirectX driver sets the vtable entry for do_stretch_blit() in the video-bitmap vtable to the DirectX hardware accelerated version.
When stretch_blit is called, it checks if the source bitmap vtable has an entry for do_stretch_blit() and if it does it calls it and returns, otherwise it calls the general-purpose software blitter.

Quote:

I put the change in ddraw_do_stretch_blit.

That would be correct.

Quote:

btw, it isn't exactly a huge speed increase,

Have you disabled vsync?

Quote:

but at the top of most of the ddraw blit functions there are about 10 lines of calculations for dest_rect and source_rect and src_key. They are only used when the acceleration check is made, so I guess it would make sense to move them into the statement to gain a teeny weeny increase in speed.

If you're right it does make sense, but not because of speed gain. I would be highly surprised if that were measurable.

Quote:

Is it possible to make unaccelerated calls to the blit, etc. functions when code would normally route it to the accelerated functions?

Not cleanly, no (hackishly, you can change the vtable manually in user code). You can switch to a non-hardware accelerated driver (the DX soft one; it's the same as the regular DX driver except that it doesn't activate any of the accelerated features).

Quote:

is it just a matter of changing the gfx flag at runtime to disable the feature, or is this a bad thing to do?

You cannot change the flag. The gfx_capabilities are logically read only and should never be changed from user code.
In general, it wouldn't have any effect anyway (the functions should only be called if the flag is set, otherwise it's a bug in Allegro). For do_stretch_blit() I believe the flags are checked, but that is certainly not the general case.

Neil Walker
Member #210
April 2000
avatar

Well, that's what happened. I put the _orig as the first line of code in the function and it crashed. To make sure I was using the right file and the right thing was being called, I simply put in a return as the first statement and it worked (i.e. nothing was displayed). Anyway, I'll recompile with debug and see where it falls over.

Quote:

I would be highly surprised if that were measurable.

A little bit here, a little bit there :) I guess if you call the function 60 times a second for each of 300 sprites on your screen, those 10 lines of additions might add up to a tiny saving?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie



Go to: