trouble switching from PDTM_SCALE to CompositeTags()

15 posts / 0 new
Last post
tekmage
tekmage's picture
Offline
Last seen: 1 year 4 months ago
Joined: 2011-10-09 03:19
trouble switching from PDTM_SCALE to CompositeTags()

Hi All,

I'm working on an App and would like to move from the old datatype scale engine to use the new CompositeTags() call. I'm getting the image but the result is not scaled. Here is what I'm working with:

  1. if(IDataTypes->DoDTMethod(dtype, NULL, NULL,DTM_PROCLAYOUT, NULL, 1)){
  2.  
  3.  
  4. if( scale)
  5. {
  6.  
  7. //DataType Do method
  8.  
  9. res = IDataTypes->GetDTAttrs(dtype,
  10. PDTA_DestBitMap, (ULONG)&bitmaptmp,
  11. PDTA_NumColors, (ULONG)&colorNumber,
  12. PDTA_CRegs, (ULONG)&colorRegisters,
  13. TAG_DONE);
  14. if (res != 3)
  15. {
  16. #if DebugLevel > 0
  17. IExec->DebugPrintF( "-->dtype: res != 3\n" );
  18. #endif
  19. }
  20.  
  21. //Use CompositeTagList for scaling
  22. IGraphics->CompositeTags( COMPOSITE_Src_Over_Dest, bitmaptmp, bitmap, COMPTAG_ScaleX, COMP_FLOAT_TO_FIX(scalefactor), COMPTAG_ScaleY, COMP_FLOAT_TO_FIX(scalefactor), TAG_END );
  23.  
  24. imageheight = IGraphics->GetBitMapAttr( bitmap, BMA_HEIGHT);
  25. imagewidth = IGraphics->GetBitMapAttr( bitmap, BMA_WIDTH);

With the above "bitmap" is passed to BltBitMapRastPort and is shown but at full size. Also, both imageheight and imagewidth are 0.

My questions are:

Do I need to use "COMPOSITE_Src_Over_Dest" or can I just use "COMPOSITE_Src"
Am I using the "COMPTAG_FLOAT_TO_FIX correctly? where float32 scalefactor;
What am I missing?

Thanks,
Bill

tekmage
tekmage's picture
Offline
Last seen: 1 year 4 months ago
Joined: 2011-10-09 03:19
I've added some more

I've added some more debugging details.

Looks like the error from the compositetags is "1" which means an incompatible source image. I checked the image format and found it to be "2" and I run GetBitMapAttr with BMA_FLAGS and all I see is 0 (Printf with %ld).

Hans
Hans's picture
Offline
Last seen: 2 months 3 weeks ago
Joined: 2010-12-09 22:04
With the above "bitmap" is

With the above "bitmap" is passed to BltBitMapRastPort and is shown but at full size. Also, both imageheight and imagewidth are 0.

That sounds like your bitmap isn't allocated properly. Howevever, your code doesn't show your allocation of the bitmap object, so I cannot say what you're doing wrong.

My questions are:

Do I need to use "COMPOSITE_Src_Over_Dest" or can I just use "COMPOSITE_Src"


That depends on what you're trying to do. If it's a straight copy, then COMPOSITE_Src will suffice. However, if you want to do a blend operation (e.g., your source bitmap has transparent areas) then you should use COMPOSITE_Src_Over_Dest.

Am I using the "COMPTAG_FLOAT_TO_FIX correctly? where float32 scalefactor;
What am I missing?

It sounds like you're using it correctly, but you've already discovered that the operation is failing with an error.

I've added some more debugging details.

Looks like the error from the compositetags is "1" which means an incompatible source image. I checked the image format and found it to be "2" and I run GetBitMapAttr with BMA_FLAGS and all I see is 0 (Printf with %ld).

Error one could also mean an incompatible destination bitmap.

Pixel format 2 is R8G8B8, and graphics cards don't like that pixel format because it's not 32-bit aligned. You should use ARGB instead for the source bitmap. I've already given you these details elsewhere, but for the benefit of others:

Use PDTM_READPIXELARRAY instead of DTM_PROCLAYOUT to extract the bitmap data from the picture object. DTM_PROCLAYOUT won't handle the alpha channel properly, and using PDTM_READPIXELARRAY gives you control over the source bitmap's pixel format.

The Composite3DDemo source code contains a good example of extracting bitmaps for use with compositing in C3D/C3DTexture.cpp. You can download the code from: http://hdrlab.org.nz/projects/amiga-os-4-projects/c3d/
Just scroll down to the download section.

Hans

http://hdrlab.org.nz/ - Amiga OS 4 projects, programming articles and more. Home of the RadeonHD driver for Amiga OS 4.x project.
http://keasigmadelta.co.nz/ - more of my software.

tekmage
tekmage's picture
Offline
Last seen: 1 year 4 months ago
Joined: 2011-10-09 03:19
Hi Hans, With your help I

Hi Hans,

With your help I have made great progress in getting this working. For the forum, here is some code that brings it together:

  1. printf("Display-Photo: Showing file %s\n",(char *) file);
  2. dtype = IDataTypes->NewDTObject( (char *) file,
  3. PDTA_DestMode,PMODE_V43,
  4. TAG_END);
  5.  
  6. printf("Display-Photo: Datatype created\n");
  7.  
  8. if (dtype == NULL)
  9. {
  10. quit("Display-Photo: Failed to load data type\n");
  11. }
  12.  
  13. res = IDataTypes->GetDTAttrs(dtype, PDTA_BitMapHeader, (ULONG)&bmh, TAG_END);
  14.  
  15. if (res != 1)
  16. {
  17. quit("Display-Photo: Unable to obtain details of picture from Datatypes\n");
  18. }
  19.  
  20. //Determine the source image size
  21. srcimagewidth = bmh->bmh_Width;
  22. srcimageheight = bmh->bmh_Height;
  23.  
  24.  
  25. printf("Display-Photo: Starting image size imagewidth %d, imageheight %d\n", srcimagewidth,srcimageheight);
  26.  
  27.  
  28. if (bmh)
  29. {
  30. printf("Display-Photo: DataType Do method\n");
  31.  
  32. //Allocate the bitmap which will hold the source. For compositing to work
  33. //the BMF_DISPLAYABLE flag must be set and the color format must be A8R8G8B8
  34. bitmapsrc = IP96->p96AllocBitMap( srcimagewidth, srcimageheight, 32, BMF_DISPLAYABLE, NULL, RGBFB_A8R8G8B8 );
  35.  
  36. // Extract the bitmap data from the picture object
  37. // NOTE: For some reason the picture datatype kills the alpha channel unless
  38. // we extract the pixel data using PDTM_READPIXELARRAY
  39. struct RenderInfo renderInfo;
  40. LONG lock = IP96->p96LockBitMap(bitmapsrc,
  41. (UBYTE*)&renderInfo, sizeof(renderInfo));
  42.  
  43. uint32 srcBytesPerRow = IP96->p96GetBitMapAttr(bitmapsrc, P96BMA_BYTESPERROW);
  44.  
  45. IIntuition->IDoMethod(dtype,
  46. PDTM_READPIXELARRAY,
  47. renderInfo.Memory,
  48. PBPAFMT_ARGB,
  49. srcBytesPerRow,
  50. 0,
  51. 0,
  52. srcimagewidth,
  53. srcimageheight,
  54. TAG_END);
  55.  
  56. //Unlock the bitmap
  57. IP96->p96UnlockBitMap(bitmapsrc, lock);
  58.  
  59.  
  60. if ( bitmapsrc )
  61. {
  62.  
  63. //Determine the new bitmap size before allocation
  64.  
  65. //scalefactor = (float32) screenwidth / srcimagewidth;
  66. destimagewidth = (int) (srcimagewidth * scalefactor);
  67. destimageheight = (int) (srcimageheight * scalefactor);
  68.  
  69. printf("Display-Photo: Scaled image size destimagewidth %d, destimageheight %d\n", destimagewidth,destimageheight);
  70.  
  71. bitmapdest = IP96->p96AllocBitMap( destimagewidth, destimagewidth, 32, BMF_DISPLAYABLE, bitmapsrc, RGBFB_A8R8G8B8 );
  72.  
  73. //Use CompositeTagList for scaling
  74. res = IGraphics->CompositeTags(
  75. COMPOSITE_Src_Over_Dest, bitmapsrc, bitmapdest,
  76. COMPTAG_ScaleX, COMP_FLOAT_TO_FIX( scalefactor ),
  77. COMPTAG_ScaleY, COMP_FLOAT_TO_FIX( scalefactor ),
  78. //COMPTAG_SrcX, 0,
  79. //COMPTAG_SrcY, 0,
  80. //COMPTAG_SrcWidth, srcimagewidth,
  81. //COMPTAG_SrcHeight, srcimageheight,
  82. //COMPTAG_DestX, 0,
  83. //COMPTAG_DestY, 0,
  84. //COMPTAG_DestWidth, destimagewidth,
  85. //COMPTAG_DestHeight, destimageheight,
  86. //COMPTAG_OffsetX, 0,
  87. //COMPTAG_OffsetY, 0,
  88. COMPTAG_Flags, COMPFLAG_IgnoreDestAlpha,
  89. TAG_DONE);
  90.  
  91. printf("Display-Photo: CompositeTags() result %d\n",res);
  92.  
  93.  
  94. //Calculate start point for image display
  95. imagestartwidth = (screenwidth / 2 ) - (destimagewidth / 2);
  96. imagestartheight = (screenheight /2 ) - (destimageheight / 2);
  97.  
  98. printf("Display-Photo: Opening bitmap, imagestartX %d, imagestartY %d, new imagewidth %d, new imageheight %d\n", imagestartwidth, imagestartheight, destimagewidth, destimageheight);
  99.  
  100.  
  101. if (bitmapsrc != NULL )
  102. {
  103. printf("Display-Photo: Freeing bitmapsrc\n");
  104. IP96->p96FreeBitMap( bitmapsrc );
  105. }
  106.  
  107. bitmap = bitmapdest;
  108.  
  109. if( bitmap )
  110. {
  111. IGraphics->BltBitMapTags(
  112. BLITA_Source, bitmapdest,
  113. BLITA_DestX, imagestartwidth,
  114. BLITA_DestY, imagestartheight,
  115. BLITA_Dest, RPort,
  116. BLITA_DestType, BLITT_RASTPORT,
  117. BLITA_Width, destimagewidth,
  118. BLITA_Height, destimageheight,
  119. BLITA_SrcBytesPerRow, srcBytesPerRow,
  120. TAG_DONE);

As Hans mentioned the critical bits are making sure the bitmap format is correct and you need to use PDTM_READPIXELARRAY.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
Hello Tekmage and Hans.

Hello Tekmage and Hans. :-)

I just examined my code and I have used both DTM_PROCLAYOUT and PDTM_READPIXELARRAY with success. I use the layout, then GetDTAttrsA() to get the bitmap, and finally read the array.

Also Tekmage your code looks a litte bit too low level. You use Picassoi96 API which should not be necessary, as graphics.libary AllocBitMap() can do that for you. But even that is more work then you need as you can call a datatype method to get a bitmap.

The following is code to do this. It's in E but gets the point across. It uses an open screen as a reference for the bitmap type. And grabs one line. BTW datatypes can also render onto a screen for you.

  1. IF (dto:=NewDTObjectA(newimage.name, [DTA_GROUPID, GID_PICTURE, PDTA_DESTMODE, PMODE_V43, PDTA_SCREEN, gamescreen, PDTA_REMAP, TRUE, PDTA_USEFRIENDBITMAP, TRUE, NIL]))
  2. doMethodA(dto,[DTM_PROCLAYOUT,NIL,1]:gplayout)
  3. GetDTAttrsA(dto,[PDTA_BITMAP, {bm}, PDTA_BITMAPHEADER, {bmh}, NIL])
  4.  
  5. doMethodA(dto,[PTDM_READPIXELARRAY,pixels,PBPAFMT_ARGB,bm.bytesperrow,0,450,1440,1])
Hans
Hans's picture
Offline
Last seen: 2 months 3 weeks ago
Joined: 2010-12-09 22:04
@hypex I just examined my

@hypex

I just examined my code and I have used both DTM_PROCLAYOUT and PDTM_READPIXELARRAY with success. I use the layout, then GetDTAttrsA() to get the bitmap, and finally read the array.

Okay, but have you tried using DTM_PROCLAYOUT with bitmaps for use with CompositeTags(). In my experience, it doesn't extract the alpha channel (unless that has been fixed since I tried it).


Also Tekmage your code looks a litte bit too low level. You use Picassoi96 API which should not be necessary, as graphics.libary AllocBitMap() can do that for you. But even that is more work then you need as you can call a datatype method to get a bitmap.

I would discourage getting the datatype to allocate the bitmap for you. It's a bit hackish, provides less control over the resulting bitmap, and raises questions over who owns the bitmap (i.e., if the datatype object is deallocated, does it automatically deallocate any bitmaps that it allocated too?).

Use AllocBitmap()/p96AllocBitMap() for allocating bitmaps; that's what they're there for. It provides full control over the bitmap's format, clear ownership, and easier to understand code.

Using Picasso96API.library is fine, even though using graphics.library calls is preferable. The graphics library's AllocBitMap() function takes a tag-list if you set the flags to BMF_DISPLAYABLE | BMF_CHECKVALUE, so it is entirely possible to do everything that you do with p96AllocBitMap() with AllocBitMap() instead. Yes, that is counter-intuitive, but that's how it works at present.

Hans

http://hdrlab.org.nz/ - Amiga OS 4 projects, programming articles and more. Home of the RadeonHD driver for Amiga OS 4.x project.
http://keasigmadelta.co.nz/ - more of my software.

mcleppa (not verified)
mcleppa's picture
I struggled with the same

I struggled with the same thing a while ago, I had to apply these hex values.

COMPTAG_ScaleX, (int32)((double)0x00010000*(double)((double)(dest_width+1)/(double)source_width)),
COMPTAG_ScaleY, (int32)((double)0x00010000*(double)((double)(dest_height)/(double)source_height)),

Hans
Hans's picture
Offline
Last seen: 2 months 3 weeks ago
Joined: 2010-12-09 22:04
@mcleppa Use the

@mcleppa

Use the COMP_FLOAT_TO_FIX( scalefactor ) macro instead of doing the fload to fix conversion manually.

Hans

http://hdrlab.org.nz/ - Amiga OS 4 projects, programming articles and more. Home of the RadeonHD driver for Amiga OS 4.x project.
http://keasigmadelta.co.nz/ - more of my software.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
@hans Okay, but have you

@hans

Okay, but have you tried using DTM_PROCLAYOUT with bitmaps for use with CompositeTags().

I haven't, no. But I wasn't using the alpha channel directly. Infact I masked it out.

Use AllocBitmap()/p96AllocBitMap() for allocating bitmaps

Using AllocBitmap() would be my preferred method. Which IIRC is what I did do as I was creating a new bitmap to hold a scaled image.

I just looked it up and found AllocBitmap() has been extended beyond measure! And this was before OS4. But why didn't they just create and AllocBitmapTags() function? :-?

But what most eludes me is how they extended the BitMap structure which is bitplabe centric to support non-bitmap and chunky display data without using the flags!? Huh? :-?

Hans
Hans's picture
Offline
Last seen: 2 months 3 weeks ago
Joined: 2010-12-09 22:04
@hypex I just looked it up

@hypex

I just looked it up and found AllocBitmap() has been extended beyond measure! And this was before OS4. But why didn't they just create and AllocBitmapTags() function? :-?

This is most likely because it originally wasn't an official extension, but done by a third party (i.e., the creators of Picasso96). The Picasso96 authors weren't in a position to add an extra function to the graphics.library, and so their only option was to patch and extend the existing one.

It is quite an ugly solution, and is something that I expect to be corrected in a future release with an AllocBitMapTags() function.

But what most eludes me is how they extended the BitMap structure which is bitplabe centric to support non-bitmap and chunky display data without using the flags!? Huh? :-?

Consider the bitmap structure a black-box from now on. With non-planar bitmaps you have no idea what the internal bitmap data is. I'm not going to tell you how they did it, because I don't want to encourage anyone to go poking around in that structure, or trying to allocate chunky bitmaps manually.

Hans

http://hdrlab.org.nz/ - Amiga OS 4 projects, programming articles and more. Home of the RadeonHD driver for Amiga OS 4.x project.
http://keasigmadelta.co.nz/ - more of my software.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
A clue is given in the

A clue is given in the BMF_STANDARD flag. If not set then none could assume RTG framebuffer. But still with no info on format. One can then assume that the BitMap structure was extended privately. Usually these private extensions still appear in include files. But here they do not so the unused plane pointers could be used instead.

That said, I have no comcern about the internals of RTG BitMap management. Although I do dispute it being a bitmap as once the the pixel depth was thrown away for a pixel width that goes across bytes it is no longer a bitmap but a chunkmap or a colour map. But that is just semantics. :-)

I prefer to use GfxLibrary myself and let it work everything out. However I do see a problem. I have been giving advice on how to make a game OS/RTG friendly. Currently this game writes directly to planar bitmaps so easiest solution is to let it do it's work and then blit to an RGB display using a standard BitMap as the source.

However there is one problem. The author wishes to optimise his code so that all gfx are in the screen format whatever that may be to increase performance and eradicate bottlenecks. Logical so far. And easy enough if loaded like we have discussed here and letting the system work out the BitMap for us. The problem is that the code does effects on the gfx data and needs to read from the BitMap, modify it. then write it back. As you can se there is potential problem here. Though easy enough to read with an 8-bit CLUT if not as efficient as having direct access to the bitmap data itself.

The problem is that the author wishes to upgrade the game engine to support 24-bit RTG. That means he needs to know what, of four variations in the ARGB model, the data is formatted as. If there are no more than four. And so not only have routnes that deal with these formats directly but be able to read, modify and write back to the frambuffer. As you can see the code already needs to do too much!

So, using the abstract functions of the OS, how can the above be achieved? If possible. Reminds me why people used to bang the hardware. Can an RTG BitMap be read, modified and written back in a known format in order to fully optimsise code? :-?

Hans
Hans's picture
Offline
Last seen: 2 months 3 weeks ago
Joined: 2010-12-09 22:04
@hypex So, using the

@hypex

So, using the abstract functions of the OS, how can the above be achieved? If possible. Reminds me why people used to bang the hardware. Can an RTG BitMap be read, modified and written back in a known format in order to fully optimsise code? :-?

The only way to directly access a bitmap is via the Picasso96API's lock and unlock bitmap functions. Please note that directly accessing individual pixels via PCI/PCIe/AGP is slow. Hence, if you're going to do a lot of software rendering, it can be quicker to have the bitmap for rendering stored in a self-allocated buffer in RAM, and use WritePixelArray()/ReadPixelArray to copy it to/from the screen/window bitmap.**

Try to use HW accelerated rendering (i.e., graphics library functions) whereever possible; they really are much faster. In particular, CompositeTags() provides a lot of possibilities.

Hans

** Please note that WritePixelArray()/ReadPixelArray() is currently DMA accelerated on the Sam460ex, so it's much faster than copying it manually (have a look at the this GfxBench2D benchmark's memcopy results). Those functions also have pretty well optimised routines for all of the other platforms, and we hope to add DMA support for more hardware in the future.

http://hdrlab.org.nz/ - Amiga OS 4 projects, programming articles and more. Home of the RadeonHD driver for Amiga OS 4.x project.
http://keasigmadelta.co.nz/ - more of my software.

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
Thanks for the tips Hans.

Thanks for the tips Hans. I've passed them on. :-)

Now when you say WritePixelArray()/ReadPixelArray(), which ones? ;-)

There is an exact match in CyberGfx API, p96WritePixelArray() in Picasso96 and WritePixelArray8() from Gfx. :-?

thomas
thomas's picture
Offline
Last seen: 9 hours 32 min ago
Joined: 2011-05-16 14:23
Shouldn't this be obvious?

Shouldn't this be obvious? CGX is third-party, P96 is part of the OS, WritePixelArray8 can only handle 8bit-pixels (hence the 8 in the name).

hypex
hypex's picture
Offline
Last seen: 1 month 2 weeks ago
Joined: 2011-09-09 16:20
@thomas Not immediataely.

@thomas

Not immediataely. Most functions I see are named in full. And Hans did recommend graphics library functions which are ones I'd prefer to stick too.

However I myself would prefer to just use generic graphics library functions that existed in OS3 and let the system work it out. And use compositing transparently if the OS supports it. But I don't know if it's optimised to do that.

Log in or register to post comments