diff options
author | Jeff Sharkey <jsharkey@android.com> | 2013-02-20 21:41:29 -0800 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2013-02-20 22:34:42 -0800 |
commit | 9cae0a9616b1b71eac7e762d198fe1da47fea901 (patch) | |
tree | 8638176e3aa644eb7a274387b91cd9fc985e0d16 | |
parent | d439bacee510759728accb29ba93687a4e380eb6 (diff) | |
download | android_packages_apps_Terminal-9cae0a9616b1b71eac7e762d198fe1da47fea901.tar.gz android_packages_apps_Terminal-9cae0a9616b1b71eac7e762d198fe1da47fea901.tar.bz2 android_packages_apps_Terminal-9cae0a9616b1b71eac7e762d198fe1da47fea901.zip |
Add CellRun to speed up cell rendering.
Change to using CellRun class, and ask JNI to fill it until text
style changes. Switch to drawPosText(), which paints an entire run
at once.
Together these changes improve screen rendering times from 170ms
to only 7ms!
Change-Id: I62f12ffbb746c0c54191a15f395bbb80229cc959
-rw-r--r-- | jni/com_android_terminal_Terminal.cpp | 72 | ||||
-rw-r--r-- | src/com/android/terminal/Terminal.java | 17 | ||||
-rw-r--r-- | src/com/android/terminal/TerminalView.java | 42 |
3 files changed, 92 insertions, 39 deletions
diff --git a/jni/com_android_terminal_Terminal.cpp b/jni/com_android_terminal_Terminal.cpp index 31589aa..4a3fecb 100644 --- a/jni/com_android_terminal_Terminal.cpp +++ b/jni/com_android_terminal_Terminal.cpp @@ -60,15 +60,15 @@ static jmethodID bellMethod; static jmethodID resizeMethod; /* - * Cell class + * CellRun class */ -static jclass cellClass; -static jfieldID cellCharsField; - +static jclass cellRunClass; +static jfieldID cellRunDataField; +static jfieldID cellRunDataSizeField; +static jfieldID cellRunColSizeField; /* * Terminal session */ - class Terminal { public: Terminal(jobject callbacks, int rows, int cols); @@ -344,6 +344,7 @@ int Terminal::readLoop() { int Terminal::resize(short unsigned int rows, short unsigned int cols) { ALOGD("resize(%d, %d)", rows, cols); + // TODO: wait for resize event to propegate back from shell? mRows = rows; mCols = cols; struct winsize size = { rows, cols, 0, 0 }; @@ -395,29 +396,52 @@ static jint com_android_terminal_Terminal_nativeResize(JNIEnv* env, return term->resize(rows, cols); } -static jint com_android_terminal_Terminal_nativeGetCell(JNIEnv* env, - jclass clazz, jint ptr, jint row, jint col, jobject cell) { +static jint com_android_terminal_Terminal_nativeGetCellRun(JNIEnv* env, + jclass clazz, jint ptr, jint row, jint col, jobject run) { Terminal* term = reinterpret_cast<Terminal*>(ptr); + jcharArray dataArray = (jcharArray) env->GetObjectField(run, cellRunDataField); + jchar* data = env->GetCharArrayElements(dataArray, 0); + int dataLen = env->GetArrayLength(dataArray); + + VTermScreenCell cell; + memset(&cell, 0, sizeof(VTermScreenCell)); + VTermPos pos = { .row = row, .col = col, }; - VTermScreenCell termCell; - memset(&termCell, 0, sizeof(VTermScreenCell)); - int res = term->getCell(pos, &termCell); + int dataSize = 0; + int colSize = 0; + while (pos.col < term->getCols()) { + int res = term->getCell(pos, &cell); - //ALOGD("getCell(%d, %d, %s)", row, col, termCell.chars); + // TODO: terminate this loop once text style changes - // TODO: support full UTF-32 characters - // for testing, 0x00020000 should become 0xD840 0xDC00 + // TODO: remove this once terminal is resized + if (cell.width == 0) { + cell.width = 1; + } + + // TODO: support full UTF-32 characters + // for testing, 0x00020000 should become 0xD840 0xDC00 + int size = 1; + + // Only include cell chars if they fit into run + if (dataSize + size <= dataLen) { + data[dataSize] = cell.chars[0]; + dataSize += size; + colSize += cell.width; + pos.col += cell.width; + } else { + break; + } + } - jintArray charsArray = (jintArray)env->GetObjectField(cell, cellCharsField); - jint *chars = env->GetIntArrayElements(charsArray, 0); - chars[0] = termCell.chars[0]; - chars[1] = 0x00; - env->ReleaseIntArrayElements(charsArray, chars, 0); + env->ReleaseCharArrayElements(dataArray, data, 0); + env->SetIntField(run, cellRunDataSizeField, dataSize); + env->SetIntField(run, cellRunColSizeField, colSize); return 0; } @@ -436,7 +460,7 @@ static JNINativeMethod gMethods[] = { { "nativeInit", "(Lcom/android/terminal/TerminalCallbacks;II)I", (void*)com_android_terminal_Terminal_nativeInit }, { "nativeReadLoop", "(I)I", (void*)com_android_terminal_Terminal_nativeReadLoop }, { "nativeResize", "(III)I", (void*)com_android_terminal_Terminal_nativeResize }, - { "nativeGetCell", "(IIILcom/android/terminal/Terminal$Cell;)I", (void*)com_android_terminal_Terminal_nativeGetCell }, + { "nativeGetCellRun", "(IIILcom/android/terminal/Terminal$CellRun;)I", (void*)com_android_terminal_Terminal_nativeGetCellRun }, { "nativeGetRows", "(I)I", (void*)com_android_terminal_Terminal_nativeGetRows }, { "nativeGetCols", "(I)I", (void*)com_android_terminal_Terminal_nativeGetCols }, }; @@ -463,10 +487,12 @@ int register_com_android_terminal_Terminal(JNIEnv* env) { android::bellMethod = env->GetMethodID(terminalCallbacksClass, "bell", "()I"); android::resizeMethod = env->GetMethodID(terminalCallbacksClass, "resize", "(II)I"); - ScopedLocalRef<jclass> cellLocal(env, - env->FindClass("com/android/terminal/Terminal$Cell")); - cellClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellLocal.get())); - cellCharsField = env->GetFieldID(cellClass, "chars", "[C"); + ScopedLocalRef<jclass> cellRunLocal(env, + env->FindClass("com/android/terminal/Terminal$CellRun")); + cellRunClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellRunLocal.get())); + cellRunDataField = env->GetFieldID(cellRunClass, "data", "[C"); + cellRunDataSizeField = env->GetFieldID(cellRunClass, "dataSize", "I"); + cellRunColSizeField = env->GetFieldID(cellRunClass, "colSize", "I"); env->GetJavaVM(&gJavaVM); diff --git a/src/com/android/terminal/Terminal.java b/src/com/android/terminal/Terminal.java index 7d4197c..dfd370b 100644 --- a/src/com/android/terminal/Terminal.java +++ b/src/com/android/terminal/Terminal.java @@ -26,9 +26,14 @@ public class Terminal { System.loadLibrary("jni_terminal"); } - public static class Cell { - char[] chars = new char[2]; - int width = 1; + /** + * Represents a run of one or more {@code VTermScreenCell} which all have + * the same formatting. + */ + public static class CellRun { + char[] data; + int dataSize; + int colSize; boolean bold; int underline; @@ -97,8 +102,8 @@ public class Terminal { return nativeGetCols(mNativePtr); } - public void getCell(int row, int col, Cell cell) { - if (nativeGetCell(mNativePtr, row, col, cell) != 0) { + public void getCellRun(int row, int col, CellRun run) { + if (nativeGetCellRun(mNativePtr, row, col, run) != 0) { throw new IllegalStateException("getCell failed"); } } @@ -106,7 +111,7 @@ public class Terminal { private static native int nativeInit(TerminalCallbacks callbacks, int rows, int cols); private static native int nativeReadLoop(int ptr); private static native int nativeResize(int ptr, int rows, int cols); - private static native int nativeGetCell(int ptr, int row, int col, Cell cell); + private static native int nativeGetCellRun(int ptr, int row, int col, CellRun run); private static native int nativeGetRows(int ptr); private static native int nativeGetCols(int ptr); } diff --git a/src/com/android/terminal/TerminalView.java b/src/com/android/terminal/TerminalView.java index adbb0a7..33b651b 100644 --- a/src/com/android/terminal/TerminalView.java +++ b/src/com/android/terminal/TerminalView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Typeface; import android.graphics.Paint.FontMetrics; import android.graphics.Rect; import android.view.View; @@ -93,6 +94,7 @@ public class TerminalView extends View { } public void setTextSize(float textSize) { + mTextPaint.setTypeface(Typeface.MONOSPACE); mTextPaint.setTextSize(textSize); // Read metrics to get exact pixel dimensions @@ -126,6 +128,8 @@ public class TerminalView extends View { updateTerminalSize(); } } + + private static final int MAX_RUN_LENGTH = 128; @Override protected void onDraw(Canvas canvas) { @@ -136,28 +140,46 @@ public class TerminalView extends View { // Only draw dirty region of console final Rect dirty = canvas.getClipBounds(); + final int rows = mTerm.getRows(); + final int cols = mTerm.getCols(); + final int startRow = dirty.top / mCharHeight; - final int endRow = dirty.bottom / mCharHeight; + final int endRow = Math.min(dirty.bottom / mCharHeight, rows - 1); final int startCol = dirty.left / mCharWidth; - final int endCol = dirty.right / mCharWidth; + final int endCol = Math.min(dirty.right / mCharWidth, cols - 1); + + final Terminal.CellRun run = new Terminal.CellRun(); + run.data = new char[MAX_RUN_LENGTH]; - final Terminal.Cell cell = new Terminal.Cell(); + // Positions of each possible cell + // TODO: make sure this works with surrogate pairs + final float[] pos = new float[MAX_RUN_LENGTH * 2]; + for (int i = 0; i < MAX_RUN_LENGTH; i++) { + pos[i * 2] = i * mCharWidth; + pos[(i * 2) + 1] = -mCharTop; + } for (int row = startRow; row <= endRow; row++) { for (int col = startCol; col <= endCol;) { - mTerm.getCell(row, col, cell); + mTerm.getCellRun(row, col, run); - mBgPaint.setColor(cell.bgColor); - mTextPaint.setColor(cell.fgColor); + mBgPaint.setColor(run.bgColor); + mTextPaint.setColor(run.fgColor); final int y = row * mCharHeight; final int x = col * mCharWidth; - final int xEnd = x + (cell.width * mCharWidth); + final int xEnd = x + (run.colSize * mCharWidth); + + canvas.save(Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG); + canvas.translate(x, y); + canvas.clipRect(0, 0, run.colSize * mCharWidth, mCharHeight); + + canvas.drawPaint(mBgPaint); + canvas.drawPosText(run.data, 0, run.dataSize, pos, mTextPaint); - canvas.drawRect(x, y, xEnd, y + mCharHeight, mBgPaint); - canvas.drawText(cell.chars, 0, cell.chars.length, x, y - mCharTop, mTextPaint); + canvas.restore(); - col += cell.width; + col += run.colSize; } } |