Merge "Better API for low disk space warnings."
diff --git a/api/current.txt b/api/current.txt
index 536a2c8..50438e6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20116,6 +20116,9 @@
method public static android.renderscript.Sampler CLAMP_LINEAR(android.renderscript.RenderScript);
method public static android.renderscript.Sampler CLAMP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
method public static android.renderscript.Sampler CLAMP_NEAREST(android.renderscript.RenderScript);
+ method public static android.renderscript.Sampler MIRRORED_REPEAT_LINEAR(android.renderscript.RenderScript);
+ method public static android.renderscript.Sampler MIRRORED_REPEAT_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
+ method public static android.renderscript.Sampler MIRRORED_REPEAT_NEAREST(android.renderscript.RenderScript);
method public static android.renderscript.Sampler WRAP_LINEAR(android.renderscript.RenderScript);
method public static android.renderscript.Sampler WRAP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript);
method public static android.renderscript.Sampler WRAP_NEAREST(android.renderscript.RenderScript);
@@ -20143,6 +20146,7 @@
enum_constant public static final android.renderscript.Sampler.Value LINEAR;
enum_constant public static final android.renderscript.Sampler.Value LINEAR_MIP_LINEAR;
enum_constant public static final android.renderscript.Sampler.Value LINEAR_MIP_NEAREST;
+ enum_constant public static final android.renderscript.Sampler.Value MIRRORED_REPEAT;
enum_constant public static final android.renderscript.Sampler.Value NEAREST;
enum_constant public static final android.renderscript.Sampler.Value WRAP;
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 9ad33a5..b678df7 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -227,6 +227,7 @@
String libDir = (appInfo.nativeLibraryDir != null)
? new File(appInfo.nativeLibraryDir).getCanonicalPath()
: null;
+ String externalFilesDir = getExternalFilesDir(null).getCanonicalPath();
// Filters, the scan queue, and the set of resulting entities
HashSet<String> filterSet = new HashSet<String>();
@@ -254,6 +255,12 @@
filterSet.add(databaseDir);
filterSet.remove(sharedPrefsDir);
fullBackupFileTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, sharedPrefsDir, filterSet, data);
+
+ // getExternalFilesDir() location associated with this app. Technically there should
+ // not be any files here if the app does not properly have permission to access
+ // external storage, but edge cases happen. fullBackupFileTree() catches
+ // IOExceptions and similar, and treats them as non-fatal, so we rely on that here.
+ fullBackupFileTree(packageName, FullBackup.MANAGED_EXTERNAL_TREE_TOKEN, externalFilesDir, null, data);
}
/**
@@ -274,6 +281,7 @@
String spDir;
String cacheDir;
String libDir;
+ String efDir;
String filePath;
ApplicationInfo appInfo = getApplicationInfo();
@@ -287,6 +295,7 @@
libDir = (appInfo.nativeLibraryDir == null)
? null
: new File(appInfo.nativeLibraryDir).getCanonicalPath();
+ efDir = getExternalFilesDir(null).getCanonicalPath();
// Now figure out which well-defined tree the file is placed in, working from
// most to least specific. We also specifically exclude the lib and cache dirs.
@@ -315,6 +324,9 @@
} else if (filePath.startsWith(mainDir)) {
domain = FullBackup.ROOT_TREE_TOKEN;
rootpath = mainDir;
+ } else if (filePath.startsWith(efDir)) {
+ domain = FullBackup.MANAGED_EXTERNAL_TREE_TOKEN;
+ rootpath = efDir;
} else {
Log.w(TAG, "File " + filePath + " is in an unsupported location; skipping");
return;
@@ -438,6 +450,8 @@
basePath = getSharedPrefsFile("foo").getParentFile().getCanonicalPath();
} else if (domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
basePath = getCacheDir().getCanonicalPath();
+ } else if (domain.equals(FullBackup.MANAGED_EXTERNAL_TREE_TOKEN)) {
+ basePath = getExternalFilesDir(null).getCanonicalPath();
} else {
// Not a supported location
Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring");
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index f859599..2fe08f3 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -46,6 +46,7 @@
public static final String DATA_TREE_TOKEN = "f";
public static final String DATABASE_TREE_TOKEN = "db";
public static final String SHAREDPREFS_TREE_TOKEN = "sp";
+ public static final String MANAGED_EXTERNAL_TREE_TOKEN = "ef";
public static final String CACHE_TREE_TOKEN = "c";
public static final String SHARED_STORAGE_TOKEN = "shared";
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 3e33e8e..ab8f82f 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -20,10 +20,12 @@
import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
/**
* Speech synthesis request that writes the audio to a WAV file.
@@ -39,16 +41,19 @@
private static final short WAV_FORMAT_PCM = 0x0001;
private final Object mStateLock = new Object();
- private final File mFileName;
+
private int mSampleRateInHz;
private int mAudioFormat;
private int mChannelCount;
- private RandomAccessFile mFile;
+
+ private FileChannel mFileChannel;
+
+ private boolean mStarted = false;
private boolean mStopped = false;
private boolean mDone = false;
- FileSynthesisCallback(File fileName) {
- mFileName = fileName;
+ FileSynthesisCallback(FileChannel fileChannel) {
+ mFileChannel = fileChannel;
}
@Override
@@ -63,54 +68,23 @@
* Must be called while holding the monitor on {@link #mStateLock}.
*/
private void cleanUp() {
- closeFileAndWidenPermissions();
- if (mFile != null) {
- mFileName.delete();
- }
+ closeFile();
}
/**
* Must be called while holding the monitor on {@link #mStateLock}.
*/
- private void closeFileAndWidenPermissions() {
+ private void closeFile() {
try {
- if (mFile != null) {
- mFile.close();
- mFile = null;
+ if (mFileChannel != null) {
+ mFileChannel.close();
+ mFileChannel = null;
}
} catch (IOException ex) {
- Log.e(TAG, "Failed to close " + mFileName + ": " + ex);
- }
-
- try {
- // Make the written file readable and writeable by everyone.
- // This allows the app that requested synthesis to read the file.
- //
- // Note that the directory this file was written must have already
- // been world writeable in order it to have been
- // written to in the first place.
- FileUtils.setPermissions(mFileName.getAbsolutePath(), 0666, -1, -1); //-rw-rw-rw
- } catch (SecurityException se) {
- Log.e(TAG, "Security exception setting rw permissions on : " + mFileName);
+ Log.e(TAG, "Failed to close output file descriptor", ex);
}
}
- /**
- * Checks whether a given file exists, and deletes it if it does.
- */
- private boolean maybeCleanupExistingFile(File file) {
- if (file.exists()) {
- Log.v(TAG, "File " + file + " exists, deleting.");
- if (!file.delete()) {
- Log.e(TAG, "Failed to delete " + file);
- return false;
- }
- }
-
- return true;
- }
-
-
@Override
public int getMaxBufferSize() {
return MAX_AUDIO_BUFFER_SIZE;
@@ -132,25 +106,20 @@
if (DBG) Log.d(TAG, "Request has been aborted.");
return TextToSpeech.ERROR;
}
- if (mFile != null) {
+ if (mStarted) {
cleanUp();
throw new IllegalArgumentException("FileSynthesisRequest.start() called twice");
}
-
- if (!maybeCleanupExistingFile(mFileName)) {
- return TextToSpeech.ERROR;
- }
-
+ mStarted = true;
mSampleRateInHz = sampleRateInHz;
mAudioFormat = audioFormat;
mChannelCount = channelCount;
+
try {
- mFile = new RandomAccessFile(mFileName, "rw");
- // Reserve space for WAV header
- mFile.write(new byte[WAV_HEADER_LENGTH]);
+ mFileChannel.write(ByteBuffer.allocate(WAV_HEADER_LENGTH));
return TextToSpeech.SUCCESS;
} catch (IOException ex) {
- Log.e(TAG, "Failed to open " + mFileName + ": " + ex);
+ Log.e(TAG, "Failed to write wav header to output file descriptor" + ex);
cleanUp();
return TextToSpeech.ERROR;
}
@@ -168,15 +137,15 @@
if (DBG) Log.d(TAG, "Request has been aborted.");
return TextToSpeech.ERROR;
}
- if (mFile == null) {
+ if (mFileChannel == null) {
Log.e(TAG, "File not open");
return TextToSpeech.ERROR;
}
try {
- mFile.write(buffer, offset, length);
+ mFileChannel.write(ByteBuffer.wrap(buffer, offset, length));
return TextToSpeech.SUCCESS;
} catch (IOException ex) {
- Log.e(TAG, "Failed to write to " + mFileName + ": " + ex);
+ Log.e(TAG, "Failed to write to output file descriptor", ex);
cleanUp();
return TextToSpeech.ERROR;
}
@@ -197,21 +166,21 @@
if (DBG) Log.d(TAG, "Request has been aborted.");
return TextToSpeech.ERROR;
}
- if (mFile == null) {
+ if (mFileChannel == null) {
Log.e(TAG, "File not open");
return TextToSpeech.ERROR;
}
try {
// Write WAV header at start of file
- mFile.seek(0);
- int dataLength = (int) (mFile.length() - WAV_HEADER_LENGTH);
- mFile.write(
+ mFileChannel.position(0);
+ int dataLength = (int) (mFileChannel.size() - WAV_HEADER_LENGTH);
+ mFileChannel.write(
makeWavHeader(mSampleRateInHz, mAudioFormat, mChannelCount, dataLength));
- closeFileAndWidenPermissions();
+ closeFile();
mDone = true;
return TextToSpeech.SUCCESS;
} catch (IOException ex) {
- Log.e(TAG, "Failed to write to " + mFileName + ": " + ex);
+ Log.e(TAG, "Failed to write to output file descriptor", ex);
cleanUp();
return TextToSpeech.ERROR;
}
@@ -226,7 +195,7 @@
}
}
- private byte[] makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
+ private ByteBuffer makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
int dataLength) {
// TODO: is AudioFormat.ENCODING_DEFAULT always the same as ENCODING_PCM_16BIT?
int sampleSizeInBytes = (audioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
@@ -251,8 +220,9 @@
header.putShort(bitsPerSample);
header.put(new byte[]{ 'd', 'a', 't', 'a' });
header.putInt(dataLength);
+ header.flip();
- return headerBuf;
+ return header;
}
}
diff --git a/core/java/android/speech/tts/ITextToSpeechService.aidl b/core/java/android/speech/tts/ITextToSpeechService.aidl
index 6982029..b7bc70c 100644
--- a/core/java/android/speech/tts/ITextToSpeechService.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechService.aidl
@@ -18,6 +18,7 @@
import android.net.Uri;
import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
import android.speech.tts.ITextToSpeechCallback;
/**
@@ -44,11 +45,12 @@
* @param callingInstance a binder representing the identity of the calling
* TextToSpeech object.
* @param text The text to synthesize.
- * @param filename The file to write the synthesized audio to.
+ * @param fileDescriptor The file descriptor to write the synthesized audio to. Has to be
+ writable.
* @param param Request parameters.
*/
- int synthesizeToFile(in IBinder callingInstance, in String text,
- in String filename, in Bundle params);
+ int synthesizeToFileDescriptor(in IBinder callingInstance, in String text,
+ in ParcelFileDescriptor fileDescriptor, in Bundle params);
/**
* Plays an existing audio resource.
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index c1af7a5..73d400e 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -27,11 +27,15 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1225,8 +1229,29 @@
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
- return service.synthesizeToFile(getCallerIdentity(), text, filename,
- getParams(params));
+ ParcelFileDescriptor fileDescriptor;
+ int returnValue;
+ try {
+ File file = new File(filename);
+ if(file.exists() && !file.canWrite()) {
+ Log.e(TAG, "Can't write to " + filename);
+ return ERROR;
+ }
+ fileDescriptor = ParcelFileDescriptor.open(file,
+ ParcelFileDescriptor.MODE_WRITE_ONLY |
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE);
+ returnValue = service.synthesizeToFileDescriptor(getCallerIdentity(), text,
+ fileDescriptor, getParams(params));
+ fileDescriptor.close();
+ return returnValue;
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Opening file " + filename + " failed", e);
+ return ERROR;
+ } catch (IOException e) {
+ Log.e(TAG, "Closing file " + filename + " failed", e);
+ return ERROR;
+ }
}
}, ERROR, "synthesizeToFile");
}
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4054740..1bcf3e0 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -26,6 +26,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
@@ -33,7 +34,8 @@
import android.text.TextUtils;
import android.util.Log;
-import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -654,19 +656,19 @@
}
}
- private class SynthesisToFileSpeechItem extends SynthesisSpeechItem {
- private final File mFile;
+ private class SynthesisToFileSpeechDescriptorItem extends SynthesisSpeechItem {
+ private final FileDescriptor mFileDescriptor;
- public SynthesisToFileSpeechItem(Object callerIdentity, int callerUid, int callerPid,
- Bundle params, String text,
- File file) {
+ public SynthesisToFileSpeechDescriptorItem(Object callerIdentity, int callerUid,
+ int callerPid, Bundle params, String text, FileDescriptor fileDescriptor) {
super(callerIdentity, callerUid, callerPid, params, text);
- mFile = file;
+ mFileDescriptor = fileDescriptor;
}
@Override
protected AbstractSynthesisCallback createSynthesisCallback() {
- return new FileSynthesisCallback(mFile);
+ FileOutputStream fileOutputStream = new FileOutputStream(mFileDescriptor);
+ return new FileSynthesisCallback(fileOutputStream.getChannel());
}
@Override
@@ -797,15 +799,15 @@
}
@Override
- public int synthesizeToFile(IBinder caller, String text, String filename,
- Bundle params) {
- if (!checkNonNull(caller, text, filename, params)) {
+ public int synthesizeToFileDescriptor(IBinder caller, String text, ParcelFileDescriptor
+ fileDescriptor, Bundle params) {
+ if (!checkNonNull(caller, text, fileDescriptor, params)) {
return TextToSpeech.ERROR;
}
- File file = new File(filename);
- SpeechItem item = new SynthesisToFileSpeechItem(caller, Binder.getCallingUid(),
- Binder.getCallingPid(), params, text, file);
+ SpeechItem item = new SynthesisToFileSpeechDescriptorItem(caller, Binder.getCallingUid(),
+ Binder.getCallingPid(), params, text,
+ fileDescriptor.getFileDescriptor());
return mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item);
}
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
index 0c8cbe6..0635559 100644
--- a/core/java/android/test/AndroidTestCase.java
+++ b/core/java/android/test/AndroidTestCase.java
@@ -20,9 +20,11 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+
import junit.framework.TestCase;
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
/**
* Extend this if you need to access Resources or other things that depend on Activity Context.
@@ -152,11 +154,11 @@
* @throws IllegalAccessException
*/
protected void scrubClass(final Class<?> testCaseClass)
- throws IllegalAccessException {
+ throws IllegalAccessException {
final Field[] fields = getClass().getDeclaredFields();
for (Field field : fields) {
- final Class<?> fieldClass = field.getDeclaringClass();
- if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()) {
+ if (!field.getType().isPrimitive() &&
+ !Modifier.isStatic(field.getModifiers())) {
try {
field.setAccessible(true);
field.set(this, null);
@@ -170,6 +172,4 @@
}
}
}
-
-
}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 9ddb32e..28c1058 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -213,6 +213,7 @@
private OnDoubleTapListener mDoubleTapListener;
private boolean mStillDown;
+ private boolean mDeferConfirmSingleTap;
private boolean mInLongPress;
private boolean mAlwaysInTapRegion;
private boolean mAlwaysInBiggerTapRegion;
@@ -267,8 +268,12 @@
case TAP:
// If the user's finger is still down, do not count it as a tap
- if (mDoubleTapListener != null && !mStillDown) {
- mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
+ if (mDoubleTapListener != null) {
+ if (!mStillDown) {
+ mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
+ } else {
+ mDeferConfirmSingleTap = true;
+ }
}
break;
@@ -533,6 +538,7 @@
mAlwaysInBiggerTapRegion = true;
mStillDown = true;
mInLongPress = false;
+ mDeferConfirmSingleTap = false;
if (mIsLongpressEnabled) {
mHandler.removeMessages(LONG_PRESS);
@@ -586,6 +592,9 @@
mInLongPress = false;
} else if (mAlwaysInTapRegion) {
handled = mListener.onSingleTapUp(ev);
+ if (mDeferConfirmSingleTap && mDoubleTapListener != null) {
+ mDoubleTapListener.onSingleTapConfirmed(ev);
+ }
} else {
// A fling must travel the minimum tap distance
@@ -612,6 +621,7 @@
mVelocityTracker = null;
}
mIsDoubleTapping = false;
+ mDeferConfirmSingleTap = false;
mHandler.removeMessages(SHOW_PRESS);
mHandler.removeMessages(LONG_PRESS);
break;
@@ -637,6 +647,7 @@
mStillDown = false;
mAlwaysInTapRegion = false;
mAlwaysInBiggerTapRegion = false;
+ mDeferConfirmSingleTap = false;
if (mInLongPress) {
mInLongPress = false;
}
@@ -649,6 +660,7 @@
mIsDoubleTapping = false;
mAlwaysInTapRegion = false;
mAlwaysInBiggerTapRegion = false;
+ mDeferConfirmSingleTap = false;
if (mInLongPress) {
mInLongPress = false;
}
@@ -671,6 +683,7 @@
private void dispatchLongPress() {
mHandler.removeMessages(TAP);
+ mDeferConfirmSingleTap = false;
mInLongPress = true;
mListener.onLongPress(mCurrentDownEvent);
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 63f0e1f..de64e14 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -32,6 +32,20 @@
public class Surface implements Parcelable {
private static final String TAG = "Surface";
+ private static native int nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
+ throws OutOfResourcesException;
+
+ private native Canvas nativeLockCanvas(int nativeObject, Rect dirty);
+ private native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas);
+
+ private static native void nativeRelease(int nativeObject);
+ private static native void nativeDestroy(int nativeObject);
+ private static native boolean nativeIsValid(int nativeObject);
+ private static native boolean nativeIsConsumerRunningBehind(int nativeObject);
+ private static native int nativeCopyFrom(int nativeObject, int surfaceControlNativeObject);
+ private static native int nativeReadFromParcel(int nativeObject, Parcel source);
+ private static native void nativeWriteToParcel(int nativeObject, Parcel dest);
+
public static final Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
public Surface createFromParcel(Parcel source) {
@@ -44,33 +58,11 @@
return null;
}
}
-
public Surface[] newArray(int size) {
return new Surface[size];
}
};
- /**
- * Rotation constant: 0 degree rotation (natural orientation)
- */
- public static final int ROTATION_0 = 0;
-
- /**
- * Rotation constant: 90 degree rotation.
- */
- public static final int ROTATION_90 = 1;
-
- /**
- * Rotation constant: 180 degree rotation.
- */
- public static final int ROTATION_180 = 2;
-
- /**
- * Rotation constant: 270 degree rotation.
- */
- public static final int ROTATION_270 = 3;
-
-
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
@@ -95,6 +87,28 @@
/**
+ * Rotation constant: 0 degree rotation (natural orientation)
+ */
+ public static final int ROTATION_0 = 0;
+
+ /**
+ * Rotation constant: 90 degree rotation.
+ */
+ public static final int ROTATION_90 = 1;
+
+ /**
+ * Rotation constant: 180 degree rotation.
+ */
+ public static final int ROTATION_180 = 2;
+
+ /**
+ * Rotation constant: 270 degree rotation.
+ */
+ public static final int ROTATION_270 = 3;
+
+
+
+ /**
* Create an empty surface, which will later be filled in by readFromParcel().
* @hide
*/
@@ -436,20 +450,4 @@
if (mNativeObject == 0) throw new NullPointerException(
"mNativeObject is null. Have you called release() already?");
}
-
- private native int nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
- throws OutOfResourcesException;
-
- private native void nativeRelease(int nativeObject);
- private native void nativeDestroy(int nativeObject);
- private native boolean nativeIsValid(int nativeObject);
-
- private native boolean nativeIsConsumerRunningBehind(int nativeObject);
-
- private native Canvas nativeLockCanvas(int nativeObject, Rect dirty);
- private native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas);
-
- private native int nativeCopyFrom(int nativeObject, int surfaceControlNativeObject);
- private native int nativeReadFromParcel(int nativeObject, Parcel source);
- private native void nativeWriteToParcel(int nativeObject, Parcel dest);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index dd288b9..9f50065 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -30,6 +30,46 @@
*/
public class SurfaceControl {
private static final String TAG = "SurfaceControl";
+
+ private static native int nativeCreate(SurfaceSession session, String name,
+ int w, int h, int format, int flags)
+ throws OutOfResourcesException;
+ private static native void nativeRelease(int nativeObject);
+ private static native void nativeDestroy(int nativeObject);
+
+ private static native Bitmap nativeScreenshot(IBinder displayToken,
+ int width, int height, int minLayer, int maxLayer, boolean allLayers);
+
+ private static native void nativeOpenTransaction();
+ private static native void nativeCloseTransaction();
+ private static native void nativeSetAnimationTransaction();
+
+ private static native void nativeSetLayer(int nativeObject, int zorder);
+ private static native void nativeSetPosition(int nativeObject, float x, float y);
+ private static native void nativeSetSize(int nativeObject, int w, int h);
+ private static native void nativeSetTransparentRegionHint(int nativeObject, Region region);
+ private static native void nativeSetAlpha(int nativeObject, float alpha);
+ private static native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
+ private static native void nativeSetFlags(int nativeObject, int flags, int mask);
+ private static native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b);
+ private static native void nativeSetLayerStack(int nativeObject, int layerStack);
+
+ private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
+ private static native IBinder nativeCreateDisplay(String name, boolean secure);
+ private static native void nativeSetDisplaySurface(
+ IBinder displayToken, int nativeSurfaceObject);
+ private static native void nativeSetDisplayLayerStack(
+ IBinder displayToken, int layerStack);
+ private static native void nativeSetDisplayProjection(
+ IBinder displayToken, int orientation,
+ int l, int t, int r, int b,
+ int L, int T, int R, int B);
+ private static native boolean nativeGetDisplayInfo(
+ IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
+ private static native void nativeBlankDisplay(IBinder displayToken);
+ private static native void nativeUnblankDisplay(IBinder displayToken);
+
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
int mNativeObject; // package visibility only for Surface.java access
@@ -532,44 +572,4 @@
throw new UnsupportedOperationException("Device is headless");
}
}
-
-
-
- private native int nativeCreate(SurfaceSession session, String name,
- int w, int h, int format, int flags)
- throws OutOfResourcesException;
- private native void nativeRelease(int nativeObject);
- private native void nativeDestroy(int nativeObject);
-
- private static native Bitmap nativeScreenshot(IBinder displayToken,
- int width, int height, int minLayer, int maxLayer, boolean allLayers);
-
- private static native void nativeOpenTransaction();
- private static native void nativeCloseTransaction();
- private static native void nativeSetAnimationTransaction();
-
- private native void nativeSetLayer(int nativeObject, int zorder);
- private native void nativeSetPosition(int nativeObject, float x, float y);
- private native void nativeSetSize(int nativeObject, int w, int h);
- private native void nativeSetTransparentRegionHint(int nativeObject, Region region);
- private native void nativeSetAlpha(int nativeObject, float alpha);
- private native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
- private native void nativeSetFlags(int nativeObject, int flags, int mask);
- private native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b);
- private native void nativeSetLayerStack(int nativeObject, int layerStack);
-
- private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
- private static native IBinder nativeCreateDisplay(String name, boolean secure);
- private static native void nativeSetDisplaySurface(
- IBinder displayToken, int nativeSurfaceObject);
- private static native void nativeSetDisplayLayerStack(
- IBinder displayToken, int layerStack);
- private static native void nativeSetDisplayProjection(
- IBinder displayToken, int orientation,
- int l, int t, int r, int b,
- int L, int T, int R, int B);
- private static native boolean nativeGetDisplayInfo(
- IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
- private static native void nativeBlankDisplay(IBinder displayToken);
- private static native void nativeUnblankDisplay(IBinder displayToken);
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index a4347a4..3ded1cd 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -1254,6 +1254,40 @@
mAutoFillData = new WebViewCore.AutoFillData();
mEditTextScroller = new Scroller(context);
+
+ // Calculate channel distance
+ calculateChannelDistance(context);
+ }
+
+ /**
+ * Calculate sChannelDistance based on the screen information.
+ * @param context A Context object used to access application assets.
+ */
+ private void calculateChannelDistance(Context context) {
+ // The channel distance is adjusted for density and screen size
+ final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ final double screenSize = Math.hypot((double)(metrics.widthPixels/metrics.densityDpi),
+ (double)(metrics.heightPixels/metrics.densityDpi));
+ if (screenSize < 3.0) {
+ sChannelDistance = 16;
+ } else if (screenSize < 5.0) {
+ sChannelDistance = 22;
+ } else if (screenSize < 7.0) {
+ sChannelDistance = 28;
+ } else {
+ sChannelDistance = 34;
+ }
+ sChannelDistance = (int)(sChannelDistance * metrics.density);
+ if (sChannelDistance < 16) sChannelDistance = 16;
+
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "sChannelDistance : " + sChannelDistance
+ + ", density : " + metrics.density
+ + ", screenSize : " + screenSize
+ + ", metrics.heightPixels : " + metrics.heightPixels
+ + ", metrics.widthPixels : " + metrics.widthPixels
+ + ", metrics.densityDpi : " + metrics.densityDpi);
+ }
}
// WebViewProvider bindings
@@ -5718,32 +5752,13 @@
}
return mWebViewPrivate.super_dispatchKeyEvent(event);
}
-
- /*
- * Here is the snap align logic:
- * 1. If it starts nearly horizontally or vertically, snap align;
- * 2. If there is a dramitic direction change, let it go;
- *
- * Adjustable parameters. Angle is the radians on a unit circle, limited
- * to quadrant 1. Values range from 0f (horizontal) to PI/2 (vertical)
- */
- private static final float HSLOPE_TO_START_SNAP = .25f;
- private static final float HSLOPE_TO_BREAK_SNAP = .4f;
- private static final float VSLOPE_TO_START_SNAP = 1.25f;
- private static final float VSLOPE_TO_BREAK_SNAP = .95f;
- /*
- * These values are used to influence the average angle when entering
- * snap mode. If is is the first movement entering snap, we set the average
- * to the appropriate ideal. If the user is entering into snap after the
- * first movement, then we average the average angle with these values.
- */
- private static final float ANGLE_VERT = 2f;
- private static final float ANGLE_HORIZ = 0f;
- /*
- * The modified moving average weight.
- * Formula: MAV[t]=MAV[t-1] + (P[t]-MAV[t-1])/n
- */
- private static final float MMA_WEIGHT_N = 5;
+
+ private static final int SNAP_BOUND = 16;
+ private static int sChannelDistance = 16;
+ private int mFirstTouchX = -1; // the first touched point
+ private int mFirstTouchY = -1;
+ private int mDistanceX = 0;
+ private int mDistanceY = 0;
private boolean inFullScreenMode() {
return mFullScreenHolder != null;
@@ -5833,12 +5848,6 @@
}
}
- private float calculateDragAngle(int dx, int dy) {
- dx = Math.abs(dx);
- dy = Math.abs(dy);
- return (float) Math.atan2(dy, dx);
- }
-
/*
* Common code for single touch and multi-touch.
* (x, y) denotes current focus point, which is the touch point for single touch
@@ -5864,6 +5873,12 @@
switch (action) {
case MotionEvent.ACTION_DOWN: {
mConfirmMove = false;
+
+ // Channel Scrolling
+ mFirstTouchX = x;
+ mFirstTouchY = y;
+ mDistanceX = mDistanceY = 0;
+
if (!mEditTextScroller.isFinished()) {
mEditTextScroller.abortAnimation();
}
@@ -6001,20 +6016,16 @@
break;
}
- // Only lock dragging to one axis if we don't have a scale in progress.
- // Scaling implies free-roaming movement. Note this is only ever a question
- // if mZoomManager.supportsPanDuringZoom() is true.
- mAverageAngle = calculateDragAngle(deltaX, deltaY);
- if (detector == null || !detector.isInProgress()) {
- // if it starts nearly horizontal or vertical, enforce it
- if (mAverageAngle < HSLOPE_TO_START_SNAP) {
- mSnapScrollMode = SNAP_X;
- mSnapPositive = deltaX > 0;
- mAverageAngle = ANGLE_HORIZ;
- } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
+ if ((detector == null || !detector.isInProgress())
+ && SNAP_NONE == mSnapScrollMode) {
+ int ax = Math.abs(x - mFirstTouchX);
+ int ay = Math.abs(y - mFirstTouchY);
+ if (ax < SNAP_BOUND && ay < SNAP_BOUND) {
+ break;
+ } else if (ax < SNAP_BOUND) {
mSnapScrollMode = SNAP_Y;
- mSnapPositive = deltaY > 0;
- mAverageAngle = ANGLE_VERT;
+ } else if (ay < SNAP_BOUND) {
+ mSnapScrollMode = SNAP_X;
}
}
@@ -6033,31 +6044,21 @@
if (deltaX == 0 && deltaY == 0) {
keepScrollBarsVisible = true;
} else {
- mAverageAngle +=
- (calculateDragAngle(deltaX, deltaY) - mAverageAngle)
- / MMA_WEIGHT_N;
- if (mSnapScrollMode != SNAP_NONE) {
- if (mSnapScrollMode == SNAP_Y) {
- // radical change means getting out of snap mode
- if (mAverageAngle < VSLOPE_TO_BREAK_SNAP) {
- mSnapScrollMode = SNAP_NONE;
- }
- }
+ if (mSnapScrollMode == SNAP_X || mSnapScrollMode == SNAP_Y) {
+ mDistanceX += Math.abs(deltaX);
+ mDistanceY += Math.abs(deltaY);
if (mSnapScrollMode == SNAP_X) {
- // radical change means getting out of snap mode
- if (mAverageAngle > HSLOPE_TO_BREAK_SNAP) {
+ if (mDistanceY > sChannelDistance) {
mSnapScrollMode = SNAP_NONE;
- }
+ } else if (mDistanceX > sChannelDistance) {
+ mDistanceX = mDistanceY = 0;
}
} else {
- if (mAverageAngle < HSLOPE_TO_START_SNAP) {
- mSnapScrollMode = SNAP_X;
- mSnapPositive = deltaX > 0;
- mAverageAngle = (mAverageAngle + ANGLE_HORIZ) / 2;
- } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
- mSnapScrollMode = SNAP_Y;
- mSnapPositive = deltaY > 0;
- mAverageAngle = (mAverageAngle + ANGLE_VERT) / 2;
+ if (mDistanceX > sChannelDistance) {
+ mSnapScrollMode = SNAP_NONE;
+ } else if (mDistanceY > sChannelDistance) {
+ mDistanceX = mDistanceY = 0;
+ }
}
}
if (mSnapScrollMode != SNAP_NONE) {
@@ -6092,6 +6093,7 @@
break;
}
case MotionEvent.ACTION_UP: {
+ mFirstTouchX = mFirstTouchY = -1;
if (mIsEditingText && mSelectionStarted) {
endScrollEdit();
mPrivateHandler.sendEmptyMessageDelayed(SCROLL_HANDLE_INTO_VIEW,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cad7ae3..a1ced6e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -607,6 +607,8 @@
int typefaceIndex = -1;
int styleIndex = -1;
boolean allCaps = false;
+ int shadowcolor = 0;
+ float dx = 0, dy = 0, r = 0;
final Resources.Theme theme = context.getTheme();
@@ -667,6 +669,22 @@
case com.android.internal.R.styleable.TextAppearance_textAllCaps:
allCaps = appearance.getBoolean(attr, false);
break;
+
+ case com.android.internal.R.styleable.TextAppearance_shadowColor:
+ shadowcolor = a.getInt(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextAppearance_shadowDx:
+ dx = a.getFloat(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextAppearance_shadowDy:
+ dy = a.getFloat(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextAppearance_shadowRadius:
+ r = a.getFloat(attr, 0);
+ break;
}
}
@@ -690,8 +708,6 @@
int maxlength = -1;
CharSequence text = "";
CharSequence hint = null;
- int shadowcolor = 0;
- float dx = 0, dy = 0, r = 0;
boolean password = false;
int inputType = EditorInfo.TYPE_NULL;
@@ -2331,6 +2347,19 @@
setTypefaceFromAttrs(familyName, typefaceIndex, styleIndex);
+ final int shadowcolor = appearance.getInt(
+ com.android.internal.R.styleable.TextAppearance_shadowColor, 0);
+ if (shadowcolor != 0) {
+ final float dx = appearance.getFloat(
+ com.android.internal.R.styleable.TextAppearance_shadowDx, 0);
+ final float dy = appearance.getFloat(
+ com.android.internal.R.styleable.TextAppearance_shadowDy, 0);
+ final float r = appearance.getFloat(
+ com.android.internal.R.styleable.TextAppearance_shadowRadius, 0);
+
+ setShadowLayer(r, dx, dy, shadowcolor);
+ }
+
if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps,
false)) {
setTransformationMethod(new AllCapsTransformationMethod(getContext()));
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index e830492..07f55e0 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -548,7 +548,7 @@
}
static jint doTextRunCursor(JNIEnv *env, SkPaint* paint, const jchar *text, jint start,
- jint count, jint flags, jint offset, jint opt) {
+ jint count, jint offset, jint opt) {
jfloat scalarArray[count];
TextLayout::getTextRunAdvances(paint, text, start, count, start + count,
@@ -592,19 +592,19 @@
}
static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, SkPaint* paint, jcharArray text,
- jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextCount, jint offset, jint cursorOpt) {
jchar* textArray = env->GetCharArrayElements(text, NULL);
- jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
+ jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount,
offset, cursorOpt);
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
return result;
}
static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, SkPaint* paint, jstring text,
- jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
+ jint contextStart, jint contextEnd, jint offset, jint cursorOpt) {
const jchar* textArray = env->GetStringChars(text, NULL);
jint result = doTextRunCursor(env, paint, textArray, contextStart,
- contextEnd - contextStart, flags, offset, cursorOpt);
+ contextEnd - contextStart, offset, cursorOpt);
env->ReleaseStringChars(text, textArray);
return result;
}
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index f8715fe..296d9b2 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -19,7 +19,7 @@
#include <stdio.h>
#include <gui/GLConsumer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <android_runtime/AndroidRuntime.h>
@@ -86,8 +86,8 @@
JNIEnv* env, jobject thiz)
{
sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
- sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
- new SurfaceTextureClient(surfaceTexture->getBufferQueue()) : NULL);
+ sp<Surface> surfaceTextureClient(surfaceTexture != NULL ?
+ new Surface(surfaceTexture->getBufferQueue()) : NULL);
return surfaceTextureClient;
}
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 29805ee..6858c0e 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -24,7 +24,6 @@
#include <utils/String16.h>
#include <utils/LruCache.h>
#include <utils/KeyedVector.h>
-#include <utils/Compare.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp
index a340fa1..80d13be 100644
--- a/core/jni/android_media_RemoteDisplay.cpp
+++ b/core/jni/android_media_RemoteDisplay.cpp
@@ -64,7 +64,7 @@
uint32_t width, uint32_t height, uint32_t flags) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
- jobject surfaceObj = android_view_Surface_createFromISurfaceTexture(env, bufferProducer);
+ jobject surfaceObj = android_view_Surface_createFromIGraphicBufferProducer(env, bufferProducer);
if (surfaceObj == NULL) {
ALOGE("Could not create Surface from surface texture %p provided by media server.",
bufferProducer.get());
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 9c7124a..26fc261 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -29,7 +29,7 @@
#include <gui/Surface.h>
#include <gui/GLConsumer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <ui/ANativeObjectBase.h>
@@ -631,7 +631,7 @@
if (surfaceTexture == NULL)
goto not_valid_surface;
- window = new android::SurfaceTextureClient(surfaceTexture->getBufferQueue());
+ window = new android::Surface(surfaceTexture->getBufferQueue());
if (window == NULL)
goto not_valid_surface;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 6f71868..ab0d38e 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -28,6 +28,7 @@
#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <gui/Surface.h>
+#include <gui/SurfaceControl.h>
#include <gui/GLConsumer.h>
#include <ui/Rect.h>
@@ -85,7 +86,7 @@
env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeObject));
}
-jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
+jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer) {
if (bufferProducer == NULL) {
return NULL;
@@ -111,7 +112,13 @@
// ----------------------------------------------------------------------------
-static jint nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
+static bool isSurfaceValid(const sp<Surface>& sur) {
+ return sur != 0 && sur->getISurfaceTexture() != 0;
+}
+
+// ----------------------------------------------------------------------------
+
+static jint nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
jobject surfaceTextureObj) {
sp<GLConsumer> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
if (st == NULL) {
@@ -127,28 +134,28 @@
return 0;
}
- surface->incStrong(surfaceObj);
+ surface->incStrong(clazz);
return int(surface.get());
}
-static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static void nativeRelease(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
- sur->decStrong(surfaceObj);
+ sur->decStrong(clazz);
}
-static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static void nativeDestroy(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
- sur->decStrong(surfaceObj);
+ sur->decStrong(clazz);
}
-static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
- return Surface::isValid(sur) ? JNI_TRUE : JNI_FALSE;
+ return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
}
-static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
- if (!Surface::isValid(sur)) {
+ if (!isSurfaceValid(sur)) {
doThrowIAE(env);
return JNI_FALSE;
}
@@ -176,7 +183,7 @@
static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
- if (!Surface::isValid(surface)) {
+ if (!isSurfaceValid(surface)) {
doThrowIAE(env);
return NULL;
}
@@ -196,8 +203,10 @@
dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
}
- Surface::SurfaceInfo info;
- status_t err = surface->lock(&info, &dirtyRegion);
+ ANativeWindow_Buffer outBuffer;
+ Rect dirtyBounds(dirtyRegion.getBounds());
+ status_t err = surface->lock(&outBuffer, &dirtyBounds);
+ dirtyRegion.set(dirtyBounds);
if (err < 0) {
const char* const exception = (err == NO_MEMORY) ?
OutOfResourcesException :
@@ -208,18 +217,18 @@
// Associate a SkCanvas object to this surface
jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
- env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
+ env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
SkBitmap bitmap;
- ssize_t bpr = info.s * bytesPerPixel(info.format);
- bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
- if (info.format == PIXEL_FORMAT_RGBX_8888) {
+ ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
+ bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
+ if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
bitmap.setIsOpaque(true);
}
- if (info.w > 0 && info.h > 0) {
- bitmap.setPixels(info.bits);
+ if (outBuffer.width > 0 && outBuffer.height > 0) {
+ bitmap.setPixels(outBuffer.bits);
} else {
// be safe with an empty bitmap.
bitmap.setPixels(NULL);
@@ -263,7 +272,7 @@
}
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
- if (!Surface::isValid(surface)) {
+ if (!isSurfaceValid(surface)) {
return;
}
@@ -284,7 +293,7 @@
// ----------------------------------------------------------------------------
-static jint nativeCopyFrom(JNIEnv* env, jobject surfaceObj,
+static jint nativeCopyFrom(JNIEnv* env, jclass clazz,
jint nativeObject, jint surfaceControlNativeObj) {
/*
* This is used by the WindowManagerService just after constructing
@@ -295,18 +304,18 @@
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
sp<Surface> other(ctrl->getSurface());
if (other != NULL) {
- other->incStrong(surfaceObj);
+ other->incStrong(clazz);
}
sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
if (sur != NULL) {
- sur->decStrong(surfaceObj);
+ sur->decStrong(clazz);
}
return int(other.get());
}
-static jint nativeReadFromParcel(JNIEnv* env, jobject surfaceObj,
+static jint nativeReadFromParcel(JNIEnv* env, jclass clazz,
jint nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel == NULL) {
@@ -315,16 +324,16 @@
}
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
if (self != NULL) {
- self->decStrong(surfaceObj);
+ self->decStrong(clazz);
}
sp<Surface> sur(Surface::readFromParcel(*parcel));
if (sur != NULL) {
- sur->incStrong(surfaceObj);
+ sur->incStrong(clazz);
}
return int(sur.get());
}
-static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj,
+static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
jint nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (parcel == NULL) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 7398895..e477e54 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -120,7 +120,7 @@
// ----------------------------------------------------------------------------
-static jint nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
+static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
@@ -130,19 +130,19 @@
jniThrowException(env, OutOfResourcesException, NULL);
return 0;
}
- surface->incStrong(surfaceObj);
+ surface->incStrong(clazz);
return int(surface.get());
}
-static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static void nativeRelease(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
- ctrl->decStrong(surfaceObj);
+ ctrl->decStrong(clazz);
}
-static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+static void nativeDestroy(JNIEnv* env, jclass clazz, jint nativeObject) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
ctrl->clear();
- ctrl->decStrong(surfaceObj);
+ ctrl->decStrong(clazz);
}
static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
@@ -210,7 +210,7 @@
SurfaceComposerClient::setAnimationTransaction();
}
-static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint zorder) {
+static void nativeSetLayer(JNIEnv* env, jclass clazz, jint nativeObject, jint zorder) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setLayer(zorder);
if (err < 0 && err != NO_INIT) {
@@ -218,7 +218,7 @@
}
}
-static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat x, jfloat y) {
+static void nativeSetPosition(JNIEnv* env, jclass clazz, jint nativeObject, jfloat x, jfloat y) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setPosition(x, y);
if (err < 0 && err != NO_INIT) {
@@ -226,7 +226,7 @@
}
}
-static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint w, jint h) {
+static void nativeSetSize(JNIEnv* env, jclass clazz, jint nativeObject, jint w, jint h) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setSize(w, h);
if (err < 0 && err != NO_INIT) {
@@ -234,7 +234,7 @@
}
}
-static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint flags, jint mask) {
+static void nativeSetFlags(JNIEnv* env, jclass clazz, jint nativeObject, jint flags, jint mask) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setFlags(flags, mask);
if (err < 0 && err != NO_INIT) {
@@ -242,7 +242,7 @@
}
}
-static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject regionObj) {
+static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jint nativeObject, jobject regionObj) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
if (!region) {
@@ -267,7 +267,7 @@
}
}
-static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat alpha) {
+static void nativeSetAlpha(JNIEnv* env, jclass clazz, jint nativeObject, jfloat alpha) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setAlpha(alpha);
if (err < 0 && err != NO_INIT) {
@@ -275,7 +275,7 @@
}
}
-static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+static void nativeSetMatrix(JNIEnv* env, jclass clazz, jint nativeObject,
jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
@@ -284,7 +284,7 @@
}
}
-static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jint nativeObject,
jint l, jint t, jint r, jint b) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
Rect crop(l, t, r, b);
@@ -294,7 +294,7 @@
}
}
-static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint layerStack) {
+static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jint nativeObject, jint layerStack) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setLayerStack(layerStack);
if (err < 0 && err != NO_INIT) {
@@ -320,7 +320,7 @@
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return;
sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
- sp<IGraphicBufferProducer> bufferProducer(sur->getSurfaceTexture());
+ sp<IGraphicBufferProducer> bufferProducer(sur->getIGraphicBufferProducer());
SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
}
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 87b312f..e75a2d8 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -23,7 +23,7 @@
#include <ui/Rect.h>
#include <gui/GLConsumer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
@@ -102,7 +102,7 @@
jobject surface) {
sp<GLConsumer> glConsumer(SurfaceTexture_getSurfaceTexture(env, surface));
- sp<ANativeWindow> window = new SurfaceTextureClient(glConsumer->getBufferQueue());
+ sp<ANativeWindow> window = new Surface(glConsumer->getBufferQueue());
window->incStrong(0);
SET_INT(textureView, gTextureViewClassInfo.nativeWindow, jint(window.get()));
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 199d5bf..37330ec 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -28,7 +28,7 @@
#include <gui/Surface.h>
#include <gui/GLConsumer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <SkBitmap.h>
#include <SkPixelRef.h>
@@ -355,7 +355,7 @@
sp<GLConsumer> glConsumer(SurfaceTexture_getSurfaceTexture(_env, native_window));
- window = new SurfaceTextureClient(glConsumer->getBufferQueue());
+ window = new Surface(glConsumer->getBufferQueue());
if (window == NULL)
goto not_valid_surface;
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index ac422ea..4cb7888 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -618,7 +618,7 @@
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verander verrekening van netwerkgebruik"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Laat die program toe om te verander hoe netwerkgebruik teenoor programme gemeet word. Nie vir gebruik deur normale programme nie."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"kry toegang tot kennisgewings"</string>
- <string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings te herwin, bestudeer en te verwyder, met inbegrip van daardie kennisgewings wat deur ander programme geplaas is."</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings op te haal, te bestudeer en te verwyder, insluitende die kennisgewings wat deur ander programme geplaas is."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 40fc411..5e3c56b 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1291,7 +1291,7 @@
<item quantity="one" msgid="8167147081136579439">"1 αποτέλεσμα"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> από <xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
- <string name="action_mode_done" msgid="7217581640461922289">"Ολοκληρώθηκε"</string>
+ <string name="action_mode_done" msgid="7217581640461922289">"Τέλος"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Αποσύνδεση του χώρου αποθήκευσης USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Αφαίρεση κάρτας SD..."</string>
<string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Διαγραφή χώρου αποθήκευσης USB..."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index a472123..d74810a 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1062,7 +1062,7 @@
<string name="noApplications" msgid="2991814273936504689">"Egy alkalmazás sem tudja végrehajtani ezt a műveletet."</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
<string name="aerr_application" msgid="932628488013092776">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás sajnos leállt."</string>
- <string name="aerr_process" msgid="4507058997035697579">"Sajnos a(z) <xliff:g id="PROCESS">%1$s</xliff:g> folyamat leállt."</string>
+ <string name="aerr_process" msgid="4507058997035697579">"Sajnos a <xliff:g id="PROCESS">%1$s</xliff:g> alkalmazás leállt."</string>
<string name="anr_title" msgid="4351948481459135709"></string>
<string name="anr_activity_application" msgid="1904477189057199066">"A(z) <xliff:g id="APPLICATION">%2$s</xliff:g> nem válaszol."\n\n"Szeretné bezárni?"</string>
<string name="anr_activity_process" msgid="5776209883299089767">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> tevékenység nem válaszol."\n\n"Szeretné bezárni?"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 186eb3e..7f7d6d2 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1054,7 +1054,7 @@
<string name="loading" msgid="7933681260296021180">"A carregar…"</string>
<string name="capital_on" msgid="1544682755514494298">"Activado"</string>
<string name="capital_off" msgid="6815870386972805832">"Desactivar"</string>
- <string name="whichApplication" msgid="4533185947064773386">"Concluir acção utilizando"</string>
+ <string name="whichApplication" msgid="4533185947064773386">"Concluir ação utilizando"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta acção."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Limpar a predefinição nas Definições do Sistema > Aplicações > Transferidas."</string>
<string name="chooseActivity" msgid="7486876147751803333">"Escolha uma ação"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index e7df782..af28134 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -618,7 +618,7 @@
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"แก้ไขการบันทึกบัญชีการใช้งานเครือข่าย"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"อนุญาตให้แอปพลิเคชันแก้ไขวิธีการบันทึกบัญชีการใช้งานเครือข่ายของแอปพลิเคชัน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"เข้าถึงการแจ้งเตือน"</string>
- <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกคืน ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกดู ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7f80706..ce5fdc06 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1062,7 +1062,7 @@
<string name="noApplications" msgid="2991814273936504689">"Жодна програма не може виконати цю дію."</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
<string name="aerr_application" msgid="932628488013092776">"На жаль, програма <xliff:g id="APPLICATION">%1$s</xliff:g> припинила роботу."</string>
- <string name="aerr_process" msgid="4507058997035697579">"На жаль, процес <xliff:g id="PROCESS">%1$s</xliff:g> припинився."</string>
+ <string name="aerr_process" msgid="4507058997035697579">"На жаль, програма <xliff:g id="PROCESS">%1$s</xliff:g> припинила роботу."</string>
<string name="anr_title" msgid="4351948481459135709"></string>
<string name="anr_activity_application" msgid="1904477189057199066">"Програма <xliff:g id="APPLICATION">%2$s</xliff:g> не відповідає."\n\n"Закрити її?"</string>
<string name="anr_activity_process" msgid="5776209883299089767">"Дія <xliff:g id="ACTIVITY">%1$s</xliff:g> не відповідає."\n\n"Закінчити її?"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0fb8a10..a3e5b2c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3061,6 +3061,14 @@
<attr name="textColorLink" />
<!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
<attr name="textAllCaps" format="boolean" />
+ <!-- Place a shadow of the specified color behind the text. -->
+ <attr name="shadowColor" format="color" />
+ <!-- Horizontal offset of the shadow. -->
+ <attr name="shadowDx" format="float" />
+ <!-- Vertical offset of the shadow. -->
+ <attr name="shadowDy" format="float" />
+ <!-- Radius of the shadow. -->
+ <attr name="shadowRadius" format="float" />
</declare-styleable>
<declare-styleable name="TextClock">
<!-- Specifies the formatting pattern used to show the time and/or date
@@ -3195,13 +3203,13 @@
specified number. -->
<attr name="maxLength" format="integer" min="0" />
<!-- Place a shadow of the specified color behind the text. -->
- <attr name="shadowColor" format="color" />
+ <attr name="shadowColor" />
<!-- Horizontal offset of the shadow. -->
- <attr name="shadowDx" format="float" />
+ <attr name="shadowDx" />
<!-- Vertical offset of the shadow. -->
- <attr name="shadowDy" format="float" />
+ <attr name="shadowDy" />
<!-- Radius of the shadow. -->
- <attr name="shadowRadius" format="float" />
+ <attr name="shadowRadius" />
<attr name="autoLink" />
<!-- If set to false, keeps the movement method from being set
to the link movement method even if autoLink causes links
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 782a701..01d22ee 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -480,7 +480,7 @@
### Gamepad buttons ###
key BUTTON_A {
- base: fallback BACK
+ base: fallback DPAD_CENTER
}
key BUTTON_B {
@@ -488,7 +488,7 @@
}
key BUTTON_C {
- base: fallback BACK
+ base: fallback DPAD_CENTER
}
key BUTTON_X {
@@ -496,7 +496,7 @@
}
key BUTTON_Y {
- base: fallback DPAD_CENTER
+ base: fallback BACK
}
key BUTTON_Z {
@@ -528,7 +528,7 @@
}
key BUTTON_START {
- base: fallback HOME
+ base: fallback DPAD_CENTER
}
key BUTTON_SELECT {
diff --git a/data/keyboards/Virtual.kcm b/data/keyboards/Virtual.kcm
index d90b790..c4647e0 100644
--- a/data/keyboards/Virtual.kcm
+++ b/data/keyboards/Virtual.kcm
@@ -477,7 +477,7 @@
### Gamepad buttons ###
key BUTTON_A {
- base: fallback BACK
+ base: fallback DPAD_CENTER
}
key BUTTON_B {
@@ -485,7 +485,7 @@
}
key BUTTON_C {
- base: fallback BACK
+ base: fallback DPAD_CENTER
}
key BUTTON_X {
@@ -493,7 +493,7 @@
}
key BUTTON_Y {
- base: fallback DPAD_CENTER
+ base: fallback BACK
}
key BUTTON_Z {
@@ -525,7 +525,7 @@
}
key BUTTON_START {
- base: fallback HOME
+ base: fallback DPAD_CENTER
}
key BUTTON_SELECT {
diff --git a/docs/html/about/versions/jelly-bean.jd b/docs/html/about/versions/jelly-bean.jd
index 6cd6f9d..acb2538 100644
--- a/docs/html/about/versions/jelly-bean.jd
+++ b/docs/html/about/versions/jelly-bean.jd
@@ -331,14 +331,14 @@
appropriate.</p>
<p>For precise control over your app UI, Android 4.2 includes new APIs that let
-you manage layout direction, text direction, text alignment, gravity, and locale
-direction in View components. You can even create custom versions of layout,
-drawables, and other resources for display when a right-to-left script is in
-use.</p>
+you manage layout direction, text direction, text alignment, gravity, and
+locale direction in View components. You can even create custom versions of
+layout, drawables, and other resources for display when a right-to-left script
+is in use.</p>
<p>To help you debug and optimize your custom right-to-left layouts, the
HierarchyViewer tool now lets you see start/end properties, layout direction,
-text direction, and text alignment for all the Views in the hierarchy,</p>
+text direction, and text alignment for all the Views in the hierarchy.</p>
<h2 id="42-intl">Enhancements for international languages</h2>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 3a83d12..7d99fec 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1849,7 +1849,7 @@
* @hide
*/
public int getTextRunCursor(String text, int contextStart, int contextEnd,
- int flags, int offset, int cursorOpt) {
+ int offset, int cursorOpt) {
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
| (text.length() - contextEnd) | cursorOpt) < 0)
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index a79ce17..f6c07d1 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -906,7 +906,8 @@
dk == DataKind.PIXEL_LA ||
dk == DataKind.PIXEL_RGB ||
dk == DataKind.PIXEL_RGBA ||
- dk == DataKind.PIXEL_DEPTH)) {
+ dk == DataKind.PIXEL_DEPTH ||
+ dk == DataKind.PIXEL_YUV)) {
throw new RSIllegalArgumentException("Unsupported DataKind");
}
if (!(dt == DataType.UNSIGNED_8 ||
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index c3ddd32..10f4daa 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -801,6 +801,9 @@
Sampler mSampler_WRAP_NEAREST;
Sampler mSampler_WRAP_LINEAR;
Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
+ Sampler mSampler_MIRRORED_REPEAT_NEAREST;
+ Sampler mSampler_MIRRORED_REPEAT_LINEAR;
+ Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index 0df1012..057e9b5 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -39,7 +39,8 @@
LINEAR_MIP_LINEAR (2),
LINEAR_MIP_NEAREST (5),
WRAP (3),
- CLAMP (4);
+ CLAMP (4),
+ MIRRORED_REPEAT (6);
int mID;
Value(int id) {
@@ -134,8 +135,8 @@
}
/**
- * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
- * to and wrap modes set to clamp.
+ * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
+ * wrap modes set to clamp.
*
* @param rs Context to which the sampler will belong.
*
@@ -174,7 +175,7 @@
}
/**
- * Retrieve a sampler with min and mag set to nearest and wrap modes set to
+ * Retrieve a sampler with min and mag set to linear and wrap modes set to
* wrap.
*
* @param rs Context to which the sampler will belong.
@@ -194,8 +195,8 @@
}
/**
- * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
- * to and wrap modes set to wrap.
+ * Retrieve a sampler with mag set to linear, min linear mipmap linear, and
+ * wrap modes set to wrap.
*
* @param rs Context to which the sampler will belong.
*
@@ -213,6 +214,65 @@
return rs.mSampler_WRAP_LINEAR_MIP_LINEAR;
}
+ /**
+ * Retrieve a sampler with min and mag set to nearest and wrap modes set to
+ * mirrored repeat.
+ *
+ * @param rs Context to which the sampler will belong.
+ *
+ * @return Sampler
+ */
+ public static Sampler MIRRORED_REPEAT_NEAREST(RenderScript rs) {
+ if(rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
+ Builder b = new Builder(rs);
+ b.setMinification(Value.NEAREST);
+ b.setMagnification(Value.NEAREST);
+ b.setWrapS(Value.MIRRORED_REPEAT);
+ b.setWrapT(Value.MIRRORED_REPEAT);
+ rs.mSampler_MIRRORED_REPEAT_NEAREST = b.create();
+ }
+ return rs.mSampler_MIRRORED_REPEAT_NEAREST;
+ }
+
+ /**
+ * Retrieve a sampler with min and mag set to linear and wrap modes set to
+ * mirrored repeat.
+ *
+ * @param rs Context to which the sampler will belong.
+ *
+ * @return Sampler
+ */
+ public static Sampler MIRRORED_REPEAT_LINEAR(RenderScript rs) {
+ if(rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
+ Builder b = new Builder(rs);
+ b.setMinification(Value.LINEAR);
+ b.setMagnification(Value.LINEAR);
+ b.setWrapS(Value.MIRRORED_REPEAT);
+ b.setWrapT(Value.MIRRORED_REPEAT);
+ rs.mSampler_MIRRORED_REPEAT_LINEAR = b.create();
+ }
+ return rs.mSampler_MIRRORED_REPEAT_LINEAR;
+ }
+
+ /**
+ * Retrieve a sampler with min and mag set to linear and wrap modes set to
+ * mirrored repeat.
+ *
+ * @param rs Context to which the sampler will belong.
+ *
+ * @return Sampler
+ */
+ public static Sampler MIRRORED_REPEAT_LINEAR_MIP_LINEAR(RenderScript rs) {
+ if(rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
+ Builder b = new Builder(rs);
+ b.setMinification(Value.LINEAR_MIP_LINEAR);
+ b.setMagnification(Value.LINEAR);
+ b.setWrapS(Value.MIRRORED_REPEAT);
+ b.setWrapT(Value.MIRRORED_REPEAT);
+ rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR = b.create();
+ }
+ return rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
+ }
/**
* Builder for creating non-standard samplers. Usefull if mix and match of
@@ -258,7 +318,7 @@
}
public void setWrapS(Value v) {
- if (v == Value.WRAP || v == Value.CLAMP) {
+ if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
mWrapS = v;
} else {
throw new IllegalArgumentException("Invalid value");
@@ -266,7 +326,7 @@
}
public void setWrapT(Value v) {
- if (v == Value.WRAP || v == Value.CLAMP) {
+ if (v == Value.WRAP || v == Value.CLAMP || v == Value.MIRRORED_REPEAT) {
mWrapT = v;
} else {
throw new IllegalArgumentException("Invalid value");
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index d1446f6..9507030 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 8830685..5e631af 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -43,7 +43,7 @@
#include <rsEnv.h>
#include <gui/Surface.h>
#include <gui/GLConsumer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
//#define LOG_API ALOGE
@@ -247,7 +247,7 @@
} else {
st = SurfaceTexture_getSurfaceTexture(_env, sur);
- window = new SurfaceTextureClient(st->getBufferQueue());
+ window = new Surface(st->getBufferQueue());
}
rsContextSetSurface(con, width, height, window.get());
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index b56aff8..53e8b49 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -37,7 +37,7 @@
extern sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj);
/* Creates a Surface from an IGraphicBufferProducer. */
-extern jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
+extern jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
const sp<IGraphicBufferProducer>& bufferProducer);
} // namespace android
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 6bc7aef..5f2a4d5 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -11,6 +11,8 @@
FontRenderer.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
+ DisplayList.cpp \
+ DeferredDisplayList.cpp \
DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
Dither.cpp \
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 20eb5e1..9a6494f 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -74,6 +74,9 @@
// Turn on to enable additional debugging in the font renderers
#define DEBUG_FONT_RENDERER 0
+// Turn on to log draw operation batching and deferral information
+#define DEBUG_DEFER 0
+
// Turn on to dump display list state
#define DEBUG_DISPLAY_LIST 0
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
new file mode 100644
index 0000000..8962964
--- /dev/null
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
+
+#include <utils/Trace.h>
+
+#include "Debug.h"
+#include "DisplayListOp.h"
+#include "OpenGLRenderer.h"
+
+#if DEBUG_DEFER
+ #define DEFER_LOGD(...) ALOGD(__VA_ARGS__)
+#else
+ #define DEFER_LOGD(...)
+#endif
+
+namespace android {
+namespace uirenderer {
+
+class DrawOpBatch {
+public:
+ DrawOpBatch() {
+ mOps.clear();
+ }
+
+ ~DrawOpBatch() {
+ mOps.clear();
+ }
+
+ void add(DrawOp* op) {
+ // NOTE: ignore empty bounds special case, since we don't merge across those ops
+ mBounds.unionWith(op->state.mBounds);
+ mOps.add(op);
+ }
+
+ bool intersects(Rect& rect) {
+ if (!rect.intersects(mBounds)) return false;
+ for (unsigned int i = 0; i < mOps.size(); i++) {
+ if (rect.intersects(mOps[i]->state.mBounds)) {
+#if DEBUG_DEFER
+ DEFER_LOGD("op intersects with op %p with bounds %f %f %f %f:", mOps[i],
+ mOps[i]->state.mBounds.left, mOps[i]->state.mBounds.top,
+ mOps[i]->state.mBounds.right, mOps[i]->state.mBounds.bottom);
+ mOps[i]->output(2);
+#endif
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Vector<DrawOp*> mOps;
+private:
+ Rect mBounds;
+};
+
+void DeferredDisplayList::clear() {
+ for (int i = 0; i < kOpBatch_Count; i++) {
+ mBatchIndices[i] = -1;
+ }
+ for (unsigned int i = 0; i < mBatches.size(); i++) {
+ delete mBatches[i];
+ }
+ mBatches.clear();
+}
+
+void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
+ if (CC_UNLIKELY(disallowReorder)) {
+ if (!mBatches.isEmpty()) {
+ mBatches[0]->add(op);
+ return;
+ }
+ DrawOpBatch* b = new DrawOpBatch();
+ b->add(op);
+ mBatches.add(b);
+ return;
+ }
+
+ // disallowReorder isn't set, so find the latest batch of the new op's type, and try to merge
+ // the new op into it
+ DrawOpBatch* targetBatch = NULL;
+ int batchId = op->getBatchId();
+
+ if (!mBatches.isEmpty()) {
+ if (op->state.mBounds.isEmpty()) {
+ // don't know the bounds for op, so add to last batch and start from scratch on next op
+ mBatches.top()->add(op);
+ for (int i = 0; i < kOpBatch_Count; i++) {
+ mBatchIndices[i] = -1;
+ }
+#if DEBUG_DEFER
+ DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches");
+ op->output(2);
+#endif
+ return;
+ }
+
+ if (batchId >= 0 && mBatchIndices[batchId] != -1) {
+ int targetIndex = mBatchIndices[batchId];
+ targetBatch = mBatches[targetIndex];
+ // iterate back toward target to see if anything drawn since should overlap the new op
+ for (int i = mBatches.size() - 1; i > targetIndex; i--) {
+ DrawOpBatch* overBatch = mBatches[i];
+ if (overBatch->intersects(op->state.mBounds)) {
+ targetBatch = NULL;
+#if DEBUG_DEFER
+ DEFER_LOGD("op couldn't join batch %d, was intersected by batch %d",
+ targetIndex, i);
+ op->output(2);
+#endif
+ break;
+ }
+ }
+ }
+ }
+ if (!targetBatch) {
+ targetBatch = new DrawOpBatch();
+ mBatches.add(targetBatch);
+ if (batchId >= 0) {
+ mBatchIndices[batchId] = mBatches.size() - 1;
+ }
+ }
+ targetBatch->add(op);
+}
+
+status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
+ uint32_t level) {
+ ATRACE_CALL();
+ status_t status = DrawGlInfo::kStatusDone;
+
+ if (isEmpty()) return status; // nothing to flush
+
+ DEFER_LOGD("--flushing");
+ DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
+ int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ int opCount = 0;
+ for (unsigned int i = 0; i < mBatches.size(); i++) {
+ DrawOpBatch* batch = mBatches[i];
+ for (unsigned int j = 0; j < batch->mOps.size(); j++) {
+ DrawOp* op = batch->mOps[j];
+
+ renderer.restoreDisplayState(op->state);
+
+#if DEBUG_DEFER
+ op->output(2);
+#endif
+ status |= op->applyDraw(renderer, dirty, level,
+ op->state.mMultipliedAlpha >= 0, op->state.mMultipliedAlpha);
+ opCount++;
+ }
+ }
+
+ DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
+ renderer.restoreToCount(restoreTo);
+ renderer.setDrawModifiers(restoreDrawModifiers);
+ clear();
+ return status;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
new file mode 100644
index 0000000..4fcb297
--- /dev/null
+++ b/libs/hwui/DeferredDisplayList.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
+#define ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
+
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+
+#include "Matrix.h"
+#include "Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+class DrawOp;
+class DrawOpBatch;
+class OpenGLRenderer;
+class SkiaShader;
+
+class DeferredDisplayList {
+public:
+ DeferredDisplayList() { clear(); }
+ ~DeferredDisplayList() { clear(); }
+
+ enum OpBatchId {
+ kOpBatch_None = -1, // Don't batch
+ kOpBatch_Bitmap,
+ kOpBatch_Patch,
+ kOpBatch_AlphaVertices,
+ kOpBatch_Vertices,
+ kOpBatch_AlphaMaskTexture,
+ kOpBatch_Text,
+ kOpBatch_ColorText,
+
+ kOpBatch_Count, // Add other batch ids before this
+ };
+
+ bool isEmpty() { return mBatches.isEmpty(); }
+
+ /**
+ * Plays back all of the draw ops recorded into batches to the renderer.
+ * Adjusts the state of the renderer as necessary, and restores it when complete
+ */
+ status_t flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
+ uint32_t level);
+
+ /**
+ * Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
+ * disallowReorder is false, respecting draw order when overlaps occur
+ */
+ void add(DrawOp* op, bool disallowReorder);
+
+private:
+ void clear();
+
+
+ Vector<DrawOpBatch*> mBatches;
+ int mBatchIndices[kOpBatch_Count];
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
new file mode 100644
index 0000000..8aac628
--- /dev/null
+++ b/libs/hwui/DisplayList.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Debug.h"
+#include "DisplayList.h"
+#include "DisplayListOp.h"
+#include "DisplayListLogBuffer.h"
+
+namespace android {
+namespace uirenderer {
+
+void DisplayList::outputLogBuffer(int fd) {
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ if (logBuffer.isEmpty()) {
+ return;
+ }
+
+ FILE *file = fdopen(fd, "a");
+
+ fprintf(file, "\nRecent DisplayList operations\n");
+ logBuffer.outputCommands(file);
+
+ String8 cachesLog;
+ Caches::getInstance().dumpMemoryUsage(cachesLog);
+ fprintf(file, "\nCaches:\n%s", cachesLog.string());
+ fprintf(file, "\n");
+
+ fflush(file);
+}
+
+DisplayList::DisplayList(const DisplayListRenderer& recorder) :
+ mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
+ mStaticMatrix(NULL), mAnimationMatrix(NULL) {
+
+ initFromDisplayListRenderer(recorder);
+}
+
+DisplayList::~DisplayList() {
+ clearResources();
+}
+
+void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
+ if (displayList) {
+ DISPLAY_LIST_LOGD("Deferring display list destruction");
+ Caches::getInstance().deleteDisplayListDeferred(displayList);
+ }
+}
+
+void DisplayList::clearResources() {
+ mDisplayListData = NULL;
+ delete mTransformMatrix;
+ delete mTransformCamera;
+ delete mTransformMatrix3D;
+ delete mStaticMatrix;
+ delete mAnimationMatrix;
+
+ mTransformMatrix = NULL;
+ mTransformCamera = NULL;
+ mTransformMatrix3D = NULL;
+ mStaticMatrix = NULL;
+ mAnimationMatrix = NULL;
+
+ Caches& caches = Caches::getInstance();
+ caches.unregisterFunctors(mFunctorCount);
+ caches.resourceCache.lock();
+
+ for (size_t i = 0; i < mBitmapResources.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
+ }
+
+ for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
+ SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+ caches.resourceCache.decrementRefcountLocked(bitmap);
+ caches.resourceCache.destructorLocked(bitmap);
+ }
+
+ for (size_t i = 0; i < mFilterResources.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
+ }
+
+ for (size_t i = 0; i < mShaders.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
+ caches.resourceCache.destructorLocked(mShaders.itemAt(i));
+ }
+
+ for (size_t i = 0; i < mSourcePaths.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
+ }
+
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
+ }
+
+ caches.resourceCache.unlock();
+
+ for (size_t i = 0; i < mPaints.size(); i++) {
+ delete mPaints.itemAt(i);
+ }
+
+ for (size_t i = 0; i < mRegions.size(); i++) {
+ delete mRegions.itemAt(i);
+ }
+
+ for (size_t i = 0; i < mPaths.size(); i++) {
+ SkPath* path = mPaths.itemAt(i);
+ caches.pathCache.remove(path);
+ delete path;
+ }
+
+ for (size_t i = 0; i < mMatrices.size(); i++) {
+ delete mMatrices.itemAt(i);
+ }
+
+ mBitmapResources.clear();
+ mOwnedBitmapResources.clear();
+ mFilterResources.clear();
+ mShaders.clear();
+ mSourcePaths.clear();
+ mPaints.clear();
+ mRegions.clear();
+ mPaths.clear();
+ mMatrices.clear();
+ mLayers.clear();
+}
+
+void DisplayList::reset() {
+ clearResources();
+ init();
+}
+
+void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
+ if (reusing) {
+ // re-using display list - clear out previous allocations
+ clearResources();
+ }
+
+ init();
+
+ mDisplayListData = recorder.getDisplayListData();
+ mSize = mDisplayListData->allocator.usedSize();
+
+ if (mSize == 0) {
+ return;
+ }
+
+ mFunctorCount = recorder.getFunctorCount();
+
+ Caches& caches = Caches::getInstance();
+ caches.registerFunctors(mFunctorCount);
+ caches.resourceCache.lock();
+
+ const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
+ for (size_t i = 0; i < bitmapResources.size(); i++) {
+ SkBitmap* resource = bitmapResources.itemAt(i);
+ mBitmapResources.add(resource);
+ caches.resourceCache.incrementRefcountLocked(resource);
+ }
+
+ const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
+ for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+ SkBitmap* resource = ownedBitmapResources.itemAt(i);
+ mOwnedBitmapResources.add(resource);
+ caches.resourceCache.incrementRefcountLocked(resource);
+ }
+
+ const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
+ for (size_t i = 0; i < filterResources.size(); i++) {
+ SkiaColorFilter* resource = filterResources.itemAt(i);
+ mFilterResources.add(resource);
+ caches.resourceCache.incrementRefcountLocked(resource);
+ }
+
+ const Vector<SkiaShader*>& shaders = recorder.getShaders();
+ for (size_t i = 0; i < shaders.size(); i++) {
+ SkiaShader* resource = shaders.itemAt(i);
+ mShaders.add(resource);
+ caches.resourceCache.incrementRefcountLocked(resource);
+ }
+
+ const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
+ for (size_t i = 0; i < sourcePaths.size(); i++) {
+ mSourcePaths.add(sourcePaths.itemAt(i));
+ caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
+ }
+
+ const Vector<Layer*>& layers = recorder.getLayers();
+ for (size_t i = 0; i < layers.size(); i++) {
+ mLayers.add(layers.itemAt(i));
+ caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
+ }
+
+ caches.resourceCache.unlock();
+
+ mPaints.appendVector(recorder.getPaints());
+ mRegions.appendVector(recorder.getRegions());
+ mPaths.appendVector(recorder.getPaths());
+ mMatrices.appendVector(recorder.getMatrices());
+}
+
+void DisplayList::init() {
+ mSize = 0;
+ mIsRenderable = true;
+ mFunctorCount = 0;
+ mLeft = 0;
+ mTop = 0;
+ mRight = 0;
+ mBottom = 0;
+ mClipChildren = true;
+ mAlpha = 1;
+ mMultipliedAlpha = 255;
+ mHasOverlappingRendering = true;
+ mTranslationX = 0;
+ mTranslationY = 0;
+ mRotation = 0;
+ mRotationX = 0;
+ mRotationY= 0;
+ mScaleX = 1;
+ mScaleY = 1;
+ mPivotX = 0;
+ mPivotY = 0;
+ mCameraDistance = 0;
+ mMatrixDirty = false;
+ mMatrixFlags = 0;
+ mPrevWidth = -1;
+ mPrevHeight = -1;
+ mWidth = 0;
+ mHeight = 0;
+ mPivotExplicitlySet = false;
+ mCaching = false;
+}
+
+size_t DisplayList::getSize() {
+ return mSize;
+}
+
+/**
+ * This function is a simplified version of replay(), where we simply retrieve and log the
+ * display list. This function should remain in sync with the replay() function.
+ */
+void DisplayList::output(uint32_t level) {
+ ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this,
+ mName.string(), isRenderable());
+
+ ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ outputViewProperties(level);
+ int flags = DisplayListOp::kOpLogFlag_Recurse;
+ for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
+ mDisplayListData->displayListOps[i]->output(level, flags);
+ }
+ ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string());
+}
+
+void DisplayList::updateMatrix() {
+ if (mMatrixDirty) {
+ if (!mTransformMatrix) {
+ mTransformMatrix = new SkMatrix();
+ }
+ if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
+ mTransformMatrix->reset();
+ } else {
+ if (!mPivotExplicitlySet) {
+ if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
+ mPrevWidth = mWidth;
+ mPrevHeight = mHeight;
+ mPivotX = mPrevWidth / 2;
+ mPivotY = mPrevHeight / 2;
+ }
+ }
+ if ((mMatrixFlags & ROTATION_3D) == 0) {
+ mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
+ mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
+ mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ } else {
+ if (!mTransformCamera) {
+ mTransformCamera = new Sk3DView();
+ mTransformMatrix3D = new SkMatrix();
+ }
+ mTransformMatrix->reset();
+ mTransformCamera->save();
+ mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ mTransformCamera->rotateX(mRotationX);
+ mTransformCamera->rotateY(mRotationY);
+ mTransformCamera->rotateZ(-mRotation);
+ mTransformCamera->getMatrix(mTransformMatrix3D);
+ mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
+ mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
+ mPivotY + mTranslationY);
+ mTransformMatrix->postConcat(*mTransformMatrix3D);
+ mTransformCamera->restore();
+ }
+ }
+ mMatrixDirty = false;
+ }
+}
+
+void DisplayList::outputViewProperties(uint32_t level) {
+ updateMatrix();
+ if (mLeft != 0 || mTop != 0) {
+ ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
+ }
+ if (mStaticMatrix) {
+ ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
+ level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
+ }
+ if (mAnimationMatrix) {
+ ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
+ level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix));
+ }
+ if (mMatrixFlags != 0) {
+ if (mMatrixFlags == TRANSLATION) {
+ ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
+ } else {
+ ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
+ level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
+ }
+ }
+ if (mAlpha < 1 && !mCaching) {
+ if (!mHasOverlappingRendering) {
+ ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha);
+ } else {
+ int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+ if (mClipChildren) {
+ flags |= SkCanvas::kClipToLayer_SaveFlag;
+ }
+ ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
+ (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+ mMultipliedAlpha, flags);
+ }
+ }
+ if (mClipChildren && !mCaching) {
+ ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
+ (float) mRight - mLeft, (float) mBottom - mTop);
+ }
+}
+
+void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
+#if DEBUG_DISPLAYLIST
+ outputViewProperties(level);
+#endif
+ updateMatrix();
+ if (mLeft != 0 || mTop != 0) {
+ renderer.translate(mLeft, mTop);
+ }
+ if (mStaticMatrix) {
+ renderer.concatMatrix(mStaticMatrix);
+ } else if (mAnimationMatrix) {
+ renderer.concatMatrix(mAnimationMatrix);
+ }
+ if (mMatrixFlags != 0) {
+ if (mMatrixFlags == TRANSLATION) {
+ renderer.translate(mTranslationX, mTranslationY);
+ } else {
+ renderer.concatMatrix(mTransformMatrix);
+ }
+ }
+ if (mAlpha < 1 && !mCaching) {
+ if (!mHasOverlappingRendering) {
+ renderer.setAlpha(mAlpha);
+ } else {
+ // TODO: should be able to store the size of a DL at record time and not
+ // have to pass it into this call. In fact, this information might be in the
+ // location/size info that we store with the new native transform data.
+ int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+ if (mClipChildren) {
+ flags |= SkCanvas::kClipToLayer_SaveFlag;
+ }
+ renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
+ mMultipliedAlpha, flags);
+ }
+ }
+ if (mClipChildren && !mCaching) {
+ renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
+ SkRegion::kIntersect_Op);
+ }
+}
+
+status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level,
+ DeferredDisplayList* deferredList) {
+ status_t drawGlStatus = DrawGlInfo::kStatusDone;
+
+#if DEBUG_DISPLAY_LIST
+ Rect* clipRect = renderer.getClipRect();
+ DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
+ (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
+ clipRect->right, clipRect->bottom);
+#endif
+
+ renderer.startMark(mName.string());
+
+ int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
+ SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
+
+ if (mAlpha < 1 && !mCaching && CC_LIKELY(deferredList)) {
+ // flush before a saveLayerAlpha/setAlpha
+ // TODO: make this cleaner
+ drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
+ }
+ setViewProperties(renderer, level);
+
+ if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
+ DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+ renderer.restoreToCount(restoreTo);
+ renderer.endMark();
+ return drawGlStatus;
+ }
+
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ int saveCount = renderer.getSaveCount() - 1;
+ for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
+ DisplayListOp *op = mDisplayListData->displayListOps[i];
+#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
+ Caches::getInstance().eventMark(strlen(op->name()), op->name());
+#endif
+
+ if (deferredList) {
+ drawGlStatus |= op->replay(renderer, dirty, flags,
+ saveCount, level, mCaching, mMultipliedAlpha, *deferredList);
+ } else {
+ drawGlStatus |= op->replay(renderer, dirty, flags,
+ saveCount, level, mCaching, mMultipliedAlpha);
+ }
+ logBuffer.writeCommand(level, op->name());
+ }
+
+ DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+ renderer.restoreToCount(restoreTo);
+ renderer.endMark();
+
+ DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
+ drawGlStatus);
+
+ if (!level && CC_LIKELY(deferredList)) {
+ drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
+ }
+
+ return drawGlStatus;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
new file mode 100644
index 0000000..d06827d
--- /dev/null
+++ b/libs/hwui/DisplayList.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_DISPLAY_LIST_H
+#define ANDROID_HWUI_DISPLAY_LIST_H
+
+#include <SkCamera.h>
+#include <SkMatrix.h>
+
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <cutils/compiler.h>
+
+#include "utils/LinearAllocator.h"
+
+#include "Debug.h"
+
+#define TRANSLATION 0x0001
+#define ROTATION 0x0002
+#define ROTATION_3D 0x0004
+#define SCALE 0x0008
+#define PIVOT 0x0010
+
+class SkBitmap;
+class SkPaint;
+class SkPath;
+class SkRegion;
+
+namespace android {
+namespace uirenderer {
+
+class DeferredDisplayList;
+class DisplayListOp;
+class DisplayListRenderer;
+class OpenGLRenderer;
+class Rect;
+class Layer;
+class SkiaColorFilter;
+class SkiaShader;
+
+/**
+ * Refcounted structure that holds data used in display list stream
+ */
+class DisplayListData: public LightRefBase<DisplayListData> {
+public:
+ LinearAllocator allocator;
+ Vector<DisplayListOp*> displayListOps;
+};
+
+/**
+ * Replays recorded drawing commands.
+ */
+class DisplayList {
+public:
+ DisplayList(const DisplayListRenderer& recorder);
+ ANDROID_API ~DisplayList();
+
+ // See flags defined in DisplayList.java
+ enum ReplayFlag {
+ kReplayFlag_ClipChildren = 0x1
+ };
+
+ void setViewProperties(OpenGLRenderer& renderer, uint32_t level);
+ void outputViewProperties(uint32_t level);
+
+ ANDROID_API size_t getSize();
+ ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
+ ANDROID_API static void outputLogBuffer(int fd);
+
+ void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
+
+ status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0,
+ DeferredDisplayList* deferredList = NULL);
+
+ void output(uint32_t level = 0);
+
+ ANDROID_API void reset();
+
+ void setRenderable(bool renderable) {
+ mIsRenderable = renderable;
+ }
+
+ bool isRenderable() const {
+ return mIsRenderable;
+ }
+
+ void setName(const char* name) {
+ if (name) {
+ mName.setTo(name);
+ }
+ }
+
+ void setClipChildren(bool clipChildren) {
+ mClipChildren = clipChildren;
+ }
+
+ void setStaticMatrix(SkMatrix* matrix) {
+ delete mStaticMatrix;
+ mStaticMatrix = new SkMatrix(*matrix);
+ }
+
+ void setAnimationMatrix(SkMatrix* matrix) {
+ delete mAnimationMatrix;
+ if (matrix) {
+ mAnimationMatrix = new SkMatrix(*matrix);
+ } else {
+ mAnimationMatrix = NULL;
+ }
+ }
+
+ void setAlpha(float alpha) {
+ alpha = fminf(1.0f, fmaxf(0.0f, alpha));
+ if (alpha != mAlpha) {
+ mAlpha = alpha;
+ mMultipliedAlpha = (int) (255 * alpha);
+ }
+ }
+
+ void setHasOverlappingRendering(bool hasOverlappingRendering) {
+ mHasOverlappingRendering = hasOverlappingRendering;
+ }
+
+ void setTranslationX(float translationX) {
+ if (translationX != mTranslationX) {
+ mTranslationX = translationX;
+ mMatrixDirty = true;
+ if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
+ mMatrixFlags &= ~TRANSLATION;
+ } else {
+ mMatrixFlags |= TRANSLATION;
+ }
+ }
+ }
+
+ void setTranslationY(float translationY) {
+ if (translationY != mTranslationY) {
+ mTranslationY = translationY;
+ mMatrixDirty = true;
+ if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
+ mMatrixFlags &= ~TRANSLATION;
+ } else {
+ mMatrixFlags |= TRANSLATION;
+ }
+ }
+ }
+
+ void setRotation(float rotation) {
+ if (rotation != mRotation) {
+ mRotation = rotation;
+ mMatrixDirty = true;
+ if (mRotation == 0.0f) {
+ mMatrixFlags &= ~ROTATION;
+ } else {
+ mMatrixFlags |= ROTATION;
+ }
+ }
+ }
+
+ void setRotationX(float rotationX) {
+ if (rotationX != mRotationX) {
+ mRotationX = rotationX;
+ mMatrixDirty = true;
+ if (mRotationX == 0.0f && mRotationY == 0.0f) {
+ mMatrixFlags &= ~ROTATION_3D;
+ } else {
+ mMatrixFlags |= ROTATION_3D;
+ }
+ }
+ }
+
+ void setRotationY(float rotationY) {
+ if (rotationY != mRotationY) {
+ mRotationY = rotationY;
+ mMatrixDirty = true;
+ if (mRotationX == 0.0f && mRotationY == 0.0f) {
+ mMatrixFlags &= ~ROTATION_3D;
+ } else {
+ mMatrixFlags |= ROTATION_3D;
+ }
+ }
+ }
+
+ void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ mMatrixDirty = true;
+ if (mScaleX == 1.0f && mScaleY == 1.0f) {
+ mMatrixFlags &= ~SCALE;
+ } else {
+ mMatrixFlags |= SCALE;
+ }
+ }
+ }
+
+ void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ mMatrixDirty = true;
+ if (mScaleX == 1.0f && mScaleY == 1.0f) {
+ mMatrixFlags &= ~SCALE;
+ } else {
+ mMatrixFlags |= SCALE;
+ }
+ }
+ }
+
+ void setPivotX(float pivotX) {
+ mPivotX = pivotX;
+ mMatrixDirty = true;
+ if (mPivotX == 0.0f && mPivotY == 0.0f) {
+ mMatrixFlags &= ~PIVOT;
+ } else {
+ mMatrixFlags |= PIVOT;
+ }
+ mPivotExplicitlySet = true;
+ }
+
+ void setPivotY(float pivotY) {
+ mPivotY = pivotY;
+ mMatrixDirty = true;
+ if (mPivotX == 0.0f && mPivotY == 0.0f) {
+ mMatrixFlags &= ~PIVOT;
+ } else {
+ mMatrixFlags |= PIVOT;
+ }
+ mPivotExplicitlySet = true;
+ }
+
+ void setCameraDistance(float distance) {
+ if (distance != mCameraDistance) {
+ mCameraDistance = distance;
+ mMatrixDirty = true;
+ if (!mTransformCamera) {
+ mTransformCamera = new Sk3DView();
+ mTransformMatrix3D = new SkMatrix();
+ }
+ mTransformCamera->setCameraLocation(0, 0, distance);
+ }
+ }
+
+ void setLeft(int left) {
+ if (left != mLeft) {
+ mLeft = left;
+ mWidth = mRight - mLeft;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setTop(int top) {
+ if (top != mTop) {
+ mTop = top;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setRight(int right) {
+ if (right != mRight) {
+ mRight = right;
+ mWidth = mRight - mLeft;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setBottom(int bottom) {
+ if (bottom != mBottom) {
+ mBottom = bottom;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setLeftTop(int left, int top) {
+ if (left != mLeft || top != mTop) {
+ mLeft = left;
+ mTop = top;
+ mWidth = mRight - mLeft;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+ if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
+ mLeft = left;
+ mTop = top;
+ mRight = right;
+ mBottom = bottom;
+ mWidth = mRight - mLeft;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void offsetLeftRight(int offset) {
+ if (offset != 0) {
+ mLeft += offset;
+ mRight += offset;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void offsetTopBottom(int offset) {
+ if (offset != 0) {
+ mTop += offset;
+ mBottom += offset;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setCaching(bool caching) {
+ mCaching = caching;
+ }
+
+ int getWidth() {
+ return mWidth;
+ }
+
+ int getHeight() {
+ return mHeight;
+ }
+
+private:
+ void init();
+
+ void clearResources();
+
+ void updateMatrix();
+
+ class TextContainer {
+ public:
+ size_t length() const {
+ return mByteLength;
+ }
+
+ const char* text() const {
+ return (const char*) mText;
+ }
+
+ size_t mByteLength;
+ const char* mText;
+ };
+
+ Vector<SkBitmap*> mBitmapResources;
+ Vector<SkBitmap*> mOwnedBitmapResources;
+ Vector<SkiaColorFilter*> mFilterResources;
+
+ Vector<SkPaint*> mPaints;
+ Vector<SkPath*> mPaths;
+ SortedVector<SkPath*> mSourcePaths;
+ Vector<SkRegion*> mRegions;
+ Vector<SkMatrix*> mMatrices;
+ Vector<SkiaShader*> mShaders;
+ Vector<Layer*> mLayers;
+
+ sp<DisplayListData> mDisplayListData;
+
+ size_t mSize;
+
+ bool mIsRenderable;
+ uint32_t mFunctorCount;
+
+ String8 mName;
+
+ // View properties
+ bool mClipChildren;
+ float mAlpha;
+ int mMultipliedAlpha;
+ bool mHasOverlappingRendering;
+ float mTranslationX, mTranslationY;
+ float mRotation, mRotationX, mRotationY;
+ float mScaleX, mScaleY;
+ float mPivotX, mPivotY;
+ float mCameraDistance;
+ int mLeft, mTop, mRight, mBottom;
+ int mWidth, mHeight;
+ int mPrevWidth, mPrevHeight;
+ bool mPivotExplicitlySet;
+ bool mMatrixDirty;
+ bool mMatrixIsIdentity;
+ uint32_t mMatrixFlags;
+ SkMatrix* mTransformMatrix;
+ Sk3DView* mTransformCamera;
+ SkMatrix* mTransformMatrix3D;
+ SkMatrix* mStaticMatrix;
+ SkMatrix* mAnimationMatrix;
+ bool mCaching;
+}; // class DisplayList
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_OPENGL_RENDERER_H
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6425b43..8e80647 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -19,7 +19,10 @@
#include <SkXfermode.h>
+#include <private/hwui/DrawGlInfo.h>
+
#include "OpenGLRenderer.h"
+#include "DeferredDisplayList.h"
#include "DisplayListRenderer.h"
#include "utils/LinearAllocator.h"
@@ -41,7 +44,6 @@
#define OP_LOGS(s) OP_LOG("%s", s)
#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
-
namespace android {
namespace uirenderer {
@@ -72,11 +74,15 @@
kOpLogFlag_JSON = 0x2 // TODO: add?
};
- //TODO: for draw batching, DrawOps should override a virtual sub-method, with
- // DrawOps::apply deferring operations to a different list if possible
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
uint32_t level, bool caching, int multipliedAlpha) = 0;
+ // same as replay above, but draw operations will defer into the deferredList if possible
+ // NOTE: colorfilters, paintfilters, shaders, shadow, and complex clips prevent deferral
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
+ uint32_t level, bool caching, int multipliedAlpha,
+ DeferredDisplayList& deferredList) = 0;
+
virtual void output(int level, uint32_t flags = 0) = 0;
// NOTE: it would be nice to declare constants and overriding the implementation in each op to
@@ -96,7 +102,28 @@
return DrawGlInfo::kStatusDone;
}
+ /**
+ * State operations are applied directly to the renderer, but can cause the deferred drawing op
+ * list to flush
+ */
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
+ uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
+ status_t status = DrawGlInfo::kStatusDone;
+ if (requiresDrawOpFlush()) {
+ // will be setting renderer state that affects ops in deferredList, so flush list first
+ status |= deferredList.flush(renderer, dirty, flags, level);
+ }
+ applyState(renderer, saveCount);
+ return status;
+ }
+
virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
+
+ /**
+ * Returns true if it affects renderer drawing state in such a way to break deferral
+ * see OpenGLRenderer::disallowDeferral()
+ */
+ virtual bool requiresDrawOpFlush() { return false; }
};
class DrawOp : public DisplayListOp {
@@ -113,6 +140,33 @@
return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
}
+ /** Draw operations are stored in the deferredList with information necessary for playback */
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
+ uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
+ if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
+ return DrawGlInfo::kStatusDone;
+ }
+
+ if (renderer.disallowDeferral()) {
+ // dispatch draw immediately, since the renderer's state is too complex for deferral
+ return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
+ }
+
+ if (!caching) multipliedAlpha = -1;
+ state.mMultipliedAlpha = multipliedAlpha;
+ if (!getLocalBounds(state.mBounds)) {
+ // empty bounds signify bounds can't be calculated
+ state.mBounds.setEmpty();
+ }
+
+ if (!renderer.storeDisplayState(state)) {
+ // op wasn't quick-rejected, so defer
+ deferredList.add(this, renderer.disallowReorder());
+ }
+
+ return DrawGlInfo::kStatusDone;
+ }
+
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
bool caching, int multipliedAlpha) = 0;
@@ -123,6 +177,19 @@
void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
bool getQuickRejected() { return mQuickRejected; }
+ /** Batching disabled by default, turned on for individual ops */
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_None;
+ }
+
+ float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
+
+public:
+ /**
+ * Stores the relevant canvas state of the object between deferral and replay (if the canvas
+ * state supports being stored) See OpenGLRenderer::simpleClipAndState()
+ */
+ DeferredDisplayState state;
protected:
SkPaint* getPaint(OpenGLRenderer& renderer) {
return renderer.filterPaint(mPaint);
@@ -189,6 +256,8 @@
}
virtual const char* name() { return "RestoreToCount"; }
+ // Note: don't have to return true for requiresDrawOpFlush - even though restore can create a
+ // complex clip, the clip and matrix are overridden by DeferredDisplayList::flush()
private:
int mCount;
@@ -209,6 +278,7 @@
}
virtual const char* name() { return "SaveLayer"; }
+ virtual bool requiresDrawOpFlush() { return true; }
private:
Rect mArea;
@@ -230,6 +300,8 @@
}
virtual const char* name() { return "SaveLayerAlpha"; }
+ virtual bool requiresDrawOpFlush() { return true; }
+
private:
Rect mArea;
int mAlpha;
@@ -389,6 +461,7 @@
}
virtual const char* name() { return "ClipPath"; }
+ virtual bool requiresDrawOpFlush() { return true; }
private:
SkPath* mPath;
@@ -411,6 +484,7 @@
}
virtual const char* name() { return "ClipRegion"; }
+ virtual bool requiresDrawOpFlush() { return true; }
private:
SkRegion* mRegion;
@@ -580,6 +654,9 @@
}
virtual const char* name() { return "DrawBitmap"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Bitmap;
+ }
protected:
SkBitmap* mBitmap;
@@ -604,6 +681,9 @@
}
virtual const char* name() { return "DrawBitmap"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Bitmap;
+ }
private:
SkBitmap* mBitmap;
@@ -630,6 +710,9 @@
}
virtual const char* name() { return "DrawBitmapRect"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Bitmap;
+ }
private:
SkBitmap* mBitmap;
@@ -652,6 +735,9 @@
}
virtual const char* name() { return "DrawBitmapData"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Bitmap;
+ }
};
class DrawBitmapMeshOp : public DrawOp {
@@ -672,6 +758,9 @@
}
virtual const char* name() { return "DrawBitmapMesh"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Bitmap;
+ }
private:
SkBitmap* mBitmap;
@@ -706,6 +795,9 @@
}
virtual const char* name() { return "DrawPatch"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Patch;
+ }
private:
SkBitmap* mBitmap;
@@ -746,15 +838,21 @@
: DrawBoundedOp(left, top, right, bottom, paint) {};
bool getLocalBounds(Rect& localBounds) {
+ localBounds.set(mLocalBounds);
if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
- float outset = mPaint->getStrokeWidth() * 0.5f;
- localBounds.set(mLocalBounds.left - outset, mLocalBounds.top - outset,
- mLocalBounds.right + outset, mLocalBounds.bottom + outset);
- } else {
- localBounds.set(mLocalBounds);
+ localBounds.outset(strokeWidthOutset());
}
return true;
}
+
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ if (mPaint->getPathEffect()) {
+ return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
+ }
+ return mPaint->isAntiAlias() ?
+ DeferredDisplayList::kOpBatch_AlphaVertices :
+ DeferredDisplayList::kOpBatch_Vertices;
+ }
};
class DrawRectOp : public DrawStrokableOp {
@@ -791,6 +889,10 @@
virtual const char* name() { return "DrawRects"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_Vertices;
+ }
+
private:
const float* mRects;
int mCount;
@@ -910,22 +1012,24 @@
virtual const char* name() { return "DrawPath"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
+ }
private:
SkPath* mPath;
};
-class DrawLinesOp : public DrawOp {
+class DrawLinesOp : public DrawBoundedOp {
public:
DrawLinesOp(float* points, int count, SkPaint* paint)
- : DrawOp(paint), mPoints(points), mCount(count) {
- /* TODO: inherit from DrawBoundedOp and calculate localbounds something like:
+ : DrawBoundedOp(paint), mPoints(points), mCount(count) {
for (int i = 0; i < count; i += 2) {
mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
mLocalBounds.top = fminf(mLocalBounds.top, points[i+1]);
mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i+1]);
}
- */
+ mLocalBounds.outset(strokeWidthOutset());
}
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
@@ -939,6 +1043,12 @@
virtual const char* name() { return "DrawLines"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return mPaint->isAntiAlias() ?
+ DeferredDisplayList::kOpBatch_AlphaVertices :
+ DeferredDisplayList::kOpBatch_Vertices;
+ }
+
protected:
float* mPoints;
int mCount;
@@ -969,6 +1079,12 @@
virtual void output(int level, uint32_t flags) {
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
+
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return mPaint->getColor() == 0xff000000 ?
+ DeferredDisplayList::kOpBatch_Text :
+ DeferredDisplayList::kOpBatch_ColorText;
+ }
protected:
const char* mText;
int mBytesCount;
@@ -1040,6 +1156,12 @@
virtual const char* name() { return "DrawText"; }
+ virtual DeferredDisplayList::OpBatchId getBatchId() {
+ return mPaint->getColor() == 0xff000000 ?
+ DeferredDisplayList::kOpBatch_Text :
+ DeferredDisplayList::kOpBatch_ColorText;
+ }
+
private:
const char* mText;
int mBytesCount;
@@ -1081,9 +1203,21 @@
public:
DrawDisplayListOp(DisplayList* displayList, int flags)
: DrawOp(0), mDisplayList(displayList), mFlags(flags) {}
+
+ virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
+ uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
+ if (mDisplayList && mDisplayList->isRenderable()) {
+ return mDisplayList->replay(renderer, dirty, mFlags, level + 1, &deferredList);
+ }
+ return DrawGlInfo::kStatusDone;
+ }
+
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
bool caching, int multipliedAlpha) {
- return renderer.drawDisplayList(mDisplayList, dirty, mFlags, level + 1);
+ if (mDisplayList && mDisplayList->isRenderable()) {
+ return mDisplayList->replay(renderer, dirty, mFlags, level + 1);
+ }
+ return DrawGlInfo::kStatusDone;
}
virtual void output(int level, uint32_t flags) {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 17ed8ac..710f12f 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -20,6 +20,8 @@
#include <private/hwui/DrawGlInfo.h>
+#include "DisplayList.h"
+#include "DeferredDisplayList.h"
#include "DisplayListLogBuffer.h"
#include "DisplayListOp.h"
#include "DisplayListRenderer.h"
@@ -28,425 +30,6 @@
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Display list
-///////////////////////////////////////////////////////////////////////////////
-
-void DisplayList::outputLogBuffer(int fd) {
- DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
- if (logBuffer.isEmpty()) {
- return;
- }
-
- FILE *file = fdopen(fd, "a");
-
- fprintf(file, "\nRecent DisplayList operations\n");
- logBuffer.outputCommands(file);
-
- String8 cachesLog;
- Caches::getInstance().dumpMemoryUsage(cachesLog);
- fprintf(file, "\nCaches:\n%s", cachesLog.string());
- fprintf(file, "\n");
-
- fflush(file);
-}
-
-DisplayList::DisplayList(const DisplayListRenderer& recorder) :
- mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
- mStaticMatrix(NULL), mAnimationMatrix(NULL) {
-
- initFromDisplayListRenderer(recorder);
-}
-
-DisplayList::~DisplayList() {
- clearResources();
-}
-
-void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
- if (displayList) {
- DISPLAY_LIST_LOGD("Deferring display list destruction");
- Caches::getInstance().deleteDisplayListDeferred(displayList);
- }
-}
-
-void DisplayList::clearResources() {
- mDisplayListData = NULL;
- delete mTransformMatrix;
- delete mTransformCamera;
- delete mTransformMatrix3D;
- delete mStaticMatrix;
- delete mAnimationMatrix;
-
- mTransformMatrix = NULL;
- mTransformCamera = NULL;
- mTransformMatrix3D = NULL;
- mStaticMatrix = NULL;
- mAnimationMatrix = NULL;
-
- Caches& caches = Caches::getInstance();
- caches.unregisterFunctors(mFunctorCount);
- caches.resourceCache.lock();
-
- for (size_t i = 0; i < mBitmapResources.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
- }
-
- for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
- SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
- caches.resourceCache.decrementRefcountLocked(bitmap);
- caches.resourceCache.destructorLocked(bitmap);
- }
-
- for (size_t i = 0; i < mFilterResources.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
- }
-
- for (size_t i = 0; i < mShaders.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
- caches.resourceCache.destructorLocked(mShaders.itemAt(i));
- }
-
- for (size_t i = 0; i < mSourcePaths.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
- }
-
- for (size_t i = 0; i < mLayers.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
- }
-
- caches.resourceCache.unlock();
-
- for (size_t i = 0; i < mPaints.size(); i++) {
- delete mPaints.itemAt(i);
- }
-
- for (size_t i = 0; i < mRegions.size(); i++) {
- delete mRegions.itemAt(i);
- }
-
- for (size_t i = 0; i < mPaths.size(); i++) {
- SkPath* path = mPaths.itemAt(i);
- caches.pathCache.remove(path);
- delete path;
- }
-
- for (size_t i = 0; i < mMatrices.size(); i++) {
- delete mMatrices.itemAt(i);
- }
-
- mBitmapResources.clear();
- mOwnedBitmapResources.clear();
- mFilterResources.clear();
- mShaders.clear();
- mSourcePaths.clear();
- mPaints.clear();
- mRegions.clear();
- mPaths.clear();
- mMatrices.clear();
- mLayers.clear();
-}
-
-void DisplayList::reset() {
- clearResources();
- init();
-}
-
-void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
- if (reusing) {
- // re-using display list - clear out previous allocations
- clearResources();
- }
-
- init();
-
- mDisplayListData = recorder.getDisplayListData();
- mSize = mDisplayListData->allocator.usedSize();
-
- if (mSize == 0) {
- return;
- }
-
- mFunctorCount = recorder.getFunctorCount();
-
- Caches& caches = Caches::getInstance();
- caches.registerFunctors(mFunctorCount);
- caches.resourceCache.lock();
-
- const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
- for (size_t i = 0; i < bitmapResources.size(); i++) {
- SkBitmap* resource = bitmapResources.itemAt(i);
- mBitmapResources.add(resource);
- caches.resourceCache.incrementRefcountLocked(resource);
- }
-
- const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
- for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
- SkBitmap* resource = ownedBitmapResources.itemAt(i);
- mOwnedBitmapResources.add(resource);
- caches.resourceCache.incrementRefcountLocked(resource);
- }
-
- const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
- for (size_t i = 0; i < filterResources.size(); i++) {
- SkiaColorFilter* resource = filterResources.itemAt(i);
- mFilterResources.add(resource);
- caches.resourceCache.incrementRefcountLocked(resource);
- }
-
- const Vector<SkiaShader*>& shaders = recorder.getShaders();
- for (size_t i = 0; i < shaders.size(); i++) {
- SkiaShader* resource = shaders.itemAt(i);
- mShaders.add(resource);
- caches.resourceCache.incrementRefcountLocked(resource);
- }
-
- const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
- for (size_t i = 0; i < sourcePaths.size(); i++) {
- mSourcePaths.add(sourcePaths.itemAt(i));
- caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
- }
-
- const Vector<Layer*>& layers = recorder.getLayers();
- for (size_t i = 0; i < layers.size(); i++) {
- mLayers.add(layers.itemAt(i));
- caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
- }
-
- caches.resourceCache.unlock();
-
- mPaints.appendVector(recorder.getPaints());
- mRegions.appendVector(recorder.getRegions());
- mPaths.appendVector(recorder.getPaths());
- mMatrices.appendVector(recorder.getMatrices());
-}
-
-void DisplayList::init() {
- mSize = 0;
- mIsRenderable = true;
- mFunctorCount = 0;
- mLeft = 0;
- mTop = 0;
- mRight = 0;
- mBottom = 0;
- mClipChildren = true;
- mAlpha = 1;
- mMultipliedAlpha = 255;
- mHasOverlappingRendering = true;
- mTranslationX = 0;
- mTranslationY = 0;
- mRotation = 0;
- mRotationX = 0;
- mRotationY= 0;
- mScaleX = 1;
- mScaleY = 1;
- mPivotX = 0;
- mPivotY = 0;
- mCameraDistance = 0;
- mMatrixDirty = false;
- mMatrixFlags = 0;
- mPrevWidth = -1;
- mPrevHeight = -1;
- mWidth = 0;
- mHeight = 0;
- mPivotExplicitlySet = false;
- mCaching = false;
-}
-
-size_t DisplayList::getSize() {
- return mSize;
-}
-
-/**
- * This function is a simplified version of replay(), where we simply retrieve and log the
- * display list. This function should remain in sync with the replay() function.
- */
-void DisplayList::output(uint32_t level) {
- ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this,
- mName.string(), isRenderable());
-
- ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- outputViewProperties(level);
- int flags = DisplayListOp::kOpLogFlag_Recurse;
- for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
- mDisplayListData->displayListOps[i]->output(level, flags);
- }
- ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string());
-}
-
-void DisplayList::updateMatrix() {
- if (mMatrixDirty) {
- if (!mTransformMatrix) {
- mTransformMatrix = new SkMatrix();
- }
- if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
- mTransformMatrix->reset();
- } else {
- if (!mPivotExplicitlySet) {
- if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
- mPrevWidth = mWidth;
- mPrevHeight = mHeight;
- mPivotX = mPrevWidth / 2;
- mPivotY = mPrevHeight / 2;
- }
- }
- if ((mMatrixFlags & ROTATION_3D) == 0) {
- mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
- mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
- mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
- } else {
- if (!mTransformCamera) {
- mTransformCamera = new Sk3DView();
- mTransformMatrix3D = new SkMatrix();
- }
- mTransformMatrix->reset();
- mTransformCamera->save();
- mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
- mTransformCamera->rotateX(mRotationX);
- mTransformCamera->rotateY(mRotationY);
- mTransformCamera->rotateZ(-mRotation);
- mTransformCamera->getMatrix(mTransformMatrix3D);
- mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
- mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
- mPivotY + mTranslationY);
- mTransformMatrix->postConcat(*mTransformMatrix3D);
- mTransformCamera->restore();
- }
- }
- mMatrixDirty = false;
- }
-}
-
-void DisplayList::outputViewProperties(uint32_t level) {
- updateMatrix();
- if (mLeft != 0 || mTop != 0) {
- ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
- }
- if (mStaticMatrix) {
- ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
- level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
- }
- if (mAnimationMatrix) {
- ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
- level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix));
- }
- if (mMatrixFlags != 0) {
- if (mMatrixFlags == TRANSLATION) {
- ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
- } else {
- ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
- level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
- }
- }
- if (mAlpha < 1 && !mCaching) {
- if (!mHasOverlappingRendering) {
- ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha);
- } else {
- int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (mClipChildren) {
- flags |= SkCanvas::kClipToLayer_SaveFlag;
- }
- ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
- (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
- mMultipliedAlpha, flags);
- }
- }
- if (mClipChildren && !mCaching) {
- ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
- (float) mRight - mLeft, (float) mBottom - mTop);
- }
-}
-
-void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
-#if DEBUG_DISPLAYLIST
- outputViewProperties(level);
-#endif
- updateMatrix();
- if (mLeft != 0 || mTop != 0) {
- renderer.translate(mLeft, mTop);
- }
- if (mStaticMatrix) {
- renderer.concatMatrix(mStaticMatrix);
- } else if (mAnimationMatrix) {
- renderer.concatMatrix(mAnimationMatrix);
- }
- if (mMatrixFlags != 0) {
- if (mMatrixFlags == TRANSLATION) {
- renderer.translate(mTranslationX, mTranslationY);
- } else {
- renderer.concatMatrix(mTransformMatrix);
- }
- }
- if (mAlpha < 1 && !mCaching) {
- if (!mHasOverlappingRendering) {
- renderer.setAlpha(mAlpha);
- } else {
- // TODO: should be able to store the size of a DL at record time and not
- // have to pass it into this call. In fact, this information might be in the
- // location/size info that we store with the new native transform data.
- int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (mClipChildren) {
- flags |= SkCanvas::kClipToLayer_SaveFlag;
- }
- renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
- mMultipliedAlpha, flags);
- }
- }
- if (mClipChildren && !mCaching) {
- renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
- SkRegion::kIntersect_Op);
- }
-}
-
-status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
- status_t drawGlStatus = DrawGlInfo::kStatusDone;
-
-#if DEBUG_DISPLAY_LIST
- Rect* clipRect = renderer.getClipRect();
- DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
- (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
- clipRect->right, clipRect->bottom);
-#endif
-
- renderer.startMark(mName.string());
-
- int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
- SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
- setViewProperties(renderer, level);
-
- if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
- DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
- renderer.restoreToCount(restoreTo);
- renderer.endMark();
- return drawGlStatus;
- }
-
- DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
- int saveCount = renderer.getSaveCount() - 1;
- for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
- DisplayListOp *op = mDisplayListData->displayListOps[i];
-#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
- Caches::getInstance().eventMark(strlen(op->name()), op->name());
-#endif
-
- drawGlStatus |= op->replay(renderer, dirty, flags,
- saveCount, level, mCaching, mMultipliedAlpha);
- logBuffer.writeCommand(level, op->name());
- }
-
- DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
- renderer.restoreToCount(restoreTo);
- renderer.endMark();
-
- DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
- drawGlStatus);
- return drawGlStatus;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Base structure
-///////////////////////////////////////////////////////////////////////////////
-
DisplayListRenderer::DisplayListRenderer():
mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
@@ -657,7 +240,7 @@
}
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
- Rect& dirty, int32_t flags, uint32_t level) {
+ Rect& dirty, int32_t flags) {
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b25288b..bff3b97 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -17,21 +17,14 @@
#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
-#include <SkChunkAlloc.h>
-#include <SkFlattenable.h>
#include <SkMatrix.h>
-#include <SkCamera.h>
#include <SkPaint.h>
#include <SkPath.h>
-#include <SkRefCnt.h>
-#include <SkTDArray.h>
-#include <SkTSearch.h>
-
#include <cutils/compiler.h>
+#include "DisplayList.h"
#include "DisplayListLogBuffer.h"
#include "OpenGLRenderer.h"
-#include "utils/LinearAllocator.h"
namespace android {
namespace uirenderer {
@@ -50,390 +43,17 @@
#define DISPLAY_LIST_LOGD(...)
#endif
-#define TRANSLATION 0x0001
-#define ROTATION 0x0002
-#define ROTATION_3D 0x0004
-#define SCALE 0x0008
-#define PIVOT 0x0010
-
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
+class DeferredDisplayList;
class DisplayListRenderer;
class DisplayListOp;
class DrawOp;
class StateOp;
/**
- * Refcounted structure that holds data used in display list stream
- */
-class DisplayListData: public LightRefBase<DisplayListData> {
-public:
- LinearAllocator allocator;
- Vector<DisplayListOp*> displayListOps;
-};
-
-/**
- * Replays recorded drawing commands.
- */
-class DisplayList {
-public:
- DisplayList(const DisplayListRenderer& recorder);
- ANDROID_API ~DisplayList();
-
- // See flags defined in DisplayList.java
- enum ReplayFlag {
- kReplayFlag_ClipChildren = 0x1
- };
-
- void setViewProperties(OpenGLRenderer& renderer, uint32_t level);
- void outputViewProperties(uint32_t level);
-
- ANDROID_API size_t getSize();
- ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
- ANDROID_API static void outputLogBuffer(int fd);
-
- void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
-
- status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
-
- void output(uint32_t level = 0);
-
- ANDROID_API void reset();
-
- void setRenderable(bool renderable) {
- mIsRenderable = renderable;
- }
-
- bool isRenderable() const {
- return mIsRenderable;
- }
-
- void setName(const char* name) {
- if (name) {
- mName.setTo(name);
- }
- }
-
- void setClipChildren(bool clipChildren) {
- mClipChildren = clipChildren;
- }
-
- void setStaticMatrix(SkMatrix* matrix) {
- delete mStaticMatrix;
- mStaticMatrix = new SkMatrix(*matrix);
- }
-
- void setAnimationMatrix(SkMatrix* matrix) {
- delete mAnimationMatrix;
- if (matrix) {
- mAnimationMatrix = new SkMatrix(*matrix);
- } else {
- mAnimationMatrix = NULL;
- }
- }
-
- void setAlpha(float alpha) {
- alpha = fminf(1.0f, fmaxf(0.0f, alpha));
- if (alpha != mAlpha) {
- mAlpha = alpha;
- mMultipliedAlpha = (int) (255 * alpha);
- }
- }
-
- void setHasOverlappingRendering(bool hasOverlappingRendering) {
- mHasOverlappingRendering = hasOverlappingRendering;
- }
-
- void setTranslationX(float translationX) {
- if (translationX != mTranslationX) {
- mTranslationX = translationX;
- mMatrixDirty = true;
- if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
- mMatrixFlags &= ~TRANSLATION;
- } else {
- mMatrixFlags |= TRANSLATION;
- }
- }
- }
-
- void setTranslationY(float translationY) {
- if (translationY != mTranslationY) {
- mTranslationY = translationY;
- mMatrixDirty = true;
- if (mTranslationX == 0.0f && mTranslationY == 0.0f) {
- mMatrixFlags &= ~TRANSLATION;
- } else {
- mMatrixFlags |= TRANSLATION;
- }
- }
- }
-
- void setRotation(float rotation) {
- if (rotation != mRotation) {
- mRotation = rotation;
- mMatrixDirty = true;
- if (mRotation == 0.0f) {
- mMatrixFlags &= ~ROTATION;
- } else {
- mMatrixFlags |= ROTATION;
- }
- }
- }
-
- void setRotationX(float rotationX) {
- if (rotationX != mRotationX) {
- mRotationX = rotationX;
- mMatrixDirty = true;
- if (mRotationX == 0.0f && mRotationY == 0.0f) {
- mMatrixFlags &= ~ROTATION_3D;
- } else {
- mMatrixFlags |= ROTATION_3D;
- }
- }
- }
-
- void setRotationY(float rotationY) {
- if (rotationY != mRotationY) {
- mRotationY = rotationY;
- mMatrixDirty = true;
- if (mRotationX == 0.0f && mRotationY == 0.0f) {
- mMatrixFlags &= ~ROTATION_3D;
- } else {
- mMatrixFlags |= ROTATION_3D;
- }
- }
- }
-
- void setScaleX(float scaleX) {
- if (scaleX != mScaleX) {
- mScaleX = scaleX;
- mMatrixDirty = true;
- if (mScaleX == 1.0f && mScaleY == 1.0f) {
- mMatrixFlags &= ~SCALE;
- } else {
- mMatrixFlags |= SCALE;
- }
- }
- }
-
- void setScaleY(float scaleY) {
- if (scaleY != mScaleY) {
- mScaleY = scaleY;
- mMatrixDirty = true;
- if (mScaleX == 1.0f && mScaleY == 1.0f) {
- mMatrixFlags &= ~SCALE;
- } else {
- mMatrixFlags |= SCALE;
- }
- }
- }
-
- void setPivotX(float pivotX) {
- mPivotX = pivotX;
- mMatrixDirty = true;
- if (mPivotX == 0.0f && mPivotY == 0.0f) {
- mMatrixFlags &= ~PIVOT;
- } else {
- mMatrixFlags |= PIVOT;
- }
- mPivotExplicitlySet = true;
- }
-
- void setPivotY(float pivotY) {
- mPivotY = pivotY;
- mMatrixDirty = true;
- if (mPivotX == 0.0f && mPivotY == 0.0f) {
- mMatrixFlags &= ~PIVOT;
- } else {
- mMatrixFlags |= PIVOT;
- }
- mPivotExplicitlySet = true;
- }
-
- void setCameraDistance(float distance) {
- if (distance != mCameraDistance) {
- mCameraDistance = distance;
- mMatrixDirty = true;
- if (!mTransformCamera) {
- mTransformCamera = new Sk3DView();
- mTransformMatrix3D = new SkMatrix();
- }
- mTransformCamera->setCameraLocation(0, 0, distance);
- }
- }
-
- void setLeft(int left) {
- if (left != mLeft) {
- mLeft = left;
- mWidth = mRight - mLeft;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setTop(int top) {
- if (top != mTop) {
- mTop = top;
- mHeight = mBottom - mTop;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setRight(int right) {
- if (right != mRight) {
- mRight = right;
- mWidth = mRight - mLeft;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setBottom(int bottom) {
- if (bottom != mBottom) {
- mBottom = bottom;
- mHeight = mBottom - mTop;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setLeftTop(int left, int top) {
- if (left != mLeft || top != mTop) {
- mLeft = left;
- mTop = top;
- mWidth = mRight - mLeft;
- mHeight = mBottom - mTop;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setLeftTopRightBottom(int left, int top, int right, int bottom) {
- if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
- mLeft = left;
- mTop = top;
- mRight = right;
- mBottom = bottom;
- mWidth = mRight - mLeft;
- mHeight = mBottom - mTop;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void offsetLeftRight(int offset) {
- if (offset != 0) {
- mLeft += offset;
- mRight += offset;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void offsetTopBottom(int offset) {
- if (offset != 0) {
- mTop += offset;
- mBottom += offset;
- if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
- mMatrixDirty = true;
- }
- }
- }
-
- void setCaching(bool caching) {
- mCaching = caching;
- }
-
- int getWidth() {
- return mWidth;
- }
-
- int getHeight() {
- return mHeight;
- }
-
-private:
- void init();
-
- void clearResources();
-
- void updateMatrix();
-
- class TextContainer {
- public:
- size_t length() const {
- return mByteLength;
- }
-
- const char* text() const {
- return (const char*) mText;
- }
-
- size_t mByteLength;
- const char* mText;
- };
-
- Vector<SkBitmap*> mBitmapResources;
- Vector<SkBitmap*> mOwnedBitmapResources;
- Vector<SkiaColorFilter*> mFilterResources;
-
- Vector<SkPaint*> mPaints;
- Vector<SkPath*> mPaths;
- SortedVector<SkPath*> mSourcePaths;
- Vector<SkRegion*> mRegions;
- Vector<SkMatrix*> mMatrices;
- Vector<SkiaShader*> mShaders;
- Vector<Layer*> mLayers;
-
- sp<DisplayListData> mDisplayListData;
-
- size_t mSize;
-
- bool mIsRenderable;
- uint32_t mFunctorCount;
-
- String8 mName;
-
- // View properties
- bool mClipChildren;
- float mAlpha;
- int mMultipliedAlpha;
- bool mHasOverlappingRendering;
- float mTranslationX, mTranslationY;
- float mRotation, mRotationX, mRotationY;
- float mScaleX, mScaleY;
- float mPivotX, mPivotY;
- float mCameraDistance;
- int mLeft, mTop, mRight, mBottom;
- int mWidth, mHeight;
- int mPrevWidth, mPrevHeight;
- bool mPivotExplicitlySet;
- bool mMatrixDirty;
- bool mMatrixIsIdentity;
- uint32_t mMatrixFlags;
- SkMatrix* mTransformMatrix;
- Sk3DView* mTransformCamera;
- SkMatrix* mTransformMatrix3D;
- SkMatrix* mStaticMatrix;
- SkMatrix* mAnimationMatrix;
- bool mCaching;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Renderer
-///////////////////////////////////////////////////////////////////////////////
-
-/**
* Records drawing commands in a display list for latter playback.
*/
class DisplayListRenderer: public OpenGLRenderer {
@@ -475,8 +95,7 @@
virtual bool clipPath(SkPath* path, SkRegion::Op op);
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
- virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
- uint32_t level = 0);
+ virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 79fae2b..5cec5a8 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -24,7 +24,6 @@
#include <SkMatrix.h>
-#include "utils/Compare.h"
#include "Matrix.h"
namespace android {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 57d16ae..d11558f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -32,6 +32,7 @@
#include <ui/Rect.h>
#include "OpenGLRenderer.h"
+#include "DeferredDisplayList.h"
#include "DisplayListRenderer.h"
#include "PathTessellator.h"
#include "Properties.h"
@@ -111,16 +112,18 @@
OpenGLRenderer::OpenGLRenderer():
mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
- mShader = NULL;
- mColorFilter = NULL;
- mHasShadow = false;
- mHasDrawFilter = false;
+ mDrawModifiers.mShader = NULL;
+ mDrawModifiers.mColorFilter = NULL;
+ mDrawModifiers.mHasShadow = false;
+ mDrawModifiers.mHasDrawFilter = false;
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
mFirstSnapshot = new Snapshot;
mScissorOptimizationDisabled = false;
+ mDrawDeferDisabled = false;
+ mDrawReorderDisabled = false;
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -137,6 +140,20 @@
} else {
INIT_LOGD(" Scissor optimization enabled");
}
+
+ if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
+ mDrawDeferDisabled = !strcasecmp(property, "true");
+ INIT_LOGD(" Draw defer %s", mDrawDeferDisabled ? "disabled" : "enabled");
+ } else {
+ INIT_LOGD(" Draw defer enabled");
+ }
+
+ if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
+ mDrawReorderDisabled = !strcasecmp(property, "true");
+ INIT_LOGD(" Draw reorder %s", mDrawReorderDisabled ? "disabled" : "enabled");
+ } else {
+ INIT_LOGD(" Draw reorder enabled");
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -770,7 +787,7 @@
layer->layer.set(bounds);
layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
bounds.getWidth() / float(layer->getWidth()), 0.0f);
- layer->setColorFilter(mColorFilter);
+ layer->setColorFilter(mDrawModifiers.mColorFilter);
layer->setBlend(true);
layer->setDirty(false);
@@ -1204,6 +1221,40 @@
}
///////////////////////////////////////////////////////////////////////////////
+// State Deferral
+///////////////////////////////////////////////////////////////////////////////
+
+bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state) {
+ const Rect& currentClip = *(mSnapshot->clipRect);
+ const mat4& currentMatrix = *(mSnapshot->transform);
+
+ // state only has bounds initialized in local coordinates
+ if (!state.mBounds.isEmpty()) {
+ currentMatrix.mapRect(state.mBounds);
+ if (!state.mBounds.intersect(currentClip)) {
+ // quick rejected
+ return true;
+ }
+ }
+
+ state.mClip.set(currentClip);
+ state.mMatrix.load(currentMatrix);
+ state.mDrawModifiers = mDrawModifiers;
+ return false;
+}
+
+void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
+ mSnapshot->transform->load(state.mMatrix);
+
+ // NOTE: a clip RECT will be saved and restored, but DeferredDisplayState doesn't support
+ // complex clips. In the future, we should add support for deferral of operations clipped by
+ // these. for now, we don't defer with complex clips (see OpenGLRenderer::disallowDeferral())
+ mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
+ dirtyClip();
+ mDrawModifiers = state.mDrawModifiers;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// Transforms
///////////////////////////////////////////////////////////////////////////////
@@ -1452,7 +1503,7 @@
if (clear) clearLayerRegions();
// Make sure setScissor & setStencil happen at the beginning of
// this method
- if (mDirtyClip) {
+ if (mDirtyClip && mCaches.scissorEnabled) {
setScissorFromClip();
setStencilFromClip();
}
@@ -1524,14 +1575,14 @@
}
void OpenGLRenderer::setupDrawShader() {
- if (mShader) {
- mShader->describe(mDescription, mExtensions);
+ if (mDrawModifiers.mShader) {
+ mDrawModifiers.mShader->describe(mDescription, mExtensions);
}
}
void OpenGLRenderer::setupDrawColorFilter() {
- if (mColorFilter) {
- mColorFilter->describe(mDescription, mExtensions);
+ if (mDrawModifiers.mColorFilter) {
+ mDrawModifiers.mColorFilter->describe(mDescription, mExtensions);
}
}
@@ -1547,16 +1598,19 @@
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
- chooseBlending((mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
- mDescription, swapSrcDst);
+ bool blend = (mColorSet && mColorA < 1.0f) ||
+ (mDrawModifiers.mShader && mDrawModifiers.mShader->blend());
+ chooseBlending(blend, mode, mDescription, swapSrcDst);
}
void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) {
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
- chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()) ||
- (mColorFilter && mColorFilter->blend()), mode, mDescription, swapSrcDst);
+ blend |= (mColorSet && mColorA < 1.0f) ||
+ (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
+ (mDrawModifiers.mColorFilter && mDrawModifiers.mColorFilter->blend());
+ chooseBlending(blend, mode, mDescription, swapSrcDst);
}
void OpenGLRenderer::setupDrawProgram() {
@@ -1609,7 +1663,7 @@
}
void OpenGLRenderer::setupDrawColorUniforms() {
- if ((mColorSet && !mShader) || (mShader && mSetShaderColor)) {
+ if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
}
}
@@ -1621,23 +1675,25 @@
}
void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
- if (mShader) {
+ if (mDrawModifiers.mShader) {
if (ignoreTransform) {
mModelView.loadInverse(*mSnapshot->transform);
}
- mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &mTextureUnit);
+ mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
+ mModelView, *mSnapshot, &mTextureUnit);
}
}
void OpenGLRenderer::setupDrawShaderIdentityUniforms() {
- if (mShader) {
- mShader->setupProgram(mCaches.currentProgram, mIdentity, *mSnapshot, &mTextureUnit);
+ if (mDrawModifiers.mShader) {
+ mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
+ mIdentity, *mSnapshot, &mTextureUnit);
}
}
void OpenGLRenderer::setupDrawColorFilterUniforms() {
- if (mColorFilter) {
- mColorFilter->setupProgram(mCaches.currentProgram);
+ if (mDrawModifiers.mColorFilter) {
+ mDrawModifiers.mColorFilter->setupProgram(mCaches.currentProgram);
}
}
@@ -1726,21 +1782,24 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
-status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList,
- Rect& dirty, int32_t flags, uint32_t level) {
-
+status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
- return displayList->replay(*this, dirty, flags, level);
+ if (CC_UNLIKELY(mDrawDeferDisabled)) {
+ return displayList->replay(*this, dirty, flags, 0);
+ }
+
+ DeferredDisplayList deferredList;
+ return displayList->replay(*this, dirty, flags, 0, &deferredList);
}
return DrawGlInfo::kStatusDone;
}
-void OpenGLRenderer::outputDisplayList(DisplayList* displayList, uint32_t level) {
+void OpenGLRenderer::outputDisplayList(DisplayList* displayList) {
if (displayList) {
- displayList->output(level);
+ displayList->output(0);
}
}
@@ -1990,7 +2049,7 @@
// Apply a scale transform on the canvas only when a shader is in use
// Skia handles the ratio between the dst and src rects as a scale factor
// when a shader is set
- bool useScaleTransform = mShader && scaled;
+ bool useScaleTransform = mDrawModifiers.mShader && scaled;
bool ignoreTransform = false;
if (CC_LIKELY(mSnapshot->transform->isPureTranslate() && !useScaleTransform)) {
@@ -2445,15 +2504,15 @@
// if shader-based correction is enabled
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
- paint, text, bytesCount, count, mShadowRadius, positions);
+ paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions);
const AutoTexture autoCleanup(shadow);
- const float sx = x - shadow->left + mShadowDx;
- const float sy = y - shadow->top + mShadowDy;
+ const float sx = x - shadow->left + mDrawModifiers.mShadowDx;
+ const float sy = y - shadow->top + mDrawModifiers.mShadowDy;
- const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
- int shadowColor = mShadowColor;
- if (mShader) {
+ const int shadowAlpha = ((mDrawModifiers.mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
+ int shadowColor = mDrawModifiers.mShadowColor;
+ if (mDrawModifiers.mShader) {
shadowColor = 0xffffffff;
}
@@ -2501,7 +2560,7 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- if (CC_UNLIKELY(mHasShadow)) {
+ if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, mode, 0.0f, 0.0f);
}
@@ -2592,7 +2651,7 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- if (CC_UNLIKELY(mHasShadow)) {
+ if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
oldX, oldY);
}
@@ -2748,8 +2807,8 @@
mCaches.activeTexture(0);
if (CC_LIKELY(!layer->region.isEmpty())) {
- SkiaColorFilter* oldFilter = mColorFilter;
- mColorFilter = layer->getColorFilter();
+ SkiaColorFilter* oldFilter = mDrawModifiers.mColorFilter;
+ mDrawModifiers.mColorFilter = layer->getColorFilter();
if (layer->region.isRect()) {
composeLayerRect(layer, layer->regionRect);
@@ -2788,7 +2847,7 @@
#endif
}
- mColorFilter = oldFilter;
+ mDrawModifiers.mColorFilter = oldFilter;
if (layer->debugDrawUpdate) {
layer->debugDrawUpdate = false;
@@ -2809,13 +2868,13 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetShader() {
- mShader = NULL;
+ mDrawModifiers.mShader = NULL;
}
void OpenGLRenderer::setupShader(SkiaShader* shader) {
- mShader = shader;
- if (mShader) {
- mShader->set(&mCaches.textureCache, &mCaches.gradientCache);
+ mDrawModifiers.mShader = shader;
+ if (mDrawModifiers.mShader) {
+ mDrawModifiers.mShader->set(&mCaches.textureCache, &mCaches.gradientCache);
}
}
@@ -2824,11 +2883,11 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetColorFilter() {
- mColorFilter = NULL;
+ mDrawModifiers.mColorFilter = NULL;
}
void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
- mColorFilter = filter;
+ mDrawModifiers.mColorFilter = filter;
}
///////////////////////////////////////////////////////////////////////////////
@@ -2836,15 +2895,15 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetShadow() {
- mHasShadow = false;
+ mDrawModifiers.mHasShadow = false;
}
void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
- mHasShadow = true;
- mShadowRadius = radius;
- mShadowDx = dx;
- mShadowDy = dy;
- mShadowColor = color;
+ mDrawModifiers.mHasShadow = true;
+ mDrawModifiers.mShadowRadius = radius;
+ mDrawModifiers.mShadowDx = dx;
+ mDrawModifiers.mShadowDy = dy;
+ mDrawModifiers.mShadowColor = color;
}
///////////////////////////////////////////////////////////////////////////////
@@ -2852,22 +2911,23 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::resetPaintFilter() {
- mHasDrawFilter = false;
+ mDrawModifiers.mHasDrawFilter = false;
}
void OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) {
- mHasDrawFilter = true;
- mPaintFilterClearBits = clearBits & SkPaint::kAllFlags;
- mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
+ mDrawModifiers.mHasDrawFilter = true;
+ mDrawModifiers.mPaintFilterClearBits = clearBits & SkPaint::kAllFlags;
+ mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
}
SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) {
- if (CC_LIKELY(!mHasDrawFilter || !paint)) return paint;
+ if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) return paint;
uint32_t flags = paint->getFlags();
mFilteredPaint = *paint;
- mFilteredPaint.setFlags((flags & ~mPaintFilterClearBits) | mPaintFilterSetBits);
+ mFilteredPaint.setFlags((flags & ~mDrawModifiers.mPaintFilterClearBits) |
+ mDrawModifiers.mPaintFilterSetBits);
return &mFilteredPaint;
}
@@ -2967,7 +3027,7 @@
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mShader) {
+ if (mDrawModifiers.mShader) {
color |= 0x00ffffff;
}
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
@@ -3040,7 +3100,7 @@
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform) {
// If a shader is set, preserve only the alpha
- if (mShader) {
+ if (mDrawModifiers.mShader) {
color |= 0x00ffffff;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index ad80d36..e12083c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -48,6 +48,34 @@
namespace android {
namespace uirenderer {
+struct DrawModifiers {
+ SkiaShader* mShader;
+ SkiaColorFilter* mColorFilter;
+
+ // Drop shadow
+ bool mHasShadow;
+ float mShadowRadius;
+ float mShadowDx;
+ float mShadowDy;
+ int mShadowColor;
+
+ // Draw filters
+ bool mHasDrawFilter;
+ int mPaintFilterClearBits;
+ int mPaintFilterSetBits;
+};
+
+struct DeferredDisplayState {
+ Rect mBounds; // local bounds, mapped with matrix to be in screen space coordinates, clipped.
+ int mMultipliedAlpha; // -1 if invalid (because caching not set)
+
+ // the below are set and used by the OpenGLRenderer at record and deferred playback
+ Rect mClip;
+ mat4 mMatrix;
+ SkiaShader* mShader;
+ DrawModifiers mDrawModifiers;
+};
+
///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////
@@ -182,9 +210,8 @@
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
virtual Rect* getClipRect();
- virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
- uint32_t level = 0);
- virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0);
+ virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
+ virtual void outputDisplayList(DisplayList* displayList);
virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
@@ -233,6 +260,23 @@
SkPaint* filterPaint(SkPaint* paint);
+ bool disallowDeferral() {
+ // returns true if the OpenGLRenderer's state can be completely represented by
+ // a DeferredDisplayState object
+ return !mSnapshot->clipRegion->isEmpty() ||
+ mSnapshot->alpha < 1.0 ||
+ (mSnapshot->flags & Snapshot::kFlagIsLayer) ||
+ (mSnapshot->flags & Snapshot::kFlagFboTarget); // ensure we're not in a layer
+ }
+
+ bool disallowReorder() { return mDrawReorderDisabled; }
+
+ bool storeDisplayState(DeferredDisplayState& state);
+ void restoreDisplayState(const DeferredDisplayState& state);
+
+ const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
+ void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
+
ANDROID_API bool isCurrentTransformSimple() {
return mSnapshot->transform->isSimple();
}
@@ -868,26 +912,11 @@
// State used to define the clipping region
sp<Snapshot> mTilingSnapshot;
- // Shaders
- SkiaShader* mShader;
-
- // Color filters
- SkiaColorFilter* mColorFilter;
-
// Used to draw textured quads
TextureVertex mMeshVertices[4];
- // Drop shadow
- bool mHasShadow;
- float mShadowRadius;
- float mShadowDx;
- float mShadowDy;
- int mShadowColor;
-
- // Draw filters
- bool mHasDrawFilter;
- int mPaintFilterClearBits;
- int mPaintFilterSetBits;
+ // shader, filters, and shadow
+ DrawModifiers mDrawModifiers;
SkPaint mFilteredPaint;
// Various caches
@@ -925,6 +954,8 @@
// See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
// Properties.h
bool mScissorOptimizationDisabled;
+ bool mDrawDeferDisabled;
+ bool mDrawReorderDisabled;
// No-ops start/endTiling when set
bool mSuppressTiling;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index cab0e54..ee7bf70 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -25,7 +25,6 @@
#include "Rect.h"
#include "Vertex.h"
-#include "utils/Compare.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 8ee8f5c..62e38d3 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -42,6 +42,35 @@
// Caching
///////////////////////////////////////////////////////////////////////////////
+int PatchCache::PatchDescription::compare(
+ const PatchCache::PatchDescription& lhs, const PatchCache::PatchDescription& rhs) {
+ int deltaInt = lhs.bitmapWidth - rhs.bitmapWidth;
+ if (deltaInt != 0) return deltaInt;
+
+ deltaInt = lhs.bitmapHeight - rhs.bitmapHeight;
+ if (deltaInt != 0) return deltaInt;
+
+ if (lhs.pixelWidth < rhs.pixelWidth) return -1;
+ if (lhs.pixelWidth > rhs.pixelWidth) return +1;
+
+ if (lhs.pixelHeight < rhs.pixelHeight) return -1;
+ if (lhs.pixelHeight > rhs.pixelHeight) return +1;
+
+ deltaInt = lhs.xCount - rhs.xCount;
+ if (deltaInt != 0) return deltaInt;
+
+ deltaInt = lhs.yCount - rhs.yCount;
+ if (deltaInt != 0) return deltaInt;
+
+ deltaInt = lhs.emptyCount - rhs.emptyCount;
+ if (deltaInt != 0) return deltaInt;
+
+ deltaInt = lhs.colorKey - rhs.colorKey;
+ if (deltaInt != 0) return deltaInt;
+
+ return 0;
+}
+
void PatchCache::clear() {
size_t count = mCache.size();
for (size_t i = 0; i < count; i++) {
@@ -50,7 +79,7 @@
mCache.clear();
}
-Patch* PatchCache::get(const float bitmapWidth, const float bitmapHeight,
+Patch* PatchCache::get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
const float pixelWidth, const float pixelHeight,
const int32_t* xDivs, const int32_t* yDivs, const uint32_t* colors,
const uint32_t width, const uint32_t height, const int8_t numColors) {
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 505798a..0822cba 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -19,7 +19,6 @@
#include <utils/KeyedVector.h>
-#include "utils/Compare.h"
#include "Debug.h"
#include "Patch.h"
@@ -47,7 +46,7 @@
PatchCache(uint32_t maxCapacity);
~PatchCache();
- Patch* get(const float bitmapWidth, const float bitmapHeight,
+ Patch* get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
const float pixelWidth, const float pixelHeight,
const int32_t* xDivs, const int32_t* yDivs, const uint32_t* colors,
const uint32_t width, const uint32_t height, const int8_t numColors);
@@ -70,7 +69,7 @@
xCount(0), yCount(0), emptyCount(0), colorKey(0) {
}
- PatchDescription(const float bitmapWidth, const float bitmapHeight,
+ PatchDescription(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
const float pixelWidth, const float pixelHeight,
const uint32_t xCount, const uint32_t yCount,
const int8_t emptyCount, const uint32_t colorKey):
@@ -80,28 +79,29 @@
emptyCount(emptyCount), colorKey(colorKey) {
}
- bool operator<(const PatchDescription& rhs) const {
- LTE_FLOAT(bitmapWidth) {
- LTE_FLOAT(bitmapHeight) {
- LTE_FLOAT(pixelWidth) {
- LTE_FLOAT(pixelHeight) {
- LTE_INT(xCount) {
- LTE_INT(yCount) {
- LTE_INT(emptyCount) {
- LTE_INT(colorKey) return false;
- }
- }
- }
- }
- }
- }
- }
- return false;
+ static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
+
+ bool operator==(const PatchDescription& other) const {
+ return compare(*this, other) == 0;
+ }
+
+ bool operator!=(const PatchDescription& other) const {
+ return compare(*this, other) != 0;
+ }
+
+ friend inline int strictly_order_type(const PatchDescription& lhs,
+ const PatchDescription& rhs) {
+ return PatchDescription::compare(lhs, rhs) < 0;
+ }
+
+ friend inline int compare_type(const PatchDescription& lhs,
+ const PatchDescription& rhs) {
+ return PatchDescription::compare(lhs, rhs);
}
private:
- float bitmapWidth;
- float bitmapHeight;
+ uint32_t bitmapWidth;
+ uint32_t bitmapHeight;
float pixelWidth;
float pixelHeight;
uint32_t xCount;
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index f0b5553..14a2376 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -160,7 +160,7 @@
// up and to the left.
// This offset value is based on an assumption that some hardware may use as
// little as 12.4 precision, so we offset by slightly more than 1/16.
- p.translate(.375, .375, 0);
+ p.translate(.065, .065, 0);
}
mat4 t(transformMatrix);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 0c75242..f3957cf 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -82,6 +82,19 @@
*/
#define PROPERTY_DISABLE_SCISSOR_OPTIMIZATION "ro.hwui.disable_scissor_opt"
+/**
+ * Disables draw operation deferral if set to "true", forcing draw
+ * commands to be issued to OpenGL in order, and processed in sequence
+ * with state-manipulation canvas commands.
+ */
+#define PROPERTY_DISABLE_DRAW_DEFER "debug.hwui.disable_draw_defer"
+
+/**
+ * Used to disable draw operation reordering when deferring draw operations
+ * Has no effect if PROPERTY_DISABLE_DRAW_DEFER is set to "true"
+ */
+#define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder"
+
// These properties are defined in mega-bytes
#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 5f4bb5a..f50ac3c 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -159,6 +159,13 @@
bottom += dy;
}
+ void outset(float delta) {
+ left -= delta;
+ top -= delta;
+ right += delta;
+ bottom += delta;
+ }
+
void snapToPixelBoundaries() {
left = floorf(left + 0.5f);
top = floorf(top + 0.5f);
diff --git a/libs/hwui/utils/Compare.h b/libs/hwui/utils/Compare.h
deleted file mode 100644
index fdd9acf..0000000
--- a/libs/hwui/utils/Compare.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_COMPARE_H
-#define ANDROID_HWUI_COMPARE_H
-
-#include <cmath>
-
-/**
- * Compare floats.
- */
-#define LTE_FLOAT(a) \
- if (a < rhs.a) return true; \
- if (a == rhs.a)
-
-/**
- * Compare integers.
- */
-#define LTE_INT(a) \
- if (a < rhs.a) return true; \
- if (a == rhs.a)
-
-#endif // ANDROID_HWUI_COMPARE_H
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f8c945b..86700b3 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -28,7 +28,6 @@
#include "JNIHelp.h"
#include <gui/Surface.h>
-#include <gui/SurfaceTextureClient.h>
#include <media/ICrypto.h>
#include <media/stagefright/MediaCodec.h>
@@ -114,9 +113,9 @@
const sp<IGraphicBufferProducer> &bufferProducer,
const sp<ICrypto> &crypto,
int flags) {
- sp<SurfaceTextureClient> client;
+ sp<Surface> client;
if (bufferProducer != NULL) {
- mSurfaceTextureClient = new SurfaceTextureClient(bufferProducer);
+ mSurfaceTextureClient = new Surface(bufferProducer);
} else {
mSurfaceTextureClient.clear();
}
@@ -398,7 +397,7 @@
if (jsurface != NULL) {
sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
if (surface != NULL) {
- bufferProducer = surface->getSurfaceTexture();
+ bufferProducer = surface->getIGraphicBufferProducer();
} else {
jniThrowException(
env,
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a9bb9af..f478788 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -32,7 +32,7 @@
struct ICrypto;
struct IGraphicBufferProducer;
struct MediaCodec;
-struct SurfaceTextureClient;
+class Surface;
struct JMediaCodec : public RefBase {
JMediaCodec(
@@ -91,7 +91,7 @@
private:
jclass mClass;
jweak mObject;
- sp<SurfaceTextureClient> mSurfaceTextureClient;
+ sp<Surface> mSurfaceTextureClient;
sp<ALooper> mLooper;
sp<MediaCodec> mCodec;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 5408a1f..7421022 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -273,7 +273,7 @@
if (jsurface) {
sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
if (surface != NULL) {
- new_st = surface->getSurfaceTexture();
+ new_st = surface->getIGraphicBufferProducer();
if (new_st == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"The surface does not have a binding SurfaceTexture!");
diff --git a/media/mca/filterfw/jni/jni_gl_environment.cpp b/media/mca/filterfw/jni/jni_gl_environment.cpp
index b64004e..9abf191 100644
--- a/media/mca/filterfw/jni/jni_gl_environment.cpp
+++ b/media/mca/filterfw/jni/jni_gl_environment.cpp
@@ -24,7 +24,7 @@
#include "native/core/gl_env.h"
#include <gui/IGraphicBufferProducer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
#include <utils/Errors.h>
#include <system/window.h>
@@ -34,7 +34,7 @@
using android::MediaRecorder;
using android::sp;
using android::IGraphicBufferProducer;
-using android::SurfaceTextureClient;
+using android::Surface;
class NativeWindowHandle : public WindowHandle {
@@ -290,7 +290,7 @@
<IGraphicBufferProducer> handle.");
return -1;
}
- sp<SurfaceTextureClient> surfaceTC = new SurfaceTextureClient(surfaceMS);
+ sp<Surface> surfaceTC = new Surface(surfaceMS);
// Get the ANativeWindow
sp<ANativeWindow> window = surfaceTC;
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index 8ed82e2..73768fe 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -161,7 +161,7 @@
// Create dummy surface using a GLConsumer
surfaceTexture_ = new GLConsumer(0);
- window_ = new SurfaceTextureClient(static_cast<sp<IGraphicBufferProducer> >(
+ window_ = new Surface(static_cast<sp<IGraphicBufferProducer> >(
surfaceTexture_->getBufferQueue()));
surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
diff --git a/media/mca/filterfw/native/core/gl_env.h b/media/mca/filterfw/native/core/gl_env.h
index 3c87195..81e1e9d 100644
--- a/media/mca/filterfw/native/core/gl_env.h
+++ b/media/mca/filterfw/native/core/gl_env.h
@@ -28,7 +28,7 @@
#include <EGL/egl.h>
#include <gui/IGraphicBufferProducer.h>
-#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
namespace android {
namespace filterfw {
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
index a6415b2..89f84fc 100644
--- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
@@ -4,6 +4,7 @@
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.content.Context;
+import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
@@ -11,6 +12,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.HashSet;
public class SharedStorageAgent extends FullBackupAgent {
static final String TAG = "SharedStorageAgent";
@@ -38,13 +40,20 @@
// "primary" shared storage volume is first in the list.
if (mVolumes != null) {
if (DEBUG) Slog.i(TAG, "Backing up " + mVolumes.length + " shared volumes");
+ // Ignore all apps' getExternalFilesDir() content; it is backed up as part of
+ // each app-specific payload.
+ HashSet<String> externalFilesDirFilter = new HashSet<String>();
+ final File externalAndroidRoot = new File(Environment.getExternalStorageDirectory(),
+ Environment.DIRECTORY_ANDROID);
+ externalFilesDirFilter.add(externalAndroidRoot.getCanonicalPath());
+
for (int i = 0; i < mVolumes.length; i++) {
StorageVolume v = mVolumes[i];
// Express the contents of volume N this way in the tar stream:
// shared/N/path/to/file
// The restore will then extract to the given volume
String domain = FullBackup.SHARED_PREFIX + i;
- fullBackupFileTree(null, domain, v.getPath(), null, output);
+ fullBackupFileTree(null, domain, v.getPath(), externalFilesDirFilter, output);
}
}
}
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a03ca33..a58c9a0 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -196,7 +196,7 @@
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ej ansluten"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
- <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi är inaktiverat"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi av"</string>
<string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Trådlös skärm"</string>
<string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådlös skärm"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ljusstyrka"</string>
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 1f3d2cf..3c3b919 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -22,12 +22,14 @@
#include <cutils/log.h>
#include <utils/String8.h>
+#include <gui/Surface.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaint.h>
#include <SkXfermode.h>
+#include <android/native_window.h>
namespace android {
@@ -197,16 +199,16 @@
if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
&& update.state.wantSurfaceVisible()) {
sp<Surface> surface = update.state.surfaceControl->getSurface();
- Surface::SurfaceInfo surfaceInfo;
- status_t status = surface->lock(&surfaceInfo);
+ ANativeWindow_Buffer outBuffer;
+ status_t status = surface->lock(&outBuffer, NULL);
if (status) {
ALOGE("Error %d locking sprite surface before drawing.", status);
} else {
SkBitmap surfaceBitmap;
- ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
+ ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
- surfaceInfo.w, surfaceInfo.h, bpr);
- surfaceBitmap.setPixels(surfaceInfo.bits);
+ outBuffer.width, outBuffer.height, bpr);
+ surfaceBitmap.setPixels(outBuffer.bits);
SkCanvas surfaceCanvas;
surfaceCanvas.setBitmapDevice(surfaceBitmap);
@@ -215,15 +217,15 @@
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
- if (surfaceInfo.w > uint32_t(update.state.icon.bitmap.width())) {
+ if (outBuffer.width > uint32_t(update.state.icon.bitmap.width())) {
paint.setColor(0); // transparent fill color
surfaceCanvas.drawRectCoords(update.state.icon.bitmap.width(), 0,
- surfaceInfo.w, update.state.icon.bitmap.height(), paint);
+ outBuffer.width, update.state.icon.bitmap.height(), paint);
}
- if (surfaceInfo.h > uint32_t(update.state.icon.bitmap.height())) {
+ if (outBuffer.height > uint32_t(update.state.icon.bitmap.height())) {
paint.setColor(0); // transparent fill color
surfaceCanvas.drawRectCoords(0, update.state.icon.bitmap.height(),
- surfaceInfo.w, surfaceInfo.h, paint);
+ outBuffer.width, outBuffer.height, paint);
}
status = surface->unlockAndPost();
@@ -371,8 +373,7 @@
sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
String8("Sprite"), width, height, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eHidden);
- if (surfaceControl == NULL || !surfaceControl->isValid()
- || !surfaceControl->getSurface()->isValid()) {
+ if (surfaceControl == NULL || !surfaceControl->isValid()) {
ALOGE("Error creating sprite surface.");
return NULL;
}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 1a8641b..6ba5cff 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -731,7 +731,8 @@
}
}
- private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged) {
+ private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
+ final boolean resetDefaultEnabledIme) {
if (!mSystemReady) {
// not system ready
return;
@@ -749,8 +750,7 @@
}
// InputMethodAndSubtypeListManager should be reset when the locale is changed.
mImListManager = new InputMethodAndSubtypeListManager(mContext, this);
- buildInputMethodListLocked(mMethodList, mMethodMap,
- updateOnlyWhenLocaleChanged /* resetDefaultEnabledIme */);
+ buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
if (!updateOnlyWhenLocaleChanged) {
final String selectedImiId = mSettings.getSelectedInputMethod();
if (TextUtils.isEmpty(selectedImiId)) {
@@ -775,14 +775,21 @@
}
private void checkCurrentLocaleChangedLocked() {
- resetAllInternalStateLocked(true);
+ resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
+ true /* resetDefaultImeLocked */);
}
private void switchUserLocked(int newUserId) {
mSettings.setCurrentUserId(newUserId);
// InputMethodFileManager should be reset when the user is changed
mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
- resetAllInternalStateLocked(false);
+ final String defaultImiId = mSettings.getSelectedInputMethod();
+ final boolean needsToResetDefaultIme = TextUtils.isEmpty(defaultImiId);
+ if (DEBUG) {
+ Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId);
+ }
+ resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */,
+ needsToResetDefaultIme);
}
@Override
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index e5cba62..9c518a1 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -718,7 +718,7 @@
synchronized (mLock) {
// Disconnect from services for the old user.
UserState oldUserState = getUserStateLocked(mCurrentUserId);
- unbindAllServicesLocked(oldUserState);
+ oldUserState.onSwitchToAnotherUser();
// Disable the local managers for the old user.
if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
@@ -737,11 +737,14 @@
if (userState.mUiAutomationService != null) {
// Switching users disables the UI automation service.
userState.mUiAutomationService.binderDied();
- } else if (readConfigurationForUserStateLocked(userState)) {
- // Update the user state if needed.
- onUserStateChangedLocked(userState);
}
+ readConfigurationForUserStateLocked(userState);
+ // Even if reading did not yield change, we have to update
+ // the state since the context in which the current user
+ // state was used has changed since it was inactive.
+ onUserStateChangedLocked(userState);
+
if (announceNewUser) {
// Schedule announcement of the current user if needed.
mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
@@ -1640,14 +1643,18 @@
if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
>= Build.VERSION_CODES.JELLY_BEAN) {
- mFetchFlags |= (info.flags
- & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 ?
- AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS : 0;
+ if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
+ mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ } else {
+ mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ }
}
- mFetchFlags |= (info.flags
- & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0 ?
- AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS : 0;
+ if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
+ mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
+ } else {
+ mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
+ }
if (mResolveInfo != null) {
mRequestTouchExplorationMode = (info.flags
@@ -2561,11 +2568,21 @@
private class UserState {
public final int mUserId;
- public final CopyOnWriteArrayList<Service> mBoundServices = new CopyOnWriteArrayList<Service>();
+ // Non-transient state.
public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
new RemoteCallbackList<IAccessibilityManagerClient>();
+ public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
+ new SparseArray<AccessibilityConnectionWrapper>();
+
+ public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
+
+ // Transient state.
+
+ public final CopyOnWriteArrayList<Service> mBoundServices =
+ new CopyOnWriteArrayList<Service>();
+
public final Map<ComponentName, Service> mComponentNameToServiceMap =
new HashMap<ComponentName, Service>();
@@ -2579,15 +2596,9 @@
public final Set<ComponentName> mTouchExplorationGrantedServices =
new HashSet<ComponentName>();
- public final SparseArray<AccessibilityConnectionWrapper>
- mInteractionConnections =
- new SparseArray<AccessibilityConnectionWrapper>();
-
- public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
-
public int mHandledFeedbackTypes = 0;
- public int mLastSentClientState;
+ public int mLastSentClientState = -1;
public boolean mIsAccessibilityEnabled;
public boolean mIsTouchExplorationEnabled;
@@ -2612,6 +2623,34 @@
}
return clientState;
}
+
+ public void onSwitchToAnotherUser() {
+ // Clear UI test automation state.
+ if (mUiAutomationService != null) {
+ mUiAutomationService.binderDied();
+ mUiAutomationService = null;
+ mUiAutomationServiceClient = null;
+ }
+
+ // Unbind all services.
+ unbindAllServicesLocked(this);
+
+ // Clear service management state.
+ mBoundServices.clear();
+ mBindingServices.clear();
+
+ // Clear event management state.
+ mHandledFeedbackTypes = 0;
+ mLastSentClientState = -1;
+
+ // Clear state persisted in settings.
+ mEnabledServices.clear();
+ mTouchExplorationGrantedServices.clear();
+ mIsAccessibilityEnabled = false;
+ mIsTouchExplorationEnabled = false;
+ mIsEnhancedWebAccessibilityEnabled = false;
+ mIsDisplayMagnificationEnabled = false;
+ }
}
private final class AccessibilityContentObserver extends ContentObserver {
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 2828e5e..e302e83 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -713,17 +713,17 @@
*/
private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
private final DisplayManagerService mDisplayManager;
- private SurfaceControl mSurface;
+ private SurfaceControl mSurfaceControl;
- public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surface) {
+ public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surfaceControl) {
mDisplayManager = displayManager;
- mSurface = surface;
+ mSurfaceControl = surfaceControl;
mDisplayManager.registerDisplayTransactionListener(this);
}
public void dispose() {
synchronized (this) {
- mSurface = null;
+ mSurfaceControl = null;
}
mDisplayManager.unregisterDisplayTransactionListener(this);
}
@@ -731,27 +731,27 @@
@Override
public void onDisplayTransaction() {
synchronized (this) {
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
return;
}
DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY);
switch (displayInfo.rotation) {
case Surface.ROTATION_0:
- mSurface.setPosition(0, 0);
- mSurface.setMatrix(1, 0, 0, 1);
+ mSurfaceControl.setPosition(0, 0);
+ mSurfaceControl.setMatrix(1, 0, 0, 1);
break;
case Surface.ROTATION_90:
- mSurface.setPosition(0, displayInfo.logicalHeight);
- mSurface.setMatrix(0, -1, 1, 0);
+ mSurfaceControl.setPosition(0, displayInfo.logicalHeight);
+ mSurfaceControl.setMatrix(0, -1, 1, 0);
break;
case Surface.ROTATION_180:
- mSurface.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight);
- mSurface.setMatrix(-1, 0, 0, -1);
+ mSurfaceControl.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight);
+ mSurfaceControl.setMatrix(-1, 0, 0, -1);
break;
case Surface.ROTATION_270:
- mSurface.setPosition(displayInfo.logicalWidth, 0);
- mSurface.setMatrix(0, 1, -1, 0);
+ mSurfaceControl.setPosition(displayInfo.logicalWidth, 0);
+ mSurfaceControl.setMatrix(0, 1, -1, 0);
break;
}
}
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 8fd5209..8cc1d02 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -157,7 +157,7 @@
+ win.isDrawnLw()
+ ", isAnimating=" + win.mWinAnimator.isAnimating());
if (!win.isDrawnLw()) {
- Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mWinAnimator.mSurface
+ Slog.v(WindowManagerService.TAG, "Not displayed: s=" + win.mWinAnimator.mSurfaceControl
+ " pv=" + win.mPolicyVisibility
+ " mDrawState=" + win.mWinAnimator.mDrawState
+ " ah=" + win.mAttachedHidden
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index a197840..774b165 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -37,24 +37,22 @@
final SurfaceControl surface;
BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
- throws Surface.OutOfResourcesException {
+ throws SurfaceControl.OutOfResourcesException {
left = l;
top = t;
this.layer = layer;
int w = r-l;
int h = b-t;
- try {
- if (WindowManagerService.DEBUG_SURFACE_TRACE) {
- surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
- + l + ", " + t + ")",
- w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- } else {
- surface = new SurfaceControl(session, "BlackSurface",
- w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
- }
- } catch (SurfaceControl.OutOfResourcesException e) {
- throw new Surface.OutOfResourcesException(e.getMessage());
+
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
+ + l + ", " + t + ")",
+ w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+ } else {
+ surface = new SurfaceControl(session, "BlackSurface",
+ w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
}
+
surface.setAlpha(1);
surface.setLayerStack(layerStack);
surface.setLayer(layer);
@@ -109,7 +107,7 @@
}
public BlackFrame(SurfaceSession session, Rect outer, Rect inner,
- int layer, final int layerStack) throws Surface.OutOfResourcesException {
+ int layer, final int layerStack) throws SurfaceControl.OutOfResourcesException {
boolean success = false;
mOuterRect = new Rect(outer);
diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/java/com/android/server/wm/DisplayMagnifier.java
index 55c6fa6..0f51028 100644
--- a/services/java/com/android/server/wm/DisplayMagnifier.java
+++ b/services/java/com/android/server/wm/DisplayMagnifier.java
@@ -491,15 +491,15 @@
private boolean mInvalidated;
public ViewportWindow(Context context) {
- SurfaceControl surface = null;
+ SurfaceControl surfaceControl = null;
try {
mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
- surface = new SurfaceControl(mWindowManagerService.mFxSession, SURFACE_TITLE,
+ surfaceControl = new SurfaceControl(mWindowManagerService.mFxSession, SURFACE_TITLE,
mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
} catch (SurfaceControl.OutOfResourcesException oore) {
/* ignore */
}
- mSurfaceControl = surface;
+ mSurfaceControl = surfaceControl;
mSurfaceControl.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
mSurfaceControl.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY)
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 63f306f..745b886 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -46,7 +46,7 @@
class DragState {
final WindowManagerService mService;
IBinder mToken;
- SurfaceControl mSurface;
+ SurfaceControl mSurfaceControl;
int mFlags;
IBinder mLocalWin;
ClipData mData;
@@ -69,17 +69,17 @@
int flags, IBinder localWin) {
mService = service;
mToken = token;
- mSurface = surface;
+ mSurfaceControl = surface;
mFlags = flags;
mLocalWin = localWin;
mNotifiedWindows = new ArrayList<WindowState>();
}
void reset() {
- if (mSurface != null) {
- mSurface.destroy();
+ if (mSurfaceControl != null) {
+ mSurfaceControl.destroy();
}
- mSurface = null;
+ mSurfaceControl = null;
mFlags = 0;
mLocalWin = null;
mToken = null;
@@ -296,9 +296,9 @@
WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
SurfaceControl.openTransaction();
try {
- mSurface.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
+ mSurfaceControl.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DRAG "
- + mSurface + ": pos=(" +
+ + mSurfaceControl + ": pos=(" +
(int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
} finally {
SurfaceControl.closeTransaction();
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 05397ac..5d4ab56 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -44,7 +44,7 @@
final Context mContext;
final Display mDisplay;
- SurfaceControl mSurface;
+ SurfaceControl mSurfaceControl;
BlackFrame mCustomBlackFrame;
BlackFrame mExitingBlackFrame;
BlackFrame mEnteringBlackFrame;
@@ -128,7 +128,7 @@
long mHalfwayPoint;
public void printTo(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
+ pw.print(prefix); pw.print("mSurface="); pw.print(mSurfaceControl);
pw.print(" mWidth="); pw.print(mWidth);
pw.print(" mHeight="); pw.println(mHeight);
if (USE_CUSTOM_BLACK_FRAME) {
@@ -220,25 +220,25 @@
try {
try {
if (WindowManagerService.DEBUG_SURFACE_TRACE) {
- mSurface = new SurfaceTrace(session, "FreezeSurface",
+ mSurfaceControl = new SurfaceTrace(session, "FreezeSurface",
mWidth, mHeight,
PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
} else {
- mSurface = new SurfaceControl(session, "FreezeSurface",
+ mSurfaceControl = new SurfaceControl(session, "FreezeSurface",
mWidth, mHeight,
PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
}
- mSurface.setLayerStack(mDisplay.getLayerStack());
- mSurface.setLayer(FREEZE_LAYER + 1);
- mSurface.setAlpha(0);
- mSurface.show();
+ mSurfaceControl.setLayerStack(mDisplay.getLayerStack());
+ mSurfaceControl.setLayer(FREEZE_LAYER + 1);
+ mSurfaceControl.setAlpha(0);
+ mSurfaceControl.show();
} catch (SurfaceControl.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate freeze surface", e);
}
if (WindowManagerService.SHOW_TRANSACTIONS ||
WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " FREEZE " + mSurface + ": CREATE");
+ " FREEZE " + mSurfaceControl + ": CREATE");
setRotationInTransaction(originalRotation);
} finally {
@@ -251,7 +251,7 @@
}
boolean hasScreenshot() {
- return mSurface != null;
+ return mSurfaceControl != null;
}
static int deltaRotation(int oldRotation, int newRotation) {
@@ -261,13 +261,13 @@
}
private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
matrix.getValues(mTmpFloats);
- mSurface.setPosition(mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
- mSurface.setMatrix(
+ mSurfaceControl.setPosition(mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
+ mSurfaceControl.setMatrix(
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
- mSurface.setAlpha(alpha);
+ mSurfaceControl.setAlpha(alpha);
if (DEBUG_TRANSFORMS) {
float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
float[] dstPnts = new float[4];
@@ -333,7 +333,7 @@
*/
private boolean startAnimation(SurfaceSession session, long maxAnimationDuration,
float animationScale, int finalWidth, int finalHeight, boolean dismissing) {
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
// Can't do animation.
return false;
}
@@ -509,7 +509,7 @@
mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3,
layerStack);
mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
- } catch (Surface.OutOfResourcesException e) {
+ } catch (SurfaceControl.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -539,7 +539,7 @@
mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2,
layerStack);
mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
- } catch (Surface.OutOfResourcesException e) {
+ } catch (SurfaceControl.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -561,7 +561,7 @@
Rect inner = new Rect(0, 0, finalWidth, finalHeight);
mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER,
layerStack);
- } catch (Surface.OutOfResourcesException e) {
+ } catch (SurfaceControl.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -580,7 +580,7 @@
public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
float animationScale, int finalWidth, int finalHeight) {
if (DEBUG_STATE) Slog.v(TAG, "Dismiss!");
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
// Can't do animation.
return false;
}
@@ -598,12 +598,12 @@
public void kill() {
if (DEBUG_STATE) Slog.v(TAG, "Kill!");
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
if (WindowManagerService.SHOW_TRANSACTIONS ||
WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
- " FREEZE " + mSurface + ": DESTROY");
- mSurface.destroy();
- mSurface = null;
+ " FREEZE " + mSurfaceControl + ": DESTROY");
+ mSurfaceControl.destroy();
+ mSurfaceControl = null;
}
if (mCustomBlackFrame != null) {
mCustomBlackFrame.kill();
@@ -861,10 +861,10 @@
return;
}
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
- mSurface.hide();
+ mSurfaceControl.hide();
}
}
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 7a0fa16..e82068c 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -314,17 +314,17 @@
mService.mDragState.mThumbOffsetY = thumbCenterY;
// Make the surface visible at the proper location
- final SurfaceControl surface = mService.mDragState.mSurface;
+ final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl;
if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
SurfaceControl.openTransaction();
try {
- surface.setPosition(touchX - thumbCenterX,
+ surfaceControl.setPosition(touchX - thumbCenterX,
touchY - thumbCenterY);
- surface.setAlpha(.7071f);
- surface.setLayer(mService.mDragState.getDragLayerLw());
- surface.setLayerStack(display.getLayerStack());
- surface.show();
+ surfaceControl.setAlpha(.7071f);
+ surfaceControl.setLayer(mService.mDragState.getDragLayerLw());
+ surfaceControl.setLayerStack(display.getLayerStack());
+ surfaceControl.show();
} finally {
SurfaceControl.closeTransaction();
if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index a2c44ef..67daf75 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -225,7 +225,7 @@
WindowStateAnimator winAnimator = win.mWinAnimator;
final int flags = winAnimator.mAttrFlags;
- if (winAnimator.mSurface != null) {
+ if (winAnimator.mSurfaceControl != null) {
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
@@ -373,7 +373,7 @@
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
- if (winAnimator.mSurface == null) {
+ if (winAnimator.mSurfaceControl == null) {
continue;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7b83c24..d38273d 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -1112,7 +1112,7 @@
if (DEBUG_INPUT_METHOD) {
Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
if (!w.isVisibleOrAdding()) {
- Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurface
+ Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurfaceControl
+ " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
+ " policyVis=" + w.mPolicyVisibility
+ " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
@@ -2278,14 +2278,14 @@
TAG, "Remove " + win + " client="
+ Integer.toHexString(System.identityHashCode(
win.mClient.asBinder()))
- + ", surface=" + win.mWinAnimator.mSurface);
+ + ", surface=" + win.mWinAnimator.mSurfaceControl);
final long origId = Binder.clearCallingIdentity();
win.disposeInputChannel();
if (DEBUG_APP_TRANSITIONS) Slog.v(
- TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurface
+ TAG, "Remove " + win + ": mSurface=" + win.mWinAnimator.mSurfaceControl
+ " mExiting=" + win.mExiting
+ " isAnimating=" + win.mWinAnimator.isAnimating()
+ " app-animation="
@@ -2775,9 +2775,9 @@
if (!win.mHasSurface) {
surfaceChanged = true;
}
- SurfaceControl surface = winAnimator.createSurfaceLocked();
- if (surface != null) {
- outSurface.copyFrom(surface);
+ SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
+ if (surfaceControl != null) {
+ outSurface.copyFrom(surfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
@@ -2817,7 +2817,7 @@
}
} else {
winAnimator.mEnterAnimationPending = false;
- if (winAnimator.mSurface != null) {
+ if (winAnimator.mSurfaceControl != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
+ ": mExiting=" + win.mExiting);
// If we are not currently running the exit animation, we
@@ -7935,15 +7935,15 @@
// TODO(multi-display): support other displays
final DisplayContent displayContent = getDefaultDisplayContentLocked();
final Display display = displayContent.getDisplay();
- SurfaceControl surface = new SurfaceControl(mFxSession,
+ SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
"thumbnail anim",
dirty.width(), dirty.height(),
PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- surface.setLayerStack(display.getLayerStack());
- appAnimator.thumbnail = surface;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surface + ": CREATE");
+ surfaceControl.setLayerStack(display.getLayerStack());
+ appAnimator.thumbnail = surfaceControl;
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
Surface drawSurface = new Surface();
- drawSurface.copyFrom(surface);
+ drawSurface.copyFrom(surfaceControl);
Canvas c = drawSurface.lockCanvas(dirty);
c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
drawSurface.unlockCanvasAndPost(c);
@@ -8064,7 +8064,7 @@
if (w.mOrientationChanging) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation start waiting for draw mDrawState=DRAW_PENDING in "
- + w + ", surface " + winAnimator.mSurface);
+ + w + ", surface " + winAnimator.mSurfaceControl);
winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
if (w.mAppToken != null) {
w.mAppToken.allDrawn = false;
@@ -8081,7 +8081,7 @@
if (w.isDrawnLw()) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
"Orientation not waiting for draw in "
- + w + ", surface " + winAnimator.mSurface);
+ + w + ", surface " + winAnimator.mSurfaceControl);
w.mOrientationChanging = false;
}
}
@@ -8429,7 +8429,7 @@
Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
+ ", isAnimating=" + winAnimator.isAnimating());
if (!w.isDrawnLw()) {
- Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
+ Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceControl
+ " pv=" + w.mPolicyVisibility
+ " mDrawState=" + winAnimator.mDrawState
+ " ah=" + w.mAttachedHidden
@@ -8914,7 +8914,7 @@
boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
boolean secure) {
- final SurfaceControl surface = winAnimator.mSurface;
+ final SurfaceControl surface = winAnimator.mSurfaceControl;
boolean leakedSurface = false;
boolean killedApps = false;
@@ -8936,28 +8936,28 @@
while (mTmpWindowsIterator.hasNext()) {
WindowState ws = mTmpWindowsIterator.next();
WindowStateAnimator wsa = ws.mWinAnimator;
- if (wsa.mSurface != null) {
+ if (wsa.mSurfaceControl != null) {
if (!mSessions.contains(wsa.mSession)) {
Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
- + ws + " surface=" + wsa.mSurface
+ + ws + " surface=" + wsa.mSurfaceControl
+ " token=" + ws.mToken
+ " pid=" + ws.mSession.mPid
+ " uid=" + ws.mSession.mUid);
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
- wsa.mSurface.destroy();
+ wsa.mSurfaceControl.destroy();
wsa.mSurfaceShown = false;
- wsa.mSurface = null;
+ wsa.mSurfaceControl = null;
ws.mHasSurface = false;
mForceRemoves.add(ws);
leakedSurface = true;
} else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
- + ws + " surface=" + wsa.mSurface
+ + ws + " surface=" + wsa.mSurfaceControl
+ " token=" + ws.mAppToken);
if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
- wsa.mSurface.destroy();
+ wsa.mSurfaceControl.destroy();
wsa.mSurfaceShown = false;
- wsa.mSurface = null;
+ wsa.mSurfaceControl = null;
ws.mHasSurface = false;
leakedSurface = true;
}
@@ -8974,7 +8974,7 @@
continue;
}
WindowStateAnimator wsa = ws.mWinAnimator;
- if (wsa.mSurface != null) {
+ if (wsa.mSurfaceControl != null) {
pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid);
}
}
@@ -9001,7 +9001,7 @@
"RECOVER DESTROY", null);
surface.destroy();
winAnimator.mSurfaceShown = false;
- winAnimator.mSurface = null;
+ winAnimator.mSurfaceControl = null;
winAnimator.mWin.mHasSurface = false;
}
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 82e59a8..3a9f7cb 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -88,7 +88,7 @@
int mAnimLayer;
int mLastLayer;
- SurfaceControl mSurface;
+ SurfaceControl mSurfaceControl;
SurfaceControl mPendingDestroySurface;
/**
@@ -404,7 +404,7 @@
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Exit animation finished in " + this
+ ": remove=" + mWin.mRemoveOnExit);
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
mService.mDestroySurface.add(mWin);
mWin.mDestroying = true;
if (WindowState.SHOW_TRANSACTIONS) WindowManagerService.logSurface(
@@ -425,10 +425,10 @@
mLastHidden = true;
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
"HIDE (performLayout)", null);
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
mSurfaceShown = false;
try {
- mSurface.hide();
+ mSurfaceControl.hide();
} catch (RuntimeException e) {
Slog.w(TAG, "Exception hiding surface in " + mWin);
}
@@ -445,7 +445,7 @@
if (mDrawState == DRAW_PENDING) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
- + mSurface);
+ + mSurfaceControl);
if (DEBUG_STARTING_WINDOW &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
Slog.v(TAG, "Draw state now committed in " + mWin);
@@ -467,7 +467,7 @@
return false;
}
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
- Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurface);
+ Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceControl);
}
mDrawState = READY_TO_SHOW;
final boolean starting = mWin.mAttrs.type == TYPE_APPLICATION_STARTING;
@@ -625,7 +625,7 @@
}
SurfaceControl createSurfaceLocked() {
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
"createSurface " + this + ": mDrawState=DRAW_PENDING");
mDrawState = DRAW_PENDING;
@@ -685,12 +685,12 @@
flags |= SurfaceControl.OPAQUE;
}
if (DEBUG_SURFACE_TRACE) {
- mSurface = new SurfaceTrace(
+ mSurfaceControl = new SurfaceTrace(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
w, h, format, flags);
} else {
- mSurface = new SurfaceControl(
+ mSurfaceControl = new SurfaceControl(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
w, h, format, flags);
@@ -698,7 +698,7 @@
mWin.mHasSurface = true;
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
" CREATE SURFACE "
- + mSurface + " IN SESSION "
+ + mSurfaceControl + " IN SESSION "
+ mSession.mSurfaceSession
+ ": pid=" + mSession.mPid + " format="
+ attrs.format + " flags=0x"
@@ -718,7 +718,7 @@
}
if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Got surface: " + mSurface
+ TAG, "Got surface: " + mSurfaceControl
+ ", set left=" + mWin.mFrame.left + " top=" + mWin.mFrame.top
+ ", animLayer=" + mAnimLayer);
if (SHOW_LIGHT_TRANSACTIONS) {
@@ -733,11 +733,11 @@
try {
mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
mSurfaceY = mWin.mFrame.top + mWin.mYOffset;
- mSurface.setPosition(mSurfaceX, mSurfaceY);
+ mSurfaceControl.setPosition(mSurfaceX, mSurfaceY);
mSurfaceLayer = mAnimLayer;
- mSurface.setLayerStack(mLayerStack);
- mSurface.setLayer(mAnimLayer);
- mSurface.setAlpha(0);
+ mSurfaceControl.setLayerStack(mLayerStack);
+ mSurfaceControl.setLayer(mAnimLayer);
+ mSurfaceControl.setAlpha(0);
mSurfaceShown = false;
} catch (RuntimeException e) {
Slog.w(TAG, "Error creating surface in " + w, e);
@@ -752,7 +752,7 @@
if (WindowManagerService.localLOGV) Slog.v(
TAG, "Created surface " + this);
}
- return mSurface;
+ return mSurfaceControl;
}
void destroySurfaceLocked() {
@@ -760,7 +760,7 @@
mWin.mAppToken.startingDisplayed = false;
}
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
int i = mWin.mChildWindows.size();
while (i > 0) {
@@ -777,10 +777,10 @@
e.fillInStackTrace();
}
Slog.w(TAG, "Window " + this + " destroying surface "
- + mSurface + ", session " + mSession, e);
+ + mSurfaceControl + ", session " + mSession, e);
}
if (mSurfaceDestroyDeferred) {
- if (mSurface != null && mPendingDestroySurface != mSurface) {
+ if (mSurfaceControl != null && mPendingDestroySurface != mSurfaceControl) {
if (mPendingDestroySurface != null) {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
RuntimeException e = null;
@@ -792,7 +792,7 @@
}
mPendingDestroySurface.destroy();
}
- mPendingDestroySurface = mSurface;
+ mPendingDestroySurface = mSurfaceControl;
}
} else {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
@@ -803,17 +803,17 @@
}
WindowManagerService.logSurface(mWin, "DESTROY", e);
}
- mSurface.destroy();
+ mSurfaceControl.destroy();
}
mAnimator.hideWallpapersLocked(mWin);
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window " + this
- + " surface " + mSurface + " session " + mSession
+ + " surface " + mSurfaceControl + " session " + mSession
+ ": " + e.toString());
}
mSurfaceShown = false;
- mSurface = null;
+ mSurfaceControl = null;
mWin.mHasSurface = false;
mDrawState = NO_SURFACE;
}
@@ -1120,7 +1120,7 @@
try {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"CROP " + w.mSystemDecorRect.toShortString(), null);
- mSurface.setWindowCrop(w.mSystemDecorRect);
+ mSurfaceControl.setWindowCrop(w.mSystemDecorRect);
} catch (RuntimeException e) {
Slog.w(TAG, "Error setting crop surface of " + w
+ " crop=" + w.mSystemDecorRect.toShortString(), e);
@@ -1164,7 +1164,7 @@
"POS " + left + ", " + top, null);
mSurfaceX = left;
mSurfaceY = top;
- mSurface.setPosition(left, top);
+ mSurfaceControl.setPosition(left, top);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + w
+ " pos=(" + left
@@ -1180,7 +1180,7 @@
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
"SIZE " + width + "x" + height, null);
mSurfaceResized = true;
- mSurface.setSize(width, height);
+ mSurfaceControl.setSize(width, height);
final int displayId = w.mDisplayContent.getDisplayId();
mAnimator.setPendingLayoutChanges(displayId,
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
@@ -1204,7 +1204,7 @@
public void prepareSurfaceLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
if (w.mOrientationChanging) {
if (DEBUG_ORIENTATION) {
Slog.v(TAG, "Orientation change skips hidden " + w);
@@ -1262,13 +1262,13 @@
+ "," + (mDtDx*w.mVScale)
+ "][" + (mDsDy*w.mHScale)
+ "," + (mDtDy*w.mVScale) + "]", null);
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
try {
mSurfaceAlpha = mShownAlpha;
- mSurface.setAlpha(mShownAlpha);
+ mSurfaceControl.setAlpha(mShownAlpha);
mSurfaceLayer = mAnimLayer;
- mSurface.setLayer(mAnimLayer);
- mSurface.setMatrix(
+ mSurfaceControl.setLayer(mAnimLayer);
+ mSurfaceControl.setMatrix(
mDsDx*w.mHScale, mDtDx*w.mVScale,
mDsDy*w.mHScale, mDtDy*w.mVScale);
@@ -1286,7 +1286,7 @@
w.mOrientationChanging = false;
}
}
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
w.mToken.hasVisible = true;
}
} catch (RuntimeException e) {
@@ -1319,7 +1319,7 @@
}
void setTransparentRegionHintLocked(final Region region) {
- if (mSurface == null) {
+ if (mSurfaceControl == null) {
Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
return;
}
@@ -1329,7 +1329,7 @@
try {
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
"transparentRegionHint=" + region, null);
- mSurface.setTransparentRegionHint(region);
+ mSurfaceControl.setTransparentRegionHint(region);
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
@@ -1356,7 +1356,7 @@
try {
if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
"POS " + left + ", " + top, null);
- mSurface.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
+ mSurfaceControl.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
updateSurfaceWindowCrop(false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
@@ -1431,7 +1431,7 @@
WindowState c = mWin.mChildWindows.get(i);
if (c.mAttachedHidden) {
c.mAttachedHidden = false;
- if (c.mWinAnimator.mSurface != null) {
+ if (c.mWinAnimator.mSurfaceControl != null) {
c.mWinAnimator.performShowLocked();
// It hadn't been shown, which means layout not
// performed on it, so now we want to make sure to
@@ -1479,9 +1479,9 @@
*/
boolean showSurfaceRobustlyLocked() {
try {
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
mSurfaceShown = true;
- mSurface.show();
+ mSurfaceControl.show();
if (mWin.mTurnOnScreen) {
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Show surface turning screen on: " + mWin);
@@ -1491,7 +1491,7 @@
}
return true;
} catch (RuntimeException e) {
- Slog.w(TAG, "Failure showing surface " + mSurface + " in " + mWin, e);
+ Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + mWin, e);
}
mService.reclaimSomeSurfaceMemoryLocked(this, "show", true);
@@ -1600,9 +1600,9 @@
pw.print(" "); mTransformation.printShortString(pw);
pw.println();
}
- if (mSurface != null) {
+ if (mSurfaceControl != null) {
if (dumpAll) {
- pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
+ pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
pw.print(prefix); pw.print("mDrawState=");
pw.print(drawStateToString(mDrawState));
pw.print(" mLastHidden="); pw.println(mLastHidden);
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
index fb818d4..9939c08 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
@@ -41,13 +41,40 @@
protected int mask() { return 0x0; };
private static final RectF gRect = new RectF(0, 0, 200, 175);
- private static final float[] gLinePts = new float[] {
- 100, 0, 200, 200, 200, 200, 0, 200, 0, 200, 100, 0
- };
private static final float[] gPts = new float[] {
0, 100, 100, 0, 100, 200, 200, 100
};
+ private static final int NUM_PARALLEL_LINES = 24;
+ private static final float[] gTriPts = new float[] {
+ 75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
+ };
+ private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
+ static {
+ int index;
+ for (index = 0; index < gTriPts.length; index++) {
+ gLinePts[index] = gTriPts[index];
+ }
+ float val = 0;
+ for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+ gLinePts[index + 0] = 150;
+ gLinePts[index + 1] = val;
+ gLinePts[index + 2] = 300;
+ gLinePts[index + 3] = val;
+ index += 4;
+ val += 8 + (2.0f/NUM_PARALLEL_LINES);
+ }
+ val = 0;
+ for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+ gLinePts[index + 0] = val;
+ gLinePts[index + 1] = 150;
+ gLinePts[index + 2] = val;
+ gLinePts[index + 3] = 300;
+ index += 4;
+ val += 8 + (2.0f/NUM_PARALLEL_LINES);
+ }
+ };
+
@SuppressWarnings("serial")
private static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> gMaps = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>() {
{
@@ -307,7 +334,7 @@
canvas.drawOval(gRect, paint);
}
});
- put("triLines", new DisplayModifier() {
+ put("lines", new DisplayModifier() {
@Override
public void modifyDrawing(Paint paint, Canvas canvas) {
canvas.drawLines(gLinePts, paint);
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
index 4d1627d..12d3185 100644
--- a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/RsYuv.java
@@ -80,8 +80,13 @@
Type t = tb.create();
mAllocationOut = Allocation.createTyped(mRS, t, Allocation.USAGE_SCRIPT |
Allocation.USAGE_IO_OUTPUT);
- mAllocationIn = Allocation.createSized(mRS, Element.U8(mRS), (mHeight * mWidth) +
- ((mHeight / 2) * (mWidth / 2) * 2));
+
+
+ tb = new Type.Builder(mRS, Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV));
+ tb.setX(mWidth);
+ tb.setY(mHeight);
+ tb.setYuvFormat(android.graphics.ImageFormat.NV21);
+ mAllocationIn = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
mYuv.setInput(mAllocationIn);
setupSurface();