Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » ddraw_clear_to_color ignores alpha value

Credits go to Trent Gamblin for helping out!
This thread is locked; no one can reply to it. rss feed Print
ddraw_clear_to_color ignores alpha value
Edgar Reynaldo
Major Reynaldo
May 2007
avatar

For a 32 bit video bitmap clear_to_color calls the bitmaps's vtable entry for clear_to_color, and in Windows that calls ddraw_clear_to_color (which uses IDirectDrawSurface2_Blt).

I noticed that ddraw_clear_to_color ignores alpha values when I tried to use set_alpha_blender and draw_trans_sprite to draw from a video bitmap I had cleared to makeacol(255,0,0,127). Instead of drawing red at half opacity it drew nothing. From examining the bitmap through gdb I could see that the pixels of the video bitmap I had cleared had the ARGB value 00ff0000, which is incorrect, but it explains why nothing was drawn because the A value is 0.

Granted, I realize that reading from a video bitmap is slow and is not what you want to do, but I want my code to work correctly no matter what kind of bitmaps I am using.

Would it be alright if I modified ddraw_clear_to_color to use alpha values when they are present, and to use its current code when they are not? Ie. Would you guys accept a patch for this? I don't know DX7, so I don't know if there is a replacement for IDirectDrawSurface2_Blt that does not ignore alpha values.

Append
If there is a DirectX(1-3) function that preserves alpha, I can't find one anywhere on the web, much less anything that references anything less than DirectX 7.

So how about an alternative function to call from ddraw_clear_to_color when the bitmap is 32 bit and there is an alpha value present, say like this one :

#SelectExpand
1void clear_to_color_soft32(BITMAP* bmp , int color) { 2 if (is_memory_bitmap(bmp)) { 3 for (int y = bmp->ct ; y < bmp->cb ; ++y) { 4 int* data = (int*)(bmp->line[y]); 5 for (int x = bmp->cl ; x < bmp->cr ; ++x) { 6 data[x] = color; 7 ++data; 8 } 9 } 10 } 11 else { 12 bmp_select(bmp); 13 bmp_write_line(bmp , 0);// in case all is clipped, then this will match up 14 // with the bmp_unwrite_line below 15 for (int y = bmp->ct ; y < bmp->cb ; ++y) { 16 unsigned long data = bmp_write_line(bmp , y); 17 for (int x = bmp->cl ; x < bmp->cr ; ++x) { 18 bmp_write32(data , color); 19 data += 4; 20 } 21 } 22 bmp_unwrite_line(bmp); 23 } 24}

Then in ddraw_clear_to_color, it could be :

#SelectExpand
1/* ddraw_clear_to_color: 2 * Accelerated screen clear routine. 3 */ 4static void ddraw_clear_to_color(BITMAP * bitmap, int color) 5{ 6 RECT dest_rect; 7 HRESULT hr; 8 DDBLTFX blt_fx; 9 BITMAP *parent; 10 11 /* Added code here */ 12 if (bitmap_color_depth(bitmap) == 32 && geta32(color)) { 13 clear_to_color_soft32(bitmap , color);// preserves alpha value of color 14 return; 15 } 16 /* End of added code */ 17 18 dest_rect.left = bitmap->cl + bitmap->x_ofs; 19 dest_rect.top = bitmap->ct + bitmap->y_ofs; 20 dest_rect.right = bitmap->x_ofs + bitmap->cr; 21 dest_rect.bottom = bitmap->y_ofs + bitmap->cb; 22 23 /* find parent */ 24 parent = bitmap; 25 while (parent->id & BMP_ID_SUB) 26 parent = (BITMAP *)parent->extra; 27 28 /* set fill color */ 29 blt_fx.dwSize = sizeof(blt_fx); 30 blt_fx.dwDDFX = 0; 31 blt_fx.dwFillColor = color; 32 33 _enter_gfx_critical(); 34 gfx_directx_release_lock(bitmap); 35 36 hr = IDirectDrawSurface2_Blt(DDRAW_SURFACE_OF(parent)->id, &dest_rect, 37 NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &blt_fx); 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) && (parent == gfx_directx_forefront_bitmap)) 45 win_gfx_driver->paint(&dest_rect); 46}

What do you think? I'm not sure what file clear_to_color32 should go in though.

Append
Does anyone have an opinion on this?

Append 2
Since I haven't gotten any replies to this at all, I guess I will take it to the [AD] mailing list.

Trent Gamblin
Member #261
April 2000
avatar

Have you tried this code? Even many moderns cards don't support alpha in the backbuffer. Since you're just writing bits there ddraw may ignore them but I'm wondering if there would be any ill effects?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Have you tried this code?

Now that you have asked, I did some testing. The alpha value is totally ignored by the GFX_DIRECTX_ACCEL, GFX_DIRECTX_WIN, and GFX_DIRECTX_SOFT graphics drivers on Windows. blit worked fine with system, video, and the screen bitmaps using my clear_to_color_soft32 function and all values of makeacol(,,,).

Trent Gamblin said:

I'm wondering if there would be any ill effects?

Well, I haven't seen any so far. Can you think of anything else I should test?

Edit
The more I think about this, the more it seems like a bad hack, and not something Allegro should do. The only reason to give alpha to a system or video bitmap is to draw it translucently, and since doing that will always be slow it seems like it would encourage bad behaviour.

So I guess forget about it. Thanks for your input Trent.

Go to: