d3d_disp->render_target is NULL, segfault
Edgar Reynaldo

Edit
I should note, I am using the DIRECT3D driver and MinGW 4.8.1 on Windows 10. When I use the OPENGL driver, it does not crash. This is with Allegro 5.1.13.

Hello all,

I am trying to resize an allegro window. When I get the RESIZE event I call al_acknowledge_resize, and then I recreate the ALLEGRO_BITMAP* buffer I am using. However when I then go to flip the display after drawing draw my buffer to the screen, it segaults in al_draw_scaled_bitmap. Here is the backtrace :

#SelectExpand
1 2c:\ctwoplus\progcode\allegro5\Spiraloid2>gdb Spiraloid2debug.exe 3GNU gdb (GDB) 7.6.1 4Copyright (C) 2013 Free Software Foundation, Inc. 5License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 6This is free software: you are free to change and redistribute it. 7There is NO WARRANTY, to the extent permitted by law. Type "show copying" 8and "show warranty" for details. 9This GDB was configured as "mingw32". 10For bug reporting instructions, please see: 11<http://www.gnu.org/software/gdb/bugs/>... 12Reading symbols from c:\ctwoplus\progcode\allegro5\Spiraloid2\Spiraloid2debug.exe...done. 13(gdb) run 14Starting program: c:\ctwoplus\progcode\allegro5\Spiraloid2/Spiraloid2debug.exe 15[New Thread 1816.0x16a4] 16[New Thread 1816.0x584] 17[New Thread 1816.0x3f0] 18[New Thread 1816.0x3a00] 19[New Thread 1816.0x227c] 20[New Thread 1816.0x35e4] 21[New Thread 1816.0x35e8] 22[New Thread 1816.0x3884] 23Recreating buffer. 24[New Thread 1816.0x123c] 25[New Thread 1816.0x1628] 26[New Thread 1816.0x3644] 27Spiraloid::SetSpiraloidTransform() : cx,cy,sx,sy = 400.00000000 , 300.00000000 , 1.00000000 , 1.00000000 28[New Thread 1816.0x33f4] 29[New Thread 1816.0x11c8] 30ALLEGRO_EVENT_DISPLAY_RESIZE received. 31Recreating buffer. 32Spiraloid::SetSpiraloidTransform() : cx,cy,sx,sy = 466.00000000 , 324.00000000 , 1.00000000 , 1.00000000 33 34Program received signal SIGSEGV, Segmentation fault. 350x677aa8e3 in d3d_lock_region (bitmap=0xff5f28, x=0, y=0, w=933, h=649, format=0, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\win\d3d_bmp.cpp:854 36854 if (d3d_disp->render_target->LockRect(&d3d_bmp->locked_rect, &rect, Flags) != D3D_OK) { 37(gdb) p d3d_disp 38$1 = (ALLEGRO_DISPLAY_D3D *) 0xff5cc8 39(gdb) p d3d_disp->render_target 40$2 = (LPDIRECT3DSURFACE9) 0x0 41(gdb) bt 42#0 0x677aa8e3 in d3d_lock_region (bitmap=0xff5f28, x=0, y=0, w=933, h=649, format=0, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\win\d3d_bmp.cpp:854 43#1 0x67704968 in al_lock_bitmap_region (bitmap=0xff5f28, x=0, y=0, width=933, height=649, format=0, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\bitmap_lock.c:108 44#2 0x6778e64f in _al_draw_soft_triangle (v1=0x64edfc, v2=0x64ee20, v3=0x64ee44, state=6614160, init=0x677396f8 <shader_texture_solid_any_init>, first=0x677399bc <shader_texture_solid_any_first>, 45 step=0x67739a8e <shader_texture_solid_any_step>, draw=0x677605b0 <shader_texture_solid_any_draw_shade_white>) at C:\mingw\LIBS\A5113release\allegro\src\tri_soft.c:836 46#3 0x6778e015 in _al_triangle_2d (texture=0xff9420, v1=0x64edfc, v2=0x64ee20, v3=0x64ee44) at C:\mingw\LIBS\A5113release\allegro\src\tri_soft.c:733 47#4 0x6772e539 in _al_draw_transformed_bitmap_memory (src=0xff9420, tint=..., sx=0, sy=0, sw=933, sh=649, dw=933, dh=649, local_trans=0x64ef20, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\memblit.c:240 48#5 0x6772e648 in _al_draw_transformed_scaled_bitmap_memory (src=0xff9420, tint=..., sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, dw=933, dh=649, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\memblit.c:257 49#6 0x6772dfdd in _al_draw_bitmap_region_memory (src=0xff9420, tint=..., sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\memblit.c:158 50#7 0x677030d8 in _bitmap_drawer (bitmap=0xff9420, tint=..., sx=0, sy=0, sw=933, sh=649, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\bitmap_draw.c:51 51#8 0x67703479 in _draw_tinted_rotated_scaled_bitmap_region (bitmap=0xff9420, tint=..., cx=0, cy=0, angle=0, xscale=1, yscale=1, sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, flags=0) 52 at C:\mingw\LIBS\A5113release\allegro\src\bitmap_draw.c:118 53#9 0x67703727 in al_draw_tinted_scaled_bitmap (bitmap=0xff9420, tint=..., sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, dw=933, dh=649, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\bitmap_draw.c:171 54#10 0x6770379d in al_draw_scaled_bitmap (bitmap=0xff9420, sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, dw=933, dh=649, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\bitmap_draw.c:184 55#11 0x00401bc6 in Display::Flip (this=0x64f9e8) at C:\ctwoplus\progcode\allegro5\Spiraloid2\Display.cpp:132 56#12 0x0040222f in main (argc=1, argv=0xff3530) at C:\ctwoplus\progcode\allegro5\Spiraloid2\SpiraloidMain.cpp:100 57(gdb) frame 10 58#10 0x6770379d in al_draw_scaled_bitmap (bitmap=0xff9420, sx=0, sy=0, sw=933, sh=649, dx=0, dy=0, dw=933, dh=649, flags=0) at C:\mingw\LIBS\A5113release\allegro\src\bitmap_draw.c:184 59184 al_draw_tinted_scaled_bitmap(bitmap, solid_white, sx, sy, sw, sh, 60(gdb) p *bitmap 61$3 = {vt = 0x0, _format = 9, _flags = 4097, _display = 0x0, _memory_format = 0, w = 933, h = 649, pitch = 3732, cl = 0, cr_excl = 933, ct = 0, cb_excl = 649, locked = true, lock_x = 0, lock_y = 0, 62 lock_w = 933, lock_h = 649, lock_data = 0x93e4020, lock_flags = 1, locked_region = {data = 0x93e4020, format = 9, pitch = 3732, pixel_size = 4}, transform = {m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, { 63 0, 0, 0, 1}}}, inverse_transform = {m = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}}, inverse_transform_dirty = false, proj_transform = {m = {{0.00214362261, 0, 0, 0}, {0, 64 -0.00308166421, 0, 0}, {0, 0, 1, 0}, {-1, 1, 0, 1}}}, shader = 0x0, parent = 0x0, xofs = 0, yofs = 0, memory = 0x93e4020 "", extra = 0x0, dirty = true} 65(gdb)

So the _display of the bitmap I am drawing is NULL, and the render_target member of the d3d_disp is NULL as well.

Any ideas what I am doing wrong? When I recreate the buffer I set the target backbuffer to the display to make sure the buffer will be associated with the display. I can show code, but I'm not sure what to show.

Here is what I am using

      if (redraw) {
         
         display.DrawToBuffer();
         if (clear_buffer || temp_clear) {
            al_clear_to_color(al_map_rgb(0,0,0));
            temp_clear = false;
         }
         spiraloid.Draw();
         display.Flip();
         
         redraw = false;
      }

         if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE) {
            printf("ALLEGRO_EVENT_DISPLAY_RESIZE received.\n");
            display.AcknowledgeResize();
            spiraloid.SetSpiraloidTransform(display.CX() , display.CY() , display.SX() , display.SY());
            redraw = true;
         }

void Display::AcknowledgeResize() {
   al_acknowledge_resize(display);
   
   if (!fs) {
      ww = al_get_display_width(display);
      wh = al_get_display_height(display);
      CreateBuffer(ww,wh);
   }
}

#SelectExpand
1bool Display::CreateBuffer(int bwidth , int bheight) { 2 if (bwidth != bw || bheight != bh) { 3 printf("Recreating buffer.\n"); 4 DestroyBuffer(); 5 bw = bwidth; 6 bh = bheight; 7 centerx = bw/2; 8 centery = bh/2; 9 scalex = (double)(fs?fsw:ww)/bw; 10 scaley = (double)(fs?fsh:wh)/bh; 11 /// al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); 12 al_set_target_backbuffer(display); 13 buffer = al_create_bitmap(bw,bh); 14 } 15 DrawToBuffer(); 16 return buffer; 17 18}

SiegeLord

There's a bug with resizing inside the Direct3D driver, see https://github.com/liballeg/allegro5/issues/565 for a bit of a discussion. Try sticking a little rest before creating the buffer or adding a `al_convert_bitmaps` call before you draw. I forget what the workaround is...

Edgar Reynaldo

Is there any way I can help debug this?

I noticed that the _display member of my bitmap is NULL. I tested this with your test program, and used al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); and creation of video bitmaps after resizing the display fails.

Edit
One other thing I noticed is that it is failing to release the video textures.

d3d      W C:\mingw\LIBS\A5113release\allegro\src\win\d3d_disp.cpp:2423 _al_d3d_destroy_bitmap           [   0.36914] d3d_destroy_bitmap: Release video texture failed.
d3d      W C:\mingw\LIBS\A5113release\allegro\src\win\d3d_disp.cpp:2434 _al_d3d_destroy_bitmap           [   0.36920] d3d_destroy_bitmap: Release render target failed.
display  I C:\mingw\LIBS\A5113release\allegro\src\display.c:240  al_resize_display                [   0.36922] Requested display resize 600x400

SiegeLord

Yep, all that information is in that bug report. The current best guess is that those failing releases are causing the device to not be reset properly, and while it is in that non-reset state, all video bitmaps will fail to create (and fall back to memory bitmaps).

Edgar Reynaldo

I haven't had the chance to fully read this yet, but here is some interesting reading on D3D resources and resetting devices.

https://msdn.microsoft.com/en-us/library/windows/desktop/bb174714%28v=vs.85%29.aspx

Quote:

All video memory must be released before a device can be reset from a lost state to an operational state.

So that failure to release the video texture is preventing us from resetting the D3D device.

RPG Hacker

Yipes. That's just one of the reasons D3D9 really blows. From what I know, later D3D versions to have this problem anymore. So... anyone in for an Allegro 6? ;D

Edgar Reynaldo

From d3d_destroy_bitmap :

#SelectExpand
1 if (d3d_bmp->video_texture) { 2 if (d3d_bmp->video_texture->Release() != 0) { 3 ALLEGRO_WARN("d3d_destroy_bitmap: Release video texture failed.\n"); 4 } 5 } 6 if (d3d_bmp->system_texture) { 7 if (d3d_bmp->system_texture->Release() != 0) { 8 ALLEGRO_WARN("d3d_destroy_bitmap: Release system texture failed.\n"); 9 } 10 } 11 12 if (d3d_bmp->render_target) { 13 if (d3d_bmp->render_target->Release() != 0) { 14 ALLEGRO_WARN("d3d_destroy_bitmap: Release render target failed.\n"); 15 } 16 }

IUnknown::Release() only returns 0 when all references to the interface are released. So there's extra references floating around out there somewhere that haven't been released yet.

SiegeLord

Should be fixed on master now.

Edgar Reynaldo

I'm on origin - should I change that?

Also, where was the leak?

SiegeLord

It happened whenever you set the target bitmap. Here's the commit that fixed it: linky. Good thing I'm not paid by lines of code :P.

'origin' is just what the git remote is called. 'master' is the branch. Just do a git fetch origin and then git checkout master and that should get you where you want to be.

EDIT:

From what I know, later D3D versions to have this problem anymore. So... anyone in for an Allegro 6? ;D

Forgot to reply to this... there's no technical reason why you couldn't add a DX1x backend to Allegro 5.x even now.

RPG Hacker

True, up to D3D11 should be no problem. Going up to D3D12 might be a different story, since it works fundamentally differnt and you'd want to make best use of it. Then again, I don't know if Allegro would really profit much from that in the first place. Most of the time, it's used for simple 2D games, which work perfectly fine in older versions of D3D and Open GL, anyways.

Edgar Reynaldo

Well that fixed it! I can resize perfectly with the D3D driver and 5.2.0 now! Minimize, maximize, and restore work too, but strangely they are not available when I right click on the taskbar icon (Windows 10). It still stretches the screen until you let go, which is kind of ugly though. I wish I could keep redrawing in the meantime.

If there were a function to filter events out of the queue, that would be perfect. That way every time you get a resize event you could just collect them all at once. I've done that kind of thing before, and there are usually only 3-5 events piled up in the queue at a time.

GullRaDriel

I had a crash like Edgar, but I just switched to OpenGL to get it working.
I may try with the patch and revert to original settings and see if I have the crash.

Thread #616195. Printed from Allegro.cc