I'm trying to draw something use OpenGL ES 1.0, the rendering to screen works good. Then I want to use ImageReader to get the image data from surface, but its callback ImageReader.OnImageAvailableListener is not called at all while rendering, what's wrong about my code?
public class ImageReaderActivity extends ActionBarActivity implements SurfaceHolder.Callback, Runnable {
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Surface mSurface;
private int mWidth, mHeight;
private boolean mRunning = false;
private ImageReader mImageReader;
private OpenGLDrawer mOpenGLDrawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imagereader);
mSurfaceView = findViewById(R.id.surface_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mWidth = width;
mHeight = height;
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);
mSurface = mImageReader.getSurface();
new Thread(this).start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mRunning = false;
}
#Override
public void run() {
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
egl.eglInitialize(dpy, version);
int[] configSpec = {
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
EGLConfig config = configs[0];
EGLContext context = egl.eglCreateContext(dpy, config,
EGL10.EGL_NO_CONTEXT, null);
EGLSurface drawSurface = egl.eglCreateWindowSurface(dpy, config, mSurfaceHolder, null);
EGLSurface readSurface = egl.eglCreateWindowSurface(dpy, config, mSurface, null);
egl.eglMakeCurrent(dpy, drawSurface, readSurface, context);
GL10 gl = (GL10)context.getGL();
mOpenGLDrawer = new OpenGLDrawer();
mOpenGLDrawer.setSize(gl, mWidth, mHeight);
mRunning = true;
while (mRunning) {
SystemClock.sleep(333);
synchronized (mSurfaceHolder) {
render(gl);
egl.eglSwapBuffers(dpy, drawSurface);
}
}
egl.eglMakeCurrent(dpy, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(dpy, drawSurface);
egl.eglDestroySurface(dpy, readSurface);
egl.eglDestroyContext(dpy, context);
egl.eglTerminate(dpy);
}
private void render(GL10 gl) {
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
mOpenGLDrawer.draw(gl);
}
private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if (image != null) {
image.close();
}
}
};
}
After long time debugging, here is the final working code:
public class ImageReaderActivity extends ActionBarActivity
implements SurfaceHolder.Callback, Runnable {
private static final int MSG_SHOW_SCREENSHOT = 0;
private static final int MSG_HIDE_SCREENSHOT = 1;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Surface mSurface;
private int mWidth, mHeight;
private boolean mRunning = false;
private ImageReader mImageReader;
private OpenGLDrawer mOpenGLDrawer;
private EGLSurface mDrawSurface;
private EGLSurface mImageReaderSurface;
private EGLDisplay mEGLDisplay;
private EGLContext mEGLContext;
private FrameLayout mFrameView;
private ImageView mScreenshotView;
private volatile boolean mIsCapturing = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_imagereader);
mSurfaceView = findViewById(R.id.surface_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mFrameView = findViewById(R.id.frame);
mScreenshotView = findViewById(R.id.screenshot);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#SuppressLint("WrongConstant")
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mWidth = width;
mHeight = height;
mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888,1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, null);
mSurface = mImageReader.getSurface();
new Thread(this).start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mRunning = false;
}
#Override
public void run() {
// 创建一个EGL实例
EGL10 egl = (EGL10) EGLContext.getEGL();
// 传教一个EGLDisplay实例
mEGLDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
// 初始化EGLDisplay实例
int[] version = new int[2];
egl.eglInitialize(mEGLDisplay, version);
int[] configSpec = {
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_ALPHA_SIZE, 8,
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_WINDOW_BIT,
EGL_RECORDABLE_ANDROID, 1,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
// 选择config创建OpenGL运行环境
egl.eglChooseConfig(mEGLDisplay, configSpec, configs, 1, num_config);
EGLConfig config = configs[0];
int ctxAttr[] = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 1,// 0x3098
EGL14.EGL_NONE
};
mEGLContext = egl.eglCreateContext(mEGLDisplay, config,
EGL10.EGL_NO_CONTEXT, ctxAttr);
// 创建新的surface
mDrawSurface = egl.eglCreateWindowSurface(mEGLDisplay, config, mSurfaceHolder, null);
mImageReaderSurface = egl.eglCreateWindowSurface(mEGLDisplay, config, mSurface, null);
// 将OpenGL环境设置为当前
egl.eglMakeCurrent(mEGLDisplay, mDrawSurface, mDrawSurface, mEGLContext);
// 获取当前OpenGL画布
GL10 gl = (GL10)mEGLContext.getGL();
mOpenGLDrawer = new OpenGLDrawer();
mOpenGLDrawer.setSize(gl, mWidth, mHeight);
mRunning = true;
while (mRunning) {
synchronized (mSurfaceHolder) {
render(gl);
// 显示绘制结果到屏幕上
egl.eglSwapBuffers(mEGLDisplay, mDrawSurface);
egl.eglMakeCurrent(mEGLDisplay, mImageReaderSurface, mImageReaderSurface, mEGLContext);
render(gl);
egl.eglSwapBuffers(mEGLDisplay, mImageReaderSurface);
egl.eglMakeCurrent(mEGLDisplay, mDrawSurface, mDrawSurface, mEGLContext);
}
SystemClock.sleep(333);
}
egl.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(mEGLDisplay, mDrawSurface);
egl.eglDestroyContext(mEGLDisplay, mEGLContext);
egl.eglTerminate(mEGLDisplay);
}
public void onTakeScreenshotClick(View view) {
synchronized (this) {
mIsCapturing = true;
}
}
private void render(GL10 gl) {
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
mOpenGLDrawer.draw(gl);
}
private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Log.d("reader", "onImageAvailable(ImageReader reader)");
Image image = reader.acquireNextImage();
if (image != null) {
Log.d("reader", "acquireLatestImage()");
synchronized (this) {
if (mIsCapturing) {
mIsCapturing = false;
int width = image.getWidth();
int height = image.getHeight();
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * width;
Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
final Rect src = new Rect(0,0, bitmap.getWidth(), bitmap.getHeight());
final RectF dst = new RectF(0,0, width, height);
canvas.drawBitmap(bitmap, src, dst, null);
mScreenshotView.post(() -> mScreenshotView.setImageBitmap(bmp));
mHandler.sendEmptyMessage(MSG_SHOW_SCREENSHOT);
}
}
image.close();
}
}
};
private Handler mHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(#NonNull Message msg) {
switch (msg.what) {
case MSG_SHOW_SCREENSHOT:
mFrameView.setVisibility(View.VISIBLE);
mHandler.sendEmptyMessageDelayed(MSG_HIDE_SCREENSHOT, 3000);
break;
case MSG_HIDE_SCREENSHOT:
mFrameView.setVisibility(View.GONE);
break;
default:
break;
}
return false;
}
});
}
Related
I am trying to detect a face on a photo that has been taken automatically but it doesnt work. After i capture the picture i send it to an ImageView and then i try to take it from their and make face detection. But there is the error, the bitmap requires R.drawble and i give R.id. I dont know what to use
Im a newbie
public class MainActivity extends AppCompatActivity {
public static int cameraID = 0;
public static boolean isBlack = true;
public static ImageView image;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.imgView);
Button btfront=(Button) findViewById(R.id.frontButton);
btfront.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
onFrontClick(v);
facedetection(v);
}
});
}
public void onFrontClick(View v){
RadioButton rdbBlack = (RadioButton) findViewById(R.id.rdb_black);
if(rdbBlack.isChecked()){
isBlack = true;
}else{
isBlack = false;
}
cameraID = 1;
Intent i = new Intent(MainActivity.this,CameraView.class);
startActivityForResult(i, 999);
}
public void onBackClick(View v){
RadioButton rdbBlack = (RadioButton) findViewById(R.id.rdb_black);
if(rdbBlack.isChecked()){
isBlack = true;
}else{
isBlack = false;
}
cameraID = 0;
Intent i = new Intent(MainActivity.this,CameraView.class);
startActivityForResult(i, 999);
}
public void facedetection(View v)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable=true;
Bitmap myBitmap = BitmapFactory.decodeResource(
getApplicationContext().getResources(),
R.id.imgView,
options);
Paint myRectPaint = new Paint();
myRectPaint.setStrokeWidth(5);
myRectPaint.setColor(Color.RED);
myRectPaint.setStyle(Paint.Style.STROKE);
Bitmap tempBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempBitmap);
tempCanvas.drawBitmap(myBitmap, 0, 0, null);
FaceDetector faceDetector = new
FaceDetector.Builder(getApplicationContext()).setTrackingEnabled(false)
.build();
if(!faceDetector.isOperational()){
new AlertDialog.Builder(v.getContext()).setMessage("Could not set up the face detector!").show();
return;
}
Frame frame = new Frame.Builder().setBitmap(myBitmap).build();
SparseArray<Face> faces = faceDetector.detect(frame);
for(int j=0; j<faces.size(); j++) {
Face thisFace = faces.valueAt(j);
float x1 = thisFace.getPosition().x;
float y1 = thisFace.getPosition().y;
float x2 = x1 + thisFace.getWidth();
float y2 = y1 + thisFace.getHeight();
tempCanvas.drawRoundRect(new RectF(x1, y1, x2, y2), 2, 2, myRectPaint);
}
image.setImageDrawable(new BitmapDrawable(getResources(),tempBitmap));
}
}
here is the class that i capture the photo
public class CameraView extends Activity implements SurfaceHolder.Callback, OnClickListener{
private static final String TAG = "CameraTest";
Camera mCamera;
boolean mPreviewRunning = false;
#SuppressWarnings("deprecation")
public void onCreate(Bundle icicle){
super.onCreate(icicle);
Log.e(TAG, "onCreate");
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.cameraview);
ImageView img = (ImageView) findViewById(R.id.blankImage);
if(MainActivity.isBlack)
img.setBackgroundResource(android.R.color.black);
else
img.setBackgroundResource(android.R.color.white);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceView.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
if (data != null){
//Intent mIntent = new Intent();
//mIntent.putExtra("image",imageData);
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
try{
BitmapFactory.Options opts = new BitmapFactory.Options();
Bitmap bitmap= BitmapFactory.decodeByteArray(data, 0, data.length,opts);
bitmap = Bitmap.createScaledBitmap(bitmap, 300, 300, false);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = 300;
int newHeight = 300;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// rotate the Bitmap
matrix.postRotate(-90);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
width, height, matrix, true);
MainActivity.image.setImageBitmap(resizedBitmap);
}catch(Exception e){
e.printStackTrace();
}
//StoreByteImage(mContext, imageData, 50,"ImageName");
//setResult(FOTO_MODE, mIntent);
setResult(585);
finish();
}
}
};
protected void onResume(){
Log.e(TAG, "onResume");
super.onResume();
}
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
}
protected void onStop(){
Log.e(TAG, "onStop");
super.onStop();
}
#TargetApi(9)
public void surfaceCreated(SurfaceHolder holder){
Log.e(TAG, "surfaceCreated");
mCamera = Camera.open(MainActivity.cameraID);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning){
mCamera.stopPreview();
}
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(300, 300);
if(MainActivity.cameraID == 0){
String stringFlashMode = p.getFlashMode();
if (stringFlashMode.equals("torch"))
p.setFlashMode("on"); // Light is set off, flash is set to normal 'on' mode
else
p.setFlashMode("torch");
}
mCamera.setParameters(p);
try{
mCamera.setPreviewDisplay(holder);
}catch (Exception e){
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
mCamera.takePicture(null, mPictureCallback, mPictureCallback);
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(TAG, "surfaceDestroyed");
//mCamera.stopPreview();
//mPreviewRunning = false;
//mCamera.release();
}
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
public void onClick(View v) {
// TODO Auto-generated method stub
mCamera.takePicture(null, mPictureCallback, mPictureCallback);
}
}
#Lefteris if its conversion you are looking at
ContextCompat.getDrawable(context, android.R.drawable.ic_dialog_email)
I use MediaPlayer to play videos with GPUImage effects apply to it. On certain devices, after a short while - a few seconds or more (seems random), the video stops playing (the image remains stuck), but audio keeps playing (most of the time). I target the MediaPlayer to a GLSurfaceView, in order to be able to use GPUImage effects on top of it.
Here is the custom view:
public class FilteredVideoView extends GLSurfaceView {
private MediaPlayer mMediaPlayer = null;
private long time = 0;
private MyCustomRenderer renderer;
private boolean mediaPlayerInitialized = false;
private String videoPath;
public FilteredVideoView(Context context) {
super(context);
setWillNotDraw(false);
init();
//startFilterChangeThread();
}
public void setFilter(MyGPUImageFilter filter) {
renderer.setFilter(filter);
}
public void stopVideo() {
mMediaPlayer.stop();
}
public void prepareVideo() {
try {
mMediaPlayer.prepare();
} catch (Exception e) {
}
}
public void playVideo() {
initMediaPlayer();
mMediaPlayer.seekTo(0);
mMediaPlayer.start();
}
private void init() {
setEGLContextClientVersion(2);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
mMediaPlayer = new MediaPlayer();
//initMediaPlayer();
renderer = new MyCustomRenderer(new MyNoFilterFilter(), mMediaPlayer);
setRenderer(renderer);
}
private void initMediaPlayer() {
if (mediaPlayerInitialized) {
return;
}
mediaPlayerInitialized = true;
try {
FileInputStream fi = new FileInputStream(new File(videoPath));
mMediaPlayer.setDataSource(fi.getFD());
mMediaPlayer.prepare();
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
onVideoPlaybackFinished();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
void onVideoPlaybackFinished() {
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}
}
And here is the renderer.
public class MyCustomRenderer implements Renderer, SurfaceTexture.OnFrameAvailableListener {
public static final int NO_IMAGE = -1;
public static final float CUBE[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
private MyGPUImageFilter mFilter;
public final Object mSurfaceChangedWaiter = new Object();
private int mTextureID = NO_IMAGE;
private SurfaceTexture mSurfaceTexture = null;
private final FloatBuffer mGLCubeBuffer;
private final FloatBuffer mGLTextureBuffer;
private IntBuffer mGLRgbBuffer;
private int mOutputWidth;
private int mOutputHeight;
private int mImageWidth;
private int mImageHeight;
private int mAddedPadding;
private final Queue<Runnable> mRunOnDraw;
private final Queue<Runnable> mRunOnDrawEnd;
private Rotation mRotation;
private boolean mFlipHorizontal;
private boolean mFlipVertical;
private GPUImage.ScaleType mScaleType = GPUImage.ScaleType.CENTER_CROP;
public SurfaceTexture mSurface;
public boolean updateSurface = false;
private MediaPlayer mMediaPlayer;
private int GL_TEXTURE_EXTERNAL_OES = 0x8D65;
private float[] mSTMatrix = new float[16];
public MyCustomRenderer(final MyGPUImageFilter filter, MediaPlayer mediaPlayer) {
mMediaPlayer = mediaPlayer;
mFilter = filter;
mRunOnDraw = new LinkedList<Runnable>();
mRunOnDrawEnd = new LinkedList<Runnable>();
mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
mGLCubeBuffer.put(CUBE).position(0);
mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
setRotation(Rotation.NORMAL, false, false);
Matrix.setIdentityM(mSTMatrix, 0);
}
#Override
public void onSurfaceCreated(final GL10 unused, final EGLConfig config) {
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
mTextureID = textures[0];
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);
mSurface = new SurfaceTexture(mTextureID);
mSurface.setOnFrameAvailableListener(this);
Surface surface = new Surface(mSurface);
mMediaPlayer.setSurface(surface);
surface.release();
synchronized (this) {
updateSurface = false;
}
GLES20.glClearColor(0, 0, 0, 1);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
mFilter.init();
//mMediaPlayer.start();
}
#Override
public void onSurfaceChanged(final GL10 gl, final int width, final int height) {
mOutputWidth = width;
mOutputHeight = height;
GLES20.glViewport(0, 0, width, height);
GLES20.glUseProgram(mFilter.getProgram());
mFilter.onOutputSizeChanged(width, height);
adjustImageScaling();
synchronized (mSurfaceChangedWaiter) {
mSurfaceChangedWaiter.notifyAll();
}
}
#Override
public void onDrawFrame(final GL10 gl) {
synchronized (this) {
if (updateSurface) {
mSurface.updateTexImage();
mSurface.getTransformMatrix(mSTMatrix);
updateSurface = false;
} else {
//return;
}
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
runAll(mRunOnDraw);
mFilter.onDraw(mTextureID, mGLCubeBuffer, mGLTextureBuffer);
runAll(mRunOnDrawEnd);
/*if (mSurfaceTexture != null) {
mSurfaceTexture.updateTexImage();
}*/
}
private void runAll(Queue<Runnable> queue) {
synchronized (queue) {
while (!queue.isEmpty()) {
queue.poll().run();
}
}
}
public void setFilter(final MyGPUImageFilter filter) {
runOnDraw(new Runnable() {
#Override
public void run() {
final MyGPUImageFilter oldFilter = mFilter;
mFilter = filter;
if (oldFilter != null) {
oldFilter.destroy();
}
mFilter.init();
GLES20.glUseProgram(mFilter.getProgram());
mFilter.onOutputSizeChanged(mOutputWidth, mOutputHeight);
}
});
}
public void deleteImage() {
runOnDraw(new Runnable() {
#Override
public void run() {
GLES20.glDeleteTextures(1, new int[]{
mTextureID
}, 0);
mTextureID = NO_IMAGE;
}
});
}
public void setScaleType(GPUImage.ScaleType scaleType) {
mScaleType = scaleType;
}
protected int getFrameWidth() {
return mOutputWidth;
}
protected int getFrameHeight() {
return mOutputHeight;
}
private void adjustImageScaling() {
float outputWidth = mOutputWidth;
float outputHeight = mOutputHeight;
if (mRotation == Rotation.ROTATION_270 || mRotation == Rotation.ROTATION_90) {
outputWidth = mOutputHeight;
outputHeight = mOutputWidth;
}
mImageWidth = App.screenW();
mImageHeight = App.screenH();
outputWidth = App.screenW();
outputHeight = App.screenH();
float ratio1 = outputWidth / mImageWidth;
float ratio2 = outputHeight / mImageHeight;
float ratioMax = Math.max(ratio1, ratio2);
int imageWidthNew = Math.round(mImageWidth * ratioMax);
int imageHeightNew = Math.round(mImageHeight * ratioMax);
float ratioWidth = imageWidthNew / outputWidth;
float ratioHeight = imageHeightNew / outputHeight;
float[] cube = CUBE;
float[] textureCords = TextureRotationUtil.getRotation(mRotation, mFlipHorizontal, mFlipVertical);
if (mScaleType == GPUImage.ScaleType.CENTER_CROP) {
float distHorizontal = (1 - 1 / ratioWidth) / 2;
float distVertical = (1 - 1 / ratioHeight) / 2;
textureCords = new float[]{
addDistance(textureCords[0], distHorizontal), addDistance(textureCords[1], distVertical),
addDistance(textureCords[2], distHorizontal), addDistance(textureCords[3], distVertical),
addDistance(textureCords[4], distHorizontal), addDistance(textureCords[5], distVertical),
addDistance(textureCords[6], distHorizontal), addDistance(textureCords[7], distVertical),
};
} else {
cube = new float[]{
CUBE[0] / ratioHeight, CUBE[1] / ratioWidth,
CUBE[2] / ratioHeight, CUBE[3] / ratioWidth,
CUBE[4] / ratioHeight, CUBE[5] / ratioWidth,
CUBE[6] / ratioHeight, CUBE[7] / ratioWidth,
};
}
mGLCubeBuffer.clear();
mGLCubeBuffer.put(cube).position(0);
mGLTextureBuffer.clear();
mGLTextureBuffer.put(textureCords).position(0);
}
private float addDistance(float coordinate, float distance) {
return coordinate == 0.0f ? distance : 1 - distance;
}
public void setRotationCamera(final Rotation rotation, final boolean flipHorizontal,
final boolean flipVertical) {
setRotation(rotation, flipVertical, flipHorizontal);
}
public void setRotation(final Rotation rotation) {
mRotation = rotation;
adjustImageScaling();
}
public void setRotation(final Rotation rotation,
final boolean flipHorizontal, final boolean flipVertical) {
mFlipHorizontal = flipHorizontal;
mFlipVertical = flipVertical;
setRotation(rotation);
}
public Rotation getRotation() {
return mRotation;
}
public boolean isFlippedHorizontally() {
return mFlipHorizontal;
}
public boolean isFlippedVertically() {
return mFlipVertical;
}
protected void runOnDraw(final Runnable runnable) {
synchronized (mRunOnDraw) {
mRunOnDraw.add(runnable);
}
}
protected void runOnDrawEnd(final Runnable runnable) {
synchronized (mRunOnDrawEnd) {
mRunOnDrawEnd.add(runnable);
}
}
#Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
updateSurface = true;
}
}
Any ideas what could be causing the issue? Maybe a memory-leak?
Thank you for your help!
I wanted to make some water ripples in my android application so I used this javascript code http://jsfiddle.net/esteewhy/5Ht3b/6/ converted into C code like it is shown here Live Wallpaper Water Ripple Effect (by esteewhy).
I have a main activity, which calls the water ripples activity after clicking a button. The water ripples are working great with my mutable bitmap, the problem is when I clicked the "back" button of the android device, the system crashes throwing this error:
FATAL EXCEPTION: Thread-2556
java.lang.NullPointerException
at com.wheelly.whater.WaterView.onDraw (line 149)
at com.wheelly.whater.WaterView$GameThread.run (line 255)
I guess there is some problem handling the Thread or the activities themselves.
Here is the code of the Water Ripples:
public class WaterView extends SurfaceView implements SurfaceHolder.Callback {
GameThread thread;
public static Bitmap icon;
//Measure frames per second.
long now;
int framesCount=0;
int framesCountAvg=0;
long framesTimer=0;
Paint fpsPaint=new Paint();
//Frame speed
long timeNow;
long timePrev = 0;
long timePrevFrame = 0;
long timeDelta;
private int width = 480;
private int height = 800;
private short riprad = 6;
boolean flip;
private short[] ripplemap, last_map;
Bitmap ripple;
private static final String TAG = null;
private Rippler rippler;
public WaterView(Context context) {
super(context);
initialize();
}
void initialize() {
//CB
icon = BitmapFactory.decodeResource(getResources(), R.drawable.sand100);
icon = convertToMutable(icon);
//--
rippler = new NativeRippler();
reinitgGlobals();
fpsPaint.setTextSize(30);
//Set thread
getHolder().addCallback(this);
setFocusable(true);
}
void reinitgGlobals() {
int size = width * (height + 2) * 2;
ripplemap = new short[size];
last_map = new short[size];
Bitmap texture = createBackground(width, height); // this creates a MUTABLE bitmap
ripple = texture;
_td = new int[width * height];
texture.getPixels(_td, 0, width, 0, 0, width, height);
_rd = new int[width * height];
}
void randomizer() {
final Random rnd = new Random();
final Handler disHAndler = new Handler();
final Runnable disturbWater = new Runnable() {
#Override
public void run() {
disturb(rnd.nextInt(width), rnd.nextInt(height));
disHAndler.postDelayed(this, 7000);
}
};
disHAndler.post(disturbWater);
}
private static Bitmap createBackground(int width, int height) {
Canvas cb = new Canvas (icon);
cb.save();
cb.restore();
return icon;
}
private Bitmap convertToMutable(Bitmap bitmap) {
try {
File file = new File("/mnt/sdcard/sample/temp.txt");
file.getParentFile().mkdirs();
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
int width_mutable = bitmap.getWidth();
int height_mutable = bitmap.getHeight();
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, width_mutable*height_mutable*4);
bitmap.copyPixelsToBuffer(map);
bitmap.recycle();
bitmap = Bitmap.createBitmap(width_mutable, height_mutable, Config.ARGB_8888);
map.position(0);
bitmap.copyPixelsFromBuffer(map);
channel.close();
randomAccessFile.close();
} catch (FileNotFoundException e) {
Log.i(TAG, "::onActivityResult:" + ""+Log.getStackTraceString(e));
} catch (IOException e) {
Log.i(TAG, "::onActivityResult:" + ""+Log.getStackTraceString(e));
}
return bitmap;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
reinitgGlobals();
}
#Override
protected void onDraw(android.graphics.Canvas canvas) {
super.onDraw(canvas);
newframe();
canvas.drawBitmap(ripple, 0, 0, null);
//Measure frame rate (unit: frames per second).
now=System.currentTimeMillis();
canvas.drawText(framesCountAvg+" fps", 40, 70, fpsPaint);
framesCount++;
if(now-framesTimer>1000) {
framesTimer=now;
framesCountAvg=framesCount;
framesCount=0;
}
}
/**
* Disturb water at specified point
*/
private void disturb(int dx, int dy) {
rippler.disturb(dx, dy, width, height, riprad, ripplemap, flip);
}
int[] _td;
int[] _rd;
/**
* Generates new ripples
*/
private void newframe() {
System.arraycopy(_td, 0, _rd, 0, width * height);
flip = !flip;
rippler.transformRipples(height, width, ripplemap, last_map, _td, _rd, flip);
ripple.setPixels(_rd, 0, width, 0, 0, width, height);
}
#Override
public synchronized boolean onTouchEvent(MotionEvent event) {
disturb((int)event.getX(), (int)event.getY());
return true;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
thread = new GameThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class GameThread extends Thread {
private SurfaceHolder surfaceHolder;
private WaterView gameView;
private boolean run = false;
public GameThread(SurfaceHolder surfaceHolder, WaterView gameView) {
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setRunning(boolean run) {
this.run = run;
}
public SurfaceHolder getSurfaceHolder() {
return surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (run) {
c = null;
//limit frame rate to max 60fps
timeNow = System.currentTimeMillis();
timeDelta = timeNow - timePrevFrame;
if ( timeDelta < 16) {
try {
Thread.sleep(16 - timeDelta);
}
catch(InterruptedException e) {
}
}
timePrevFrame = System.currentTimeMillis();
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
//call methods to draw and process next fame
gameView.onDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
I found the solution:
I had to interrupt the thread in the onPause method of the activity instead of doing it in the onStop method. Now it is just working fine.
Thanks a LOT to all of you for helping me with that problem.
you should shut down your working thread in the method Activity.onStop
#Override
protected void onStop() {
thread.interrupt();
super.onStop();
}
in the run method of GameThread check if thread was interrupted right before you call gameView.onDraw(c); like this:
if(isInterrupted()) {
break;
}
gameView.onDraw(c);
BTW, probably it would be better if you replace gameView.onDraw(c) with gameView.invalidate();
Don't call onDraw directly on a view, but rather call gameView.invalidate()
synchronized (surfaceHolder) {
//call methods to draw and process next fame
gameView.invalidate();
}
If it doesn't work, try using debugger with a breakpoint to see which variable is null exactly
I'm learning android and java and am trying to learn how to make a live wallpaper
I am using the aquarium tutorial, I put it all in one file instead of spreading it but what I am trying to do is get one scale number for everything, I want to get the height of the screen divide that by the background image height (which will always be bigger), this should give me a ratio to use for scaling everything, I tried this in a surfaceView code and it worked perfect, I tried it in livewallpaper and nada.
In the surfaceView test I use onSizeChange and got the height that way and it worked no problems.
This is what I did for the livewallpaper one
This is what I put for the onSurfaceChange
public int screenWidth;
public float rescaler;
public float totalHeight = theTemplate._backgroundImage.getHeight();
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//add rescale and width
screenWidth = width;
rescaler = (float) (height / totalHeight);
super.onSurfaceChanged(holder, format, width, height);
}
The background image comes from an inner class named TheTemplate
This is what I did there
The variables
private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float theScaler = theTest.rescaler;
then I try and rescale it using theScaler
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this._backgroundImage = BitmapFactory.decodeResource(context.getResources(),ca.samsstuff.testonepagewallpaper.R.drawable.sky, options);
this.theBackgroundImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
this.addSprites();
}
Then it passes it to draw the background
private void renderBackGround(Canvas canvas) {
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
Which sends it to draw
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
}
I keep getting errors and don't know what I am doing wrong. Like I said I am learning both android and java but this method worked in another test I did but I got the screen height from onSizeChange can I get the height by using onSurfaceChange?
Any help would be appreciated
Thanks in advance
sam
EDIT
I also tried to rescale within the theTemplate class just to see if it would work having everything within its own class and still having issues, I used the DisplayMetrics to get the screen height this time.
This might work if I can get it going properly.
Here is this attempt
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
private Bitmap theBackgroundImage;
private float theScaler = initFrameParams() / _backgroundImage.getHeight();
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
//get the screen height to use to rescale everything
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}
As I stated before any help would be appreciated.
Thanks again in advance
Sam
Edit SOLVED Here is an answer I came up with, The rescale code is where the comments are
Hope this helps someone out.
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
//private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float totalHeight = _backgroundImage.getHeight();
private int screenSized = initFrameParams();
private float theScaler = (float) (screenSized / totalHeight);
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}
I added the answer to the original post, hope this helps someone.
Sam
Sorry about that folks, new to this method of using a forum
Here is the answer, I added comments in the code where I made the changes for scaling images.
This method can also be used for positioning also.
Here is the answer.
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.sky);;
private Context _context;
// add rescale stuff
//private SpriteAnimationActivityEngine theTest;
private Bitmap theBackgroundImage;
private float totalHeight = _backgroundImage.getHeight();
private int screenSized = initFrameParams();
private float theScaler = (float) (screenSized / totalHeight);
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
int initFrameParams()
{
DisplayMetrics metrics = new DisplayMetrics();
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(metrics);
int screenHeight = display.getHeight();
return screenHeight;
}
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point(100, 100);
this._sprites.add(new SpriteOne(this._context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this._sprites.add(new SpriteOne(this._context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this._sprites.add(new SpriteOne(this._context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas)
{
canvas.drawBitmap(this.theBackgroundImage, 0, 0, null);
}
}
I am developing game in Android and got OpenGlContext error,any suggestions to overcome the same?
Below is my Code:
public class GLView extends SurfaceView implements SurfaceHolder.Callback
{
private OpenGLContext ctx;
private Tunnel3D tunnel;
private boolean created;
private GL10 gl;
private int w;
private int h;
private Bitmap bmp;
private int tex;
public GLView (Context context)
{
// Parent...
super (context);
getHolder ().addCallback (this);
// Internal members..
ctx = new OpenGLContext (OpenGLContext.DEPTH_BUFFER);
gl = (GL10)ctx.getGL ();
tunnel = new Tunnel3D (10, 20);
created = false;
// Enabling the state...
gl.glEnable (GL10.GL_DEPTH_TEST);
gl.glEnable (GL10.GL_TEXTURE_2D);
gl.glEnableClientState (GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState (GL10.GL_COLOR_ARRAY);
gl.glEnableClientState (GL10.GL_TEXTURE_COORD_ARRAY);
// Loading texture...
bmp = BitmapFactory.decodeResource (context.getResources(), R.drawable.plants03);
tex = loadTexture (gl, bmp);
}
public boolean surfaceCreated (SurfaceHolder holder)
{
synchronized (this)
{
created = true;
}
return true;
}
public void surfaceDestroyed (SurfaceHolder holder)
{
synchronized (this)
{
created = false;
}
}
public void surfaceChanged (SurfaceHolder holder, int format, int w, int h)
{
synchronized (this)
{
this.w = w;
this.h = h;
}
}
public void render ()
{
// Check the created flag...
boolean c = false;
synchronized (this)
{
c = created;
}
if (!c) return;
// Start the surface holder...
SurfaceHolder sh = getHolder ();
Canvas g = sh.lockCanvas ();
// Hooking GL with the view...
ctx.makeCurrent (g, null);
// Setting up the projection...
float ratio = (float)w / h;
gl.glMatrixMode (GL10.GL_PROJECTION);
gl.glLoadIdentity ();
gl.glViewport (0, 0, w, h);
GLU.gluPerspective (gl, 45.0f, ((float)w)/h, 1f, 100f);
// Setting up the modelview...
gl.glMatrixMode (GL10.GL_MODELVIEW);
gl.glLoadIdentity ();
// Clear the z-buffer...
gl.glClear (GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Render the tunnel...
tunnel.render (gl, -1.6f);
tunnel.nextFrame ();
// OpenGL finish
gl.glFlush ();
gl.glFinish ();
// Finish with hook
ctx.waitGL ();
// End the surface holder...
sh.unlockCanvasAndPost (g);
}
private int loadTexture (GL10 gl, Bitmap bmp)
{
ByteBuffer bb = ByteBuffer.allocateDirect(bmp.height()*bmp.width()*4);
bb.order(ByteOrder.nativeOrder());
IntBuffer ib = bb.asIntBuffer();
for (int y=0;y<bmp.height();y++)
for (int x=0;x<bmp.width();x++) {
ib.put(bmp.getPixel(x,y));
}
ib.position(0);
bb.position(0);
int[] tmp_tex = new int[1];
gl.glGenTextures(1, tmp_tex, 0);
int tex = tmp_tex[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, bmp.width(), bmp.height(), 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
return tex;
}
Use Android's GLSurfaceView instead of making your own wrapper. However, if you really want to make your own GL wrapper you should make a correct implementation, which you can find here.