p96LockBitMap freezes the system

6 posts / 0 new
Last post
walkero
walkero's picture
Offline
Last seen: 4 months 3 weeks ago
Joined: 2009-05-03 16:54
p96LockBitMap freezes the system

Hello to all.
I am trying to make Comicami work under AmigaOS 4.1upd6. I use th P96 library for the manipulation of the images, but I stuck at the IP96->p96LockBitMap, which crashes and lock my system. If I remark this function and a few of the rest that use the lock, then the program doesn't crash at all, no matter how many times I load it. Does anyone have a clue on what is going on?

Below is the function that uses it.

  1. struct BitMap *P96_readimage_using_datatype(STRPTR fname, uint32 *Width, uint32 *Height)
  2. {
  3. Object *dt_Obj;
  4.  
  5.  
  6. dt_Obj = IDataTypes->NewDTObject(fname,
  7. DTA_GroupID, GID_PICTURE,
  8. PDTA_ModeID, PMODE_V43,
  9. TAG_DONE);
  10. if(dt_Obj != NULL)
  11. {
  12. struct BitMapHeader *bmhd = NULL;
  13.  
  14. IDataTypes->GetDTAttrs(dt_Obj,
  15. PDTA_BitMapHeader, &bmhd,
  16. TAG_DONE);
  17.  
  18. if(bmhd != NULL)
  19. {
  20. struct BitMap *bitmapsrc;
  21.  
  22. IDOS->Printf("BMHD width: %ld, height: %ld \n", bmhd->bmh_Width, bmhd->bmh_Height);
  23. bitmapsrc = IP96->p96AllocBitMap( bmhd->bmh_Width, bmhd->bmh_Height, 32, 0, NULL, RGBFB_A8R8G8B8 );
  24.  
  25. if(bitmapsrc != NULL)
  26. {
  27. LONG P96_imglock;
  28. struct RenderInfo RenderInfoBuffer;
  29. struct pdtBlitPixelArray pbpa;
  30.  
  31. IDOS->Printf("bitmapsrc loaded sucessfully \n");
  32. IDOS->Printf("P96 Bitmap Lock\n");
  33.  
  34. P96_imglock = IP96->p96LockBitMap( bitmapsrc, (APTR)&RenderInfoBuffer, sizeof(RenderInfoBuffer) );
  35.  
  36. IDOS->Printf("Bitmap Lock worked\n");
  37.  
  38. pbpa.MethodID = PDTM_READPIXELARRAY;
  39. pbpa.pbpa_PixelData = RenderInfoBuffer.Memory;
  40. pbpa.pbpa_PixelFormat = PBPAFMT_ARGB;
  41. pbpa.pbpa_PixelArrayMod = RenderInfoBuffer.BytesPerRow, //bmhd->bmh_Width*4;
  42. pbpa.pbpa_Left = 0;
  43. pbpa.pbpa_Top = 0;
  44. pbpa.pbpa_Width = bmhd->bmh_Width;
  45. pbpa.pbpa_Height = bmhd->bmh_Height;
  46.  
  47. IIntuition->IDoMethodA( dt_Obj, (APTR)&pbpa );
  48.  
  49. IP96->p96UnlockBitMap( bitmapsrc, P96_imglock );
  50.  
  51.  
  52. IDataTypes->DisposeDTObject(dt_Obj);
  53.  
  54. *Width = bmhd->bmh_Width;
  55. *Height = bmhd->bmh_Height;
  56.  
  57. return bitmapsrc;
  58. }
  59. else {
  60. IDOS->Printf("NO bitmapsrc\n");
  61. }
  62. }
  63. IDataTypes->DisposeDTObject(dt_Obj);
  64. }
  65. return NULL;
  66. }
broadblues
broadblues's picture
Offline
Last seen: 4 years 10 months ago
Joined: 2012-05-02 21:48
Re: p96LockBitMap freezes the system

1. Yes that's what it does, well okay not quite, it locks access to your bitmap and at the same time all other bitmaps (though you can't rely on that being always true) so whilst you have the bitmap locked nothing else can render.

2. First thing you do after locking the bitmap is call IDOS->Prinif() that's highly likely to render some text to a bitmap, oh wait.... use IExec->DebugPrintF to get arround that possible deadlock...

3. Then you do some highlevel datatypes stuff while the bitmaps are still locked, good possibilty for deadlocking there as you don't know whats going on inside that method.

Best solution, don't go locking any bitmaps unless you want to make low level access to the bitmap yourself, whithout relying on any high level functions ie no Intuition calls...

...never make low level access to a bitmap yourself, even when it locked, unless you are writen driver level stuff or a hyperoptimised screen grabber or something.

In this case I would allocate an array of ARGB 32 and extract the image to that, then write that into the bitmap using BltBitMapTags(). Even though that's two steps this will probably be faster since BltBitMapTags() is DMA accelaerated where possible and directly unpacking the datatypes data into the locked bitmap is lijkely not and has to do CPU access across the video bus (slow).

