on delphi/android how to draw a TbitmapSurface on

2020-05-06 16:27发布

问题:

Under delphi (and under firemonkey/android), What is the most fastest way to draw on a Tcanvas a TbitmapSurface ?

I try to use TTexture like MyTexture.Assign(aBitmapSurface) and later do TCustomCanvasGpu(Canvas).DrawTexture but MyTexture.Assign(aBitmapSurface) have 2 main drawbacks :

  1. it's must be done inside the main thread (i don't know why else we have black screen)
  2. it's relatively slow operation

回答1:

I do not use/code for Android so read with extreme prejudice. As Delphi uses VCL so I stick to it. If Delphi under Android does not then you can ignore this answer.

It looks like it is similar problem to Windows when accessing any OS visual stuff (does not matter if by GDI or WinAPI) from outside main thread will invalidate the OS API making weird things latter like random crashes, wrong rendering, etc. Another reason can be the use of GPU related calls which are usually bound to process/thread and device context. So to make it thread safe you could have to create shared context if possible if not you need to stick to main thread.

By Assign you are creating new image and copy the old to it that takes time comparable to drawing itself not to mention on devices with slow memory it can really slow down the whole thing considerably a lot more.

If you are dealing with VCL graphic components then try to use Draw directly:

  • blablabla->Canvas->Draw(x,y,aBitmapSurface);

if blablabla and aBitmapSurface are valid gfx components then it should work. As I mentioned not sure if this is present also in Android. The x,y is the position where you want to draw the aBitmapSurface. There is also StretchDraw if you need to rescale but that is a bit slower.

See Display an array of color in C sections GDI and GDI Bitmap for some ideas under VCL



回答2:

TBitmapSurface is in system memory so you need to assign your TBitmapSurface to a TBitmap first, to be converted to native OS bitmap (or texture) format that FMX uses for drawing:

bmp.Assign(surf);

Then draw the Bitmap to the canvas:

canvas.BeginScene();
canvas.DrawBitmap(bmp, SrcRect, DstRect, AOpacity);
canvas.EndScene();

I have tested it on Windows and Android. On android you need to call the Repaint too see the change.