B4A Library [Lib] Accelerated surface

This library provides a dedicated drawing surface embedded inside a view, which benefits from the hardware acceleration. With it, you get the speed of OpenGL for 2D without the complexity.
It includes many Canvas methods (with anti-aliasing, matrix and camera) and a few useful methods for Bitmaps and Drawables (AlterColors, Crop, LoadNinePatch, ReduceColors, SetDensity, etc.). You can import the Matrix, Camera, Paint and Path objects from another library (if they are not wrapped).

surface.png

imageviews.jpg


You can use it to make games:

princess_tiles.png

space_enemies.png


It includes a tool (TextFactory) to do nice titles (that you can export to a bitmap):

textfactory.jpg


It supports Porter-Duff modes, color filters and texture blending (the processing time is very fast):

pdmodes.jpg


The archive includes four benchmarks:

Perf.png


Because of my lack of (free) time, don't expect answers from me about this library if you're not one of my donors.

Download the latest version (1.12)
To convert a project from v0.9x to v1.x, read this.

Hints & Tips

This library does not work with Android versions < 2 (Eclair and Froyo may exhibit performance problems, so I recommend only Gingerbread or a newer version for animations with a high FPS).
The hardware acceleration is not enabled with Android versions < 3.
 

Attachments

  • Java source - AcceleratedSurface.zip
    21.3 KB · Views: 653
Last edited:

sorex

Expert
Licensed User
Longtime User
not sure if you need a donation just to answer this question? ;)

but "you get the speed of OpenGL for 2D without the complexity."

does this mean it's still using GL but with easier command?

or is it GL less and working on < 3.0 but still faster than the normal bitmap/canvas methods ?
 

Informatix

Expert
Licensed User
Longtime User
not sure if you need a donation just to answer this question? ;)

but "you get the speed of OpenGL for 2D without the complexity."

does this mean it's still using GL but with easier command?

or is it GL less and working on < 3.0 but still faster than the normal bitmap/canvas methods ?

With Android 3 or newer version, the drawing surface is a OpenGL2 surface. So behind a method like DrawBitmap, you have OpenGL2 methods. With Android 2, the Canvas is a normal Canvas, not hardware accelerated. That allows to have the same code with all Android versions. However, that doesn't mean the code is slow on a Gingerbread device. On my main phone, I can display about 75 smileys at 60FPS.
 
Last edited:

sorex

Expert
Licensed User
Longtime User
ok, that's clever to go for one piece of code for both OGL supporting and none supporting devices.
 

Informatix

Expert
Licensed User
Longtime User
New version

New version 0.95:
I added the support of textures (new class: Texture, and new functions: DrawRectWithTexture, DrawPathWithTexture, etc.);
I added a timer making direct calls to the Draw event handler (StartRegularDraw, StopRegularDraw, ElapsedTimeSinceLastDraw);
I added several examples.
 

airblaster

Active Member
Licensed User
Longtime User
Hi Informatix,

since you are writing this could be a good replace for image views:
Would it have advantages to use accelerated surface instead of image views in your ULV library?
 

Informatix

Expert
Licensed User
Longtime User
Hi Informatix,

since you are writing this could be a good replace for image views:
Would it have advantages to use accelerated surface instead of image views in your ULV library?

Yes and no. If your ImageViews display static images loaded with LoadBitmap, then you can replace them, but if you use LoadImageAsync, you cannot because this function expects an ImageView as the first parameter. A trick would be to create a dummy ImageView that you pass to LoadImageAsync with a custom location. In the CustomLoadCallback function, you load the image in the AS view, put it in the cache with the Feed...WithBitmap functions and return null so nothing is displayed in the ImageView. This way you benefit from the asynchronous operation and from the cache, but it's cumbersome!
 

Informatix

Expert
Licensed User
Longtime User
New version

New version 0.96:
- I use now a hardware layer (it solves issues with some devices);
- I added the Update event and the StartRegularUpdateAndDraw function;
- I added three functions: AlterColors, DrawArcWithTexture, and DrawTextWithTexture;
- I added a game: Space Enemies.

For animations, the Draw event is sufficient, but for games, it is better to have a separate Update event to compute moves and detect collisions. If you use the new function "StartRegularUpdateAndDraw", a timer is going to trigger regularly the Update event, then the Draw event.
 

jmbm

New Member
Licensed User
Longtime User
Hi Informatix,

I'm trying your great lib.
I think there is a bug in the Lib. When you try to draw a text and you have used before a Texture, the text is draw textured.
As reference, you can see it in the water sample, with the FPS text count. There is no color in the text, you see the background texture.

Excuse my English.

Thanks and regards.
 

sterlingy

Active Member
Licensed User
Longtime User
I'm looking into if your lib will fix some issues for me. In my app, I use DrawBitmapRotated, and that seems to be one of the methods that you didn't mimic. However, I could use your MatrixSetRotate, but it doesn't look like it rotates around the Bitmap center point.

Is there a solution with your lib?

Cheers,

Sterling
 

Informatix