In fact you may not need to get p96 involved at all in the above as you can allocate a suitable bitmap directly with gfx lib calls, depending on what exacty you intend to do with it.

salass00
salass00's picture
Offline
Last seen: 7 months 1 week ago
Joined: 2011-02-03 11:27
Re: p96LockBitMap freezes the system

The Printf() call after p96LockBitMap() is what causes the lock up.

It would certainly be more future proof to read with PDTM_READPIXELARRAY into a normal memory buffer and then use IGraphics->WritePixelArray() to copy the data into the bitmap. This method also works with more than just one pixel format so if you don't need the alpha channel you can make future blitting faster if you allocate your bitmap as a friend of the screen bitmap.

The intermediate buffer doesn't have to be large enough to take the whole bitmap (to save memory you can do just one row at a time).

As for the risks of the current method:

The way the p96AllocBitMap() is formulated there is not much chance of the bitmap being in VRAM yet as the graphics system won't know what gfx card to use because no friend bitmap is specified and no operations have been done which require it to be in VRAM either.

Also the PDTM_READPIXELARRAY is little more than a copy operation, with some pixel conversion if needed, but it is possible that this could change in the future...

salass00
salass00's picture
Offline
Last seen: 7 months 1 week ago
Joined: 2011-02-03 11:27
Re: p96LockBitMap freezes the system

Also:


pbpa.pbpa_PixelArrayMod = RenderInfoBuffer.BytesPerRow,

That comma (',') at the end of the line should be a semicolon (';'). Right now it looks like you are setting pbpa_PixelArrayMod to the same value as pbpa_Left which is zero.

salass00
salass00's picture
Offline
Last seen: 7 months 1 week ago
Joined: 2011-02-03 11:27
Re: p96LockBitMap freezes the system

I rewrote the function using V54 graphics.library calls instead of P96 and WritePixelArray() instead of bitmap locking:

  1. struct BitMap *DTReadBitMapARGB32(CONST_STRPTR fname, uint32 *widthp, uint32 *heightp)
  2. {
  3. Object *dtobj;
  4.  
  5. dtobj = IDataTypes->NewDTObject(fname,
  6. DTA_GroupID, GID_PICTURE,
  7. PDTA_ModeID, PMODE_V43,
  8. TAG_END);
  9. if (dtobj != NULL)
  10. {
  11. struct BitMapHeader *bmh = NULL;
  12.  
  13. IDataTypes->GetDTAttrs(dtobj,
  14. PDTA_BitMapHeader, &bmh,
  15. TAG_END);
  16. if (bmh != NULL)
  17. {
  18. uint32 width = bmh->bmh_Width;
  19. uint32 height = bmh->bmh_Height;
  20. struct BitMap *bm;
  21.  
  22. bm = IGraphics->AllocBitMapTags(width, height, 32,
  23. BMA_PIXELFORMAT, PIXF_A8R8G8B8,
  24. TAG_END);
  25. if (bm != NULL)
  26. {
  27. APTR buffer;
  28.  
  29. buffer = IExec->AllocVecTags(4 * width, TAG_END);
  30. if (buffer != NULL) {
  31. struct pdtBlitPixelArray pbpa;
  32. struct RastPort temp_rp;
  33. uint32 y;
  34.  
  35. pbpa.MethodID = PDTM_READPIXELARRAY;
  36. pbpa.pbpa_PixelData = buffer;
  37. pbpa.pbpa_PixelFormat = PBPAFMT_ARGB;
  38. pbpa.pbpa_PixelArrayMod = 4 * width;
  39. pbpa.pbpa_Left = 0;
  40. pbpa.pbpa_Width = width;
  41. pbpa.pbpa_Height = 1;
  42.  
  43. IGraphics->InitRastPort(&temp_rp);
  44. temp_rp.BitMap = bm;
  45.  
  46. for (y = 0; y != height; y++) {
  47. pbpa.pbpa_Top = y;
  48.  
  49. IIntuition->IDoMethodA(dtobj, (Msg)&pbpa);
  50.  
  51. IGraphics->WritePixelArray(buffer, 0, 0, 4 * width, PIXF_A8R8G8B8,
  52. &temp_rp, 0, y, width, 1);
  53. }
  54.  
  55. IDataTypes->DisposeDTObject(dtobj);
  56. IExec->FreeVec(buffer);
  57.  
  58. *widthp = width;
  59. *heightp = height;
  60. return bm;
  61. }
  62.  
  63. IGraphics->FreeBitMap(bm);
  64. }
  65. }
  66.  
  67. IDataTypes->DisposeDTObject(dtobj);
  68. }
  69.  
  70. return NULL;
  71. }
walkero
walkero's picture
Offline
Last seen: 4 months 3 weeks ago
Joined: 2009-05-03 16:54
Re: p96LockBitMap freezes the system

Thank you all guys for your great info. I will test them on my project and keep you informed.

Log in or register to post comments