Merge "free EGL resources associated to a thread when it terminates"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 1911839..6d6f77e 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -82,6 +82,7 @@
{ "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
{ "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
{ "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
+ { "rs", "RenderScript", ATRACE_TAG_RS, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 9a332a9..89bea91 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -315,7 +315,13 @@
);
}
+static void sigpipe_handler(int n) {
+ (void)n;
+ exit(EXIT_FAILURE);
+}
+
int main(int argc, char *argv[]) {
+ struct sigaction sigact;
int do_add_date = 0;
int do_compress = 0;
int do_vibrate = 1;
@@ -336,7 +342,9 @@
}
ALOGI("begin\n");
- signal(SIGPIPE, SIG_IGN);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = sigpipe_handler;
+ sigaction(SIGPIPE, &sigact, NULL);
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
diff --git a/include/android/input.h b/include/android/input.h
index c8ac938..fead769 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -692,7 +692,7 @@
/* Get the time that a historical movement occurred between this event and
* the previous event, in the java.lang.System.nanoTime() time base. */
-int64_t AMotionEvent_getHistoricalEventTime(AInputEvent* motion_event,
+int64_t AMotionEvent_getHistoricalEventTime(const AInputEvent* motion_event,
size_t history_index);
/* Get the historical raw X coordinate of this event for the given pointer index that
@@ -719,14 +719,14 @@
* occurred between this event and the previous motion event.
* Whole numbers are pixels; the value may have a fraction for input devices
* that are sub-pixel precise. */
-float AMotionEvent_getHistoricalX(AInputEvent* motion_event, size_t pointer_index,
+float AMotionEvent_getHistoricalX(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
/* Get the historical Y coordinate of this event for the given pointer index that
* occurred between this event and the previous motion event.
* Whole numbers are pixels; the value may have a fraction for input devices
* that are sub-pixel precise. */
-float AMotionEvent_getHistoricalY(AInputEvent* motion_event, size_t pointer_index,
+float AMotionEvent_getHistoricalY(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
/* Get the historical pressure of this event for the given pointer index that
@@ -734,7 +734,7 @@
* The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure),
* although values higher than 1 may be generated depending on the calibration of
* the input device. */
-float AMotionEvent_getHistoricalPressure(AInputEvent* motion_event, size_t pointer_index,
+float AMotionEvent_getHistoricalPressure(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
/* Get the current scaled value of the approximate size for the given pointer index that
@@ -744,7 +744,7 @@
* touch is normalized with the device specific range of values
* and scaled to a value between 0 and 1. The value of size can be used to
* determine fat touch events. */
-float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_index,
+float AMotionEvent_getHistoricalSize(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
/* Get the historical length of the major axis of an ellipse that describes the touch area
diff --git a/include/binder/TextOutput.h b/include/binder/TextOutput.h
index de2fbbe..974a194 100644
--- a/include/binder/TextOutput.h
+++ b/include/binder/TextOutput.h
@@ -25,6 +25,9 @@
// ---------------------------------------------------------------------------
namespace android {
+class String8;
+class String16;
+
class TextOutput
{
public:
@@ -76,6 +79,8 @@
TextOutput& operator<<(TextOutput& to, double);
TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
TextOutput& operator<<(TextOutput& to, const void*);
+TextOutput& operator<<(TextOutput& to, const String8& val);
+TextOutput& operator<<(TextOutput& to, const String16& val);
class TypeCode
{
diff --git a/include/utils/Log.h b/include/utils/Log.h
index 98c441c..4259c86 100644
--- a/include/utils/Log.h
+++ b/include/utils/Log.h
@@ -62,7 +62,7 @@
* }
*/
#define ALOGD_IF_SLOW(timeoutMillis, message) \
- LogIfSlow _logIfSlow(LOG_TAG, ANDROID_LOG_DEBUG, timeoutMillis, message);
+ android::LogIfSlow _logIfSlow(LOG_TAG, ANDROID_LOG_DEBUG, timeoutMillis, message);
} // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index aa19d17..359742c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1473,6 +1473,8 @@
if (objectsSize) {
objects = (size_t*)malloc(objectsSize*sizeof(size_t));
if (!objects) {
+ free(data);
+
mError = NO_MEMORY;
return NO_MEMORY;
}
@@ -1553,7 +1555,7 @@
mError = NO_MEMORY;
return NO_MEMORY;
}
-
+
if(!(mDataCapacity == 0 && mObjects == NULL
&& mObjectsCapacity == 0)) {
ALOGE("continueWrite: %d/%p/%d/%d", mDataCapacity, mObjects, mObjectsCapacity, desired);
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 9637334..db3e858 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -18,6 +18,9 @@
#include <binder/Debug.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -119,6 +122,18 @@
return to;
}
+TextOutput& operator<<(TextOutput& to, const String8& val)
+{
+ to << val.string();
+ return to;
+}
+
+TextOutput& operator<<(TextOutput& to, const String16& val)
+{
+ to << String8(val).string();
+ return to;
+}
+
static void textOutputPrinter(void* cookie, const char* txt)
{
((TextOutput*)cookie)->print(txt, strlen(txt));
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 93d6127..4f63c31 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -220,22 +220,6 @@
// initial covariance: Var{ x(t0) }
// TODO: initialize P correctly
P = 0;
-
- // it is unclear how to set the initial covariance. It does affect
- // how quickly the fusion converges. Experimentally it would take
- // about 10 seconds at 200 Hz to estimate the gyro-drift with an
- // initial covariance of 0, and about a second with an initial covariance
- // of about 1 deg/s.
- const float covv = 0;
- const float covu = 0.5f * (float(M_PI) / 180);
- mat33_t& Pv = P[0][0];
- Pv[0][0] = covv;
- Pv[1][1] = covv;
- Pv[2][2] = covv;
- mat33_t& Pu = P[1][1];
- Pu[0][0] = covu;
- Pu[1][1] = covu;
- Pu[2][2] = covu;
}
bool Fusion::hasEstimate() const {
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 4837b97..a0a17da 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -53,8 +53,8 @@
// 200 Hz for gyro events is a good compromise between precision
// and power/cpu usage.
- mGyroRate = 200;
- mTargetDelayNs = 1000000000LL/mGyroRate;
+ mEstimatedGyroRate = 200;
+ mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
mFusion.init();
}
}
@@ -63,14 +63,15 @@
if (event.type == mGyro.getType()) {
if (mGyroTime != 0) {
const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
+ mFusion.handleGyro(vec3_t(event.data), dT);
+ // here we estimate the gyro rate (useful for debugging)
const float freq = 1 / dT;
if (freq >= 100 && freq<1000) { // filter values obviously wrong
const float alpha = 1 / (1 + dT); // 1s time-constant
- mGyroRate = freq + (mGyroRate - freq)*alpha;
+ mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
}
}
mGyroTime = event.timestamp;
- mFusion.handleGyro(vec3_t(event.data), 1.0f/mGyroRate);
} else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
const vec3_t mag(event.data);
mFusion.handleMag(mag);
@@ -142,7 +143,7 @@
"b=< %g, %g, %g >\n",
mEnabled ? "enabled" : "disabled",
mClients.size(),
- mGyroRate,
+ mEstimatedGyroRate,
fusion.getAttitude().x,
fusion.getAttitude().y,
fusion.getAttitude().z,
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index 4c99bcb..3c2244e 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -44,7 +44,7 @@
Sensor mGyro;
Fusion mFusion;
bool mEnabled;
- float mGyroRate;
+ float mEstimatedGyroRate;
nsecs_t mTargetDelayNs;
nsecs_t mGyroTime;
vec4_t mAttitude;
@@ -60,7 +60,7 @@
mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
vec4_t getAttitude() const { return mAttitude; }
vec3_t getGyroBias() const { return mFusion.getBias(); }
- float getEstimatedRate() const { return mGyroRate; }
+ float getEstimatedRate() const { return mEstimatedGyroRate; }
status_t activate(void* ident, bool enabled);
status_t setDelay(void* ident, int64_t ns);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c15dfd5..ee69222 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -559,31 +559,88 @@
clearWithOpenGL(hw, clip, 0,0,0,0);
}
+static void setupOpenGL10(bool premultipliedAlpha, bool opaque, int alpha) {
+ // OpenGL ES 1.0 doesn't support texture combiners.
+ // This path doesn't properly handle opaque layers that have non-opaque
+ // alpha values. The alpha channel will be copied into the framebuffer or
+ // screenshot, so if the framebuffer or screenshot is blended on top of
+ // something else, whatever is below the window will incorrectly show
+ // through.
+ if (CC_UNLIKELY(alpha < 0xFF)) {
+ GLfloat floatAlpha = alpha * (1.0f / 255.0f);
+ if (premultipliedAlpha) {
+ glColor4f(floatAlpha, floatAlpha, floatAlpha, floatAlpha);
+ } else {
+ glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
+ }
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ } else {
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ }
+}
+
+static void setupOpenGL11(bool premultipliedAlpha, bool opaque, int alpha) {
+ GLenum combineRGB;
+ GLenum combineAlpha;
+ GLenum src0Alpha;
+ GLfloat envColor[4];
+
+ if (CC_UNLIKELY(alpha < 0xFF)) {
+ // Cv = premultiplied ? Cs*alpha : Cs
+ // Av = !opaque ? alpha*As : 1.0
+ combineRGB = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
+ combineAlpha = !opaque ? GL_MODULATE : GL_REPLACE;
+ src0Alpha = GL_CONSTANT;
+ envColor[0] = alpha * (1.0f / 255.0f);
+ } else {
+ // Cv = Cs
+ // Av = opaque ? 1.0 : As
+ combineRGB = GL_REPLACE;
+ combineAlpha = GL_REPLACE;
+ src0Alpha = opaque ? GL_CONSTANT : GL_TEXTURE;
+ envColor[0] = 1.0f;
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, combineRGB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ if (combineRGB == GL_MODULATE) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ }
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, combineAlpha);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, src0Alpha);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ if (combineAlpha == GL_MODULATE) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
+ if (combineRGB == GL_MODULATE || src0Alpha == GL_CONSTANT) {
+ envColor[1] = envColor[0];
+ envColor[2] = envColor[0];
+ envColor[3] = envColor[0];
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
+ }
+}
+
void Layer::drawWithOpenGL(
const sp<const DisplayDevice>& hw, const Region& clip) const {
const uint32_t fbHeight = hw->getHeight();
const State& s(drawingState());
- GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
- if (CC_UNLIKELY(s.alpha < 0xFF)) {
- const GLfloat alpha = s.alpha * (1.0f/255.0f);
- if (mPremultipliedAlpha) {
- glColor4f(alpha, alpha, alpha, alpha);
- } else {
- glColor4f(1, 1, 1, alpha);
- }
- glEnable(GL_BLEND);
- glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ if (mFlinger->getGlesVersion() == GLES_VERSION_1_0) {
+ setupOpenGL10(mPremultipliedAlpha, isOpaque(), s.alpha);
} else {
- glColor4f(1, 1, 1, 1);
- glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- if (!isOpaque()) {
- glEnable(GL_BLEND);
- glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
- } else {
- glDisable(GL_BLEND);
- }
+ setupOpenGL11(mPremultipliedAlpha, isOpaque(), s.alpha);
+ }
+
+ if (s.alpha < 0xFF || !isOpaque()) {
+ glEnable(GL_BLEND);
+ glBlendFunc(mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ glDisable(GL_BLEND);
}
LayerMesh mesh;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6ab33ef..fbd9f25 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -414,6 +414,22 @@
return ctxt;
}
+static GlesVersion parseGlesVersion(const char* str) {
+ int major, minor;
+ if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+ ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+ return GLES_VERSION_1_0;
+ }
+
+ if (major == 1 && minor == 0) return GLES_VERSION_1_0;
+ if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
+ if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
+ if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
+
+ ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
+ return GLES_VERSION_1_0;
+}
+
void SurfaceFlinger::initializeGL(EGLDisplay display) {
GLExtensions& extensions(GLExtensions::getInstance());
extensions.initWithGLStrings(
@@ -425,6 +441,8 @@
eglQueryString(display, EGL_VERSION),
eglQueryString(display, EGL_EXTENSIONS));
+ mGlesVersion = parseGlesVersion(extensions.getVersion());
+
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e7745b8..089c265 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -72,6 +72,13 @@
eTransactionMask = 0x07
};
+enum GlesVersion {
+ GLES_VERSION_1_0 = 0x10000,
+ GLES_VERSION_1_1 = 0x10001,
+ GLES_VERSION_2_0 = 0x20000,
+ GLES_VERSION_3_0 = 0x30000,
+};
+
class SurfaceFlinger : public BinderService<SurfaceFlinger>,
public BnSurfaceComposer,
private IBinder::DeathRecipient,
@@ -121,6 +128,11 @@
// TODO: this should be made accessible only to HWComposer
const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
+ // return the version of the OpenGL ES composition context
+ GlesVersion getGlesVersion() const {
+ return mGlesVersion;
+ }
+
private:
friend class Client;
friend class DisplayEventConnection;
@@ -421,6 +433,7 @@
EGLConfig mEGLConfig;
EGLDisplay mEGLDisplay;
EGLint mEGLNativeVisualId;
+ GlesVersion mGlesVersion;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES];
// Can only accessed from the main thread, these members