Expert
Licensed User
Longtime User
I'm looking into if your lib will fix some issues for me. In my app, I use DrawBitmapRotated, and that seems to be one of the methods that you didn't mimic. However, I could use your MatrixSetRotate, but it doesn't look like it rotates around the Bitmap center point.

Is there a solution with your lib?

You are right, I voluntarily omitted the DrawBitmapRotated function because rotating a bitmap with a matrix is faster and allows to change the pivot point (it can be anywhere, so you have different rotation effects at your disposal).

The pivot point, at start, is always located in the top left corner. So if you want to rotate your bitmap, you have to:
- move the pivot point to the center of your bitmap:
AC.MatrixSetTranslate(-myBmp.width/2, -myBmp.height/2)
- do the rotation:
AC.MatrixPostRotate(angle)
- go back to the top left corner (and draw the bitmap to its final location on screen):
AC.DrawBitmapWithMatrixAt(myBmp.bmp, myBmp.width/2 + destX, myBmp.height/2 + destY, True)
 

Informatix

Expert
Licensed User
Longtime User
I think there is a bug in the Lib. When you try to draw a text and you have used before a Texture, the text is draw textured.
As reference, you can see it in the water sample, with the FPS text count. There is no color in the text, you see the background texture.

All texts should be separated from the other drawings for two reasons:
- the bug you noticed and a couple of another bugs (all fixed in Jelly Bean 4.2);
- they don't need to be refreshed 60 times per second.

In the Space Enemies example, I use a second layer for the title and I animate it only when needed. I disabled the hardware acceleration in this Accelerated Surface to avoid a bug with TextOnPath in Honeycomb and ICS (and I don't really need the HW acceleration to animate two words, even on a slow device).

I didn't isolate the score in its own AcceleratedSurface, but maybe I should have. It's not necessary to redraw this score every 16ms. Only when it changes.
 

padvou

Active Member
Licensed User
Longtime User
Hi!
If I want to draw a shape, which consists of n dots (example: 100 dots)?
each dot has a fixed distance from a center spot and also each dot has a know x and y coordinate value. All distances are in mm
How would you do that?
 

Informatix

Expert
Licensed User
Longtime User
Hi!
If I want to draw a shape, which consists of n dots (example: 100 dots)?
each dot has a fixed distance from a center spot and also each dot has a know x and y coordinate value.

It depends on what you want to achieve. Is it a closed shape? Is it a static polygon (not moving, not changing)? The most obvious solution is to use a Path (with a DrawPath function), but it's slow.

All distances are in mm
How would you do that?

You have to use a scale. For example: 1 mm = 0.1%x.
 

sterlingy

Active Member
Licensed User
Longtime User
The pivot point, at start, is always located in the top left corner. So if you want to rotate your bitmap, you have to:
- move the pivot point to the center of your bitmap:
AC.MatrixSetTranslate(-myBmp.width/2, -myBmp.height/2)
- do the rotation:
AC.MatrixPostRotate(angle)
- go back to the top left corner (and draw the bitmap to its final location on screen):
AC.DrawBitmapWithMatrixAt(myBmp.bmp, myBmp.width/2 + destX, myBmp.height/2 + destY, True)

Informatix,

I did as you suggested. I've been trying to compare AC against GameView. I did see a speed improvement from about 27FPS with GV to 30FPS with AC.

BTW, I really like the library, so I donated, even though I may not use it for my current project. I'm sure I will use it in something.

I have a feeling there are some ways to get better performance. I'm making a tile based game. Each Tile is 240x240px and on my Nexus 7, it can sometimes need to process 30 tiles per tick. That's to rotate and draw them to a canvas. This is just for the background.

I would like to keep all the sprites in GV, unless you think it would be faster to keep everything in AC, or maybe even keep everything in GV.

What do you think?

Cheers,

Sterling
 

Informatix

Expert
Licensed User
Longtime User
Informatix,

I did as you suggested. I've been trying to compare AC against GameView. I did see a speed improvement from about 27FPS with GV to 30FPS with AC.

BTW, I really like the library, so I donated, even though I may not use it for my current project. I'm sure I will use it in something.

I have a feeling there are some ways to get better performance. I'm making a tile based game. Each Tile is 240x240px and on my Nexus 7, it can sometimes need to process 30 tiles per tick. That's to rotate and draw them to a canvas. This is just for the background.

I would like to keep all the sprites in GV, unless you think it would be faster to keep everything in AC, or maybe even keep everything in GV.

What do you think?

Cheers,

Sterling

Thank you for your donation. I will send you a few things later this day. I'm currently making two new examples for this lib. One of them uses tiles. Maybe that will answer to your question.
 

padvou

Active Member
Licensed User
Longtime User
It depends on what you want to achieve. Is it a closed shape? Is it a static polygon (not moving, not changing)? The most obvious solution is to use a Path (with a DrawPath function), but it's slow.



You have to use a scale. For example: 1 mm = 0.1%x.

It's a closed shape, like an ellipse.
Drawpath? I'll look into it..
Thank you for your reply!
 
Top