summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2013-02-20 21:41:29 -0800
committerJeff Sharkey <jsharkey@android.com>2013-02-20 22:34:42 -0800
commit9cae0a9616b1b71eac7e762d198fe1da47fea901 (patch)
tree8638176e3aa644eb7a274387b91cd9fc985e0d16
parentd439bacee510759728accb29ba93687a4e380eb6 (diff)
downloadandroid_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.cpp72
-rw-r--r--src/com/android/terminal/Terminal.java17
-rw-r--r--src/com/android/terminal/TerminalView.java42
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;
}
}