synchronize access to the bitmap and owning canvas used first by

jni-sourced drawing and then by doDraw to put the bits on the screen.
This should fix crashes when screen orientation changes while
board_draw is running in the JNI thread, but for some reason the
emulators aren't signaling config changes so I can't test.
This commit is contained in:
eehouse 2010-02-20 19:19:45 +00:00
parent de58f33b4c
commit cbbf30d0b7
3 changed files with 38 additions and 13 deletions

View file

@ -13,7 +13,6 @@ import android.os.Handler;
import android.os.Message;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import android.content.res.Configuration;
import android.content.Intent;
import java.util.concurrent.Semaphore;
import android.net.Uri;
@ -168,7 +167,7 @@ public class BoardActivity extends Activity implements UtilCtxt {
}
m_jniThread = new
JNIThread( m_jniGamePtr, m_gi,
JNIThread( m_jniGamePtr, m_gi, m_view,
new Handler() {
public void handleMessage( Message msg ) {
switch( msg.what ) {

View file

@ -16,8 +16,8 @@ import android.graphics.drawable.BitmapDrawable;
import android.content.res.Resources;
import android.graphics.Paint.FontMetricsInt;
public class BoardView extends View implements DrawCtx,
BoardHandler {
public class BoardView extends View implements DrawCtx, BoardHandler,
SyncedDraw {
private Paint m_fillPaint;
private Paint m_strokePaint;
@ -26,8 +26,8 @@ public class BoardView extends View implements DrawCtx,
private CurGameInfo m_gi;
private int m_layoutWidth = 0;
private int m_layoutHeight = 0;
private Canvas m_canvas;
private Bitmap m_bitmap;
private Bitmap m_bitmap; // the board
private Canvas m_canvas; // owns the bitmap
private int m_trayOwner;
private Rect m_valRect;
private Rect m_letterRect;
@ -105,10 +105,14 @@ public class BoardView extends View implements DrawCtx,
return true; // required to get subsequent events
}
// This will be called from the UI thread
@Override
protected void onDraw( Canvas canvas )
{
if ( layoutBoardOnce() ) {
canvas.drawBitmap( m_bitmap, m_left, m_top, new Paint() );
synchronized( this ) {
if ( layoutBoardOnce() ) {
canvas.drawBitmap( m_bitmap, m_left, m_top, new Paint() );
}
}
}
@ -192,8 +196,9 @@ public class BoardView extends View implements DrawCtx,
layoutDone = true;
}
return layoutDone;
}
} // layoutBoardOnce
// BoardHandler interface implementation
public void startHandling( JNIThread thread, int gamePtr, CurGameInfo gi )
{
m_jniThread = thread;
@ -201,6 +206,18 @@ public class BoardView extends View implements DrawCtx,
m_gi = gi;
}
// SyncedDraw interface implementation
public void doJNIDraw()
{
boolean drew;
synchronized( this ) {
drew = XwJNI.board_draw( m_jniGamePtr );
}
if ( !drew ) {
Utils.logf( "draw not complete" );
}
}
// DrawCtxt interface implementation
public void scoreBegin( Rect rect, int numPlayers, int[] scores,
int remCount, int dfs )

View file

@ -51,6 +51,8 @@ public class JNIThread extends Thread {
private int m_jniGamePtr;
private CurGameInfo m_gi;
private Handler m_handler;
private SyncedDraw m_drawer;
LinkedBlockingQueue<QueueElem> m_queue;
private class QueueElem {
@ -62,10 +64,13 @@ public class JNIThread extends Thread {
Object[] m_args;
}
public JNIThread( int gamePtr, CurGameInfo gi, Handler handler ) {
public JNIThread( int gamePtr, CurGameInfo gi, SyncedDraw drawer,
Handler handler )
{
m_jniGamePtr = gamePtr;
m_gi = gi;
m_handler = handler;
m_drawer = drawer;
m_queue = new LinkedBlockingQueue<QueueElem>();
}
@ -303,9 +308,13 @@ public class JNIThread extends Thread {
}
if ( draw ) {
if ( !XwJNI.board_draw( m_jniGamePtr ) ) {
Utils.logf( "draw not complete" );
}
// do the drawing in this thread but in BoardView
// where it can be synchronized with that class's use
// of the same bitmap for blitting.
m_drawer.doJNIDraw();
// main UI thread has to invalidate view as it created
// it.
Message.obtain( m_handler, DRAW ).sendToTarget();
}
}