Fix INVALID_OPERATION error with layers rendering.
This change is a workaround for a driver bug that causes an INVALID_OPERATION
to be thrown on every glCopyTexSubImage() call. This change also adds a new
test for gradients local matrices.
Change-Id: I41b7437481026702d0a3a9677f099b4557c0a84e
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 595bac8..00324a85 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,7 +17,6 @@
package android.view;
import android.content.ClipData;
-import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -55,7 +54,6 @@
import android.util.Pools;
import android.util.SparseArray;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.DragEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -2038,7 +2036,6 @@
*
*/
boolean mCanAcceptDrop;
- private boolean mIsCurrentDropTarget;
private int mThumbnailWidth;
private int mThumbnailHeight;
@@ -9800,11 +9797,14 @@
+ " surface=" + surface);
if (token != null) {
Canvas canvas = surface.lockCanvas(null);
- onDrawDragThumbnail(canvas);
- surface.unlockCanvasAndPost(canvas);
+ try {
+ onDrawDragThumbnail(canvas);
+ } finally {
+ surface.unlockCanvasAndPost(canvas);
+ }
okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
- touchX, touchY, thumbnailTouchX, thumbnailTouchX, data);
+ touchX, touchY, thumbnailTouchX, thumbnailTouchY, data);
if (DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
}
} catch (Exception e) {
@@ -9837,8 +9837,8 @@
* The View must call this method from onMeasureDragThumbnail() in order to
* specify the dimensions of the drag thumbnail image.
*
- * @param width
- * @param height
+ * @param width The desired thumbnail width.
+ * @param height The desired thumbnail height.
*/
protected final void setDragThumbnailDimension(int width, int height) {
mPrivateFlags |= MEASURED_DIMENSION_SET;
@@ -9973,30 +9973,6 @@
ViewConfiguration.getLongPressTimeout() - delayOffset);
}
- private static int[] stateSetUnion(final int[] stateSet1, final int[] stateSet2) {
- final int stateSet1Length = stateSet1.length;
- final int stateSet2Length = stateSet2.length;
- final int[] newSet = new int[stateSet1Length + stateSet2Length];
- int k = 0;
- int i = 0;
- int j = 0;
- // This is a merge of the two input state sets and assumes that the
- // input sets are sorted by the order imposed by ViewDrawableStates.
- for (int viewState : R.styleable.ViewDrawableStates) {
- if (i < stateSet1Length && stateSet1[i] == viewState) {
- newSet[k++] = viewState;
- i++;
- } else if (j < stateSet2Length && stateSet2[j] == viewState) {
- newSet[k++] = viewState;
- j++;
- }
- if (k > 1) {
- assert(newSet[k - 1] > newSet[k - 2]);
- }
- }
- return newSet;
- }
-
/**
* Inflate a view from an XML resource. This convenience method wraps the {@link
* LayoutInflater} class, which provides a full range of options for view inflation.
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 60523db..a0cc5d6 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -44,7 +44,7 @@
uint32_t id;
bool operator<(const LayerSize& rhs) const {
- if (id != 0 && rhs.id != 0) {
+ if (id != 0 && rhs.id != 0 && id != rhs.id) {
return id < rhs.id;
}
if (width == rhs.width) {
@@ -54,7 +54,7 @@
}
bool operator==(const LayerSize& rhs) const {
- return width == rhs.width && height == rhs.height;
+ return id == rhs.id && width == rhs.width && height == rhs.height;
}
}; // struct LayerSize
@@ -83,7 +83,7 @@
*/
bool blend;
/**
- * Indicates that this layer has never been used before.
+ * Indicates whether this layer has been used already.
*/
bool empty;
}; // struct Layer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 2770868..8c70cf9 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -114,6 +114,8 @@
glGenTextures(1, &layer->texture);
glBindTexture(GL_TEXTURE_2D, layer->texture);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 23de3a5..0810fb8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -366,6 +366,8 @@
return false;
}
+ glActiveTexture(GL_TEXTURE0);
+
LayerSize size(bounds.getWidth(), bounds.getHeight());
Layer* layer = mCaches.layerCache.get(size);
if (!layer) {
@@ -383,17 +385,22 @@
// Copy the framebuffer into the layer
glBindTexture(GL_TEXTURE_2D, layer->texture);
- if (layer->empty) {
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
- bounds.getWidth(), bounds.getHeight(), 0);
- layer->empty = false;
- } else {
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, mHeight - bounds.bottom,
- bounds.getWidth(), bounds.getHeight());
- }
+ // TODO: Workaround for b/3054204
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
+ bounds.getWidth(), bounds.getHeight(), 0);
- if (flags & SkCanvas::kClipToLayer_SaveFlag) {
- if (mSnapshot->clipTransformed(bounds)) setScissorFromClip();
+ // TODO: Waiting for b/3054204 to be fixed
+// if (layer->empty) {
+// glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
+// bounds.getWidth(), bounds.getHeight(), 0);
+// layer->empty = false;
+// } else {
+// glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, mHeight - bounds.bottom,
+// bounds.getWidth(), bounds.getHeight());
+// }
+
+ if (flags & SkCanvas::kClipToLayer_SaveFlag && mSnapshot->clipTransformed(bounds)) {
+ setScissorFromClip();
}
// Enqueue the buffer coordinates to clear the corresponding region later
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index af71a0f..4be41b9 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -164,6 +164,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="GradientsActivity"
+ android:label="_Gradients">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name="ShadersActivity"
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java
new file mode 100644
index 0000000..b70f3a9
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class GradientsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new ShadersView(this));
+ }
+
+ static class ShadersView extends View {
+ private final Paint mPaint;
+ private final float mDrawWidth;
+ private final float mDrawHeight;
+ private final LinearGradient mGradient;
+ private final Matrix mMatrix;
+
+ ShadersView(Context c) {
+ super(c);
+
+ mDrawWidth = 200;
+ mDrawHeight = 200;
+
+ mGradient = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
+ mMatrix = new Matrix();
+
+ mPaint = new Paint();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(255, 255, 255);
+
+ // Gradients
+ canvas.save();
+ float top = 40.0f;
+ float right = 40.0f + mDrawWidth;
+ float left = 40.0f;
+ float bottom = 40.0f + mDrawHeight;
+
+ mPaint.setShader(mGradient);
+
+ mMatrix.setScale(1, mDrawWidth);
+ mMatrix.postRotate(90);
+ mMatrix.postTranslate(right, top);
+ mGradient.setLocalMatrix(mMatrix);
+ canvas.drawRect(right - mDrawWidth, top, right, top + mDrawHeight, mPaint);
+
+ top += 40.0f + mDrawHeight;
+ bottom += 40.0f + mDrawHeight;
+
+ mMatrix.setScale(1, mDrawHeight);
+ mMatrix.postTranslate(left, top);
+ mGradient.setLocalMatrix(mMatrix);
+ canvas.drawRect(left, top, right, top + mDrawHeight, mPaint);
+
+ left += 40.0f + mDrawWidth;
+ right += 40.0f + mDrawWidth;
+ top -= 40.0f + mDrawHeight;
+ bottom -= 40.0f + mDrawHeight;
+
+ mMatrix.setScale(1, mDrawHeight);
+ mMatrix.postRotate(180);
+ mMatrix.postTranslate(left, bottom);
+ mGradient.setLocalMatrix(mMatrix);
+ canvas.drawRect(left, bottom - mDrawHeight, right, bottom, mPaint);
+
+ top += 40.0f + mDrawHeight;
+ bottom += 40.0f + mDrawHeight;
+
+ mMatrix.setScale(1, mDrawWidth);
+ mMatrix.postRotate(-90);
+ mMatrix.postTranslate(left, top);
+ mGradient.setLocalMatrix(mMatrix);
+ canvas.drawRect(left, top, left + mDrawWidth, bottom, mPaint);
+
+ canvas.restore();
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
index 9c8e7ec..2db1071 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
@@ -77,8 +77,13 @@
m2.setScale(0.5f, 0.5f);
mScaledShader.setLocalMatrix(m2);
- mHorGradient = new LinearGradient(0.0f, 0.0f, mDrawWidth, 0.0f,
+ mHorGradient = new LinearGradient(0.0f, 0.0f, 1.0f, 0.0f,
Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
+ Matrix m3 = new Matrix();
+ m3.setScale(mDrawHeight, 1.0f);
+ m3.postRotate(-90.0f);
+ m3.postTranslate(0.0f, mDrawHeight);
+ mHorGradient.setLocalMatrix(m3);
mDiagGradient = new LinearGradient(0.0f, 0.0f, mDrawWidth / 1.5f, mDrawHeight,
Color.BLUE, Color.MAGENTA, Shader.TileMode.CLAMP);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index f47b00f..763169a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -87,6 +87,7 @@
ListView list = (ListView) findViewById(R.id.list);
list.setAdapter(adapter);
list.setCacheColorHint(0);
+ list.setVerticalFadingEdgeEnabled(true);
registerForContextMenu(list);
}