diff options
66 files changed, 1141 insertions, 2294 deletions
@@ -36,6 +36,7 @@ LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS)) # EventLogTags files. LOCAL_SRC_FILES += \ core/java/android/content/EventLogTags.logtags \ + core/java/android/speech/tts/EventLogTags.logtags \ core/java/android/webkit/EventLogTags.logtags \ telephony/java/com/android/internal/telephony/EventLogTags.logtags \ @@ -16272,20 +16272,10 @@ package android.renderscript { public class AllocationAdapter extends android.renderscript.Allocation { method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation); - method public void readData(int[]); - method public void readData(float[]); method public void setFace(android.renderscript.Type.CubemapFace); method public void setLOD(int); method public void setY(int); method public void setZ(int); - method public void subData(int, android.renderscript.FieldPacker); - method public void subData1D(int, int, int[]); - method public void subData1D(int, int, short[]); - method public void subData1D(int, int, byte[]); - method public void subData1D(int, int, float[]); - method public void subData2D(int, int, int, int, int[]); - method public void subData2D(int, int, int, int, float[]); - method public void subElementData(int, int, android.renderscript.FieldPacker); } class BaseObj { diff --git a/api/current.txt b/api/current.txt index 91c561c..d507940 100644 --- a/api/current.txt +++ b/api/current.txt @@ -941,6 +941,7 @@ package android { field public static final int tension = 16843370; // 0x101026a field public static final int testOnly = 16843378; // 0x1010272 field public static final int text = 16843087; // 0x101014f + field public static final int textAllCaps = 16843680; // 0x10103a0 field public static final int textAppearance = 16842804; // 0x1010034 field public static final int textAppearanceButton = 16843271; // 0x1010207 field public static final int textAppearanceInverse = 16842805; // 0x1010035 @@ -16681,23 +16682,12 @@ package android.renderscript { } public class AllocationAdapter extends android.renderscript.Allocation { + method public static android.renderscript.AllocationAdapter create1D(android.renderscript.RenderScript, android.renderscript.Allocation); method public static android.renderscript.AllocationAdapter create2D(android.renderscript.RenderScript, android.renderscript.Allocation); - method public void readData(int[]); - method public void readData(float[]); method public void setFace(android.renderscript.Type.CubemapFace); method public void setLOD(int); method public void setY(int); method public void setZ(int); - method public void subData(int, android.renderscript.FieldPacker); - method public void subData1D(int, int, int[]); - method public void subData1D(int, int, short[]); - method public void subData1D(int, int, byte[]); - method public void subData1D(int, int, float[]); - method public void subData1D(int, int, android.renderscript.AllocationAdapter, int); - method public void subData2D(int, int, int, int, int[]); - method public void subData2D(int, int, int, int, float[]); - method public void subData2D(int, int, int, int, android.renderscript.AllocationAdapter, int, int); - method public void subElementData(int, int, android.renderscript.FieldPacker); } public class BaseObj { @@ -26162,6 +26152,7 @@ package android.widget { method public boolean onTextContextMenuItem(int); method public void removeTextChangedListener(android.text.TextWatcher); method protected void resetLayoutDirectionResolution(); + method public void setAllCaps(boolean); method public final void setAutoLinkMask(int); method public void setCompoundDrawablePadding(int); method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable); diff --git a/core/java/android/content/XmlDocumentProvider.java b/core/java/android/content/XmlDocumentProvider.java deleted file mode 100644 index 76539c7..0000000 --- a/core/java/android/content/XmlDocumentProvider.java +++ /dev/null @@ -1,438 +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. - */ - -package android.content; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.client.methods.HttpGet; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import android.content.ContentResolver.OpenResourceIdResult; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.net.http.AndroidHttpClient; -import android.util.Log; -import android.widget.CursorAdapter; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.BitSet; -import java.util.Stack; -import java.util.regex.Pattern; - -/** - * @hide -- not yet ready to support, should be provided just as a static lib. - * - * A read-only content provider which extracts data out of an XML document. - * - * <p>A XPath-like selection pattern is used to select some nodes in the XML document. Each such - * node will create a row in the {@link Cursor} result.</p> - * - * Each row is then populated with columns that are also defined as XPath-like projections. These - * projections fetch attributes values or text in the matching row node or its children. - * - * <p>To add this provider in your application, you should add its declaration to your application - * manifest: - * <pre class="prettyprint"> - * <provider android:name="android.content.XmlDocumentProvider" android:authorities="xmldocument" /> - * </pre> - * </p> - * - * <h2>Node selection syntax</h2> - * The node selection syntax is made of the concatenation of an arbitrary number (at least one) of - * <code>/node_name</code> node selection patterns. - * - * <p>The <code>/root/child1/child2</code> pattern will for instance match all nodes named - * <code>child2</code> which are children of a node named <code>child1</code> which are themselves - * children of a root node named <code>root</code>.</p> - * - * Any <code>/</code> separator in the previous expression can be replaced by a <code>//</code> - * separator instead, which indicated a <i>descendant</i> instead of a child. - * - * <p>The <code>//node1//node2</code> pattern will for instance match all nodes named - * <code>node2</code> which are descendant of a node named <code>node1</code> located anywhere in - * the document hierarchy.</p> - * - * Node names can contain namespaces in the form <code>namespace:node</code>. - * - * <h2>Projection syntax</h2> - * For every selected node, the projection will then extract actual data from this node and its - * descendant. - * - * <p>Use a syntax similar to the selection syntax described above to select the text associated - * with a child of the selected node. The implicit root of this projection pattern is the selected - * node. <code>/</code> will hence refer to the text of the selected node, while - * <code>/child1</code> will fetch the text of its child named <code>child1</code> and - * <code>//child1</code> will match any <i>descendant</i> named <code>child1</code>. If several - * nodes match the projection pattern, their texts are appended as a result.</p> - * - * A projection can also fetch any node attribute by appending a <code>@attribute_name</code> - * pattern to the previously described syntax. <code>//child1@price</code> will for instance match - * the attribute <code>price</code> of any <code>child1</code> descendant. - * - * <p>If a projection does not match any node/attribute, its associated value will be an empty - * string.</p> - * - * <h2>Example</h2> - * Using the following XML document: - * <pre class="prettyprint"> - * <library> - * <book id="EH94"> - * <title>The Old Man and the Sea</title> - * <author>Ernest Hemingway</author> - * </book> - * <book id="XX10"> - * <title>The Arabian Nights: Tales of 1,001 Nights</title> - * </book> - * <no-id> - * <book> - * <title>Animal Farm</title> - * <author>George Orwell</author> - * </book> - * </no-id> - * </library> - * </pre> - * A selection pattern of <code>/library//book</code> will match the three book entries (while - * <code>/library/book</code> will only match the first two ones). - * - * <p>Defining the projections as <code>/title</code>, <code>/author</code> and <code>@id</code> - * will retrieve the associated data. Note that the author of the second book as well as the id of - * the third are empty strings. - */ -public class XmlDocumentProvider extends ContentProvider { - /* - * Ideas for improvement: - * - Expand XPath-like syntax to allow for [nb] child number selector - * - Address the starting . bug in AbstractCursor which prevents a true XPath syntax. - * - Provide an alternative to concatenation when several node match (list-like). - * - Support namespaces in attribute names. - * - Incremental Cursor creation, pagination - */ - private static final String LOG_TAG = "XmlDocumentProvider"; - private AndroidHttpClient mHttpClient; - - @Override - public boolean onCreate() { - return true; - } - - /** - * Query data from the XML document referenced in the URI. - * - * <p>The XML document can be a local resource or a file that will be downloaded from the - * Internet. In the latter case, your application needs to request the INTERNET permission in - * its manifest.</p> - * - * The URI will be of the form <code>content://xmldocument/?resource=R.xml.myFile</code> for a - * local resource. <code>xmldocument</code> should match the authority declared for this - * provider in your manifest. Internet documents are referenced using - * <code>content://xmldocument/?url=</code> followed by an encoded version of the URL of your - * document (see {@link Uri#encode(String)}). - * - * <p>The number of columns of the resulting Cursor is equal to the size of the projection - * array plus one, named <code>_id</code> which will contain a unique row id (allowing the - * Cursor to be used with a {@link CursorAdapter}). The other columns' names are the projection - * patterns.</p> - * - * @param uri The URI of your local resource or Internet document. - * @param projection A set of patterns that will be used to extract data from each selected - * node. See class documentation for pattern syntax. - * @param selection A selection pattern which will select the nodes that will create the - * Cursor's rows. See class documentation for pattern syntax. - * @param selectionArgs This parameter is ignored. - * @param sortOrder The row order in the resulting cursor is determined from the node order in - * the XML document. This parameter is ignored. - * @return A Cursor or null in case of error. - */ - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - - XmlPullParser parser = null; - mHttpClient = null; - - final String url = uri.getQueryParameter("url"); - if (url != null) { - parser = getUriXmlPullParser(url); - } else { - final String resource = uri.getQueryParameter("resource"); - if (resource != null) { - Uri resourceUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + - getContext().getPackageName() + "/" + resource); - parser = getResourceXmlPullParser(resourceUri); - } - } - - if (parser != null) { - XMLCursor xmlCursor = new XMLCursor(selection, projection); - try { - xmlCursor.parseWith(parser); - return xmlCursor; - } catch (IOException e) { - Log.w(LOG_TAG, "I/O error while parsing XML " + uri, e); - } catch (XmlPullParserException e) { - Log.w(LOG_TAG, "Error while parsing XML " + uri, e); - } finally { - if (mHttpClient != null) { - mHttpClient.close(); - } - } - } - - return null; - } - - /** - * Creates an XmlPullParser for the provided URL. Can be overloaded to provide your own parser. - * @param url The URL of the XML document that is to be parsed. - * @return An XmlPullParser on this document. - */ - protected XmlPullParser getUriXmlPullParser(String url) { - XmlPullParser parser = null; - try { - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - factory.setNamespaceAware(true); - parser = factory.newPullParser(); - } catch (XmlPullParserException e) { - Log.e(LOG_TAG, "Unable to create XmlPullParser", e); - return null; - } - - InputStream inputStream = null; - try { - final HttpGet get = new HttpGet(url); - mHttpClient = AndroidHttpClient.newInstance("Android"); - HttpResponse response = mHttpClient.execute(get); - if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { - final HttpEntity entity = response.getEntity(); - if (entity != null) { - inputStream = entity.getContent(); - } - } - } catch (IOException e) { - Log.w(LOG_TAG, "Error while retrieving XML file " + url, e); - return null; - } - - try { - parser.setInput(inputStream, null); - } catch (XmlPullParserException e) { - Log.w(LOG_TAG, "Error while reading XML file from " + url, e); - return null; - } - - return parser; - } - - /** - * Creates an XmlPullParser for the provided local resource. Can be overloaded to provide your - * own parser. - * @param resourceUri A fully qualified resource name referencing a local XML resource. - * @return An XmlPullParser on this resource. - */ - protected XmlPullParser getResourceXmlPullParser(Uri resourceUri) { - OpenResourceIdResult resourceId; - try { - resourceId = getContext().getContentResolver().getResourceId(resourceUri); - return resourceId.r.getXml(resourceId.id); - } catch (FileNotFoundException e) { - Log.w(LOG_TAG, "XML resource not found: " + resourceUri.toString(), e); - return null; - } - } - - /** - * Returns "vnd.android.cursor.dir/xmldoc". - */ - @Override - public String getType(Uri uri) { - return "vnd.android.cursor.dir/xmldoc"; - } - - /** - * This ContentProvider is read-only. This method throws an UnsupportedOperationException. - **/ - @Override - public Uri insert(Uri uri, ContentValues values) { - throw new UnsupportedOperationException(); - } - - /** - * This ContentProvider is read-only. This method throws an UnsupportedOperationException. - **/ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); - } - - /** - * This ContentProvider is read-only. This method throws an UnsupportedOperationException. - **/ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); - } - - private static class XMLCursor extends MatrixCursor { - private final Pattern mSelectionPattern; - private Pattern[] mProjectionPatterns; - private String[] mAttributeNames; - private String[] mCurrentValues; - private BitSet[] mActiveTextDepthMask; - private final int mNumberOfProjections; - - public XMLCursor(String selection, String[] projections) { - super(projections); - // The first column in projections is used for the _ID - mNumberOfProjections = projections.length - 1; - mSelectionPattern = createPattern(selection); - createProjectionPattern(projections); - } - - private Pattern createPattern(String input) { - String pattern = input.replaceAll("//", "/(.*/|)").replaceAll("^/", "^/") + "$"; - return Pattern.compile(pattern); - } - - private void createProjectionPattern(String[] projections) { - mProjectionPatterns = new Pattern[mNumberOfProjections]; - mAttributeNames = new String[mNumberOfProjections]; - mActiveTextDepthMask = new BitSet[mNumberOfProjections]; - // Add a column to store _ID - mCurrentValues = new String[mNumberOfProjections + 1]; - - for (int i=0; i<mNumberOfProjections; i++) { - mActiveTextDepthMask[i] = new BitSet(); - String projection = projections[i + 1]; // +1 to skip the _ID column - int atIndex = projection.lastIndexOf('@', projection.length()); - if (atIndex >= 0) { - mAttributeNames[i] = projection.substring(atIndex+1); - projection = projection.substring(0, atIndex); - } else { - mAttributeNames[i] = null; - } - - // Conforms to XPath standard: reference to local context starts with a . - if (projection.charAt(0) == '.') { - projection = projection.substring(1); - } - mProjectionPatterns[i] = createPattern(projection); - } - } - - public void parseWith(XmlPullParser parser) throws IOException, XmlPullParserException { - StringBuilder path = new StringBuilder(); - Stack<Integer> pathLengthStack = new Stack<Integer>(); - - // There are two parsing mode: in root mode, rootPath is updated and nodes matching - // selectionPattern are searched for and currentNodeDepth is negative. - // When a node matching selectionPattern is found, currentNodeDepth is set to 0 and - // updated as children are parsed and projectionPatterns are searched in nodePath. - int currentNodeDepth = -1; - - // Index where local selected node path starts from in path - int currentNodePathStartIndex = 0; - - int eventType = parser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - - if (eventType == XmlPullParser.START_TAG) { - // Update path - pathLengthStack.push(path.length()); - path.append('/'); - String prefix = null; - try { - // getPrefix is not supported by local Xml resource parser - prefix = parser.getPrefix(); - } catch (RuntimeException e) { - prefix = null; - } - if (prefix != null) { - path.append(prefix); - path.append(':'); - } - path.append(parser.getName()); - - if (currentNodeDepth >= 0) { - currentNodeDepth++; - } else { - // A node matching selection is found: initialize child parsing mode - if (mSelectionPattern.matcher(path.toString()).matches()) { - currentNodeDepth = 0; - currentNodePathStartIndex = path.length(); - mCurrentValues[0] = Integer.toString(getCount()); // _ID - for (int i = 0; i < mNumberOfProjections; i++) { - // Reset values to default (empty string) - mCurrentValues[i + 1] = ""; - mActiveTextDepthMask[i].clear(); - } - } - } - - // This test has to be separated from the previous one as currentNodeDepth can - // be modified above (when a node matching selection is found). - if (currentNodeDepth >= 0) { - final String localNodePath = path.substring(currentNodePathStartIndex); - for (int i = 0; i < mNumberOfProjections; i++) { - if (mProjectionPatterns[i].matcher(localNodePath).matches()) { - String attribute = mAttributeNames[i]; - if (attribute != null) { - mCurrentValues[i + 1] = - parser.getAttributeValue(null, attribute); - } else { - mActiveTextDepthMask[i].set(currentNodeDepth, true); - } - } - } - } - - } else if (eventType == XmlPullParser.END_TAG) { - // Pop last node from path - final int length = pathLengthStack.pop(); - path.setLength(length); - - if (currentNodeDepth >= 0) { - if (currentNodeDepth == 0) { - // Leaving a selection matching node: add a new row with results - addRow(mCurrentValues); - } else { - for (int i = 0; i < mNumberOfProjections; i++) { - mActiveTextDepthMask[i].set(currentNodeDepth, false); - } - } - currentNodeDepth--; - } - - } else if ((eventType == XmlPullParser.TEXT) && (!parser.isWhitespace())) { - for (int i = 0; i < mNumberOfProjections; i++) { - if ((currentNodeDepth >= 0) && - (mActiveTextDepthMask[i].get(currentNodeDepth))) { - mCurrentValues[i + 1] += parser.getText(); - } - } - } - - eventType = parser.next(); - } - } - } -} diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index c7603ee..8ef4295 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -384,11 +384,16 @@ class AudioPlaybackHandler { } count += written; } + + param.mLogger.onPlaybackStart(); } private void handleSynthesisDone(MessageParams msg) { final SynthesisMessageParams params = (SynthesisMessageParams) msg; handleSynthesisDone(params); + // This call is delayed more than it should be, but we are + // certain at this point that we have all the data we want. + params.mLogger.onWriteData(); } // Flush all remaining data to the audio track, stop it and release @@ -416,6 +421,8 @@ class AudioPlaybackHandler { final SynthesisMessageParams params = (SynthesisMessageParams) msg; if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")"); + params.mLogger.onPlaybackStart(); + // Channel config and bytes per frame are checked before // this message is sent. int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount); diff --git a/core/java/android/speech/tts/EventLogTags.logtags b/core/java/android/speech/tts/EventLogTags.logtags new file mode 100644 index 0000000..1a9f5fe --- /dev/null +++ b/core/java/android/speech/tts/EventLogTags.logtags @@ -0,0 +1,6 @@ +# See system/core/logcat/event.logtags for a description of the format of this file. + +option java_package android.speech.tts; + +76001 tts_speak_success (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3) +76002 tts_speak_failure (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1) diff --git a/core/java/android/speech/tts/EventLogger.java b/core/java/android/speech/tts/EventLogger.java new file mode 100644 index 0000000..63b954b --- /dev/null +++ b/core/java/android/speech/tts/EventLogger.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2011 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 android.speech.tts; + +import android.os.SystemClock; +import android.text.TextUtils; + +/** + * Writes data about a given speech synthesis request to the event logs. + * The data that is logged includes the calling app, length of the utterance, + * speech rate / pitch and the latency and overall time taken. + * + * Note that {@link EventLogger#onStopped()} and {@link EventLogger#onError()} + * might be called from any thread, but on {@link EventLogger#onPlaybackStart()} and + * {@link EventLogger#onComplete()} must be called from a single thread + * (usually the audio playback thread} + */ +class EventLogger { + private final SynthesisRequest mRequest; + private final String mCallingApp; + private final String mServiceApp; + private final long mReceivedTime; + private long mPlaybackStartTime = -1; + private volatile long mRequestProcessingStartTime = -1; + private volatile long mEngineStartTime = -1; + private volatile long mEngineCompleteTime = -1; + + private volatile boolean mError = false; + private volatile boolean mStopped = false; + private boolean mLogWritten = false; + + EventLogger(SynthesisRequest request, String callingApp, + String serviceApp) { + mRequest = request; + mCallingApp = callingApp; + mServiceApp = serviceApp; + mReceivedTime = SystemClock.elapsedRealtime(); + } + + /** + * Notifies the logger that this request has been selected from + * the processing queue for processing. Engine latency / total time + * is measured from this baseline. + */ + public void onRequestProcessingStart() { + mRequestProcessingStartTime = SystemClock.elapsedRealtime(); + } + + /** + * Notifies the logger that a chunk of data has been received from + * the engine. Might be called multiple times. + */ + public void onEngineDataReceived() { + if (mEngineStartTime == -1) { + mEngineStartTime = SystemClock.elapsedRealtime(); + } + } + + /** + * Notifies the logger that the engine has finished processing data. + * Will be called exactly once. + */ + public void onEngineComplete() { + mEngineCompleteTime = SystemClock.elapsedRealtime(); + } + + /** + * Notifies the logger that audio playback has started for some section + * of the synthesis. This is normally some amount of time after the engine + * has synthesized data and varides depending on utterances and + * other audio currently in the queue. + */ + public void onPlaybackStart() { + // For now, keep track of only the first chunk of audio + // that was played. + if (mPlaybackStartTime == -1) { + mPlaybackStartTime = SystemClock.elapsedRealtime(); + } + } + + /** + * Notifies the logger that the current synthesis was stopped. + * Latency numbers are not reported for stopped syntheses. + */ + public void onStopped() { + mStopped = false; + } + + /** + * Notifies the logger that the current synthesis resulted in + * an error. This is logged using {@link EventLogTags#writeTtsSpeakFailure}. + */ + public void onError() { + mError = true; + } + + /** + * Notifies the logger that the current synthesis has completed. + * All available data is not logged. + */ + public void onWriteData() { + if (mLogWritten) { + return; + } else { + mLogWritten = true; + } + + long completionTime = SystemClock.elapsedRealtime(); + // onPlaybackStart() should normally always be called if an + // error does not occur. + if (mError || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) { + EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallingApp, + getUtteranceLength(), getLocaleString(), + mRequest.getSpeechRate(), mRequest.getPitch()); + return; + } + + // We don't report stopped syntheses because their overall + // total time spent will be innacurate (will not correlate with + // the length of the utterance). + if (mStopped) { + return; + } + + final long audioLatency = mPlaybackStartTime - mReceivedTime; + final long engineLatency = mEngineStartTime - mRequestProcessingStartTime; + final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime; + EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallingApp, + getUtteranceLength(), getLocaleString(), + mRequest.getSpeechRate(), mRequest.getPitch(), + engineLatency, engineTotal, audioLatency); + } + + /** + * @return the length of the utterance for the given synthesis, 0 + * if the utterance was {@code null}. + */ + private int getUtteranceLength() { + final String utterance = mRequest.getText(); + return utterance == null ? 0 : utterance.length(); + } + + /** + * Returns a formatted locale string from the synthesis params of the + * form lang-country-variant. + */ + private String getLocaleString() { + StringBuilder sb = new StringBuilder(mRequest.getLanguage()); + if (!TextUtils.isEmpty(mRequest.getCountry())) { + sb.append('-'); + sb.append(mRequest.getCountry()); + + if (!TextUtils.isEmpty(mRequest.getVariant())) { + sb.append('-'); + sb.append(mRequest.getVariant()); + } + } + + return sb.toString(); + } + +} diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java index bdaa1b8..38030a6 100644 --- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java +++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java @@ -65,29 +65,42 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { private final UtteranceCompletedDispatcher mDispatcher; private final String mCallingApp; + private final EventLogger mLogger; PlaybackSynthesisCallback(int streamType, float volume, float pan, AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher, - String callingApp) { + String callingApp, EventLogger logger) { mStreamType = streamType; mVolume = volume; mPan = pan; mAudioTrackHandler = audioTrackHandler; mDispatcher = dispatcher; mCallingApp = callingApp; + mLogger = logger; } @Override void stop() { if (DBG) Log.d(TAG, "stop()"); + // Note that mLogger.mError might be true too at this point. + mLogger.onStopped(); + synchronized (mStateLock) { - if (mToken == null || mStopped) { - Log.w(TAG, "stop() called twice, before start(), or after done()"); + if (mStopped) { + Log.w(TAG, "stop() called twice"); return; } - mAudioTrackHandler.stop(mToken); - mToken = null; + // mToken will be null if the engine encounters + // an error before it called start(). + if (mToken != null) { + mAudioTrackHandler.stop(mToken); + mToken = null; + } else { + // In all other cases, mAudioTrackHandler.stop() will + // result in onComplete being called. + mLogger.onWriteData(); + } mStopped = true; } } @@ -124,7 +137,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { } SynthesisMessageParams params = new SynthesisMessageParams( mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan, - mDispatcher, mCallingApp); + mDispatcher, mCallingApp, mLogger); mAudioTrackHandler.enqueueSynthesisStart(params); mToken = params; @@ -157,6 +170,8 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken); } + mLogger.onEngineDataReceived(); + return TextToSpeech.SUCCESS; } @@ -177,6 +192,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { } mAudioTrackHandler.enqueueSynthesisDone(mToken); + mLogger.onEngineComplete(); } return TextToSpeech.SUCCESS; } @@ -184,6 +200,9 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { @Override public void error() { if (DBG) Log.d(TAG, "error() [will call stop]"); + // Currently, this call will not be logged if error( ) is called + // before start. + mLogger.onError(); stop(); } @@ -208,7 +227,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback { } SynthesisMessageParams params = new SynthesisMessageParams( mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan, - mDispatcher, mCallingApp); + mDispatcher, mCallingApp, mLogger); params.addBuffer(buffer, offset, length); mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params); diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java index 51f3d2e..caf02ef 100644 --- a/core/java/android/speech/tts/SynthesisMessageParams.java +++ b/core/java/android/speech/tts/SynthesisMessageParams.java @@ -30,6 +30,7 @@ final class SynthesisMessageParams extends MessageParams { final int mChannelCount; final float mVolume; final float mPan; + final EventLogger mLogger; public volatile AudioTrack mAudioTrack; @@ -38,7 +39,7 @@ final class SynthesisMessageParams extends MessageParams { SynthesisMessageParams(int streamType, int sampleRate, int audioFormat, int channelCount, float volume, float pan, UtteranceCompletedDispatcher dispatcher, - String callingApp) { + String callingApp, EventLogger logger) { super(dispatcher, callingApp); mStreamType = streamType; @@ -47,6 +48,7 @@ final class SynthesisMessageParams extends MessageParams { mChannelCount = channelCount; mVolume = volume; mPan = pan; + mLogger = logger; // initially null. mAudioTrack = null; diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 7ea9373..010c155 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -82,8 +82,7 @@ public abstract class TextToSpeechService extends Service { private AudioPlaybackHandler mAudioPlaybackHandler; private CallbackMap mCallbacks; - - private int mDefaultAvailability = TextToSpeech.LANG_NOT_SUPPORTED; + private String mPackageName; @Override public void onCreate() { @@ -99,9 +98,10 @@ public abstract class TextToSpeechService extends Service { mCallbacks = new CallbackMap(); + mPackageName = getApplicationInfo().packageName; + // Load default language - mDefaultAvailability = onLoadLanguage(getDefaultLanguage(), - getDefaultCountry(), getDefaultVariant()); + onLoadLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant()); } @Override @@ -457,12 +457,14 @@ public abstract class TextToSpeechService extends Service { // Non null after synthesis has started, and all accesses // guarded by 'this'. private AbstractSynthesisCallback mSynthesisCallback; + private final EventLogger mEventLogger; public SynthesisSpeechItem(String callingApp, Bundle params, String text) { super(callingApp, params); mText = text; mSynthesisRequest = new SynthesisRequest(mText, mParams); setRequestParams(mSynthesisRequest); + mEventLogger = new EventLogger(mSynthesisRequest, getCallingApp(), mPackageName); } public String getText() { @@ -485,6 +487,7 @@ public abstract class TextToSpeechService extends Service { @Override protected int playImpl() { AbstractSynthesisCallback synthesisCallback; + mEventLogger.onRequestProcessingStart(); synchronized (this) { mSynthesisCallback = createSynthesisCallback(); synthesisCallback = mSynthesisCallback; @@ -495,7 +498,7 @@ public abstract class TextToSpeechService extends Service { protected AbstractSynthesisCallback createSynthesisCallback() { return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(), - mAudioPlaybackHandler, this, getCallingApp()); + mAudioPlaybackHandler, this, getCallingApp(), mEventLogger); } private void setRequestParams(SynthesisRequest request) { diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java new file mode 100644 index 0000000..f9920dd --- /dev/null +++ b/core/java/android/text/method/AllCapsTransformationMethod.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 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 android.text.method; + +import android.content.Context; +import android.graphics.Rect; +import android.util.Log; +import android.view.View; + +import java.util.Locale; + +/** + * Transforms source text into an ALL CAPS string, locale-aware. + * + * @hide + */ +public class AllCapsTransformationMethod implements TransformationMethod2 { + private static final String TAG = "AllCapsTransformationMethod"; + + private boolean mEnabled; + private Locale mLocale; + + public AllCapsTransformationMethod(Context context) { + mLocale = context.getResources().getConfiguration().locale; + } + + @Override + public CharSequence getTransformation(CharSequence source, View view) { + if (mEnabled) { + return source != null ? source.toString().toUpperCase(mLocale) : null; + } + Log.w(TAG, "Caller did not enable length changes; not transforming text"); + return source; + } + + @Override + public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, + Rect previouslyFocusedRect) { + } + + @Override + public void setLengthChangesAllowed(boolean allowLengthChanges) { + mEnabled = allowLengthChanges; + } + +} diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java new file mode 100644 index 0000000..ef00ecd --- /dev/null +++ b/core/java/android/text/method/TransformationMethod2.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 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 android.text.method; + +/** + * TransformationMethod2 extends the TransformationMethod interface + * and adds the ability to relax restrictions of TransformationMethod. + * + * @hide + */ +public interface TransformationMethod2 extends TransformationMethod { + /** + * Relax the contract of TransformationMethod to allow length changes, + * or revert to the length-restricted behavior. + * + * @param allowLengthChanges true to allow the transformation to change the length + * of the input string. + */ + public void setLengthChangesAllowed(boolean allowLengthChanges); +} diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b6c5522..4987e2f 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -246,8 +246,19 @@ class GLES20Canvas extends HardwareCanvas { return nIsBackBufferPreserved(); } - private static native boolean nIsBackBufferPreserved(); - + private static native boolean nIsBackBufferPreserved(); + + /** + * Disables v-sync. For performance testing only. + * + * @hide + */ + public static void disableVsync() { + nDisableVsync(); + } + + private static native void nDisableVsync(); + @Override void onPreDraw(Rect dirty) { if (dirty != null) { @@ -265,7 +276,7 @@ class GLES20Canvas extends HardwareCanvas { void onPostDraw() { nFinish(mRenderer); } - + private static native void nFinish(int renderer); @Override diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index bbfb4c1..188970c 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -57,6 +57,16 @@ public abstract class HardwareRenderer { * "false", to disable partial invalidates */ static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions"; + + /** + * System property used to enable or disable vsync. + * The default value of this property is assumed to be false. + * + * Possible values: + * "true", to disable vsync + * "false", to enable vsync + */ + static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync"; /** * Turn on to draw dirty regions every other frame. @@ -303,6 +313,7 @@ public abstract class HardwareRenderer { boolean mDirtyRegions; final boolean mDirtyRegionsRequested; + final boolean mVsyncDisabled; final int mGlVersion; final boolean mTranslucent; @@ -314,10 +325,17 @@ public abstract class HardwareRenderer { GlRenderer(int glVersion, boolean translucent) { mGlVersion = glVersion; mTranslucent = translucent; + final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true"); //noinspection PointlessBooleanExpression,ConstantConditions mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty); mDirtyRegionsRequested = mDirtyRegions; + + final String vsyncProperty = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false"); + mVsyncDisabled = "true".equalsIgnoreCase(vsyncProperty); + if (mVsyncDisabled) { + Log.d(LOG_TAG, "Disabling v-sync"); + } } /** @@ -765,6 +783,14 @@ public abstract class HardwareRenderer { } @Override + void setup(int width, int height) { + super.setup(width, height); + if (mVsyncDisabled) { + GLES20Canvas.disableVsync(); + } + } + + @Override DisplayList createDisplayList(View v) { return new GLES20DisplayList(v); } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 41412de..e6fdb17 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -46,7 +46,6 @@ import com.android.internal.util.Predicate; import java.util.ArrayList; import java.util.HashSet; -import java.util.Locale; /** * <p> @@ -5019,7 +5018,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ @Override protected void resolveTextDirection() { - int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED; + int resolvedTextDirection; switch(mTextDirection) { default: case TEXT_DIRECTION_INHERIT: diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java index 4c42cde..f9d0067d 100644 --- a/core/java/android/webkit/L10nUtils.java +++ b/core/java/android/webkit/L10nUtils.java @@ -74,7 +74,8 @@ public class L10nUtils { com.android.internal.R.string.autofill_country_code_re, // IDS_AUTOFILL_COUNTRY_CODE_RE com.android.internal.R.string.autofill_area_code_notext_re, // IDS_AUTOFILL_AREA_CODE_NOTEXT_RE com.android.internal.R.string.autofill_phone_prefix_separator_re, // IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE - com.android.internal.R.string.autofill_phone_suffix_separator_re // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE + com.android.internal.R.string.autofill_phone_suffix_separator_re, // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE + com.android.internal.R.string.credit_card_number_preview_format // IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT }; private static Context mApplicationContext; diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 4f97066..c652e55 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -2235,16 +2235,15 @@ public final class WebViewCore { // called by JNI private void updateViewport() { - // if updateViewport is called before first layout, wait until first - // layout to update the viewport. In the rare case, this is called after - // first layout, force an update as we have just parsed the viewport - // meta tag. - if (mBrowserFrame.firstLayoutDone()) { - setupViewport(true); - } + // Update viewport asap to make sure we get correct one. + setupViewport(true); } private void setupViewport(boolean updateViewState) { + if (mWebView == null || mSettings == null) { + // We've been destroyed or are being destroyed, return early + return; + } // set the viewport settings from WebKit setViewportSettingsFromNative(); @@ -2375,8 +2374,12 @@ public final class WebViewCore { (float) webViewWidth / mViewportWidth; } else { mInitialViewState.mTextWrapScale = adjust; - // 0 will trigger WebView to turn on zoom overview mode - mInitialViewState.mViewScale = 0; + if (mSettings.getUseWideViewPort()) { + // 0 will trigger WebView to turn on zoom overview mode + mInitialViewState.mViewScale = 0; + } else { + mInitialViewState.mViewScale = adjust; + } } } @@ -2407,7 +2410,7 @@ public final class WebViewCore { mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED); mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null, EventHub.VIEW_SIZE_CHANGED, data)); - } else if (mSettings.getUseWideViewPort()) { + } else { if (viewportWidth == 0) { // Trick to ensure VIEW_SIZE_CHANGED will be sent from WebView // to WebViewCore diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 772e8e9..1e63e26 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,6 +16,11 @@ package android.widget; +import com.android.internal.util.FastMath; +import com.android.internal.widget.EditableInputConnection; + +import org.xmlpull.v1.XmlPullParserException; + import android.R; import android.content.ClipData; import android.content.ClipData.Item; @@ -62,6 +67,7 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.method.AllCapsTransformationMethod; import android.text.method.ArrowKeyMovementMethod; import android.text.method.DateKeyListener; import android.text.method.DateTimeKeyListener; @@ -76,6 +82,7 @@ import android.text.method.SingleLineTransformationMethod; import android.text.method.TextKeyListener; import android.text.method.TimeKeyListener; import android.text.method.TransformationMethod; +import android.text.method.TransformationMethod2; import android.text.method.WordIterator; import android.text.style.ClickableSpan; import android.text.style.ParagraphStyle; @@ -125,11 +132,6 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.RemoteViews.RemoteView; -import com.android.internal.util.FastMath; -import com.android.internal.widget.EditableInputConnection; - -import org.xmlpull.v1.XmlPullParserException; - import java.io.IOException; import java.lang.ref.WeakReference; import java.text.BreakIterator; @@ -424,6 +426,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int textSize = 15; int typefaceIndex = -1; int styleIndex = -1; + boolean allCaps = false; /* * Look the appearance up without checking first if it exists because @@ -471,6 +474,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case com.android.internal.R.styleable.TextAppearance_textStyle: styleIndex = appearance.getInt(attr, -1); break; + + case com.android.internal.R.styleable.TextAppearance_textAllCaps: + allCaps = appearance.getBoolean(attr, false); + break; } } @@ -822,6 +829,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case com.android.internal.R.styleable.TextView_suggestionsEnabled: mSuggestionsEnabled = a.getBoolean(attr, true); break; + + case com.android.internal.R.styleable.TextView_textAllCaps: + allCaps = a.getBoolean(attr, false); + break; } } a.recycle(); @@ -1004,6 +1015,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } setRawTextSize(textSize); + if (allCaps) { + setTransformationMethod(new AllCapsTransformationMethod(getContext())); + } + if (password || passwordInputType || webPasswordInputType || numberPasswordInputType) { setTransformationMethod(PasswordTransformationMethod.getInstance()); typefaceIndex = MONOSPACE; @@ -1331,6 +1346,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mTransformation = method; + if (method instanceof TransformationMethod2) { + TransformationMethod2 method2 = (TransformationMethod2) method; + mAllowTransformationLengthChange = !mTextIsSelectable && !(mText instanceof Editable); + method2.setLengthChangesAllowed(mAllowTransformationLengthChange); + } else { + mAllowTransformationLengthChange = false; + } + setText(mText); } @@ -1775,6 +1798,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setTypefaceByIndex(typefaceIndex, styleIndex); + if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps, + false)) { + setTransformationMethod(new AllCapsTransformationMethod(getContext())); + } + appearance.recycle(); } @@ -2823,14 +2851,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mBufferType = type; mText = text; - if (mTransformation == null) + if (mTransformation == null) { mTransformed = text; - else + } else { mTransformed = mTransformation.getTransformation(text, this); + } final int textLength = text.length(); - if (text instanceof Spannable) { + if (text instanceof Spannable && !mAllowTransformationLengthChange) { Spannable sp = (Spannable) text; // Remove any ChangeWatchers that might have come @@ -2852,7 +2881,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mTransformation != null) { sp.setSpan(mTransformation, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } if (mMovement != null) { @@ -6570,6 +6598,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Sets the properties of this field to transform input to ALL CAPS + * display. This may use a "small caps" formatting if available. + * This setting will be ignored if this field is editable or selectable. + * + * This call replaces the current transformation method. Disabling this + * will not necessarily restore the previous behavior from before this + * was enabled. + * + * @see #setTransformationMethod(TransformationMethod) + * @attr ref android.R.styleable#TextView_textAllCaps + */ + public void setAllCaps(boolean allCaps) { + if (allCaps) { + setTransformationMethod(new AllCapsTransformationMethod(getContext())); + } else { + setTransformationMethod(null); + } + } + + /** * If true, sets the properties of this field (number of lines, horizontally scrolling, * transformation method) to be for a single-line input; if false, restores these to the default * conditions. @@ -10254,6 +10302,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private MovementMethod mMovement; private TransformationMethod mTransformation; + private boolean mAllowTransformationLengthChange; private ChangeWatcher mChangeWatcher; private ArrayList<TextWatcher> mListeners = null; diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 2e7ec58..b754d94 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -26,6 +26,9 @@ package com.android.internal.util; * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI + * Protocol.MAX_MESSAGE * + * NOTE: After a value is created and source released a value shouldn't be changed to + * maintain backwards compatibility. + * * {@hide} */ public class Protocol { @@ -40,7 +43,7 @@ public class Protocol { public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; - public static final int BASE_DATA_CONNECTION_TRACKER = 0x00050000; + public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000; //TODO: define all used protocols } diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index 3b497e4..09bebae 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -154,12 +154,7 @@ public class ActionMenuItemView extends LinearLayout // populate accessibility description with title setContentDescription(title); - if (mShowTextAllCaps && title != null) { - mTextButton.setText(title.toString().toUpperCase( - getContext().getResources().getConfiguration().locale)); - } else { - mTextButton.setText(mTitle); - } + mTextButton.setText(mTitle); updateTextButtonVisibility(); } diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java index 2f7adf0..40e5e8a 100644 --- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java +++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java @@ -260,7 +260,6 @@ public class ScrollingTabContainerView extends HorizontalScrollView { if (mTextView == null) { TextView textView = new TextView(getContext(), null, com.android.internal.R.attr.actionBarTabTextStyle); - textView.setSingleLine(); textView.setEllipsize(TruncateAt.END); LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 2106eb4..681f43f 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -115,6 +115,18 @@ static jboolean android_view_GLES20Canvas_isBackBufferPreserved(JNIEnv* env, job return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED; } +static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) { + EGLDisplay display = eglGetCurrentDisplay(); + + eglGetError(); + eglSwapInterval(display, 0); + + EGLint error = eglGetError(); + if (error != EGL_SUCCESS) { + RENDERER_LOGD("Could not disable v-sync (%x)", error); + } +} + // ---------------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------------- @@ -621,7 +633,7 @@ static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject if (layer) { jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->texture; + storage[0] = layer->getTexture(); env->ReleaseIntArrayElements(layerInfo, storage, 0); } @@ -634,8 +646,8 @@ static Layer* android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz, if (layer) { jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->width; - storage[1] = layer->height; + storage[0] = layer->getWidth(); + storage[1] = layer->getHeight(); env->ReleaseIntArrayElements(layerInfo, storage, 0); } @@ -647,8 +659,8 @@ static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz, LayerRenderer::resizeLayer(layer, width, height); jint* storage = env->GetIntArrayElements(layerInfo, NULL); - storage[0] = layer->width; - storage[1] = layer->height; + storage[0] = layer->getWidth(); + storage[1] = layer->getHeight(); env->ReleaseIntArrayElements(layerInfo, storage, 0); } @@ -722,6 +734,7 @@ static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER { "nIsBackBufferPreserved", "()Z", (void*) android_view_GLES20Canvas_isBackBufferPreserved }, { "nPreserveBackBuffer", "()Z", (void*) android_view_GLES20Canvas_preserveBackBuffer }, + { "nDisableVsync", "()V", (void*) android_view_GLES20Canvas_disableVsync }, { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer }, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2cc8171..39de054 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2810,6 +2810,8 @@ <attr name="textColorHint" /> <!-- Color of the links. --> <attr name="textColorLink" /> + <!-- Present the text in ALL CAPS. This may use a small-caps form when available. --> + <attr name="textAllCaps" format="boolean" /> </declare-styleable> <declare-styleable name="TextSwitcher"> </declare-styleable> @@ -3074,6 +3076,8 @@ <attr name="textIsSelectable" /> <!-- Suggestions will be displayed when the user double taps on editable text. --> <attr name="suggestionsEnabled" /> + <!-- Present the text in ALL CAPS. This may use a small-caps form when available. --> + <attr name="textAllCaps" /> </declare-styleable> <!-- An <code>input-extras</code> is a container for extra data to supply to an input method. Contains diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2de9cd3..3c23add 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1779,6 +1779,8 @@ <public type="attr" name="backgroundStacked" /> <public type="attr" name="backgroundSplit" /> + <public type="attr" name="textAllCaps" /> + <public type="style" name="TextAppearance.SuggestionHighlight" /> <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" /> <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 50f8df7..97a8c0b 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2085,6 +2085,10 @@ <!-- Do not translate. Regex used by AutoFill. --> <string name="autofill_phone_suffix_separator_re">^-$</string> + <!-- Do not translate. Regex used by AutoFill. --> + <!-- Ex: ************1234 --> + <string name="credit_card_number_preview_format">$1</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 11016f4..8a8f81a 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1319,6 +1319,7 @@ <item name="android:textSize">12sp</item> <item name="android:textStyle">bold</item> <item name="android:textColor">?android:attr/actionMenuTextColor</item> + <item name="android:textAllCaps">true</item> </style> <style name="TextAppearance.Holo.Widget.ActionMode"> @@ -1857,6 +1858,7 @@ <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">12sp</item> <item name="android:textStyle">bold</item> + <item name="android:textAllCaps">true</item> </style> <style name="Widget.Holo.ActionMode" parent="Widget.ActionMode"> diff --git a/docs/html/images/opengl/coordinates.png b/docs/html/images/opengl/coordinates.png Binary files differdeleted file mode 100644 index 7180cd5..0000000 --- a/docs/html/images/opengl/coordinates.png +++ /dev/null diff --git a/docs/html/images/opengl/helloopengl-es10-1.png b/docs/html/images/opengl/helloopengl-es10-1.png Binary files differdeleted file mode 100644 index bdfbcdb..0000000 --- a/docs/html/images/opengl/helloopengl-es10-1.png +++ /dev/null diff --git a/docs/html/images/opengl/helloopengl-es10-2.png b/docs/html/images/opengl/helloopengl-es10-2.png Binary files differdeleted file mode 100644 index c07dabb..0000000 --- a/docs/html/images/opengl/helloopengl-es10-2.png +++ /dev/null diff --git a/docs/html/images/opengl/helloopengl-es20-1.png b/docs/html/images/opengl/helloopengl-es20-1.png Binary files differdeleted file mode 100644 index 44abe77..0000000 --- a/docs/html/images/opengl/helloopengl-es20-1.png +++ /dev/null diff --git a/docs/html/images/opengl/helloopengl-es20-2.png b/docs/html/images/opengl/helloopengl-es20-2.png Binary files differdeleted file mode 100644 index 22fa52c..0000000 --- a/docs/html/images/opengl/helloopengl-es20-2.png +++ /dev/null diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index 06a046d..0fc10bf 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -782,26 +782,6 @@ var ANDROID_RESOURCES = [ } }, { - tags: ['tutorial', 'gl', 'new'], - path: 'tutorials/opengl/opengl-es10.html', - title: { - en: 'Hello OpenGL ES 1.0' - }, - description: { - en: 'The basics of implementing an application using the OpenGL ES 1.0 APIs.' - } - }, - { - tags: ['tutorial', 'gl', 'new'], - path: 'tutorials/opengl/opengl-es20.html', - title: { - en: 'Hello OpenGL ES 2.0' - }, - description: { - en: 'The basics of implementing an application using the OpenGL ES 2.0 APIs.' - } - }, - { tags: ['tutorial', 'testing'], path: 'tutorials/testing/helloandroid_test.html', title: { diff --git a/docs/html/resources/tutorials/opengl/opengl-es10.jd b/docs/html/resources/tutorials/opengl/opengl-es10.jd deleted file mode 100644 index d18a547..0000000 --- a/docs/html/resources/tutorials/opengl/opengl-es10.jd +++ /dev/null @@ -1,409 +0,0 @@ -page.title=Hello OpenGL ES 1.0 -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - - -<div id="qv-wrapper"> - <div id="qv"> - <h2>In this document</h2> - - <ol> - <li><a href="#creating">Creating an OpenGL ES 1.0 Application</a></li> - <li> - <a href="#drawing">Drawing Graphic Elements</a> - <ol> - <li><a href="#define-triangle">Defining a Triangle</a></li> - <li><a href="#draw-triangle">Draw the Triangle</a></li> - </ol> - </li> - <li><a href="#projection-and-views">Using Projection and Views</a></li> - <li><a href="#motion">Adding Motion</a></li> - <li><a href="#resources">Additional Resources</a></li> - - </ol> - <h2 id="code-samples-list">Related Samples</h2> - <ol> - <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ -index.html">API Demos - graphics</a></li> - <li><a - href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ -GLSurfaceViewActivity.html">GLSurfaceViewActivity</a></li> - </ol> - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li> - <li><a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html">Hello OpenGL -ES 2.0</a></li> - </ol> - </div> - </div> - -<p>This tutorial shows you how to create a simple Android application that uses OpenGL ES 1.0 and -perform some basic operations using the OpenGL ES 1.0 API, including:</p> - -<ul> - <li>Creating an application using {@link android.opengl.GLSurfaceView} and {@link -android.opengl.GLSurfaceView.Renderer}</li> - <li>Defining a graphic object and drawing it</li> - <li>Defining and applying an projection and view</li> - <li>Applying rotation to the drawn object</li> -</ul> - -<p>This tutorial demonstrates use of the OpenGL ES 1.0 API. Both the OpenGL ES 1.0 and the ES 1.1 -API are supported by the Android framework since release 1.0 (API Level 1). The OpenGL ES 1.1 API -is an extention of the 1.0 API, and it's capabilities are beyond the scope of this tutorial.</p> - -<p>Beginning with Android 2.2 (API Level 8), the framework supports OpenGL ES 2.0. For more -information about compatibility for OpenGL versions and Android devices, see the <a -href="{@docRoot}guide/topics/graphics/opengl.html#compatibility">3D with OpenGL</a> document.</p> - - -<h2 id="creating">Creating an OpenGL ES 1.0 Application</h2> - -<p>OpenGL applications for Android have the same basic structure as other applications, however -OpenGL applications use {@link android.opengl.GLSurfaceView} where other, non-OpenGL -applications use the {@link android.view.View} or {@link android.view.SurfaceView} class.<p> - -<p>To get started using OpenGL in your Android application, you must implement both a {@link -android.opengl.GLSurfaceView} and a {@link android.opengl.GLSurfaceView.Renderer}. The {@link -android.opengl.GLSurfaceView} is the main view type for the OpenGL applications and the {@link -android.opengl.GLSurfaceView.Renderer} controls what is drawn within that view. For more -information about these classes, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">3D -with OpenGL</a> document.</p> - -<p>To create an application that uses OpenGL ES 1.0:</p> - -<ol> - <li>Start a new Android project with an Activity called <code>HelloOpenGLES10</code>. - - <p class="note"><b>Note:</b> If you have not created a basic Android application yet, follow the - <a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a> instructions - to familiarize yourself with the process.</p> - </li> - - <li>Modify the <code>HelloOpenGLES10</code> class as follows: -<pre> -package com.example.android.apis.graphics; - -import android.app.Activity; -import android.content.Context; -import android.opengl.GLSurfaceView; -import android.os.Bundle; - -public class HelloOpenGLES10 extends Activity { - - private GLSurfaceView mGLView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mGLView = new HelloOpenGLSurfaceView(this); - setContentView(mGLView); - } - - @Override - protected void onPause() { - super.onPause(); - mGLView.onPause(); - } - - @Override - protected void onResume() { - super.onResume(); - mGLView.onResume(); - } - -} - -class HelloOpenGLES10SurfaceView extends GLSurfaceView { - - public HelloOpenGLES10SurfaceView(Context context){ - super(context); - setRenderer(new HelloOpenGLES10Renderer()); - } - -} -</pre> - <p>This Activity class creates a basic container for a {@link android.opengl.GLSurfaceView}.</p> - </li> - - <li>Create the following class <code>HelloOpenGLES10Renderer</code>, which implements the - {@link android.opengl.GLSurfaceView.Renderer} interface: - -<pre> -package com.example.android.apis.graphics; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import android.opengl.GLSurfaceView; - -public class HelloOpenGLES10Renderer implements GLSurfaceView.Renderer { - - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - // Set the background frame color - gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - } - - public void onDrawFrame(GL10 gl) { - // Redraw background color - gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - } - - public void onSurfaceChanged(GL10 gl, int width, int height) { - gl.glViewport(0, 0, width, height); - } - -} -</pre> - </li> -</ol> - -<p>These classes create a simple Android application which displays a grey screen using OpenGL -ES 1.0 calls. While this application does not do anything very interesting, by creating these two -classes, you have layed the foundation needed to start drawing graphic elements with OpenGL ES -1.0.</p> - -<p>If you are familiar with the OpenGL ES APIs, these two classes should give you enough information -to start using the OpenGL ES 1.0 API and creating graphics. However, if you need a bit more help -getting started with OpenGL, head on to the next sections for a few more tips.</p> - -<h2 id="drawing">Drawing Graphic Elements</h2> - -<p>Once you have implemented a {@link android.opengl.GLSurfaceView.Renderer}, the next step is to -draw something on it. This section shows you how to define and draw a basic triangle shape with the -Android OpenGL ES 1.0 API.</p> - -<p class="note"><b>Note:</b> The following instructions build on the previous section, so if you -have not been following along, go back to the <a href="#get-started">previous section</a> and catch -up.</p> - -<h3 id="define-triangle">Defining a Triangle</h3> - -<p>OpenGL allows you to define objects using coordinates in three-dimensional space. So, before you - can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to - define a vertex array for the coordinates.</p> - -<p>By default, OpenGL ES assumes a coordinate system where 0,0,0 (X,Y,Z) specifies the center of - the {@link android.opengl.GLSurfaceView} frame, 1,1,0 is the top right corner of the frame and --1,-1,0 is bottom left corner of the frame.</p> - -<p>To define a vertex array for a triangle:</p> - -<ol> - <li>In your <code>HelloOpenGLES10Renderer</code> class, add new member variable to contain the -vertices of a triangle shape: -<pre> - private FloatBuffer triangleVB; -</pre> - </li> - - <li>Create a method, <code>initShapes()</code> which populates this member variable: -<pre> - private void initShapes(){ - - float triangleCoords[] = { - // X, Y, Z - -0.5f, -0.25f, 0, - 0.5f, -0.25f, 0, - 0.0f, 0.559016994f, 0 - }; - - // initialize vertex Buffer for triangle - ByteBuffer vbb = ByteBuffer.allocateDirect( - // (# of coordinate values * 4 bytes per float) - triangleCoords.length * 4); - vbb.order(ByteOrder.nativeOrder()); - triangleVB = vbb.asFloatBuffer(); - triangleVB.put(triangleCoords); - triangleVB.position(0); - - } -</pre> - <p>This method defines a two-dimensional triangle shape with three equal sides.</p> - </li> - <li>Modify your <code>onSurfaceCreated()</code> method to initialize your triangle: - <pre> - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - - // Set the background frame color - gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - - // initialize the triangle vertex array - initShapes(); - } -</pre> - <p class="warning"><strong>Warning:</strong> Shapes and other static objects should be initialized - once in your <code>onSurfaceCreated()</code> method for best performance. Avoid initializing the - new objects in <code>onDrawFrame()</code>, as this causes the system to re-create the objects - for every frame redraw and slows down your application. - </p> - </li> - -</ol> - -<h3 id="draw-triangle">Draw the Triangle</h3> - -<p>Now that you have defined a shape to draw, you can use the OpenGL APIs to draw the -object.</p> - -<p>To draw the triangle with OpenGL:</p> - -<ol> - <li>Before you can draw your triangle, you must tell OpenGL that you are using vertex arrays. - Modify your <code>onSurfaceCreated()</code> method to enable vertex arrays. -<pre> - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - - // Set the background frame color - gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - - // initialize the triangle vertex array - initShapes(); - - // Enable use of vertex arrays - gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); - } -</pre> - <p>At this point, you are ready to draw the triangle object in the OpenGL frame.</p> - </li> - - <li>Modify your <code>onDrawFrame()</code> method to draw the triangle. -<pre> - public void onDrawFrame(GL10 gl) { - // Redraw background color - gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - - // Draw the triangle - gl.glColor4f(0.63671875f, 0.76953125f, 0.22265625f, 0.0f); - gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVB); - gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); - } -</pre> - <p><b>Note:</b> Since the triangle is stationary at this point, the system is redrawing the - object repeatedly in exactly the same place and so is not the most efficient use of the OpenGL - graphics pipeline. In a <a href="#motion">later section</a>, we add motion to the object to - justify this use of processing power.</p> - </li> -</ol> - -<p id="squashed-triangle">Try running this example application on your emulator or test device and -you should see something like this:</p> - -<img src="{@docRoot}images/opengl/helloopengl-es10-1.png"> - -<p>There are a few problems with this example. First of all, it's not going to impress your -friends. Secondly, the triangle is a bit squashed and changes shape when you change the screen -orientation of the test device. The reason the shape is skewed is due to the fact that the object is -being rendered in a frame which is not perfectly square. We fix that problem in the -<a href="#projection-and-views">next section</a>.</p> - -<h2 id="projection-and-views">Using Projection and Views</h2> - -<p>OpenGL Projection and Views provide a way to calculate the coordinates of graphic objects in -realistic proportions on graphics displays of any size. One of the basic problems in displaying -graphics is that Android device displays are typically not square and—by default—OpenGL -happily maps a perfectly square, uniform coordinate system onto your typically non-square -screen.</p> - -<img src="{@docRoot}images/opengl/coordinates.png"> - -<p>The illustration above shows the uniform coordinate system assumed for an OpenGL frame on the - left, and how these coordinates actually map to a typical device screen in landscape orientation - on the right. To solve this problem, you can apply OpenGL projection modes and views to transform - object coordinates so your graphic objects have the correct proportions on any display.</p> - -<p>To use a projection transformation on your triangle:</p> -<ol> - <li>Modify your <code>onSurfaceChanged()</code> method to enable {@link - javax.microedition.khronos.opengles.GL10#GL_PROJECTION GL10.GL_PROJECTION} mode, calculate the - screen ratio and apply the ratio as a transformation of the object coordinates. -<pre> - public void onSurfaceChanged(GL10 gl, int width, int height) { - gl.glViewport(0, 0, width, height); - - // make adjustments for screen ratio - float ratio = (float) width / height; - gl.glMatrixMode(GL10.GL_PROJECTION); - gl.glLoadIdentity(); - gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); - } -</pre> - </li> - - <li>Next, modify your <code>onDrawFrame()</code> method to apply the {@link -javax.microedition.khronos.opengles.GL10#GL_MODELVIEW GL_MODELVIEW} mode and set -a view point for the display using {@link -android.opengl.GLU#gluLookAt(javax.microedition.khronos.opengles.GL10, float, float, float, float, -float, float, float, float, float) GLU#gluLookAt()}. -<pre> - public void onDrawFrame(GL10 gl) { - // Redraw background color - gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - - // Set GL_MODELVIEW transformation mode - gl.glMatrixMode(GL10.GL_MODELVIEW); - gl.glLoadIdentity(); - - // When using GL_MODELVIEW, you must set the view point - GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); - - // Draw the triangle - ... - } -</pre> - </li> -</ol> - -<p>Try running this updated application on your emulator or test device and you should see something -like this:</p> - -<img src="{@docRoot}images/opengl/helloopengl-es10-2.png"> - -<p>Now that you have applied this transformation, the triangle has three equal sides, instead of the -squashed display in the <a href="#squashed-triangle">earlier version</a>.</p> - -<h2 id="motion">Adding Motion</h2> - -<p>While it may be interesting exercise to create static graphic objects with OpenGL ES, chances -are you want at least some of your objects to move. In this section, we add motion to to our -triangle by rotating it.</p> - -<p>To add rotation to your triangle:</p> -<ul> - <li>Modify your <code>onDrawFrame()</code> method to rotate the triangle object: -<pre> - public void onDrawFrame(GL10 gl) { - ... - // When using GL_MODELVIEW, you must set the view point - GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); - - // Create a rotation for the triangle - long time = SystemClock.uptimeMillis() % 4000L; - float angle = 0.090f * ((int) time); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - - // Draw the triangle - ... - } -</pre> - </li> -</ul> - -<p>Run the application with this code and your triangle should rotate around its center.</p> - -<!-- - <h2>TouchScreen Interaction</h2> - Optional extra (using code from API examples) - --> - -<h2 id="resources">Additional Resources</h2> - -<p>Be sure to check out the OpenGL ES code samples are available in the -<a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">API -Demos</a> sample application and listed in <a href="#code-samples-list">Related Samples</a> -sidebar above. -</p> diff --git a/docs/html/resources/tutorials/opengl/opengl-es20.jd b/docs/html/resources/tutorials/opengl/opengl-es20.jd deleted file mode 100644 index 5cdc343..0000000 --- a/docs/html/resources/tutorials/opengl/opengl-es20.jd +++ /dev/null @@ -1,514 +0,0 @@ -page.title=Hello OpenGL ES 1.0 -parent.title=Tutorials -parent.link=../../browser.html?tag=tutorial -@jd:body - - -<div id="qv-wrapper"> - <div id="qv"> - <h2>In this document</h2> - - <ol> - <li><a href="#creating">Creating an OpenGL ES 2.0 Application</a></li> - <li> - <a href="#drawing">Drawing Graphic Elements</a> - <ol> - <li><a href="#define-triangle">Defining a Triangle</a></li> - <li><a href="#draw-triangle">Draw the Triangle</a></li> - </ol> - </li> - <li><a href="#projection-and-views">Using Projection and Views</a></li> - <li><a href="#motion">Adding Motion</a></li> - <li><a href="#resources">Additional Resources</a></li> - - </ol> - <h2 id="code-samples-list">Related Samples</h2> - <ol> - <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ -index.html">API Demos - graphics</a></li> - <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ -GLES20Activity.html">OpenGL ES 2.0 Example</a></li> - </ol> - <h2>See also</h2> - <ol> - <li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li> - <li><a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html">Hello OpenGL -ES 1.0</a></li> - </ol> - </div> - </div> - -<p>This tutorial shows you how to create a simple Android application that uses OpenGL ES 2.0 and -perform some basic operations using the OpenGL ES 2.0 API, including:</p> - -<ul> - <li>Creating an application using {@link android.opengl.GLSurfaceView} and {@link -android.opengl.GLSurfaceView.Renderer}</li> - <li>Defining a graphic object and drawing it</li> - <li>Defining and applying an projection and view</li> - <li>Applying rotation to the drawn object</li> -</ul> - -<p>This tutorial demonstrates use of the OpenGL ES 2.0 API. Beginning with Android 2.2 (API Level -8), the framework supports OpenGL ES 2.0.</p> - -<p>Both the OpenGL ES 1.0 and the ES 1.1 API are supported by the Android framework since release -1.0 (API Level 1).For more information about compatibility for OpenGL versions and Android devices, -see the <a href="{@docRoot}guide/topics/graphics/opengl.html#compatibility">3D with OpenGL</a> -document.</p> - - -<h2 id="creating">Creating an OpenGL ES 1.0 Application</h2> - -<p>OpenGL applications for Android have the same basic structure as other applications, however -OpenGL applications use {@link android.opengl.GLSurfaceView} where other, non-OpenGL -applications use the {@link android.view.View} or {@link android.view.SurfaceView} class.<p> - -<p>To get started using OpenGL in your Android application, you must implement both a {@link -android.opengl.GLSurfaceView} and a {@link android.opengl.GLSurfaceView.Renderer}. The {@link -android.opengl.GLSurfaceView} is the main view type for the OpenGL applications and the {@link -android.opengl.GLSurfaceView.Renderer} controls what is drawn within that view. For more -information about these classes, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">3D -with OpenGL</a> document.</p> - -<p>To create an application that uses OpenGL ES 2.0:</p> - -<ol> - <li>Start a new Android project with an Activity called <code>HelloOpenGLES20</code>. - - <p class="note"><b>Note:</b> If you have not created a basic Android application yet, follow the - <a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a> instructions - to familiarize yourself with the process.</p> - </li> - - <li>Modify the <code>HelloOpenGLES20</code> class as follows: -<pre> -package com.example.android.apis.graphics; - -import android.app.Activity; -import android.content.Context; -import android.opengl.GLSurfaceView; -import android.os.Bundle; - -public class HelloOpenGLES20 extends Activity { - - private GLSurfaceView mGLView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mGLView = new HelloOpenGLES20SurfaceView(this); - setContentView(mGLView); - } - - @Override - protected void onPause() { - super.onPause(); - mGLView.onPause(); - } - - @Override - protected void onResume() { - super.onResume(); - mGLView.onResume(); - } -} - -class HelloOpenGLES20SurfaceView extends GLSurfaceView { - - public HelloOpenGLES20SurfaceView(Context context){ - super(context); - - // Create an OpenGL ES 2.0 context. - setEGLContextClientVersion(2); - - setRenderer(new HelloOpenGLES20Renderer()); - } -} -</pre> - <p>This Activity class creates a basic container for a {@link android.opengl.GLSurfaceView}.</p> - </li> - - <li>Create the following class <code>HelloOpenGLES20Renderer</code>, which implements the - {@link android.opengl.GLSurfaceView.Renderer} interface: - -<pre> -package com.example.android.apis.graphics; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; - -public class HelloOpenGLES20Renderer implements GLSurfaceView.Renderer { - - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - - // Set the background frame color - GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - } - - public void onDrawFrame(GL10 unused) { - - // Redraw background color - GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - } - - public void onSurfaceChanged(GL10 unused, int width, int height) { - GLES20.glViewport(0, 0, width, height); - } - -} -</pre> - </li> -</ol> - -<p>These classes create a simple Android application which displays a grey screen using OpenGL -ES 2.0 calls. While this application does not do anything very interesting, by creating these two -classes, you have layed the foundation needed to start drawing graphic elements with OpenGL ES -2.0.</p> - -<p>If your application only supports OpenGL ES 2.0, then you should declare that your application - requires OpenGL ES 2.0 by adding the following settings to your <a -href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a></code> file as -shown below.</p> - -<pre> -... - </application> - - <!-- Tell the system that you need ES 2.0. --> - <uses-feature android:glEsVersion="0x00020000" android:required="true" /> - -</manifest> -</pre> - -<p>Adding this declaration hides your application from devices that do not support OpenGL ES 2.0 -in the Android Market.</p> - -<p>If you are familiar with the OpenGL ES APIs, these preceding classes and the AndroidManifest.xml -declaration should give you enough information to start using the OpenGL ES API and creating -graphics. However, if you need a bit more help getting started with OpenGL, head on to the next -sections for a few more tips.</p> - - -<h2 id="drawing">Drawing Graphic Elements</h2> - -<p>Once you have implemented a {@link android.opengl.GLSurfaceView.Renderer}, the next step is to -draw something on it. This section shows you how to define and draw a basic triangle shape with the -OpenGL ES 2.0 API.</p> - -<p class="note"><b>Note:</b> The following instructions build on the previous section, so if you -have not been following along, go back to the <a href="#get-started">previous section</a> and catch -up.</p> - -<h3 id="define-triangle">Defining a Triangle</h3> - -<p>OpenGL allows you to define objects using coordinates in three-dimensional space. So, before you - can draw a triangle, you must define its coordinates. In OpenGL, the typical way to do this is to - define a vertex array for the coordinates.</p> - -<p>By default, OpenGL ES assumes a coordinate system where 0,0,0 (X,Y,Z) specifies the center of - the {@link android.opengl.GLSurfaceView} frame, 1,1,0 is the top right corner of the frame and --1,-1,0 is bottom left corner of the frame.</p> - -<p>To define a vertex array for a triangle:</p> - -<ol> - <li>In your <code>HelloOpenGLES20Renderer</code> class, add new member variable to contain the -vertices of a triangle shape: -<pre> - private FloatBuffer triangleVB; -</pre> - </li> - - <li>Create a method, <code>initShapes()</code> which populates this member variable: -<pre> - private void initShapes(){ - - float triangleCoords[] = { - // X, Y, Z - -0.5f, -0.25f, 0, - 0.5f, -0.25f, 0, - 0.0f, 0.559016994f, 0 - }; - - // initialize vertex Buffer for triangle - ByteBuffer vbb = ByteBuffer.allocateDirect( - // (# of coordinate values * 4 bytes per float) - triangleCoords.length * 4); - vbb.order(ByteOrder.nativeOrder()); - triangleVB = vbb.asFloatBuffer(); - triangleVB.put(triangleCoords); - triangleVB.position(0); - - } -</pre> - <p>This method defines a two-dimensional triangle shape with three equal sides.</p> - </li> - <li>Modify your <code>onSurfaceCreated()</code> method to initialize your triangle: -<pre> - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - - // Set the background frame color - GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - - // initialize the triangle vertex array - initShapes(); - } -</pre> - <p class="warning"><strong>Warning:</strong> Shapes and other static objects should be initialized - once in your <code>onSurfaceCreated()</code> method for best performance. Avoid initializing the - new objects in <code>onDrawFrame()</code>, as this causes the system to re-create the objects - for every frame redraw and slows down your application. - </p> - </li> - -</ol> - -<h3 id="draw-triangle">Draw the Triangle</h3> - -<p>Now that you have defined a shape to draw, you can now use the OpenGL APIs to draw the - object. In order to do this with OpenGL ES 2.0, you must define a vertex shader and a -fragment shader to describe how to draw your shape.</p> - -<p>To draw the triangle with OpenGL:</p> - -<ol> - <li>In your <code>HelloOpenGLES20Renderer</code> class, define a vertex shader and a fragment -shader. -<pre> - private final String vertexShaderCode = - "attribute vec4 vPosition; \n" + - "void main(){ \n" + - " gl_Position = vPosition; \n" + - "} \n"; - - private final String fragmentShaderCode = - "precision mediump float; \n" + - "void main(){ \n" + - " gl_FragColor = vec4 (0.63671875, 0.76953125, 0.22265625, 1.0); \n" + - "} \n"; -</pre> - </li> - <li>In your <code>HelloOpenGLES20Renderer</code> class, create a method for loading the shaders. -<pre> - private int loadShader(int type, String shaderCode){ - - int shader = GLES20.glCreateShader(type); - - GLES20.glShaderSource(shader, shaderCode); - GLES20.glCompileShader(shader); - - return shader; - } -</pre> - </li> - - <li>Add the following members to your <code>HelloOpenGLES20Renderer</code> class for an OpenGL -Program. -<pre> - private int mProgram; - private int maPositionHandle; -</pre> - </li> - - <li>Modify your <code>onSurfaceCreated()</code> method to load the shaders and attach them to a -OpenGL Program. -<pre> - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - - // Set the background frame color - GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - - // initialize the triangle vertex array - initShapes(); - - // Create shaders for shape and attach to program - int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); - int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); - - mProgram = GLES20.glCreateProgram(); - GLES20.glAttachShader(mProgram, vertexShader); - GLES20.glAttachShader(mProgram, fragmentShader); - GLES20.glLinkProgram(mProgram); - - maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); - } -</pre> - <p>At this point, you are ready to draw the triangle object in the OpenGL frame.</p> - </li> - - <li>Modify your <code>onDrawFrame()</code> method to draw the triangle. -<pre> - public void onDrawFrame(GL10 unused) { - - // Redraw background color - GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); - - // Specify a program with shaders - GLES20.glUseProgram(mProgram); - - // Prepare the triangle data - GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 12, triangleVB); - GLES20.glEnableVertexAttribArray(maPositionHandle); - - // Draw the triangle - GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); - } -</pre> - <p><b>Note:</b> Since the triangle is stationary at this point, the system is redrawing the - object repeatedly in exactly the same place and so is not the most efficient use of the OpenGL - graphics pipeline. In a <a href="#motion">later section</a>, we add motion to the object to - justify this use of processing power.</p> - </li> -</ol> - -<p id="squashed-triangle">Try running this example application on your emulator or test device and -you should see something like this:</p> - -<img src="{@docRoot}images/opengl/helloopengl-es20-1.png"> - -<p>There are a few problems with this example. First of all, it's not going to impress your -friends. Secondly, the triangle is a bit squashed and changes shape when you change the screen -orientation of the test device. The reason the shape is skewed is due to the fact that the object is -being rendered in a frame which is not perfectly square. We fix that problem in the -<a href="#projection-and-views">next section</a>.</p> - -<h2 id="projection-and-views">Using Projection and Views</h2> - -<p>OpenGL Projection and Views provide a way to calculate the coordinates of graphic objects in -realistic proportions on graphics displays of any size. One of the basic problems in displaying -graphics is that Android device displays are typically not square and—by default—OpenGL -happily maps a perfectly square, uniform coordinate system onto your typically non-square -screen.</p> - -<img src="{@docRoot}images/opengl/coordinates.png"> - -<p>The illustration above shows the uniform coordinate system assumed for an OpenGL frame on the - left, and how these coordinates actually map to a typical device screen in landscape orientation - on the right. To solve this problem, you can apply OpenGL projection modes and views to transform - object coordinates so your graphic objects have the correct proportions on any display.</p> - -<p>To use a projection transformation on your triangle:</p> -<ol> - <li>Add the following members to your <code>HelloOpenGLES20Renderer</code> class. -<pre> - private int muMVPMatrixHandle; - private float[] mMVPMatrix = new float[16]; - private float[] mMMatrix = new float[16]; - private float[] mVMatrix = new float[16]; - private float[] mProjMatrix = new float[16]; -</pre> - </li> - <li>Modify your <code>vertexShaderCode</code> string to add a variable for a model view -projection matrix. -<pre> - private final String vertexShaderCode = - "uniform mat4 uMVPMatrix; \n" + - "attribute vec4 vPosition; \n" + - "void main(){ \n" + - " gl_Position = uMVPMatrix * vPosition; \n" + - "} \n"; -</pre> - </li> - <li>Modify your <code>onSurfaceChanged()</code> method to reference the <code>uMVPMatrix</code> -shader variable you added and define a view transformation matrix. -<pre> - public void onSurfaceCreated(GL10 unused, EGLConfig config) { - ... - maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); - - muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); - Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); - } -</pre> - </li> - <li>Next, modify your <code>onSurfaceChanged()</code> method to calculate the device screen -ration and create a projection matrix. -<pre> - public void onSurfaceChanged(GL10 unused, int width, int height) { - GLES20.glViewport(0, 0, width, height); - - float ratio = (float) width / height; - Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); - } -</pre> - </li> - <li>Finally, modify your <code>onDrawFrame()</code> method to apply the transformation. -<pre> - public void onDrawFrame(GL10 unused) { - ... - // Apply a ModelView Projection transformation - Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); - GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); - - // Draw the triangle - GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); - } -</pre> - </li> - </ol> - -<p>Try running this updated application on your emulator or test device and you should see -something like this:</p> - - <img src="{@docRoot}images/opengl/helloopengl-es20-2.png"> - -<p>Now that you have applied this transformation, the triangle has three equal sides, instead of the -squashed display in the <a href="#squashed-triangle">earlier version</a>.</p> - - -<h2 id="motion">Adding Motion</h2> - -<p>While it may be interesting exercise to create static graphic objects with OpenGL ES, chances -are you want at least some of your objects to move. In this section, we add motion to to our -triangle by rotating it.</p> - -<p>To add rotation to your triangle:</p> -<ol> - <li>Add an additional tranformation matrix member to your <code>HelloOpenGLES20Renderer</code> -class. - <pre> - private float[] mMMatrix = new float[16]; - </pre> - </li> <li>Modify your <code>onDrawFrame()</code> method to rotate the triangle object: -<pre> - public void onDrawFrame(GL10 gl) { - ... - - // Create a rotation for the triangle - long time = SystemClock.uptimeMillis() % 4000L; - float angle = 0.090f * ((int) time); - Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f); - Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); - Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); - - // Apply a ModelView Projection transformation - //Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0); - GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); - - // Draw the triangle - ... - } -</pre> - </li> -</ol> - -<p>Run the application with this code and your triangle should rotate around its center.</p> - -<!-- - <h2>TouchScreen Interaction</h2> - Optional extra (using code from API examples) - --> - -<h2 id="resources">Additional Resources</h2> - -<p>Be sure to check out the OpenGL ES code samples are available in the -<a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">API -Demos</a> sample application and listed in <a href="#code-samples-list">Related Samples</a> -sidebar above. -</p> diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java index e900584..6254192 100644 --- a/graphics/java/android/renderscript/Allocation.java +++ b/graphics/java/android/renderscript/Allocation.java @@ -67,6 +67,22 @@ public class Allocation extends BaseObj { Type mType; Bitmap mBitmap; int mUsage; + Allocation mAdaptedAllocation; + + boolean mConstrainedLOD; + boolean mConstrainedFace; + boolean mConstrainedY; + boolean mConstrainedZ; + int mSelectedY; + int mSelectedZ; + int mSelectedLOD; + Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X; + + int mCurrentDimX; + int mCurrentDimY; + int mCurrentDimZ; + int mCurrentCount; + /** * The usage of the allocation. These signal to renderscript @@ -139,6 +155,19 @@ public class Allocation extends BaseObj { } } + private void updateCacheInfo(Type t) { + mCurrentDimX = t.getX(); + mCurrentDimY = t.getY(); + mCurrentDimZ = t.getZ(); + mCurrentCount = mCurrentDimX; + if (mCurrentDimY > 1) { + mCurrentCount *= mCurrentDimY; + } + if (mCurrentDimZ > 1) { + mCurrentCount *= mCurrentDimZ; + } + } + Allocation(int id, RenderScript rs, Type t, int usage) { super(id, rs); if ((usage & ~(USAGE_SCRIPT | @@ -149,6 +178,10 @@ public class Allocation extends BaseObj { throw new RSIllegalArgumentException("Unknown usage specified."); } mType = t; + + if (t != null) { + updateCacheInfo(t); + } } private void validateIsInt32() { @@ -210,6 +243,7 @@ public class Allocation extends BaseObj { if(typeID != 0) { mType = new Type(typeID, mRS); mType.updateFromNative(); + updateCacheInfo(mType); } } @@ -234,15 +268,15 @@ public class Allocation extends BaseObj { public void copyFrom(BaseObj[] d) { mRS.validate(); validateIsObject(); - if (d.length != mType.getCount()) { + if (d.length != mCurrentCount) { throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + - mType.getCount() + ", array length = " + d.length); + mCurrentCount + ", array length = " + d.length); } int i[] = new int[d.length]; for (int ct=0; ct < d.length; ct++) { i[ct] = d[ct].getID(); } - copy1DRangeFromUnchecked(0, mType.getCount(), i); + copy1DRangeFromUnchecked(0, mCurrentCount, i); } private void validateBitmapFormat(Bitmap b) { @@ -292,8 +326,7 @@ public class Allocation extends BaseObj { } private void validateBitmapSize(Bitmap b) { - if(mType.getX() != b.getWidth() || - mType.getY() != b.getHeight()) { + if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) { throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); } } @@ -307,7 +340,7 @@ public class Allocation extends BaseObj { */ public void copyFromUnchecked(int[] d) { mRS.validate(); - copy1DRangeFromUnchecked(0, mType.getCount(), d); + copy1DRangeFromUnchecked(0, mCurrentCount, d); } /** * Copy an allocation from an array. This variant is not type @@ -318,7 +351,7 @@ public class Allocation extends BaseObj { */ public void copyFromUnchecked(short[] d) { mRS.validate(); - copy1DRangeFromUnchecked(0, mType.getCount(), d); + copy1DRangeFromUnchecked(0, mCurrentCount, d); } /** * Copy an allocation from an array. This variant is not type @@ -329,7 +362,7 @@ public class Allocation extends BaseObj { */ public void copyFromUnchecked(byte[] d) { mRS.validate(); - copy1DRangeFromUnchecked(0, mType.getCount(), d); + copy1DRangeFromUnchecked(0, mCurrentCount, d); } /** * Copy an allocation from an array. This variant is not type @@ -340,7 +373,7 @@ public class Allocation extends BaseObj { */ public void copyFromUnchecked(float[] d) { mRS.validate(); - copy1DRangeFromUnchecked(0, mType.getCount(), d); + copy1DRangeFromUnchecked(0, mCurrentCount, d); } /** @@ -352,7 +385,7 @@ public class Allocation extends BaseObj { */ public void copyFrom(int[] d) { mRS.validate(); - copy1DRangeFrom(0, mType.getCount(), d); + copy1DRangeFrom(0, mCurrentCount, d); } /** @@ -364,7 +397,7 @@ public class Allocation extends BaseObj { */ public void copyFrom(short[] d) { mRS.validate(); - copy1DRangeFrom(0, mType.getCount(), d); + copy1DRangeFrom(0, mCurrentCount, d); } /** @@ -376,7 +409,7 @@ public class Allocation extends BaseObj { */ public void copyFrom(byte[] d) { mRS.validate(); - copy1DRangeFrom(0, mType.getCount(), d); + copy1DRangeFrom(0, mCurrentCount, d); } /** @@ -388,7 +421,7 @@ public class Allocation extends BaseObj { */ public void copyFrom(float[] d) { mRS.validate(); - copy1DRangeFrom(0, mType.getCount(), d); + copy1DRangeFrom(0, mCurrentCount, d); } /** @@ -420,8 +453,7 @@ public class Allocation extends BaseObj { throw new RSIllegalArgumentException("Field packer length " + data.length + " not divisible by element size " + eSize + "."); } - data1DChecks(xoff, count, data.length, data.length); - mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length); + copy1DRangeFromUnchecked(xoff, count, data); } /** @@ -448,7 +480,8 @@ public class Allocation extends BaseObj { " does not match component size " + eSize + "."); } - mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length); + mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD, + component_number, data, data.length); } private void data1DChecks(int off, int count, int len, int dataSize) { @@ -459,11 +492,11 @@ public class Allocation extends BaseObj { if(count < 1) { throw new RSIllegalArgumentException("Count must be >= 1."); } - if((off + count) > mType.getCount()) { - throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() + + if((off + count) > mCurrentCount) { + throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount + ", got " + count + " at offset " + off + "."); } - if((len) < dataSize) { + if(len < dataSize) { throw new RSIllegalArgumentException("Array too small for allocation type."); } } @@ -494,7 +527,7 @@ public class Allocation extends BaseObj { public void copy1DRangeFromUnchecked(int off, int count, int[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); } /** * Copy part of an allocation from an array. This variant is @@ -508,7 +541,7 @@ public class Allocation extends BaseObj { public void copy1DRangeFromUnchecked(int off, int count, short[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 2, dataSize); - mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); } /** * Copy part of an allocation from an array. This variant is @@ -522,7 +555,7 @@ public class Allocation extends BaseObj { public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length, dataSize); - mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); } /** * Copy part of an allocation from an array. This variant is @@ -536,7 +569,7 @@ public class Allocation extends BaseObj { public void copy1DRangeFromUnchecked(int off, int count, float[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); } /** @@ -606,21 +639,25 @@ public class Allocation extends BaseObj { */ public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) { mRS.nAllocationData2D(getID(), off, 0, - 0, Type.CubemapFace.POSITIVE_X.mID, + mSelectedLOD, mSelectedFace.mID, count, 1, data.getID(), dataOff, 0, - 0, Type.CubemapFace.POSITIVE_X.mID); + data.mSelectedLOD, data.mSelectedFace.mID); } private void validate2DRange(int xoff, int yoff, int w, int h) { - if (xoff < 0 || yoff < 0) { - throw new RSIllegalArgumentException("Offset cannot be negative."); - } - if (h < 0 || w < 0) { - throw new RSIllegalArgumentException("Height or width cannot be negative."); - } - if ((xoff + w) > mType.mDimX || - (yoff + h) > mType.mDimY) { - throw new RSIllegalArgumentException("Updated region larger than allocation."); + if (mAdaptedAllocation != null) { + + } else { + + if (xoff < 0 || yoff < 0) { + throw new RSIllegalArgumentException("Offset cannot be negative."); + } + if (h < 0 || w < 0) { + throw new RSIllegalArgumentException("Height or width cannot be negative."); + } + if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { + throw new RSIllegalArgumentException("Updated region larger than allocation."); + } } } @@ -637,25 +674,29 @@ public class Allocation extends BaseObj { public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { mRS.validate(); validate2DRange(xoff, yoff, w, h); - mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length); + mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, + w, h, data, data.length); } public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { mRS.validate(); validate2DRange(xoff, yoff, w, h); - mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2); + mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, + w, h, data, data.length * 2); } public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { mRS.validate(); validate2DRange(xoff, yoff, w, h); - mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); + mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, + w, h, data, data.length * 4); } public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { mRS.validate(); validate2DRange(xoff, yoff, w, h); - mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); + mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, + w, h, data, data.length * 4); } /** @@ -675,9 +716,9 @@ public class Allocation extends BaseObj { mRS.validate(); validate2DRange(xoff, yoff, w, h); mRS.nAllocationData2D(getID(), xoff, yoff, - 0, Type.CubemapFace.POSITIVE_X.mID, + mSelectedLOD, mSelectedFace.mID, w, h, data.getID(), dataXoff, dataYoff, - 0, Type.CubemapFace.POSITIVE_X.mID); + data.mSelectedLOD, data.mSelectedFace.mID); } /** @@ -693,7 +734,7 @@ public class Allocation extends BaseObj { mRS.validate(); validateBitmapFormat(data); validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); - mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data); + mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data); } @@ -750,6 +791,7 @@ public class Allocation extends BaseObj { int typeID = mRS.nAllocationGetType(getID()); mType = new Type(typeID, mRS); mType.updateFromNative(); + updateCacheInfo(mType); } /* diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java index 77dd86a..ca5246a 100644 --- a/graphics/java/android/renderscript/AllocationAdapter.java +++ b/graphics/java/android/renderscript/AllocationAdapter.java @@ -17,228 +17,92 @@ package android.renderscript; import android.content.res.Resources; -import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.util.Log; import android.util.TypedValue; /** * **/ public class AllocationAdapter extends Allocation { - private boolean mConstrainedLOD; - private boolean mConstrainedFace; - private boolean mConstrainedY; - private boolean mConstrainedZ; - - private int mSelectedDimX; - private int mSelectedDimY; - private int mSelectedDimZ; - private int mSelectedCount; - private Allocation mAlloc; - - private int mSelectedLOD = 0; - private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X; - AllocationAdapter(int id, RenderScript rs, Allocation alloc) { - super(id, rs, null, alloc.mUsage); - mAlloc = alloc; + super(id, rs, alloc.mType, alloc.mUsage); + mAdaptedAllocation = alloc; } - int getID() { - return mAlloc.getID(); + return mAdaptedAllocation.getID(); } - public void copyFrom(BaseObj[] d) { - mRS.validate(); - if (d.length != mSelectedCount) { - throw new RSIllegalArgumentException("Array size mismatch, allocation size = " + - mSelectedCount + ", array length = " + d.length); - } - int i[] = new int[d.length]; - for (int ct=0; ct < d.length; ct++) { - i[ct] = d[ct].getID(); - } - subData1D(0, mAlloc.mType.getCount(), i); - } - - void validateBitmap(Bitmap b) { - mRS.validate(); - if(mSelectedDimX != b.getWidth() || - mSelectedDimY != b.getHeight()) { - throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); - } - } - - public void copyFrom(int[] d) { - mRS.validate(); - subData1D(0, mSelectedCount, d); - } - public void copyFrom(short[] d) { - mRS.validate(); - subData1D(0, mSelectedCount, d); - } - public void copyFrom(byte[] d) { - mRS.validate(); - subData1D(0, mSelectedCount, d); - } - public void copyFrom(float[] d) { - mRS.validate(); - subData1D(0, mSelectedCount, d); - } - public void copyFrom(Bitmap b) { - validateBitmap(b); - mRS.nAllocationCopyFromBitmap(getID(), b); - } - - public void copyTo(Bitmap b) { - validateBitmap(b); - mRS.nAllocationCopyToBitmap(getID(), b); - } - - + /** + * @hide + */ public void subData(int xoff, FieldPacker fp) { - int eSize = mAlloc.mType.mElement.getSizeBytes(); - final byte[] data = fp.getData(); - - int count = data.length / eSize; - if ((eSize * count) != data.length) { - throw new RSIllegalArgumentException("Field packer length " + data.length + - " not divisible by element size " + eSize + "."); - } - data1DChecks(xoff, count, data.length, data.length); - mRS.nAllocationData1D(getID(), xoff, mSelectedLOD, count, data, data.length); + super.setFromFieldPacker(xoff, fp); } - - + /** + * @hide + */ public void subElementData(int xoff, int component_number, FieldPacker fp) { - if (component_number >= mAlloc.mType.mElement.mElements.length) { - throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); - } - if(xoff < 0) { - throw new RSIllegalArgumentException("Offset must be >= 0."); - } - - final byte[] data = fp.getData(); - int eSize = mAlloc.mType.mElement.mElements[component_number].getSizeBytes(); - - if (data.length != eSize) { - throw new RSIllegalArgumentException("Field packer sizelength " + data.length + - " does not match component size " + eSize + "."); - } - - mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD, component_number, data, data.length); + super.setFromFieldPacker(xoff, component_number, fp); } - - void data1DChecks(int off, int count, int len, int dataSize) { - mRS.validate(); - if(off < 0) { - throw new RSIllegalArgumentException("Offset must be >= 0."); - } - if(count < 1) { - throw new RSIllegalArgumentException("Count must be >= 1."); - } - if((off + count) > mSelectedCount) { - throw new RSIllegalArgumentException("Overflow, Available count " + mAlloc.mType.getCount() + - ", got " + count + " at offset " + off + "."); - } - if((len) < dataSize) { - throw new RSIllegalArgumentException("Array too small for allocation type. len = " + - len + ", dataSize = " + dataSize); - } - } - + /** + * @hide + */ public void subData1D(int off, int count, int[] d) { - int dataSize = mAlloc.mType.mElement.getSizeBytes() * count; - data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); + super.copy1DRangeFrom(off, count, d); } + /** + * @hide + */ public void subData1D(int off, int count, short[] d) { - int dataSize = mAlloc.mType.mElement.getSizeBytes() * count; - data1DChecks(off, count, d.length * 2, dataSize); - mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); + super.copy1DRangeFrom(off, count, d); } + /** + * @hide + */ public void subData1D(int off, int count, byte[] d) { - int dataSize = mAlloc.mType.mElement.getSizeBytes() * count; - data1DChecks(off, count, d.length, dataSize); - mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); + super.copy1DRangeFrom(off, count, d); } + /** + * @hide + */ public void subData1D(int off, int count, float[] d) { - int dataSize = mAlloc.mType.mElement.getSizeBytes() * count; - data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize); + super.copy1DRangeFrom(off, count, d); } - /** - * Copy part of an allocation from another allocation. - * - * @param off The offset of the first element to be copied. - * @param count The number of elements to be copied. - * @param data the source data allocation. - * @param dataOff off The offset of the first element in data to - * be copied. + * @hide */ - public void subData1D(int off, int count, AllocationAdapter data, int dataOff) { - mRS.nAllocationData2D(getID(), off, 0, - mSelectedLOD, mSelectedFace.mID, - count, 1, data.getID(), dataOff, 0, - data.mSelectedLOD, data.mSelectedFace.mID); - } - - public void subData2D(int xoff, int yoff, int w, int h, int[] d) { - mRS.validate(); - mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, - w, h, d, d.length * 4); + super.copy2DRangeFrom(xoff, yoff, w, h, d); } - + /** + * @hide + */ public void subData2D(int xoff, int yoff, int w, int h, float[] d) { - mRS.validate(); - mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, - w, h, d, d.length * 4); + super.copy2DRangeFrom(xoff, yoff, w, h, d); } - /** - * Copy a rectangular region into the allocation from another - * allocation. - * - * @param xoff X offset of the region to update. - * @param yoff Y offset of the region to update. - * @param w Width of the incoming region to update. - * @param h Height of the incoming region to update. - * @param data source allocation. - * @param dataXoff X offset in data of the region to update. - * @param dataYoff Y offset in data of the region to update. + * @hide */ - public void subData2D(int xoff, int yoff, int w, int h, - AllocationAdapter data, int dataXoff, int dataYoff) { - mRS.validate(); - mRS.nAllocationData2D(getID(), xoff, yoff, - mSelectedLOD, mSelectedFace.mID, - w, h, data.getID(), dataXoff, dataYoff, - data.mSelectedLOD, data.mSelectedFace.mID); - } - public void readData(int[] d) { - mRS.validate(); - mRS.nAllocationRead(getID(), d); + super.copyTo(d); } - + /** + * @hide + */ public void readData(float[] d) { - mRS.validate(); - mRS.nAllocationRead(getID(), d); + super.copyTo(d); } - private void initLOD(int lod) { + void initLOD(int lod) { if (lod < 0) { throw new RSIllegalArgumentException("Attempting to set negative lod (" + lod + ")."); } - int tx = mAlloc.mType.getX(); - int ty = mAlloc.mType.getY(); - int tz = mAlloc.mType.getZ(); + int tx = mAdaptedAllocation.mType.getX(); + int ty = mAdaptedAllocation.mType.getY(); + int tz = mAdaptedAllocation.mType.getZ(); for (int ct=0; ct < lod; ct++) { if ((tx==1) && (ty == 1) && (tz == 1)) { @@ -250,25 +114,31 @@ public class AllocationAdapter extends Allocation { if (tz > 1) tz >>= 1; } - mSelectedDimX = tx; - mSelectedDimY = ty; - mSelectedCount = tx; - if (ty > 1) { - mSelectedCount *= ty; + mCurrentDimX = tx; + mCurrentDimY = ty; + mCurrentDimZ = tz; + mCurrentCount = mCurrentDimX; + if (mCurrentDimY > 1) { + mCurrentCount *= mCurrentDimY; } - if (tz > 1) { - mSelectedCount *= tz; + if (mCurrentDimZ > 1) { + mCurrentCount *= mCurrentDimZ; } + mSelectedY = 0; + mSelectedZ = 0; } /** * Set the active LOD. The LOD must be within the range for the - * type being adapted. + * type being adapted. The base allocation must have mipmaps. + * + * Because this changes the dimensions of the adapter the + * current Y and Z will be reset. * * @param lod The LOD to make active. */ public void setLOD(int lod) { - if (!mAlloc.getType().hasMipmaps()) { + if (!mAdaptedAllocation.getType().hasMipmaps()) { throw new RSInvalidStateException("Cannot set LOD when the allocation type does not include mipmaps."); } if (!mConstrainedLOD) { @@ -278,22 +148,81 @@ public class AllocationAdapter extends Allocation { initLOD(lod); } + /** + * Set the active Face. The base allocation must be of a type + * that includes faces. + * + * @param cf The face to make active. + */ public void setFace(Type.CubemapFace cf) { + if (!mAdaptedAllocation.getType().hasFaces()) { + throw new RSInvalidStateException("Cannot set Face when the allocation type does not include faces."); + } + if (!mConstrainedFace) { + throw new RSInvalidStateException("Cannot set LOD when the adapter includes mipmaps."); + } + if (cf == null) { + throw new RSIllegalArgumentException("Cannot set null face."); + } + mSelectedFace = cf; } + /** + * Set the active Y. The y value must be within the range for + * the allocation being adapted. The base allocation must + * contain the Y dimension. + * + * @param y The y to make active. + */ public void setY(int y) { - mSelectedDimY = y; + if (mAdaptedAllocation.getType().getY() == 0) { + throw new RSInvalidStateException("Cannot set Y when the allocation type does not include Y dim."); + } + if (mAdaptedAllocation.getType().getY() <= y) { + throw new RSInvalidStateException("Cannot set Y greater than dimension of allocation."); + } + if (!mConstrainedY) { + throw new RSInvalidStateException("Cannot set Y when the adapter includes Y."); + } + + mSelectedY = y; } + /** + * Set the active Z. The z value must be within the range for + * the allocation being adapted. The base allocation must + * contain the Z dimension. + * + * @param z The z to make active. + */ public void setZ(int z) { + if (mAdaptedAllocation.getType().getZ() == 0) { + throw new RSInvalidStateException("Cannot set Z when the allocation type does not include Z dim."); + } + if (mAdaptedAllocation.getType().getZ() <= z) { + throw new RSInvalidStateException("Cannot set Z greater than dimension of allocation."); + } + if (!mConstrainedZ) { + throw new RSInvalidStateException("Cannot set Z when the adapter includes Z."); + } + + mSelectedZ = z; } - // creation - //static public AllocationAdapter create1D(RenderScript rs, Allocation a) { - //} + static public AllocationAdapter create1D(RenderScript rs, Allocation a) { + rs.validate(); + AllocationAdapter aa = new AllocationAdapter(0, rs, a); + aa.mConstrainedLOD = true; + aa.mConstrainedFace = true; + aa.mConstrainedY = true; + aa.mConstrainedZ = true; + aa.initLOD(0); + return aa; + } static public AllocationAdapter create2D(RenderScript rs, Allocation a) { + android.util.Log.e("rs", "create2d " + a); rs.validate(); AllocationAdapter aa = new AllocationAdapter(0, rs, a); aa.mConstrainedLOD = true; @@ -305,6 +234,16 @@ public class AllocationAdapter extends Allocation { } + /** + * Override the Allocation resize. Resizing adapters is not + * allowed and will throw a RSInvalidStateException. + * + * @param dimX ignored. + */ + public synchronized void resize(int dimX) { + throw new RSInvalidStateException("Resize not allowed for Adapters."); + } + } diff --git a/include/media/EffectBassBoostApi.h b/include/media/EffectBassBoostApi.h deleted file mode 100644 index 56119eb..0000000 --- a/include/media/EffectBassBoostApi.h +++ /dev/null @@ -1,43 +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_EFFECTBASSBOOSTAPI_H_ -#define ANDROID_EFFECTBASSBOOSTAPI_H_ - -#include <hardware/audio_effect.h> - -#if __cplusplus -extern "C" { -#endif - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_; -#endif //OPENSL_ES_H_ - -/* enumerated parameter settings for BassBoost effect */ -typedef enum -{ - BASSBOOST_PARAM_STRENGTH_SUPPORTED, - BASSBOOST_PARAM_STRENGTH -} t_bassboost_params; - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTBASSBOOSTAPI_H_*/ diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h deleted file mode 100644 index f11c5ec..0000000 --- a/include/media/EffectEnvironmentalReverbApi.h +++ /dev/null @@ -1,69 +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_EFFECTENVIRONMENTALREVERBAPI_H_ -#define ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_ - -#include <hardware/audio_effect.h> - -#if __cplusplus -extern "C" { -#endif - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } }; -const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_; -#endif //OPENSL_ES_H_ - -/* enumerated parameter settings for environmental reverb effect */ -typedef enum -{ - // Parameters below are as defined in OpenSL ES specification for environmental reverb interface - REVERB_PARAM_ROOM_LEVEL, // in millibels, range -6000 to 0 - REVERB_PARAM_ROOM_HF_LEVEL, // in millibels, range -4000 to 0 - REVERB_PARAM_DECAY_TIME, // in milliseconds, range 100 to 20000 - REVERB_PARAM_DECAY_HF_RATIO, // in permilles, range 100 to 1000 - REVERB_PARAM_REFLECTIONS_LEVEL, // in millibels, range -6000 to 0 - REVERB_PARAM_REFLECTIONS_DELAY, // in milliseconds, range 0 to 65 - REVERB_PARAM_REVERB_LEVEL, // in millibels, range -6000 to 0 - REVERB_PARAM_REVERB_DELAY, // in milliseconds, range 0 to 65 - REVERB_PARAM_DIFFUSION, // in permilles, range 0 to 1000 - REVERB_PARAM_DENSITY, // in permilles, range 0 to 1000 - REVERB_PARAM_PROPERTIES, - REVERB_PARAM_BYPASS -} t_env_reverb_params; - -//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification. -typedef struct s_reverb_settings { - int16_t roomLevel; - int16_t roomHFLevel; - uint32_t decayTime; - int16_t decayHFRatio; - int16_t reflectionsLevel; - uint32_t reflectionsDelay; - int16_t reverbLevel; - uint32_t reverbDelay; - int16_t diffusion; - int16_t density; -} __attribute__((packed)) t_reverb_settings; - - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_*/ diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h deleted file mode 100644 index 950d138..0000000 --- a/include/media/EffectEqualizerApi.h +++ /dev/null @@ -1,58 +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_EFFECTEQUALIZERAPI_H_ -#define ANDROID_EFFECTEQUALIZERAPI_H_ - -#include <hardware/audio_effect.h> - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_; -#endif //OPENSL_ES_H_ - -#if __cplusplus -extern "C" { -#endif - -/* enumerated parameters for Equalizer effect */ -typedef enum -{ - EQ_PARAM_NUM_BANDS, // Gets the number of frequency bands that the equalizer supports. - EQ_PARAM_LEVEL_RANGE, // Returns the minimum and maximum band levels supported. - EQ_PARAM_BAND_LEVEL, // Gets/Sets the gain set for the given equalizer band. - EQ_PARAM_CENTER_FREQ, // Gets the center frequency of the given band. - EQ_PARAM_BAND_FREQ_RANGE, // Gets the frequency range of the given frequency band. - EQ_PARAM_GET_BAND, // Gets the band that has the most effect on the given frequency. - EQ_PARAM_CUR_PRESET, // Gets/Sets the current preset. - EQ_PARAM_GET_NUM_OF_PRESETS, // Gets the total number of presets the equalizer supports. - EQ_PARAM_GET_PRESET_NAME, // Gets the preset name based on the index. - EQ_PARAM_PROPERTIES // Gets/Sets all parameters at a time. -} t_equalizer_params; - -//t_equalizer_settings groups all current equalizer setting for backup and restore. -typedef struct s_equalizer_settings { - uint16_t curPreset; - uint16_t numBands; - uint16_t bandLevels[]; -} t_equalizer_settings; - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/ diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h deleted file mode 100644 index e5b168a..0000000 --- a/include/media/EffectPresetReverbApi.h +++ /dev/null @@ -1,55 +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_EFFECTPRESETREVERBAPI_H_ -#define ANDROID_EFFECTPRESETREVERBAPI_H_ - -#include <hardware/audio_effect.h> - -#if __cplusplus -extern "C" { -#endif - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_; -#endif //OPENSL_ES_H_ - -/* enumerated parameter settings for preset reverb effect */ -typedef enum -{ - REVERB_PARAM_PRESET -} t_preset_reverb_params; - - -typedef enum -{ - REVERB_PRESET_NONE, - REVERB_PRESET_SMALLROOM, - REVERB_PRESET_MEDIUMROOM, - REVERB_PRESET_LARGEROOM, - REVERB_PRESET_MEDIUMHALL, - REVERB_PRESET_LARGEHALL, - REVERB_PRESET_PLATE, - REVERB_PRESET_LAST = REVERB_PRESET_PLATE -} t_reverb_presets; - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTPRESETREVERBAPI_H_*/ diff --git a/include/media/EffectVirtualizerApi.h b/include/media/EffectVirtualizerApi.h deleted file mode 100644 index 2e216e2..0000000 --- a/include/media/EffectVirtualizerApi.h +++ /dev/null @@ -1,43 +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_EFFECTVIRTUALIZERAPI_H_ -#define ANDROID_EFFECTVIRTUALIZERAPI_H_ - -#include <hardware/audio_effect.h> - -#if __cplusplus -extern "C" { -#endif - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_; -#endif //OPENSL_ES_H_ - -/* enumerated parameter settings for virtualizer effect */ -typedef enum -{ - VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, - VIRTUALIZER_PARAM_STRENGTH -} t_virtualizer_params; - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTVIRTUALIZERAPI_H_*/ diff --git a/include/media/EffectVisualizerApi.h b/include/media/EffectVisualizerApi.h deleted file mode 100644 index e0fa328..0000000 --- a/include/media/EffectVisualizerApi.h +++ /dev/null @@ -1,56 +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_EFFECTVISUALIZERAPI_H_ -#define ANDROID_EFFECTVISUALIZERAPI_H_ - -#include <hardware/audio_effect.h> - -#if __cplusplus -extern "C" { -#endif - -#ifndef OPENSL_ES_H_ -static const effect_uuid_t SL_IID_VISUALIZATION_ = - { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }; -const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_; -#endif //OPENSL_ES_H_ - -#define VISUALIZER_CAPTURE_SIZE_MAX 1024 // maximum capture size in samples -#define VISUALIZER_CAPTURE_SIZE_MIN 128 // minimum capture size in samples - -/* enumerated parameters for Visualizer effect */ -typedef enum -{ - VISU_PARAM_CAPTURE_SIZE, // Sets the number PCM samples in the capture. -} t_visualizer_params; - -/* commands */ -typedef enum -{ - VISU_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture. -}t_visualizer_cmds; - -// VISU_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine. -// It returns the number of samples specified by VISU_PARAM_CAPTURE_SIZE -// in 8 bit unsigned format (0 = 0x80) - -#if __cplusplus -} // extern "C" -#endif - - -#endif /*ANDROID_EFFECTVISUALIZERAPI_H_*/ diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h index b8746c2..5d2c874 100644 --- a/include/media/Visualizer.h +++ b/include/media/Visualizer.h @@ -18,7 +18,7 @@ #define ANDROID_MEDIA_VISUALIZER_H #include <media/AudioEffect.h> -#include <media/EffectVisualizerApi.h> +#include <audio_effects/effect_visualizer.h> #include <string.h> /** diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 0310bc3..3c2d80d 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -27,6 +27,7 @@ #include "Rect.h" #include "SkiaColorFilter.h" +#include "Texture.h" #include "Vertex.h" namespace android { @@ -40,14 +41,18 @@ namespace uirenderer { * A layer has dimensions and is backed by an OpenGL texture or FBO. */ struct Layer { - Layer(const uint32_t layerWidth, const uint32_t layerHeight): - width(layerWidth), height(layerHeight) { + Layer(const uint32_t layerWidth, const uint32_t layerHeight) { mesh = NULL; meshIndices = NULL; meshElementCount = 0; - isCacheable = true; - isTextureLayer = false; + cacheable = true; + textureLayer = false; renderTarget = GL_TEXTURE_2D; + texture.width = layerWidth; + texture.height = layerHeight; + colorFilter = NULL; + firstFilter = true; + firstWrap = true; } ~Layer() { @@ -64,12 +69,152 @@ struct Layer { regionRect.set(bounds.leftTop().x, bounds.leftTop().y, bounds.rightBottom().x, bounds.rightBottom().y); - const float texX = 1.0f / float(width); - const float texY = 1.0f / float(height); + const float texX = 1.0f / float(texture.width); + const float texY = 1.0f / float(texture.height); const float height = layer.getHeight(); texCoords.set( regionRect.left * texX, (height - regionRect.top) * texY, regionRect.right * texX, (height - regionRect.bottom) * texY); + + regionRect.translate(layer.left, layer.top); + } + + inline uint32_t getWidth() { + return texture.width; + } + + inline uint32_t getHeight() { + return texture.height; + } + + void setSize(uint32_t width, uint32_t height) { + texture.width = width; + texture.height = height; + } + + inline void setBlend(bool blend) { + texture.blend = blend; + } + + inline bool isBlend() { + return texture.blend; + } + + inline void setAlpha(int alpha) { + this->alpha = alpha; + } + + inline void setAlpha(int alpha, SkXfermode::Mode mode) { + this->alpha = alpha; + this->mode = mode; + } + + inline int getAlpha() { + return alpha; + } + + inline SkXfermode::Mode getMode() { + return mode; + } + + inline void setEmpty(bool empty) { + this->empty = empty; + } + + inline bool isEmpty() { + return empty; + } + + inline void setFbo(GLuint fbo) { + this->fbo = fbo; + } + + inline GLuint getFbo() { + return fbo; + } + + inline GLuint* getTexturePointer() { + return &texture.id; + } + + inline GLuint getTexture() { + return texture.id; + } + + inline GLenum getRenderTarget() { + return renderTarget; + } + + inline void setRenderTarget(GLenum renderTarget) { + this->renderTarget = renderTarget; + } + + void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) { + if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) { + firstWrap = true; + texture.setWrap(wrapS, wrapT); + if (bindTexture) { + glBindTexture(renderTarget, texture.id); + } + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT); + } + } + + void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) { + if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) { + firstFilter = false; + texture.setFilter(min, mag); + if (bindTexture) { + glBindTexture(renderTarget, texture.id); + } + glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min); + glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag); + } + } + + inline bool isCacheable() { + return cacheable; + } + + inline void setCacheable(bool cacheable) { + this->cacheable = cacheable; + } + + inline bool isTextureLayer() { + return textureLayer; + } + + inline void setTextureLayer(bool textureLayer) { + this->textureLayer = textureLayer; + } + + inline SkiaColorFilter* getColorFilter() { + return colorFilter; + } + + inline void setColorFilter(SkiaColorFilter* filter) { + colorFilter = filter; + } + + inline void bindTexture() { + glBindTexture(renderTarget, texture.id); + } + + inline void generateTexture() { + glGenTextures(1, &texture.id); + } + + inline void deleteTexture() { + if (texture.id) glDeleteTextures(1, &texture.id); + } + + inline void allocateTexture(GLenum format, GLenum storage) { + glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL); + } + + inline mat4& getTexTransform() { + return texTransform; } /** @@ -82,23 +227,29 @@ struct Layer { Rect texCoords; /** - * Name of the FBO used to render the layer. If the name is 0 - * this layer is not backed by an FBO, but a simple texture. + * Dirty region indicating what parts of the layer + * have been drawn. */ - GLuint fbo; - + Region region; /** - * Opacity of the layer. + * If the region is a rectangle, coordinates of the + * region are stored here. */ - int alpha; + Rect regionRect; + /** - * Blending mode of the layer. + * If the layer can be rendered as a mesh, this is non-null. */ - SkXfermode::Mode mode; + TextureVertex* mesh; + uint16_t* meshIndices; + GLsizei meshElementCount; + +private: /** - * Indicates whether this layer should be blended. + * Name of the FBO used to render the layer. If the name is 0 + * this layer is not backed by an FBO, but a simple texture. */ - bool blend; + GLuint fbo; /** * Indicates whether this layer has been used already. @@ -106,28 +257,25 @@ struct Layer { bool empty; /** - * Name of the texture used to render the layer. - */ - GLuint texture; - /** - * Width of the layer texture. + * The texture backing this layer. */ - uint32_t width; + Texture texture; + /** - * Height of the layer texture. + * If set to true (by default), the layer can be reused. */ - uint32_t height; + bool cacheable; /** - * Dirty region indicating what parts of the layer - * have been drawn. + * When set to true, this layer must be treated as a texture + * layer. */ - Region region; + bool textureLayer; + /** - * If the region is a rectangle, coordinates of the - * region are stored here. + * Indicates the render target. */ - Rect regionRect; + GLenum renderTarget; /** * Color filter used to draw this layer. Optional. @@ -135,32 +283,21 @@ struct Layer { SkiaColorFilter* colorFilter; /** - * If the layer can be rendered as a mesh, this is non-null. - */ - TextureVertex* mesh; - uint16_t* meshIndices; - GLsizei meshElementCount; - - /** - * If set to true (by default), the layer can be reused. + * Opacity of the layer. */ - bool isCacheable; - + int alpha; /** - * When set to true, this layer must be treated as a texture - * layer. + * Blending mode of the layer. */ - bool isTextureLayer; + SkXfermode::Mode mode; /** * Optional texture coordinates transform. */ mat4 texTransform; - /** - * Indicates the render target. - */ - GLenum renderTarget; + bool firstFilter; + bool firstWrap; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index b2d795f..1a15e87 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -68,8 +68,8 @@ void LayerCache::setMaxSize(uint32_t maxSize) { void LayerCache::deleteLayer(Layer* layer) { if (layer) { - mSize -= layer->width * layer->height * 4; - glDeleteTextures(1, &layer->texture); + mSize -= layer->getWidth() * layer->getHeight() * 4; + layer->deleteTexture(); delete layer; } } @@ -93,29 +93,23 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { mCache.removeAt(index); layer = entry.mLayer; - mSize -= layer->width * layer->height * 4; + mSize -= layer->getWidth() * layer->getHeight() * 4; - LAYER_LOGD("Reusing layer %dx%d", layer->width, layer->height); + LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight()); } else { LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight); layer = new Layer(entry.mWidth, entry.mHeight); - layer->blend = true; - layer->empty = true; - layer->fbo = 0; - layer->colorFilter = NULL; - - glGenTextures(1, &layer->texture); - glBindTexture(GL_TEXTURE_2D, layer->texture); - + layer->setBlend(true); + layer->setEmpty(true); + layer->setFbo(0); + + layer->generateTexture(); + layer->bindTexture(); + layer->setFilter(GL_NEAREST, GL_NEAREST); + layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); 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); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - #if DEBUG_LAYERS size_t size = mCache.size(); for (size_t i = 0; i < size; i++) { @@ -133,30 +127,30 @@ bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t heigh // size already in the cache, and reuse it instead of creating a new one LayerEntry entry(width, height); - if (entry.mWidth <= layer->width && entry.mHeight <= layer->height) { + if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) { return true; } - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, layer->texture); + uint32_t oldWidth = layer->getWidth(); + uint32_t oldHeight = layer->getHeight(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry.mWidth, entry.mHeight, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glActiveTexture(GL_TEXTURE0); + layer->bindTexture(); + layer->setSize(entry.mWidth, entry.mHeight); + layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); if (glGetError() != GL_NO_ERROR) { + layer->setSize(oldWidth, oldHeight); return false; } - layer->width = entry.mWidth; - layer->height = entry.mHeight; - return true; } bool LayerCache::put(Layer* layer) { - if (!layer->isCacheable) return false; + if (!layer->isCacheable()) return false; - const uint32_t size = layer->width * layer->height * 4; + const uint32_t size = layer->getWidth() * layer->getHeight() * 4; // Don't even try to cache a layer that's bigger than the cache if (size < mMaxSize) { // TODO: Use an LRU diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index d2d5f39..81b8bf3 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -119,7 +119,7 @@ private: } LayerEntry(Layer* layer): - mLayer(layer), mWidth(layer->width), mHeight(layer->height) { + mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) { } bool operator<(const LayerEntry& rhs) const { diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index e034a86..1fa343b 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -32,9 +32,9 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { - LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo); + LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo()); - glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo()); const float width = mLayer->layer.getWidth(); const float height = mLayer->layer.getHeight(); @@ -62,14 +62,14 @@ void LayerRenderer::finish() { generateMesh(); - LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->fbo); + LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->getFbo()); // No need to unbind our FBO, this will be taken care of by the caller // who will invoke OpenGLRenderer::resume() } GLint LayerRenderer::getTargetFbo() { - return mLayer->fbo; + return mLayer->getFbo(); } /////////////////////////////////////////////////////////////////////////////// @@ -128,8 +128,8 @@ void LayerRenderer::generateMesh() { } mLayer->meshElementCount = elementCount; - const float texX = 1.0f / float(mLayer->width); - const float texY = 1.0f / float(mLayer->height); + const float texX = 1.0f / float(mLayer->getWidth()); + const float texY = 1.0f / float(mLayer->getHeight()); const float height = mLayer->layer.getHeight(); TextureVertex* mesh = mLayer->mesh; @@ -182,40 +182,41 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque return NULL; } - layer->fbo = fbo; + layer->setFbo(fbo); layer->layer.set(0.0f, 0.0f, width, height); - layer->texCoords.set(0.0f, height / float(layer->height), - width / float(layer->width), 0.0f); - layer->alpha = 255; - layer->mode = SkXfermode::kSrcOver_Mode; - layer->blend = !isOpaque; - layer->colorFilter = NULL; + layer->texCoords.set(0.0f, height / float(layer->getHeight()), + width / float(layer->getWidth()), 0.0f); + layer->setAlpha(255, SkXfermode::kSrcOver_Mode); + layer->setBlend(!isOpaque); + layer->setColorFilter(NULL); layer->region.clear(); GLuint previousFbo; glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); - glBindTexture(GL_TEXTURE_2D, layer->texture); + glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo()); + layer->bindTexture(); // Initialize the texture if needed - if (layer->empty) { - layer->empty = false; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (layer->isEmpty()) { + layer->setEmpty(false); + layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); if (glGetError() != GL_NO_ERROR) { LOGD("Could not allocate texture"); + glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - glDeleteTextures(1, &layer->texture); Caches::getInstance().fboCache.put(fbo); + + layer->deleteTexture(); delete layer; + return NULL; } } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - layer->texture, 0); + layer->getTexture(), 0); glDisable(GL_SCISSOR_TEST); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -229,14 +230,14 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { if (layer) { - LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height); + LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height); if (Caches::getInstance().layerCache.resize(layer, width, height)) { layer->layer.set(0.0f, 0.0f, width, height); - layer->texCoords.set(0.0f, height / float(layer->height), - width / float(layer->width), 0.0f); + layer->texCoords.set(0.0f, height / float(layer->getHeight()), + width / float(layer->getWidth()), 0.0f); } else { - if (layer->texture) glDeleteTextures(1, &layer->texture); + layer->deleteTexture(); delete layer; return false; } @@ -245,37 +246,23 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { return true; } -static void setTextureParameters(Layer* layer) { - glBindTexture(layer->renderTarget, layer->texture); - - glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} - Layer* LayerRenderer::createTextureLayer(bool isOpaque) { LAYER_RENDERER_LOGD("Creating new texture layer"); Layer* layer = new Layer(0, 0); - layer->isCacheable = false; - layer->isTextureLayer = true; - layer->blend = !isOpaque; - layer->empty = true; - layer->fbo = 0; - layer->colorFilter = NULL; - layer->fbo = 0; + layer->setCacheable(false); + layer->setTextureLayer(true); + layer->setBlend(!isOpaque); + layer->setEmpty(true); + layer->setFbo(0); + layer->setAlpha(255, SkXfermode::kSrcOver_Mode); layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f); layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f); - layer->alpha = 255; - layer->mode = SkXfermode::kSrcOver_Mode; - layer->colorFilter = NULL; layer->region.clear(); - layer->renderTarget = GL_NONE; // see ::updateTextureLayer() + layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer() glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &layer->texture); + layer->generateTexture(); return layer; } @@ -283,31 +270,32 @@ Layer* LayerRenderer::createTextureLayer(bool isOpaque) { void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, GLenum renderTarget, float* transform) { if (layer) { - layer->blend = !isOpaque; - layer->width = width; - layer->height = height; + layer->setBlend(!isOpaque); + layer->setSize(width, height); layer->layer.set(0.0f, 0.0f, width, height); layer->region.set(width, height); layer->regionRect.set(0.0f, 0.0f, width, height); - layer->texTransform.load(transform); + layer->getTexTransform().load(transform); - if (renderTarget != layer->renderTarget) { - layer->renderTarget = renderTarget; - setTextureParameters(layer); + if (renderTarget != layer->getRenderTarget()) { + layer->setRenderTarget(renderTarget); + layer->bindTexture(); + layer->setFilter(GL_NEAREST, GL_NEAREST, false, true); + layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false, true); } } } void LayerRenderer::destroyLayer(Layer* layer) { if (layer) { - LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo); + LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->getFbo()); - if (layer->fbo) { - Caches::getInstance().fboCache.put(layer->fbo); + if (layer->getFbo()) { + Caches::getInstance().fboCache.put(layer->getFbo()); } if (!Caches::getInstance().layerCache.put(layer)) { - if (layer->texture) glDeleteTextures(1, &layer->texture); + layer->deleteTexture(); delete layer; } else { layer->region.clear(); @@ -317,7 +305,7 @@ void LayerRenderer::destroyLayer(Layer* layer) { void LayerRenderer::destroyLayerDeferred(Layer* layer) { if (layer) { - LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo); + LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo()); Caches::getInstance().deleteLayerDeferred(layer); } @@ -325,7 +313,7 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) { bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); - if (layer && layer->isTextureLayer && bitmap->width() <= caches.maxTextureSize && + if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { GLuint fbo = caches.fboCache.get(); @@ -365,12 +353,11 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { break; } - float alpha = layer->alpha; - SkXfermode::Mode mode = layer->mode; + float alpha = layer->getAlpha(); + SkXfermode::Mode mode = layer->getMode(); - layer->mode = SkXfermode::kSrc_Mode; - layer->alpha = 255; - layer->fbo = fbo; + layer->setAlpha(255, SkXfermode::kSrc_Mode); + layer->setFbo(fbo); glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -381,8 +368,8 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); @@ -399,7 +386,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { LayerRenderer renderer(layer); renderer.setViewport(bitmap->width(), bitmap->height()); renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f, - bitmap->width(), bitmap->height(), !layer->blend); + bitmap->width(), bitmap->height(), !layer->isBlend()); if ((error = glGetError()) != GL_NO_ERROR) goto error; { @@ -424,9 +411,8 @@ error: #endif glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - layer->mode = mode; - layer->alpha = alpha; - layer->fbo = 0; + layer->setAlpha(alpha, mode); + layer->setFbo(0); glDeleteTextures(1, &texture); caches.fboCache.put(fbo); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 1c06a0b..a349121 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -449,12 +449,11 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, return false; } - layer->mode = mode; - layer->alpha = alpha; + layer->setAlpha(alpha, mode); layer->layer.set(bounds); - layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height), - bounds.getWidth() / float(layer->width), 0.0f); - layer->colorFilter = mColorFilter; + layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()), + bounds.getWidth() / float(layer->getWidth()), 0.0f); + layer->setColorFilter(mColorFilter); // Save the layer in the snapshot snapshot->flags |= Snapshot::kFlagIsLayer; @@ -464,12 +463,13 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, return createFboLayer(layer, bounds, snapshot, previousFbo); } else { // Copy the framebuffer into the layer - glBindTexture(GL_TEXTURE_2D, layer->texture); + layer->bindTexture(); if (!bounds.isEmpty()) { - if (layer->empty) { - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, - snapshot->height - bounds.bottom, layer->width, layer->height, 0); - layer->empty = false; + if (layer->isEmpty()) { + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + bounds.left, snapshot->height - bounds.bottom, + layer->getWidth(), layer->getHeight(), 0); + layer->setEmpty(false); } else { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); @@ -485,7 +485,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot, GLuint previousFbo) { - layer->fbo = mCaches.fboCache.get(); + layer->setFbo(mCaches.fboCache.get()); #if RENDER_LAYERS_AS_REGIONS snapshot->region = &snapshot->layer->region; @@ -507,7 +507,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna clip.translate(-bounds.left, -bounds.top); snapshot->flags |= Snapshot::kFlagIsFboLayer; - snapshot->fbo = layer->fbo; + snapshot->fbo = layer->getFbo(); snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); @@ -516,18 +516,17 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna snapshot->orthoMatrix.load(mOrthoMatrix); // Bind texture to FBO - glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); - glBindTexture(GL_TEXTURE_2D, layer->texture); + glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo()); + layer->bindTexture(); // Initialize the texture if needed - if (layer->empty) { - layer->empty = false; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (layer->isEmpty()) { + layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); + layer->setEmpty(false); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - layer->texture, 0); + layer->getTexture(), 0); #if DEBUG_LAYERS_AS_REGIONS GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -535,8 +534,8 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna LOGE("Framebuffer incomplete (GL error code 0x%x)", status); glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - glDeleteTextures(1, &layer->texture); - mCaches.fboCache.put(layer->fbo); + layer->deleteTexture(); + mCaches.fboCache.put(layer->getFbo()); delete layer; @@ -578,11 +577,11 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { Layer* layer = current->layer; const Rect& rect = layer->layer; - if (!fboLayer && layer->alpha < 255) { + if (!fboLayer && layer->getAlpha() < 255) { drawColorRect(rect.left, rect.top, rect.right, rect.bottom, - layer->alpha << 24, SkXfermode::kDstIn_Mode, true); + layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true); // Required below, composeLayerRect() will divide by 255 - layer->alpha = 255; + layer->setAlpha(255); } mCaches.unbindMeshBuffer(); @@ -593,18 +592,16 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { // drawing only the dirty region if (fboLayer) { dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform); - if (layer->colorFilter) { - setupColorFilter(layer->colorFilter); + if (layer->getColorFilter()) { + setupColorFilter(layer->getColorFilter()); } composeLayerRegion(layer, rect); - if (layer->colorFilter) { + if (layer->getColorFilter()) { resetColorFilter(); } - } else { - if (!rect.isEmpty()) { - dirtyLayer(rect.left, rect.top, rect.right, rect.bottom); - composeLayerRect(layer, rect, true); - } + } else if (!rect.isEmpty()) { + dirtyLayer(rect.left, rect.top, rect.right, rect.bottom); + composeLayerRect(layer, rect, true); } if (fboLayer) { @@ -622,16 +619,16 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { // Failing to add the layer to the cache should happen only if the layer is too large if (!mCaches.layerCache.put(layer)) { LAYER_LOGD("Deleting layer"); - glDeleteTextures(1, &layer->texture); + layer->deleteTexture(); delete layer; } } void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { - float alpha = layer->alpha / 255.0f; + float alpha = layer->getAlpha() / 255.0f; setupDraw(); - if (layer->renderTarget == GL_TEXTURE_2D) { + if (layer->getRenderTarget() == GL_TEXTURE_2D) { setupDrawWithTexture(); } else { setupDrawWithExternalTexture(); @@ -639,17 +636,28 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { setupDrawTextureTransform(); setupDrawColor(alpha, alpha, alpha, alpha); setupDrawColorFilter(); - setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode); + setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode()); setupDrawProgram(); - setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); - if (layer->renderTarget == GL_TEXTURE_2D) { - setupDrawTexture(layer->texture); + if (layer->getRenderTarget() == GL_TEXTURE_2D) { + setupDrawTexture(layer->getTexture()); + } else { + setupDrawExternalTexture(layer->getTexture()); + } + if (mSnapshot->transform->isPureTranslate() && + layer->getWidth() == (uint32_t) rect.getWidth() && + layer->getHeight() == (uint32_t) rect.getHeight()) { + const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f); + const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f); + + layer->setFilter(GL_NEAREST, GL_NEAREST); + setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true); } else { - setupDrawExternalTexture(layer->texture); + layer->setFilter(GL_LINEAR, GL_LINEAR); + setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom); } - setupDrawTextureTransformUniforms(layer->texTransform); + setupDrawTextureTransformUniforms(layer->getTexTransform()); setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); @@ -658,14 +666,34 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { } void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { - if (!layer->isTextureLayer) { + if (!layer->isTextureLayer()) { const Rect& texCoords = layer->texCoords; resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom); - drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture, - layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0], - &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap); + float x = rect.left; + float y = rect.top; + bool simpleTransform = mSnapshot->transform->isPureTranslate() && + layer->getWidth() == (uint32_t) rect.getWidth() && + layer->getHeight() == (uint32_t) rect.getHeight(); + + if (simpleTransform) { + // When we're swapping, the layer is already in screen coordinates + if (!swap) { + x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f); + y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f); + } + + layer->setFilter(GL_NEAREST, GL_NEAREST, true); + } else { + layer->setFilter(GL_LINEAR, GL_LINEAR, true); + } + + drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(), + layer->getTexture(), layer->getAlpha() / 255.0f, + layer->getMode(), layer->isBlend(), + &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], + GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform); resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); } else { @@ -690,9 +718,9 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { size_t count; const android::Rect* rects = layer->region.getArray(&count); - const float alpha = layer->alpha / 255.0f; - const float texX = 1.0f / float(layer->width); - const float texY = 1.0f / float(layer->height); + const float alpha = layer->getAlpha() / 255.0f; + const float texX = 1.0f / float(layer->getWidth()); + const float texY = 1.0f / float(layer->getHeight()); const float height = rect.getHeight(); TextureVertex* mesh = mCaches.getRegionMesh(); @@ -702,13 +730,22 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { setupDrawWithTexture(); setupDrawColor(alpha, alpha, alpha, alpha); setupDrawColorFilter(); - setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false); + setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false); setupDrawProgram(); setupDrawDirtyRegionsDisabled(); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); - setupDrawTexture(layer->texture); - setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom); + setupDrawTexture(layer->getTexture()); + if (mSnapshot->transform->isPureTranslate()) { + const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f); + const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f); + + layer->setFilter(GL_NEAREST, GL_NEAREST); + setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true); + } else { + layer->setFilter(GL_LINEAR, GL_LINEAR); + setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom); + } setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]); for (size_t i = 0; i < count; i++) { @@ -2154,8 +2191,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); - layer->alpha = alpha; - layer->mode = mode; + layer->setAlpha(alpha, mode); #if RENDER_LAYERS_AS_REGIONS if (!layer->region.isEmpty()) { @@ -2169,13 +2205,23 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) { setupDrawWithTexture(); setupDrawColor(a, a, a, a); setupDrawColorFilter(); - setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false); + setupDrawBlending(layer->isBlend() || a < 1.0f, layer->getMode(), false); setupDrawProgram(); - setupDrawModelViewTranslate(x, y, - x + layer->layer.getWidth(), y + layer->layer.getHeight()); setupDrawPureColorUniforms(); setupDrawColorFilterUniforms(); - setupDrawTexture(layer->texture); + setupDrawTexture(layer->getTexture()); + if (mSnapshot->transform->isPureTranslate()) { + x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f); + y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f); + + layer->setFilter(GL_NEAREST, GL_NEAREST); + setupDrawModelViewTranslate(x, y, + x + layer->layer.getWidth(), y + layer->layer.getHeight(), true); + } else { + layer->setFilter(GL_LINEAR, GL_LINEAR); + setupDrawModelViewTranslate(x, y, + x + layer->layer.getWidth(), y + layer->layer.getHeight()); + } setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]); glDrawElements(GL_TRIANGLES, layer->meshElementCount, diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index 4922bb3..c6ae326 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -29,8 +29,22 @@ struct Texture { Texture() { cleanup = false; bitmapSize = 0; + wrapS = GL_CLAMP_TO_EDGE; wrapT = GL_CLAMP_TO_EDGE; + + minFilter = GL_NEAREST; + magFilter = GL_NEAREST; + } + + void setWrap(GLenum wrapS, GLenum wrapT) { + this->wrapS = wrapS; + this->wrapT = wrapT; + } + + void setFilter(GLenum min, GLenum mag) { + minFilter = min; + magFilter = mag; } /** @@ -67,6 +81,12 @@ struct Texture { */ GLenum wrapS; GLenum wrapT; + + /** + * Last filters set on this texture. Defaults to GL_NEAREST. + */ + GLenum minFilter; + GLenum magFilter; }; // struct Texture class AutoTexture { diff --git a/media/jni/audioeffect/Android.mk b/media/jni/audioeffect/Android.mk index 4c5cf71..3e493b1 100644 --- a/media/jni/audioeffect/Android.mk +++ b/media/jni/audioeffect/Android.mk @@ -12,6 +12,9 @@ LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libmedia +LOCAL_C_INCLUDES := \ + system/media/audio_effects/include + LOCAL_MODULE:= libaudioeffect_jni include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk index 99cfdfa..ab13605 100644 --- a/media/libeffects/lvm/wrapper/Android.mk +++ b/media/libeffects/lvm/wrapper/Android.mk @@ -30,7 +30,8 @@ endif LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/Bundle \ $(LOCAL_PATH)/../lib/Common/lib/ \ - $(LOCAL_PATH)/../lib/Bundle/lib/ + $(LOCAL_PATH)/../lib/Bundle/lib/ \ + system/media/audio_effects/include include $(BUILD_SHARED_LIBRARY) @@ -64,6 +65,6 @@ LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/Reverb \ $(LOCAL_PATH)/../lib/Common/lib/ \ $(LOCAL_PATH)/../lib/Reverb/lib/ \ - + system/media/audio_effects/include include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h index 2b51029..5634ca1 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h @@ -17,9 +17,9 @@ #ifndef ANDROID_EFFECTBUNDLE_H_ #define ANDROID_EFFECTBUNDLE_H_ -#include <media/EffectEqualizerApi.h> -#include <media/EffectBassBoostApi.h> -#include <media/EffectVirtualizerApi.h> +#include <audio_effects/effect_bassboost.h> +#include <audio_effects/effect_equalizer.h> +#include <audio_effects/effect_virtualizer.h> #include <LVM.h> #include <limits.h> diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h index 093992b..7c15b18 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h @@ -17,8 +17,8 @@ #ifndef ANDROID_EFFECTREVERB_H_ #define ANDROID_EFFECTREVERB_H_ -#include <media/EffectEnvironmentalReverbApi.h> -#include <media/EffectPresetReverbApi.h> +#include <audio_effects/effect_environmentalreverb.h> +#include <audio_effects/effect_presetreverb.h> #if __cplusplus extern "C" { diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_ index 98d477b..249ebf4 100644 --- a/media/libeffects/testlibs/Android.mk_ +++ b/media/libeffects/testlibs/Android.mk_ @@ -23,6 +23,7 @@ LOCAL_SHARED_LIBRARIES += libdl endif LOCAL_C_INCLUDES := \ + system/media/audio_effects/include \ $(call include-path-for, graphics corecg) LOCAL_MODULE_TAGS := optional @@ -58,7 +59,8 @@ LOCAL_SHARED_LIBRARIES += libdl endif LOCAL_C_INCLUDES := \ - $(call include-path-for, graphics corecg) + $(call include-path-for, graphics corecg) \ + system/media/audio_effects/include LOCAL_MODULE_TAGS := optional diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp index 43dfa82..c2ffce5 100644 --- a/media/libeffects/testlibs/EffectEqualizer.cpp +++ b/media/libeffects/testlibs/EffectEqualizer.cpp @@ -26,7 +26,8 @@ #include "AudioEqualizer.h" #include "AudioBiquadFilter.h" #include "AudioFormatAdapter.h" -#include <media/EffectEqualizerApi.h> +#include <audio_effects/effect_equalizer.h> + // effect_handle_t interface implementation for equalizer effect extern "C" const struct effect_interface_s gEqualizerInterface; diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h index a239814..8e2cc31 100644 --- a/media/libeffects/testlibs/EffectReverb.h +++ b/media/libeffects/testlibs/EffectReverb.h @@ -17,8 +17,8 @@ #ifndef ANDROID_EFFECTREVERB_H_ #define ANDROID_EFFECTREVERB_H_ -#include <media/EffectEnvironmentalReverbApi.h> -#include <media/EffectPresetReverbApi.h> +#include <audio_effects/effect_environmentalreverb.h> +#include <audio_effects/effect_presetreverb.h> /*------------------------------------ diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk index 3a0f438..dff585f 100644 --- a/media/libeffects/visualizer/Android.mk +++ b/media/libeffects/visualizer/Android.mk @@ -23,8 +23,8 @@ LOCAL_SHARED_LIBRARIES += libdl endif LOCAL_C_INCLUDES := \ - $(call include-path-for, graphics corecg) - + $(call include-path-for, graphics corecg) \ + system/media/audio_effects/include include $(BUILD_SHARED_LIBRARY) diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp index 80d1f69..aeebd4d 100644 --- a/media/libeffects/visualizer/EffectVisualizer.cpp +++ b/media/libeffects/visualizer/EffectVisualizer.cpp @@ -21,7 +21,7 @@ #include <stdlib.h> #include <string.h> #include <new> -#include <media/EffectVisualizerApi.h> +#include <audio_effects/effect_visualizer.h> extern "C" { @@ -375,7 +375,7 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, p->status = 0; *replySize = sizeof(effect_param_t) + sizeof(uint32_t); if (p->psize != sizeof(uint32_t) || - *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) { + *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) { p->status = -EINVAL; break; } @@ -394,7 +394,7 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, effect_param_t *p = (effect_param_t *)pCmdData; if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t) || - *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) { + *(uint32_t *)p->data != VISUALIZER_PARAM_CAPTURE_SIZE) { *(int32_t *)pReplyData = -EINVAL; break;; } @@ -407,9 +407,9 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, break; - case VISU_CMD_CAPTURE: + case VISUALIZER_CMD_CAPTURE: if (pReplyData == NULL || *replySize != pContext->mCaptureSize) { - LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d", + LOGV("VISUALIZER_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d", *replySize, pContext->mCaptureSize); return -EINVAL; } diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 121e38a4..f7c54fa 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -68,6 +68,7 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/base/include/media/stagefright/openmax \ external/icu4c/common \ - external/expat/lib + external/expat/lib \ + system/media/audio_effects/include include $(BUILD_SHARED_LIBRARY) diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp index 366707c..bf40481 100644 --- a/media/libmedia/Visualizer.cpp +++ b/media/libmedia/Visualizer.cpp @@ -143,7 +143,7 @@ status_t Visualizer::setCaptureSize(uint32_t size) p->psize = sizeof(uint32_t); p->vsize = sizeof(uint32_t); - *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE; + *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; *((int32_t *)p->data + 1)= size; status_t status = setParameter(p); @@ -171,7 +171,7 @@ status_t Visualizer::getWaveForm(uint8_t *waveform) status_t status = NO_ERROR; if (mEnabled) { uint32_t replySize = mCaptureSize; - status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform); + status = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform); LOGV("getWaveForm() command returned %d", status); if (replySize == 0) { status = NOT_ENOUGH_DATA; @@ -276,7 +276,7 @@ uint32_t Visualizer::initCaptureSize() p->psize = sizeof(uint32_t); p->vsize = sizeof(uint32_t); - *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE; + *(int32_t *)p->data = VISUALIZER_PARAM_CAPTURE_SIZE; status_t status = getParameter(p); if (status == NO_ERROR) { diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 408436a..6190c9b 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -318,7 +318,11 @@ public class RecentsPanelView extends RelativeLayout } private Drawable getFullResIcon(Resources resources, int iconId) { - return resources.getDrawableForDensity(iconId, mIconDpi); + try { + return resources.getDrawableForDensity(iconId, mIconDpi); + } catch (Resources.NotFoundException e) { + return getFullResDefaultActivityIcon(); + } } private Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) { diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 2222e8b..75d24a1 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -10,6 +10,9 @@ LOCAL_SRC_FILES:= \ AudioResamplerCubic.cpp.arm \ AudioPolicyService.cpp +LOCAL_C_INCLUDES := \ + system/media/audio_effects/include + LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index f716e63..daf94f2 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -50,7 +50,7 @@ #include "AudioFlinger.h" #include <media/EffectsFactoryApi.h> -#include <media/EffectVisualizerApi.h> +#include <audio_effects/effect_visualizer.h> // ---------------------------------------------------------------------------- diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index 9695344..1f24b58 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -76,8 +76,6 @@ public class GsmDataConnection extends DataConnection { + "' APN: '" + mApn.apn + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port); - setHttpProxy (mApn.proxy, mApn.port); - createTime = -1; lastFailTime = -1; lastFailCause = FailCause.NONE; @@ -152,38 +150,6 @@ public class GsmDataConnection extends DataConnection { Log.d(LOG_TAG, "[" + getName() + "] " + s); } - private void setHttpProxy(String httpProxy, String httpPort) { - - if (DBG) log("set http proxy for" - + "' APN: '" + mActiveApnType - + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port); - if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) { - if (httpProxy == null || httpProxy.length() == 0) { - phone.setSystemProperty("net.gprs.http-proxy", null); - return; - } - - if (httpPort == null || httpPort.length() == 0) { - httpPort = "8080"; // Default to port 8080 - } - - phone.setSystemProperty("net.gprs.http-proxy", - "http://" + httpProxy + ":" + httpPort + "/"); - } else { - if (httpProxy == null || httpProxy.length() == 0) { - phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null); - return; - } - - if (httpPort == null || httpPort.length() == 0) { - httpPort = "8080"; // Default to port 8080 - } - - phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, - "http://" + httpProxy + ":" + httpPort + "/"); - } - } - private boolean isIpAddress(String address) { if (address == null) return false; diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java index e1ca756..949589f 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java @@ -39,7 +39,10 @@ import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; - +import java.io.BufferedOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -57,6 +60,25 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa mTextureView = new TextureView(this); mTextureView.setSurfaceTextureListener(this); + mTextureView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Bitmap b = mTextureView.getBitmap(800, 800); + BufferedOutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png")); + b.compress(Bitmap.CompressFormat.PNG, 100, out); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (out != null) try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }); setContentView(mTextureView, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, @@ -77,7 +99,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - ((View) mTextureView.getParent()).invalidate(); + mTextureView.invalidate(); } }); animator.start(); diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java index c857ded..634e7e3 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java @@ -16,7 +16,6 @@ package com.android.test.hwui; -import android.animation.AnimatorSet; import android.app.Activity; import android.graphics.SurfaceTexture; import android.hardware.Camera; @@ -34,7 +33,6 @@ public class TextureViewActivity extends Activity implements TextureView.Surface private Camera mCamera; private TextureView mTextureView; private FrameLayout mContent; - private AnimatorSet mAnimatorSet; @Override protected void onCreate(Bundle savedInstanceState) { @@ -53,7 +51,6 @@ public class TextureViewActivity extends Activity implements TextureView.Surface @Override public void onClick(View v) { if (mAdded) { - if (mAnimatorSet != null) mAnimatorSet.cancel(); mContent.removeView(mTextureView); } else { mContent.addView(mTextureView); @@ -62,7 +59,9 @@ public class TextureViewActivity extends Activity implements TextureView.Surface } }); - mContent.addView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER)); + mContent.addView(mTextureView, new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, + Gravity.CENTER)); mContent.addView(button, new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); @@ -72,6 +71,9 @@ public class TextureViewActivity extends Activity implements TextureView.Surface @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mCamera = Camera.open(); + Camera.Size previewSize = mCamera.getParameters().getPreviewSize(); + mTextureView.setLayoutParams(new FrameLayout.LayoutParams( + previewSize.width, previewSize.height, Gravity.CENTER)); try { mCamera.setPreviewTexture(surface); @@ -82,20 +84,6 @@ public class TextureViewActivity extends Activity implements TextureView.Surface mCamera.startPreview(); mTextureView.setCameraDistance(5000); - -// ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); -// rotationY.setRepeatMode(ObjectAnimator.REVERSE); -// rotationY.setRepeatCount(ObjectAnimator.INFINITE); -// rotationY.setDuration(4000); - -// ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f); -// alpha.setRepeatMode(ObjectAnimator.REVERSE); -// alpha.setRepeatCount(ObjectAnimator.INFINITE); -// alpha.setDuration(4000); - -// mAnimatorSet = new AnimatorSet(); -// mAnimatorSet.play(alpha).with(rotationY); -// mAnimatorSet.start(); } @Override |