FrameBuffer.blit(..) - Improving performances and eventual alternatives

Started by danilox6, September 06, 2012, 12:09:29 AM

Previous topic - Next topic

danilox6

Hi everybody, I'm working on a Live Wallpaper that shows a waving flag in two different fashions:
- "fullscreen" in which all you can see is a waving cloth that fills the screen;
- "standard" that shows the flag attached to a pole.

Everything works just fine except for the fact that I can't display a bitmap behind my scene when I'm in "standard" mode. The bitmap should act like a background for the displayed scene.

I premise that I'm very new to 3d and OpenGL so it's just my fault not being able to achieve what I want.

I tried to use the FrameBuffer.blit(Texture [...]) method but it slows down too much my animation. Right now I'm using a 512x512 bitmap. This size is not fixed because users will be able to select from their gallery a custom image to set as background. Anyway I've already written an interactive ImageCropper that outputs only 2^x px squared bitmaps.
The way I'm using the blit method right now is the following:
framebuffer.blit(TextureManager.getInstance().getTexture(background),0,0,0,0,512,512,FrameBuffer.OPAQUE_BLITTING);


So I tried to look for different approaches.
I read somewhere that if I clear my framebuffer using an RBG whith alpha value assigned, I can make it transparent.

Since, as I said, I'm not  able to write OpenGL on my own, I surfed the net looking for some code snippets that would fit my needs.

I found this tutorial and after a little of tweaking I've been able to show my bitmap in front of my 3d model. It basically draws a square with a texture but I couldn't place the square behind my Object3D. I don't know if this is caused by the fact that the framebuffer isn't transparent or just because I'm incapable (probably is the second because I was basically trying to draw the square before clearing the framebuffer...)

I've also tried to set the background in the WallpaperService.Engine that creates and manages my Renderer:
in onSurfaceChanged(SurfaceHolder holder, int format, int width, int height), I call the following method:

private void drawFrame() {
           final SurfaceHolder holder = getSurfaceHolder();

            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.sky_day);
                    Rect dest = new Rect(0, 0, width, height);
                    Paint paint = new Paint();
                    paint.setFilterBitmap(true);
                    c.drawBitmap(background, null, dest, paint);
                }
            } finally {
                if (c != null) holder.unlockCanvasAndPost(c);
            }

            // Reschedule the next redraw
            mHandler.removeCallbacks(mDrawCube);
            if (mVisible) {
                mHandler.postDelayed(mDrawCube, 1000 / 25);
            }
        }


The above method gets then rescheduled using an android.os.Handler.

What I got is a flickering image that switches very fast bethwin the 3d scene and the background, probably because I work on the same surface using concurrent threads. So I tried to call the above method in my Renderer's  drawFrame(GL10 gl) but I got the following error: "CPU may be pegged" that probably have to do with that lock on the Canvas...     

So what I want to know is:
Are there any other ways to set a bitmap as background for a scene?
Otherwise, what is the correct way to blit a bitmap without significant frame rate loss?

Thanks, and apologise me for my inaccuracies and for wasting your time with such newbie's questions..

EgonOlsen

You are not supposed to fiddle around with OpenGL directly in the context of jPCT unless you really know what you are doing and for some very rare special cases. This is none! Neither can mixing Android's image stuff with OpenGL cause you anything but trouble (and it won't be any faster even if it would work). The right way of doing it is indeed your first approach using FrameBuffer.blit(...), which is a pretty basic operation that actually doesn't slow down much. If you are on a low end device, it might be noticable because it uses some fillrate which mobile chips don't have much...which device are you using?

danilox6

I'm testing it on an Lg Optimus One (P500).
Anyway, I solved my issue...
Since I offer various built-in background and images to put on the flag, plus I give to the user the opportunity to load their own pictures, i dynamically load/remove my textures.
In my drawFrame(GL10 gl) method I call a static method of an utility class that loads my texture only if the TextureManager doesn't contains it yet. Well... I was "BitmapHelper.converting" my drawable before actually checking the above condition.. every frame..

I'm sorry for having bothered you..
Thank you for your time!