diff options
65 files changed, 3617 insertions, 2385 deletions
diff --git a/GenerationCache.h b/GenerationCache.h deleted file mode 100644 index 42e6d9bb8cda..000000000000 --- a/GenerationCache.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_GENERATION_CACHE_H -#define ANDROID_HWUI_GENERATION_CACHE_H - -#include <utils/KeyedVector.h> -#include <utils/RefBase.h> - -namespace android { -namespace uirenderer { - -template<typename EntryKey, typename EntryValue> -class OnEntryRemoved { -public: - virtual ~OnEntryRemoved() { }; - virtual void operator()(EntryKey& key, EntryValue& value) = 0; -}; // class OnEntryRemoved - -template<typename EntryKey, typename EntryValue> -struct Entry: public LightRefBase<Entry<EntryKey, EntryValue> > { - Entry() { } - Entry(const Entry<EntryKey, EntryValue>& e): - key(e.key), value(e.value), parent(e.parent), child(e.child) { } - Entry(sp<Entry<EntryKey, EntryValue> > e): - key(e->key), value(e->value), parent(e->parent), child(e->child) { } - - EntryKey key; - EntryValue value; - - sp<Entry<EntryKey, EntryValue> > parent; - sp<Entry<EntryKey, EntryValue> > child; -}; // struct Entry - -template<typename K, typename V> -class GenerationCache { -public: - GenerationCache(uint32_t maxCapacity); - virtual ~GenerationCache(); - - enum Capacity { - kUnlimitedCapacity, - }; - - void setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener); - - void clear(); - - bool contains(K key) const; - V get(K key); - K getKeyAt(uint32_t index) const; - bool put(K key, V value); - V remove(K key); - V removeOldest(); - V getValueAt(uint32_t index) const; - - uint32_t size() const; - - void addToCache(sp<Entry<K, V> > entry, K key, V value); - void attachToCache(sp<Entry<K, V> > entry); - void detachFromCache(sp<Entry<K, V> > entry); - - V removeAt(ssize_t index); - - KeyedVector<K, sp<Entry<K, V> > > mCache; - uint32_t mMaxCapacity; - - OnEntryRemoved<K, V>* mListener; - - sp<Entry<K, V> > mOldest; - sp<Entry<K, V> > mYoungest; -}; // class GenerationCache - -template<typename K, typename V> -GenerationCache<K, V>::GenerationCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity), mListener(NULL) { -}; - -template<typename K, typename V> -GenerationCache<K, V>::~GenerationCache() { - clear(); -}; - -template<typename K, typename V> -uint32_t GenerationCache<K, V>::size() const { - return mCache.size(); -} - -template<typename K, typename V> -void GenerationCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) { - mListener = listener; -} - -template<typename K, typename V> -void GenerationCache<K, V>::clear() { - if (mListener) { - for (uint32_t i = 0; i < mCache.size(); i++) { - sp<Entry<K, V> > entry = mCache.valueAt(i); - if (mListener) { - (*mListener)(entry->key, entry->value); - } - } - } - mCache.clear(); - mYoungest.clear(); - mOldest.clear(); -} - -template<typename K, typename V> -bool GenerationCache<K, V>::contains(K key) const { - return mCache.indexOfKey(key) >= 0; -} - -template<typename K, typename V> -K GenerationCache<K, V>::getKeyAt(uint32_t index) const { - return mCache.keyAt(index); -} - -template<typename K, typename V> -V GenerationCache<K, V>::getValueAt(uint32_t index) const { - return mCache.valueAt(index)->value; -} - -template<typename K, typename V> -V GenerationCache<K, V>::get(K key) { - ssize_t index = mCache.indexOfKey(key); - if (index >= 0) { - sp<Entry<K, V> > entry = mCache.valueAt(index); - if (entry.get()) { - detachFromCache(entry); - attachToCache(entry); - return entry->value; - } - } - - return NULL; -} - -template<typename K, typename V> -bool GenerationCache<K, V>::put(K key, V value) { - if (mMaxCapacity != kUnlimitedCapacity && mCache.size() >= mMaxCapacity) { - removeOldest(); - } - - ssize_t index = mCache.indexOfKey(key); - if (index < 0) { - sp<Entry<K, V> > entry = new Entry<K, V>; - addToCache(entry, key, value); - return true; - } - - return false; -} - -template<typename K, typename V> -void GenerationCache<K, V>::addToCache(sp<Entry<K, V> > entry, K key, V value) { - entry->key = key; - entry->value = value; - mCache.add(key, entry); - attachToCache(entry); -} - -template<typename K, typename V> -V GenerationCache<K, V>::remove(K key) { - ssize_t index = mCache.indexOfKey(key); - if (index >= 0) { - return removeAt(index); - } - - return NULL; -} - -template<typename K, typename V> -V GenerationCache<K, V>::removeAt(ssize_t index) { - sp<Entry<K, V> > entry = mCache.valueAt(index); - if (mListener) { - (*mListener)(entry->key, entry->value); - } - mCache.removeItemsAt(index, 1); - detachFromCache(entry); - - return entry->value; -} - -template<typename K, typename V> -V GenerationCache<K, V>::removeOldest() { - if (mOldest.get()) { - ssize_t index = mCache.indexOfKey(mOldest->key); - if (index >= 0) { - return removeAt(index); - } - } - - return NULL; -} - -template<typename K, typename V> -void GenerationCache<K, V>::attachToCache(sp<Entry<K, V> > entry) { - if (!mYoungest.get()) { - mYoungest = mOldest = entry; - } else { - entry->parent = mYoungest; - mYoungest->child = entry; - mYoungest = entry; - } -} - -template<typename K, typename V> -void GenerationCache<K, V>::detachFromCache(sp<Entry<K, V> > entry) { - if (entry->parent.get()) { - entry->parent->child = entry->child; - } - - if (entry->child.get()) { - entry->child->parent = entry->parent; - } - - if (mOldest == entry) { - mOldest = entry->child; - } - - if (mYoungest == entry) { - mYoungest = entry->parent; - } - - entry->parent.clear(); - entry->child.clear(); -} - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_GENERATION_CACHE_H diff --git a/api/current.txt b/api/current.txt index 4b3918e6adba..a98ffae88899 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1490,9 +1490,11 @@ package android { field public static final int Theme_Holo_Light_Dialog_NoActionBar_MinWidth = 16973942; // 0x1030076 field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0 field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c + field public static final int Theme_Holo_Light_SplitActionBarWhenNarrow = 16974067; // 0x10300f3 field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d field public static final int Theme_Holo_Panel = 16973947; // 0x103007b + field public static final int Theme_Holo_SplitActionBarWhenNarrow = 16974066; // 0x10300f2 field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e field public static final int Theme_InputMethod = 16973908; // 0x1030054 @@ -21010,6 +21012,21 @@ package android.view { method public void setZOrderOnTop(boolean); } + public class TextureView extends android.view.View { + ctor public TextureView(android.content.Context); + ctor public TextureView(android.content.Context, android.util.AttributeSet); + ctor public TextureView(android.content.Context, android.util.AttributeSet, int); + method public final void draw(android.graphics.Canvas); + method public android.graphics.SurfaceTexture getSurfaceTexture(); + method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener(); + method protected final void onDraw(android.graphics.Canvas); + method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener); + } + + public static abstract interface TextureView.SurfaceTextureListener { + method public abstract void onSurfaceTextureAvailable(android.graphics.SurfaceTexture); + } + public class TouchDelegate { ctor public TouchDelegate(android.graphics.Rect, android.view.View); method public boolean onTouchEvent(android.view.MotionEvent); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f5849c24e59a..02b6619dfaf9 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2482,6 +2482,7 @@ public class Activity extends ContextThemeWrapper break; case Window.FEATURE_ACTION_BAR: + initActionBar(); mActionBar.dispatchMenuVisibilityChanged(false); break; } diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java index 9309b05c6fda..757a8c3db075 100644 --- a/core/java/android/text/BoringLayout.java +++ b/core/java/android/text/BoringLayout.java @@ -234,18 +234,17 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback * provided Metrics object (or a new one if the provided one was null) * if boring. */ - public static Metrics isBoring(CharSequence text, TextPaint paint, - Metrics metrics) { + public static Metrics isBoring(CharSequence text, TextPaint paint, Metrics metrics) { char[] temp = TextUtils.obtain(500); - int len = text.length(); + int length = text.length(); boolean boring = true; outer: - for (int i = 0; i < len; i += 500) { + for (int i = 0; i < length; i += 500) { int j = i + 500; - if (j > len) - j = len; + if (j > length) + j = length; TextUtils.getChars(text, i, j, temp, 0); @@ -265,7 +264,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback if (boring && text instanceof Spanned) { Spanned sp = (Spanned) text; - Object[] styles = sp.getSpans(0, text.length(), ParagraphStyle.class); + Object[] styles = sp.getSpans(0, length, ParagraphStyle.class); if (styles.length > 0) { boring = false; } @@ -278,7 +277,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback } TextLine line = TextLine.obtain(); - line.set(paint, text, 0, text.length(), Layout.DIR_LEFT_TO_RIGHT, + line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT, Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null); fm.width = (int) FloatMath.ceil(line.metrics(fm)); TextLine.recycle(line); @@ -289,52 +288,63 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback } } - @Override public int getHeight() { + @Override + public int getHeight() { return mBottom; } - @Override public int getLineCount() { + @Override + public int getLineCount() { return 1; } - @Override public int getLineTop(int line) { + @Override + public int getLineTop(int line) { if (line == 0) return 0; else return mBottom; } - @Override public int getLineDescent(int line) { + @Override + public int getLineDescent(int line) { return mDesc; } - @Override public int getLineStart(int line) { + @Override + public int getLineStart(int line) { if (line == 0) return 0; else return getText().length(); } - @Override public int getParagraphDirection(int line) { + @Override + public int getParagraphDirection(int line) { return DIR_LEFT_TO_RIGHT; } - @Override public boolean getLineContainsTab(int line) { + @Override + public boolean getLineContainsTab(int line) { return false; } - @Override public float getLineMax(int line) { + @Override + public float getLineMax(int line) { return mMax; } - @Override public final Directions getLineDirections(int line) { + @Override + public final Directions getLineDirections(int line) { return Layout.DIRS_ALL_LEFT_TO_RIGHT; } + @Override public int getTopPadding() { return mTopPadding; } + @Override public int getBottomPadding() { return mBottomPadding; } diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 1b7f2f310c9f..0f8097a948a6 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -815,6 +815,13 @@ class TextLine { int limit, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, FontMetricsInt fmi, boolean needWidth) { + // Case of an empty line, make sure we update fmi according to mPaint + if (start == measureLimit) { + TextPaint wp = mWorkPaint; + wp.set(mPaint); + return handleText(wp, 0, 0, 0, 0, runIsRtl, c, x, top, y, bottom, fmi, needWidth); + } + // Shaping needs to take into account context up to metric boundaries, // but rendering needs to take into account character style boundaries. // So we iterate through metric runs to get metric bounds, diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java new file mode 100644 index 000000000000..729c5064204e --- /dev/null +++ b/core/java/android/util/NtpTrustedTime.java @@ -0,0 +1,96 @@ +/* + * 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.util; + +import android.net.SntpClient; +import android.os.SystemClock; + +/** + * {@link TrustedTime} that connects with a remote NTP server as its remote + * trusted time source. + * + * @hide + */ +public class NtpTrustedTime implements TrustedTime { + private String mNtpServer; + private long mNtpTimeout; + + private boolean mHasCache; + private long mCachedNtpTime; + private long mCachedNtpElapsedRealtime; + private long mCachedNtpCertainty; + + public NtpTrustedTime() { + } + + public void setNtpServer(String server, long timeout) { + mNtpServer = server; + mNtpTimeout = timeout; + } + + /** {@inheritDoc} */ + public boolean forceRefresh() { + if (mNtpServer == null) { + throw new IllegalStateException("Missing NTP server"); + } + + final SntpClient client = new SntpClient(); + if (client.requestTime(mNtpServer, (int) mNtpTimeout)) { + mHasCache = true; + mCachedNtpTime = client.getNtpTime(); + mCachedNtpElapsedRealtime = client.getNtpTimeReference(); + mCachedNtpCertainty = client.getRoundTripTime() / 2; + return true; + } else { + return false; + } + } + + /** {@inheritDoc} */ + public boolean hasCache() { + return mHasCache; + } + + /** {@inheritDoc} */ + public long getCacheAge() { + if (mHasCache) { + return SystemClock.elapsedRealtime() - mCachedNtpElapsedRealtime; + } else { + return Long.MAX_VALUE; + } + } + + /** {@inheritDoc} */ + public long getCacheCertainty() { + if (mHasCache) { + return mCachedNtpCertainty; + } else { + return Long.MAX_VALUE; + } + } + + /** {@inheritDoc} */ + public long currentTimeMillis() { + if (!mHasCache) { + throw new IllegalStateException("Missing authoritative time source"); + } + + // current time is age after the last ntp cache; callers who + // want fresh values will hit makeAuthoritative() first. + return mCachedNtpTime + getCacheAge(); + } +} diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java new file mode 100644 index 000000000000..263d7821a085 --- /dev/null +++ b/core/java/android/util/TrustedTime.java @@ -0,0 +1,55 @@ +/* + * 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.util; + +/** + * Interface that provides trusted time information, possibly coming from an NTP + * server. Implementations may cache answers until {@link #forceRefresh()}. + * + * @hide + */ +public interface TrustedTime { + /** + * Force update with an external trusted time source, returning {@code true} + * when successful. + */ + public boolean forceRefresh(); + + /** + * Check if this instance has cached a response from a trusted time source. + */ + public boolean hasCache(); + + /** + * Return time since last trusted time source contact, or + * {@link Long#MAX_VALUE} if never contacted. + */ + public long getCacheAge(); + + /** + * Return certainty of cached trusted time in milliseconds, or + * {@link Long#MAX_VALUE} if never contacted. Smaller values are more + * precise. + */ + public long getCacheCertainty(); + + /** + * Return current time similar to {@link System#currentTimeMillis()}, + * possibly using a cached authoritative time source. + */ + public long currentTimeMillis(); +} diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b8c5c2acadc8..cdf8954f5b2f 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -160,8 +160,11 @@ class GLES20Canvas extends HardwareCanvas { // Hardware layers /////////////////////////////////////////////////////////////////////////// + static native int nCreateTextureLayer(int[] layerInfo); static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo); + static native void nUpdateTextureLayer(int layerId, int width, int height, + float[] textureTransform); static native void nDestroyLayer(int layerId); static native void nDestroyLayerDeferred(int layerId); @@ -272,7 +275,7 @@ class GLES20Canvas extends HardwareCanvas { } private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint); - + void interrupt() { nInterrupt(mRenderer); } diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java index 6000a4a53bff..bc191a6fae9b 100644 --- a/core/java/android/view/GLES20Layer.java +++ b/core/java/android/view/GLES20Layer.java @@ -14,39 +14,21 @@ * limitations under the License. */ -package android.view; -import android.graphics.Canvas; +package android.view; /** * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. */ -class GLES20Layer extends HardwareLayer { - private int mLayer; - - private int mLayerWidth; - private int mLayerHeight; - - private final GLES20Canvas mCanvas; +abstract class GLES20Layer extends HardwareLayer { + int mLayer; + Finalizer mFinalizer; - @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) - private final Finalizer mFinalizer; - - GLES20Layer(int width, int height, boolean isOpaque) { - super(width, height, isOpaque); - - int[] layerInfo = new int[2]; - mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo); - if (mLayer != 0) { - mLayerWidth = layerInfo[0]; - mLayerHeight = layerInfo[1]; + GLES20Layer() { + } - mCanvas = new GLES20Canvas(mLayer, !isOpaque); - mFinalizer = new Finalizer(mLayer); - } else { - mCanvas = null; - mFinalizer = null; - } + GLES20Layer(int width, int height, boolean opaque) { + super(width, height, opaque); } /** @@ -58,55 +40,14 @@ class GLES20Layer extends HardwareLayer { return mLayer; } - @Override - boolean isValid() { - return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0; - } - - @Override - void resize(int width, int height) { - if (!isValid() || width <= 0 || height <= 0) return; - - mWidth = width; - mHeight = height; - - if (width != mLayerWidth || height != mLayerHeight) { - int[] layerInfo = new int[2]; - - GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo); - - mLayerWidth = layerInfo[0]; - mLayerHeight = layerInfo[1]; - } - } - - @Override - HardwareCanvas getCanvas() { - return mCanvas; - } - - @Override - void end(Canvas currentCanvas) { - if (currentCanvas instanceof GLES20Canvas) { - ((GLES20Canvas) currentCanvas).resume(); - } - } - - @Override - HardwareCanvas start(Canvas currentCanvas) { - if (currentCanvas instanceof GLES20Canvas) { - ((GLES20Canvas) currentCanvas).interrupt(); - } - return getCanvas(); - } - + @Override void destroy() { - mFinalizer.destroy(); + if (mFinalizer != null) mFinalizer.destroy(); mLayer = 0; } - private static class Finalizer { + static class Finalizer { private int mLayerId; public Finalizer(int layerId) { diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java new file mode 100644 index 000000000000..7adac1ce3e3f --- /dev/null +++ b/core/java/android/view/GLES20RenderLayer.java @@ -0,0 +1,91 @@ +/* + * 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.view; + +import android.graphics.Canvas; + +/** + * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This + * implementation can be used a rendering target. It generates a + * {@link Canvas} that can be used to render into an FBO using OpenGL. + */ +class GLES20RenderLayer extends GLES20Layer { + + private int mLayerWidth; + private int mLayerHeight; + + private final GLES20Canvas mCanvas; + + GLES20RenderLayer(int width, int height, boolean isOpaque) { + super(width, height, isOpaque); + + int[] layerInfo = new int[2]; + mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo); + if (mLayer != 0) { + mLayerWidth = layerInfo[0]; + mLayerHeight = layerInfo[1]; + + mCanvas = new GLES20Canvas(mLayer, !isOpaque); + mFinalizer = new Finalizer(mLayer); + } else { + mCanvas = null; + mFinalizer = null; + } + } + + @Override + boolean isValid() { + return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0; + } + + @Override + void resize(int width, int height) { + if (!isValid() || width <= 0 || height <= 0) return; + + mWidth = width; + mHeight = height; + + if (width != mLayerWidth || height != mLayerHeight) { + int[] layerInfo = new int[2]; + + GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo); + + mLayerWidth = layerInfo[0]; + mLayerHeight = layerInfo[1]; + } + } + + @Override + HardwareCanvas getCanvas() { + return mCanvas; + } + + @Override + void end(Canvas currentCanvas) { + if (currentCanvas instanceof GLES20Canvas) { + ((GLES20Canvas) currentCanvas).resume(); + } + } + + @Override + HardwareCanvas start(Canvas currentCanvas) { + if (currentCanvas instanceof GLES20Canvas) { + ((GLES20Canvas) currentCanvas).interrupt(); + } + return getCanvas(); + } +} diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java new file mode 100644 index 000000000000..21fbdfcf6af3 --- /dev/null +++ b/core/java/android/view/GLES20TextureLayer.java @@ -0,0 +1,76 @@ +/* + * 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.view; + +import android.graphics.Canvas; +import android.graphics.SurfaceTexture; + +/** + * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This + * implementation can be used as a texture. Rendering into this + * layer is not controlled by a {@link HardwareCanvas}. + */ +class GLES20TextureLayer extends GLES20Layer { + private int mTexture; + private SurfaceTexture mSurface; + + GLES20TextureLayer() { + int[] layerInfo = new int[2]; + mLayer = GLES20Canvas.nCreateTextureLayer(layerInfo); + + if (mLayer != 0) { + mTexture = layerInfo[0]; + mFinalizer = new Finalizer(mLayer); + } else { + mFinalizer = null; + } + } + + @Override + boolean isValid() { + return mLayer != 0 && mTexture != 0; + } + + @Override + void resize(int width, int height) { + } + + @Override + HardwareCanvas getCanvas() { + return null; + } + + @Override + HardwareCanvas start(Canvas currentCanvas) { + return null; + } + + @Override + void end(Canvas currentCanvas) { + } + + SurfaceTexture getSurfaceTexture() { + if (mSurface == null) { + mSurface = new SurfaceTexture(mTexture); + } + return mSurface; + } + + void update(int width, int height, float[] textureTransform) { + GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, textureTransform); + } +} diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index d01b8ce37854..86dec3f16eff 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -26,12 +26,24 @@ import android.graphics.Canvas; * drawn several times. */ abstract class HardwareLayer { + /** + * Indicates an unknown dimension (width or height.) + */ + static final int DIMENSION_UNDEFINED = -1; + int mWidth; int mHeight; final boolean mOpaque; /** + * Creates a new hardware layer with undefined dimensions. + */ + HardwareLayer() { + this(DIMENSION_UNDEFINED, DIMENSION_UNDEFINED, false); + } + + /** * Creates a new hardware layer at least as large as the supplied * dimensions. * diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 66f37f29b0bd..5b2983d548a1 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -20,6 +20,7 @@ package android.view; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.SurfaceTexture; import android.os.*; import android.util.EventLog; import android.util.Log; @@ -166,6 +167,14 @@ public abstract class HardwareRenderer { abstract DisplayList createDisplayList(View v); /** + * Creates a new hardware layer. A hardware layer built by calling this + * method will be treated as a texture layer, instead of as a render target. + * + * @return A hardware layer + */ + abstract HardwareLayer createHardwareLayer(); + + /** * Creates a new hardware layer. * * @param width The minimum width of the layer @@ -175,6 +184,29 @@ public abstract class HardwareRenderer { * @return A hardware layer */ abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque); + + /** + * Creates a new {@link SurfaceTexture} that can be used to render into the + * specified hardware layer. + * + * + * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} + * + * @return A {@link SurfaceTexture} + */ + abstract SurfaceTexture createSuraceTexture(HardwareLayer layer); + + /** + * Updates the specified layer. + * + * @param layer The hardware layer to update + * @param width The layer's width + * @param height The layer's height + * @param textureTransform A 4x4 column-first transform matrix to apply to + * texture coordinates + */ + abstract void updateTextureLayer(HardwareLayer layer, int width, int height, + float[] textureTransform); /** * Initializes the hardware renderer for the specified surface and setup the @@ -856,10 +888,26 @@ public abstract class HardwareRenderer { DisplayList createDisplayList(View v) { return new GLES20DisplayList(v); } - + + @Override + HardwareLayer createHardwareLayer() { + return new GLES20TextureLayer(); + } + @Override HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { - return new GLES20Layer(width, height, isOpaque); + return new GLES20RenderLayer(width, height, isOpaque); + } + + @Override + SurfaceTexture createSuraceTexture(HardwareLayer layer) { + return ((GLES20TextureLayer) layer).getSurfaceTexture(); + } + + @Override + void updateTextureLayer(HardwareLayer layer, int width, int height, + float[] textureTransform) { + ((GLES20TextureLayer) layer).update(width, height, textureTransform); } static HardwareRenderer create(boolean translucent) { diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java new file mode 100644 index 000000000000..6380e1b5c7bd --- /dev/null +++ b/core/java/android/view/TextureView.java @@ -0,0 +1,296 @@ +/* + * 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.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.SurfaceTexture; +import android.util.AttributeSet; +import android.util.Log; + +/** + * <p>A TextureView can be used to display a content stream. Such a content + * stream can for instance be a video or an OpenGL scene. The content stream + * can come from the application's process as well as a remote process.</p> + * + * <p>TextureView can only be used in a hardware accelerated window. When + * rendered in software, TextureView will draw nothing.</p> + * + * <p>Unlike {@link SurfaceView}, TextureView does not create a separate + * window but behaves as a regular View. This key difference allows a + * TextureView to be moved, transformed, animated, etc. For instance, you + * can make a TextureView semi-translucent by calling + * <code>myView.setAlpha(0.5f)</code>.</p> + * + * <p>Using a TextureView is simple: all you need to do is get its + * {@link SurfaceTexture}. The {@link SurfaceTexture} can then be used to + * render content. The following example demonstrates how to render the + * camera preview into a TextureView:</p> + * + * <pre> + * public class LiveCameraActivity extends Activity implements TextureView.SurfaceTextureListener { + * private Camera mCamera; + * private TextureView mTextureView; + * + * protected void onCreate(Bundle savedInstanceState) { + * super.onCreate(savedInstanceState); + * + * mTextureView = new TextureView(this); + * mTextureView.setSurfaceTextureListener(this); + * + * setContentView(mTextureView); + * } + * + * protected void onDestroy() { + * super.onDestroy(); + * + * mCamera.stopPreview(); + * mCamera.release(); + * } + * + * public void onSurfaceTextureAvailable(SurfaceTexture surface) { + * mCamera = Camera.open(); + * + * try { + * mCamera.setPreviewTexture(surface); + * mCamera.startPreview(); + * } catch (IOException ioe) { + * // Something bad happened + * } + * } + * } + * </pre> + * + * <p>A TextureView's SurfaceTexture can be obtained either by invoking + * {@link #getSurfaceTexture()} or by using a {@link SurfaceTextureListener}. + * It is important to know that a SurfaceTexture is available only after the + * TextureView is attached to a window (and {@link #onAttachedToWindow()} has + * been invoked.) It is therefore highly recommended you use a listener to + * be notified when the SurfaceTexture becomes available.</p> + * + * @see SurfaceView + * @see SurfaceTexture + */ +public class TextureView extends View { + private HardwareLayer mLayer; + private SurfaceTexture mSurface; + private SurfaceTextureListener mListener; + + private final float[] mTextureTransform = new float[16]; + + private final Runnable mUpdateLayerAction = new Runnable() { + @Override + public void run() { + updateLayer(); + } + }; + + /** + * Creates a new TextureView. + * + * @param context The context to associate this view with. + */ + public TextureView(Context context) { + super(context); + init(); + } + + /** + * Creates a new TextureView. + * + * @param context The context to associate this view with. + * @param attrs The attributes of the XML tag that is inflating the view. + */ + @SuppressWarnings({"UnusedDeclaration"}) + public TextureView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + /** + * Creates a new TextureView. + * + * @param context The context to associate this view with. + * @param attrs The attributes of the XML tag that is inflating the view. + * @param defStyle The default style to apply to this view. If 0, no style + * will be applied (beyond what is included in the theme). This may + * either be an attribute resource, whose value will be retrieved + * from the current theme, or an explicit style resource. + */ + @SuppressWarnings({"UnusedDeclaration"}) + public TextureView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + private void init() { + mLayerPaint = new Paint(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + if (!isHardwareAccelerated()) { + Log.w("TextureView", "A TextureView or a subclass can only be " + + "used with hardware acceleration enabled."); + } + } + + /** + * The layer type of a TextureView is ignored since a TextureView is always + * considered to act as a hardware layer. The optional paint supplied to this + * method will however be taken into account when rendering the content of + * this TextureView. + * + * @param layerType The ype of layer to use with this view, must be one of + * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or + * {@link #LAYER_TYPE_HARDWARE} + * @param paint The paint used to compose the layer. This argument is optional + * and can be null. It is ignored when the layer type is + * {@link #LAYER_TYPE_NONE} + */ + @Override + public void setLayerType(int layerType, Paint paint) { + if (paint != mLayerPaint) { + mLayerPaint = paint; + invalidate(); + } + } + + /** + * Always returns {@link #LAYER_TYPE_HARDWARE}. + */ + @Override + public int getLayerType() { + return LAYER_TYPE_HARDWARE; + } + + /** + * Calling this method has no effect. + */ + @Override + public void buildLayer() { + } + + /** + * Subclasses of TextureView cannot do their own rendering + * with the {@link Canvas} object. + * + * @param canvas The Canvas to which the View is rendered. + */ + @Override + public final void draw(Canvas canvas) { + super.draw(canvas); + } + + /** + * Subclasses of TextureView cannot do their own rendering + * with the {@link Canvas} object. + * + * @param canvas The Canvas to which the View is rendered. + */ + @Override + protected final void onDraw(Canvas canvas) { + } + + @Override + HardwareLayer getHardwareLayer() { + if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) { + return null; + } + + if (mLayer == null) { + mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(); + mSurface = mAttachInfo.mHardwareRenderer.createSuraceTexture(mLayer); + + mSurface.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { + @Override + public void onFrameAvailable(SurfaceTexture surfaceTexture) { + // Per SurfaceTexture's documentation, the callback may be invoked + // from an arbitrary thread + post(mUpdateLayerAction); + } + }); + + if (mListener != null) { + mListener.onSurfaceTextureAvailable(mSurface); + } + } + + return mLayer; + } + + private void updateLayer() { + if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) { + return; + } + + mSurface.updateTexImage(); + mSurface.getTransformMatrix(mTextureTransform); + + mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight(), + mTextureTransform); + + invalidate(); + } + + /** + * Returns the {@link SurfaceTexture} used by this view. This method + * may return null if the view is not attached to a window. + */ + public SurfaceTexture getSurfaceTexture() { + return mSurface; + } + + /** + * Returns the {@link SurfaceTextureListener} currently associated with this + * texture view. + * + * @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener) + * @see SurfaceTextureListener + */ + public SurfaceTextureListener getSurfaceTextureListener() { + return mListener; + } + + /** + * Sets the {@link SurfaceTextureListener} used to listen to surface + * texture events. + * + * @see #getSurfaceTextureListener() + * @see SurfaceTextureListener + */ + public void setSurfaceTextureListener(SurfaceTextureListener listener) { + mListener = listener; + } + + /** + * This listener can be used to be notified when the surface texture + * associated with this texture view is available. + */ + public static interface SurfaceTextureListener { + /** + * Invoked when a {@link TextureView}'s SurfaceTexture is ready for use. + * + * @param surface The surface returned by + * {@link android.view.TextureView#getSurfaceTexture()} + */ + public void onSurfaceTextureAvailable(SurfaceTexture surface); + } +} diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 3e11197df764..4755362537f5 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -19,7 +19,6 @@ package android.webkit; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.os.Build; import android.os.Handler; import android.os.Message; @@ -137,6 +136,9 @@ public class WebSettings { OFF } + // TODO: Keep this up to date + private static final String PREVIOUS_VERSION = "3.1"; + // WebView associated with this WebSettings. private WebView mWebView; // BrowserFrame used to access the native frame pointer. @@ -470,7 +472,14 @@ public class WebSettings { // Add version final String version = Build.VERSION.RELEASE; if (version.length() > 0) { - buffer.append(version); + if (Character.isDigit(version.charAt(0))) { + // Release is a version, eg "3.1" + buffer.append(version); + } else { + // Release is a codename, eg "Honeycomb" + // In this case, use the previous release's version + buffer.append(PREVIOUS_VERSION); + } } else { // default to "1.0" buffer.append("1.0"); diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index dccfa6c537fb..57df259acca9 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -71,7 +71,7 @@ public class ActionBarImpl extends ActionBar { private ActionBarContainer mContainerView; private ActionBarView mActionView; private ActionBarContextView mUpperContextView; - private LinearLayout mLowerContextView; + private LinearLayout mLowerView; private View mContentView; private ViewGroup mExternalTabView; @@ -106,8 +106,8 @@ public class ActionBarImpl extends ActionBar { new AnimatorListenerAdapter() { // NORMAL_VIEW @Override public void onAnimationEnd(Animator animation) { - if (mLowerContextView != null) { - mLowerContextView.removeAllViews(); + if (mLowerView != null) { + mLowerView.removeAllViews(); } mCurrentModeAnim = null; hideAllExcept(NORMAL_VIEW); @@ -162,7 +162,7 @@ public class ActionBarImpl extends ActionBar { mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar); mUpperContextView = (ActionBarContextView) decor.findViewById( com.android.internal.R.id.action_context_bar); - mLowerContextView = (LinearLayout) decor.findViewById( + mLowerView = (LinearLayout) decor.findViewById( com.android.internal.R.id.lower_action_context_bar); mContainerView = (ActionBarContainer) decor.findViewById( com.android.internal.R.id.action_bar_container); @@ -173,8 +173,8 @@ public class ActionBarImpl extends ActionBar { } mActionView.setContextView(mUpperContextView); - mContextDisplayMode = mLowerContextView == null ? - CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT; + mContextDisplayMode = mActionView.isSplitActionBar() ? + CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; if (!mActionView.hasEmbeddedTabs()) { HorizontalScrollView tabScroller = new HorizontalScrollView(mContext); @@ -348,9 +348,9 @@ public class ActionBarImpl extends ActionBar { mode.invalidate(); mUpperContextView.initForMode(mode); animateTo(CONTEXT_VIEW); - if (mLowerContextView != null) { + if (mLowerView != null) { // TODO animate this - mLowerContextView.setVisibility(View.VISIBLE); + mLowerView.setVisibility(View.VISIBLE); } mActionMode = mode; return mode; @@ -616,9 +616,9 @@ public class ActionBarImpl extends ActionBar { // Clear out the context mode views after the animation finishes mUpperContextView.closeMode(); - if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) { + if (mLowerView != null && mLowerView.getVisibility() != View.GONE) { // TODO Animate this - mLowerContextView.setVisibility(View.GONE); + mLowerView.setVisibility(View.GONE); } mActionMode = null; diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java new file mode 100644 index 000000000000..2689f09c518e --- /dev/null +++ b/core/java/com/android/internal/util/Protocol.java @@ -0,0 +1,37 @@ +/* + * 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 com.android.internal.util; + +/** + * This class defines Message.what base addresses for various protocols that are recognized + * to be unique by any {@link com.android.internal.util.Statemachine} implementation. This + * allows for interaction between different StateMachine implementations without a conflict + * of message codes. + * + * As an example, all messages in {@link android.net.wifi.WifiStateMachine} will have message + * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI + + * Protocol.MAX_MESSAGE + * + * {@hide} + */ +public class Protocol { + public static final int MAX_MESSAGE = 0x0000FFFF; + + public static final int BASE_WIFI = 0x00010000; + public static final int BASE_DHCP = 0x00020000; + //TODO: define all used protocols +} diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index a05fa53e425a..e210b78c268f 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -73,10 +73,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter { int width = mWidthLimit; if (mReserveOverflow) { - OverflowMenuButton button = new OverflowMenuButton(mContext); - mOverflowButton = button; - final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - mOverflowButton.measure(spec, spec); + if (mOverflowButton == null) { + mOverflowButton = new OverflowMenuButton(mContext); + final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + mOverflowButton.measure(spec, spec); + } width -= mOverflowButton.getMeasuredWidth(); } else { mOverflowButton = null; @@ -88,6 +89,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter { mScrapActionButtonView = null; } + public void setWidthLimit(int width) { + if (mReserveOverflow) { + width -= mOverflowButton.getMeasuredWidth(); + } + mActionItemWidthLimit = width; + } + + public void setItemLimit(int itemCount) { + mMaxItems = itemCount; + } + @Override public MenuView getMenuView(ViewGroup root) { MenuView result = super.getMenuView(root); diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index a572e1168372..0c13f7bfbe60 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -110,7 +110,7 @@ public class ActionBarView extends ViewGroup { private int mProgressStyle; private int mIndeterminateProgressStyle; - private boolean mShowMenu; + private boolean mSplitActionBar; private boolean mUserTitle; private boolean mIncludeTabs; @@ -119,6 +119,7 @@ public class ActionBarView extends ViewGroup { private ActionMenuPresenter mActionMenuPresenter; private ActionBarContextView mContextView; + private ViewGroup mSplitView; private ActionMenuItem mLogoNavItem; @@ -245,6 +246,26 @@ public class ActionBarView extends ViewGroup { addView(mIndeterminateProgressView); } + public void setSplitActionBar(boolean splitActionBar) { + if (mSplitActionBar != splitActionBar) { + if (mMenuView != null) { + if (splitActionBar) { + removeView(mMenuView); + if (mSplitView != null) { + mSplitView.addView(mMenuView); + } + } else { + addView(mMenuView); + } + } + mSplitActionBar = splitActionBar; + } + } + + public boolean isSplitActionBar() { + return mSplitActionBar; + } + public boolean hasEmbeddedTabs() { return mIncludeTabs; } @@ -284,10 +305,29 @@ public class ActionBarView extends ViewGroup { final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); menuView.setLayoutParams(layoutParams); - addView(menuView); + if (!mSplitActionBar) { + addView(menuView); + } else { + // Allow full screen width in split mode. + mActionMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels); + // No limit to the item count; use whatever will fit. + mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + if (mSplitView != null) { + mSplitView.addView(menuView); + } // We'll add this later if we missed it this time. + } mMenuView = menuView; } + public void setSplitView(ViewGroup splitView) { + mSplitView = splitView; + splitView.setVisibility(VISIBLE); + if (mMenuView != null) { + splitView.addView(mMenuView); + } + } + public boolean showOverflowMenu() { if (mActionMenuPresenter != null) { return mActionMenuPresenter.showOverflowMenu(); @@ -718,7 +758,7 @@ public class ActionBarView extends ViewGroup { leftOfCenter -= homeWidth; } - if (mMenuView != null) { + if (mMenuView != null && mMenuView.getParent() == this) { availableWidth = measureChildView(mMenuView, availableWidth, childSpecHeight, 0); rightOfCenter -= mMenuView.getMeasuredWidth(); @@ -880,7 +920,7 @@ public class ActionBarView extends ViewGroup { } int menuLeft = r - l - getPaddingRight(); - if (mMenuView != null) { + if (mMenuView != null && mMenuView.getParent() == this) { positionChildInverse(mMenuView, menuLeft, y, contentHeight); menuLeft -= mMenuView.getMeasuredWidth(); } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 314c2ee3b176..af7639a541d8 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -539,6 +539,19 @@ static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env return NULL; } +static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz, + jintArray layerInfo) { + Layer* layer = LayerRenderer::createTextureLayer(); + + if (layer) { + jint* storage = env->GetIntArrayElements(layerInfo, NULL); + storage[0] = layer->texture; + env->ReleaseIntArrayElements(layerInfo, storage, 0); + } + + return layer; +} + static Layer* android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz, jint width, jint height, jboolean isOpaque, jintArray layerInfo) { Layer* layer = LayerRenderer::createLayer(width, height, isOpaque); @@ -563,6 +576,13 @@ static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz, env->ReleaseIntArrayElements(layerInfo, storage, 0); } +static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz, + Layer* layer, jint width, jint height, jfloatArray texTransform) { + jfloat* transform = env->GetFloatArrayElements(texTransform, NULL); + LayerRenderer::updateTextureLayer(layer, width, height, transform); + env->ReleaseFloatArrayElements(texTransform, transform, 0); +} + static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) { LayerRenderer::destroyLayer(layer); } @@ -696,6 +716,8 @@ static JNINativeMethod gMethods[] = { { "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer }, { "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer }, { "nResizeLayer", "(III[I)V" , (void*) android_view_GLES20Canvas_resizeLayer }, + { "nCreateTextureLayer", "([I)I", (void*) android_view_GLES20Canvas_createTextureLayer }, + { "nUpdateTextureLayer", "(III[F)V" , (void*) android_view_GLES20Canvas_updateTextureLayer }, { "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer }, { "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred }, { "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer }, diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 70af26519ea6..14af446abf20 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -47,5 +47,6 @@ This is an optimized layout for a screen with the Action Bar enabled. android:layout_width="match_parent" android:layout_height="wrap_content" style="?android:attr/actionBarStyle" - android:visibility="gone" /> + android:visibility="gone" + android:gravity="center"/> </LinearLayout> diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml index cfa335e51d47..aebbe411566f 100644 --- a/core/res/res/layout/screen_action_bar_overlay.xml +++ b/core/res/res/layout/screen_action_bar_overlay.xml @@ -51,5 +51,6 @@ the Action Bar enabled overlaying application content. android:layout_height="wrap_content" android:layout_alignParentBottom="true" style="?android:attr/actionBarStyle" - android:visibility="gone" /> + android:visibility="gone" + android:gravity="center"/> </RelativeLayout> diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml index c202d90d403b..8206e792dbe5 100644 --- a/core/res/res/values-w480dp/bools.xml +++ b/core/res/res/values-w480dp/bools.xml @@ -19,4 +19,5 @@ <resources> <bool name="allow_action_menu_item_text_with_icon">true</bool> <bool name="action_bar_embed_tabs">true</bool> + <bool name="split_action_bar_is_narrow">false</bool> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 3a44e4f73a82..dac3bd24aa22 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -299,6 +299,10 @@ when there is not reserved space for their UI (such as an Action Bar). --> <attr name="windowActionModeOverlay" format="boolean" /> + <!-- Flag indicating that the action bar should be split to provide more + room for elements. --> + <attr name="windowSplitActionBar" format="boolean" /> + <!-- Defines the default soft input state that this window would like when it is displayed. --> <attr name="windowSoftInputMode"> @@ -1429,6 +1433,7 @@ <attr name="windowActionBar" /> <attr name="windowActionModeOverlay" /> <attr name="windowActionBarOverlay" /> + <attr name="windowSplitActionBar" /> <attr name="windowEnableSplitTouch" /> <attr name="windowCloseOnTouchOutside" /> <!-- The minimum width the window is allowed to be, along the major diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index 6eb006f32f03..8e27be4a904d 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -19,4 +19,5 @@ <resources> <bool name="allow_action_menu_item_text_with_icon">false</bool> <bool name="action_bar_embed_tabs">false</bool> + <bool name="split_action_bar_is_narrow">true</bool> </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 501d4784632a..7ca5e98a9873 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1660,6 +1660,8 @@ <public type="style" name="Theme.Holo.Light.NoActionBar" /> <public type="style" name="TextAppearance.SuggestionHighlight" /> + <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" /> + <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" /> <public type="attr" name="textSuggestionsWindowStyle" /> <public type="attr" name="textEditSuggestionsBottomWindowLayout" /> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index be7b42fa61fc..cdfdd11a6492 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -1538,4 +1538,17 @@ <item name="android:windowNoTitle">true</item> </style> + <!-- Variant of the holographic (dark) theme with an action bar that + splits across the top and bottom of the activity when constrained + for horizontal space. --> + <style name="Theme.Holo.SplitActionBarWhenNarrow"> + <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item> + </style> + + <!-- Variant of the holographic (light) theme with an action bar that + splits across the top and bottom of the activity when constrained + for horizontal space. --> + <style name="Theme.Holo.Light.SplitActionBarWhenNarrow"> + <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item> + </style> </resources> diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index 2da022c3c58e..4a574be82244 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -295,7 +295,9 @@ Available Resources</a> document.</p> {@link android.view.ViewGroup.MarginLayoutParams} for further information. </p> -<p>For more information about dimensions, see <a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">Dimension Values</a>.</p> + <p>For more information about dimensions, see + <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Dimension Values</a>. + </p> diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index c7db9a63153f..72416c1a22c7 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -26,7 +26,6 @@ #endif #include <private/pixelflinger/ggl_context.h> -#include <hardware/copybit.h> #include <hardware/gralloc.h> #include <GLES/gl.h> @@ -606,7 +605,6 @@ struct prims_t { struct copybits_context_t { // A handle to the blit engine, if it exists, else NULL. - copybit_device_t* blitEngine; int32_t minScale; int32_t maxScale; android_native_buffer_t* drawSurfaceBuffer; diff --git a/include/ui/Region.h b/include/ui/Region.h index 925fd0620d60..6c9a6203e793 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -24,8 +24,6 @@ #include <ui/Rect.h> -#include <hardware/copybit.h> - namespace android { // --------------------------------------------------------------------------- @@ -183,27 +181,6 @@ Region& Region::operator -= (const Region& rhs) { Region& Region::operator += (const Point& pt) { return translateSelf(pt.x, pt.y); } - -// --------------------------------------------------------------------------- - -struct region_iterator : public copybit_region_t { - region_iterator(const Region& region) - : b(region.begin()), e(region.end()) { - this->next = iterate; - } -private: - static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { - region_iterator const* me = static_cast<region_iterator const*>(self); - if (me->b != me->e) { - *reinterpret_cast<Rect*>(rect) = *me->b++; - return 1; - } - return 0; - } - mutable Region::const_iterator b; - Region::const_iterator const e; -}; - // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 58bb0d31f4e2..b5737ffff18f 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -38,3 +38,7 @@ ifeq ($(TARGET_SIMULATOR),true) endif include $(BUILD_SHARED_LIBRARY) + +ifeq (,$(ONE_SHOT_MAKEFILE)) +include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index ecd09951153e..8d3a9b5ebafa 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -36,9 +36,6 @@ LOCAL_C_INCLUDES := \ include $(BUILD_EXECUTABLE) -# Build the manual test programs. -include $(call all-subdir-makefiles) - endif # Include subdirectory makefiles diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 6c4a2a9a972d..16566b80164d 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -45,6 +45,8 @@ struct Layer { mesh = NULL; meshIndices = NULL; meshElementCount = 0; + isCacheable = true; + isTextureLayer = false; } ~Layer() { @@ -137,6 +139,22 @@ struct Layer { TextureVertex* mesh; uint16_t* meshIndices; GLsizei meshElementCount; + + /** + * If set to true (by default), the layer can be reused. + */ + bool isCacheable; + + /** + * When set to true, this layer must be treated as a texture + * layer. + */ + bool isTextureLayer; + + /** + * Optional texture coordinates transform. + */ + mat4 texTransform; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index a9710ad6adbf..b2d795f3516b 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -154,6 +154,8 @@ bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t heigh } bool LayerCache::put(Layer* layer) { + if (!layer->isCacheable) return false; + const uint32_t size = layer->width * layer->height * 4; // Don't even try to cache a layer that's bigger than the cache if (size < mMaxSize) { diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index ca1e7ae0027b..e167336c8657 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -20,6 +20,7 @@ #include "LayerCache.h" #include "LayerRenderer.h" +#include "Matrix.h" #include "Properties.h" #include "Rect.h" @@ -165,6 +166,40 @@ void LayerRenderer::generateMesh() { // Layers management /////////////////////////////////////////////////////////////////////////////// +Layer* LayerRenderer::createTextureLayer() { + LAYER_RENDERER_LOGD("Creating new texture layer"); + + Layer* layer = new Layer(0, 0); + layer->isCacheable = false; + layer->isTextureLayer = true; + layer->blend = true; + layer->empty = true; + layer->fbo = 0; + layer->colorFilter = NULL; + layer->fbo = 0; + 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(); + + glActiveTexture(GL_TEXTURE0); + + glGenTextures(1, &layer->texture); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, layer->texture); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + return layer; +} + Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height); @@ -244,6 +279,18 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { return true; } +void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + float* transform) { + if (layer) { + layer->width = width; + layer->height = 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); + } +} + void LayerRenderer::destroyLayer(Layer* layer) { if (layer) { LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo); diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index d2f565e4f307..b3cd5db4fbe2 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -53,8 +53,11 @@ public: Region* getRegion(); GLint getTargetFbo(); + static Layer* createTextureLayer(); static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); + static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + float* transform); static void destroyLayer(Layer* layer); static void destroyLayerDeferred(Layer* layer); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ea4283897273..34d8fd31e206 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -633,15 +633,43 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { } } +void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { + float alpha = layer->alpha / 255.0f; + + setupDraw(); + setupDrawWithExternalTexture(); + setupDrawColor(alpha, alpha, alpha, alpha); + setupDrawColorFilter(); + setupDrawBlending(layer->blend, layer->mode); + setupDrawProgram(); + setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom); + setupDrawPureColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawExternalTexture(layer->texture); + setupDrawTextureTransform(layer->texTransform); + setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); + + finishDrawTexture(); +} + void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { - const Rect& texCoords = layer->texCoords; - resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom); + 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); + 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); - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + } else { + resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); + drawTextureLayer(layer, rect); + resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + } } void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { @@ -882,6 +910,10 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { mDescription.hasAlpha8Texture = isAlpha8; } +void OpenGLRenderer::setupDrawWithExternalTexture() { + mDescription.hasExternalTexture = true; +} + void OpenGLRenderer::setupDrawAALine() { mDescription.hasWidth = true; } @@ -1055,6 +1087,19 @@ void OpenGLRenderer::setupDrawTexture(GLuint texture) { glEnableVertexAttribArray(mTexCoordsSlot); } +void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) { + bindExternalTexture(texture); + glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++); + + mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); + glEnableVertexAttribArray(mTexCoordsSlot); +} + +void OpenGLRenderer::setupDrawTextureTransform(mat4& transform) { + glUniformMatrix4fv(mCaches.currentProgram->getUniform("mainTextureTransform"), 1, + GL_FALSE, &transform.data[0]); +} + void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { if (!vertices) { mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 918e1fb4178d..0ffd70b4ef99 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -248,6 +248,8 @@ private: */ void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false); + void drawTextureLayer(Layer* layer, const Rect& rect); + /** * Mark the layer as dirty at the specified coordinates. The coordinates * are transformed with the supplied matrix. @@ -387,6 +389,14 @@ private: } /** + * Binds the specified EGLImage texture. The texture unit must have been selected + * prior to calling this method. + */ + inline void bindExternalTexture(GLuint texture) { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); + } + + /** * Sets the wrap modes for the specified texture. The wrap modes are modified * only when needed. */ @@ -425,6 +435,7 @@ private: * Various methods to setup OpenGL rendering. */ void setupDrawWithTexture(bool isAlpha8 = false); + void setupDrawWithExternalTexture(); void setupDrawAALine(); void setupDrawPoint(float pointSize); void setupDrawColor(int color); @@ -453,6 +464,8 @@ private: void setupDrawColorFilterUniforms(); void setupDrawSimpleMesh(); void setupDrawTexture(GLuint texture); + void setupDrawExternalTexture(GLuint texture); + void setupDrawTextureTransform(mat4& transform); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); void setupDrawVertices(GLvoid* vertices); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth); diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 80b1917809ca..62ac2baaf7b6 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -41,6 +41,8 @@ const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; const char* gVS_Header_Attributes_Distance = "attribute float vtxDistance;\n"; +const char* gVS_Header_Uniforms_TextureTransform = + "uniform mat4 mainTextureTransform;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; const char* gVS_Header_Uniforms_IsPoint = @@ -76,6 +78,8 @@ const char* gVS_Main = "\nvoid main(void) {\n"; const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n"; +const char* gVS_Main_OutTransformedTexCoords = + " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n"; const char* gVS_Main_OutGradient[3] = { // Linear " linear = vec2((screenSpace * position).x, 0.5);\n", @@ -103,6 +107,8 @@ const char* gVS_Footer = const char* gFS_Header_Extension_FramebufferFetch = "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; +const char* gFS_Header_Extension_ExternalTexture = + "#extension GL_OES_EGL_image_external : require\n\n"; const char* gFS_Header = "precision mediump float;\n\n"; const char* gFS_Uniforms_Color = @@ -116,6 +122,8 @@ const char* gFS_Header_Uniforms_PointHasBitmap = "uniform float pointSize;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D sampler;\n"; +const char* gFS_Uniforms_ExternalTextureSampler = + "uniform samplerExternalOES sampler;\n"; const char* gFS_Uniforms_GradientSampler[3] = { // Linear "uniform sampler2D gradientSampler;\n", @@ -369,7 +377,7 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { // Add attributes String8 shader(gVS_Header_Attributes); - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Attributes_TexCoords); } if (description.hasWidth) { @@ -377,6 +385,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description } // Uniforms shader.append(gVS_Header_Uniforms); + if (description.hasExternalTexture) { + shader.append(gVS_Header_Uniforms_TextureTransform); + } if (description.hasGradient) { shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); } @@ -387,7 +398,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Uniforms_IsPoint); } // Varyings - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { @@ -407,6 +418,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture) { shader.append(gVS_Main_OutTexCoords); } + if (description.hasExternalTexture) { + shader.append(gVS_Main_OutTransformedTexCoords); + } if (description.hasWidth) { shader.append(gVS_Main_Width); } @@ -440,11 +454,14 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (blendFramebuffer) { shader.append(gFS_Header_Extension_FramebufferFetch); } + if (description.hasExternalTexture) { + shader.append(gFS_Header_Extension_ExternalTexture); + } shader.append(gFS_Header); // Varyings - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { @@ -461,7 +478,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Uniforms int modulateOp = MODULATE_OP_NO_MODULATE; - const bool singleColor = !description.hasTexture && + const bool singleColor = !description.hasTexture && !description.hasExternalTexture && !description.hasGradient && !description.hasBitmap; if (description.modulate || singleColor) { @@ -471,6 +488,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture) { shader.append(gFS_Uniforms_TextureSampler); } + if (description.hasExternalTexture) { + shader.append(gFS_Uniforms_ExternalTextureSampler); + } if (description.hasWidth) { shader.append(gFS_Uniforms_Width); } @@ -487,11 +507,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; - const bool singleTexture = description.hasTexture && + const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && !description.hasAlpha8Texture && noShader; const bool singleA8Texture = description.hasTexture && description.hasAlpha8Texture && noShader; - const bool singleGradient = !description.hasTexture && + const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && description.hasGradient && !description.hasBitmap && description.gradientType == ProgramDescription::kGradientLinear; @@ -554,7 +574,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Begin the shader shader.append(gFS_Main); { // Stores the result in fragColor directly - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { if (!description.hasGradient && !description.hasBitmap) { shader.append(gFS_Main_FetchA8Texture[modulateOp]); diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 18d98cb05e10..70909fd622bf 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -77,6 +77,8 @@ namespace uirenderer { #define PROGRAM_HAS_WIDTH_SHIFT 37 +#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 + /////////////////////////////////////////////////////////////////////////////// // Types /////////////////////////////////////////////////////////////////////////////// @@ -113,6 +115,7 @@ struct ProgramDescription { // Texturing bool hasTexture; bool hasAlpha8Texture; + bool hasExternalTexture; // Modulate, this should only be set when setColor() return true bool modulate; @@ -151,6 +154,7 @@ struct ProgramDescription { void reset() { hasTexture = false; hasAlpha8Texture = false; + hasExternalTexture = false; hasWidth = false; @@ -240,6 +244,7 @@ struct ProgramDescription { if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; if (hasWidth) key |= programid(0x1) << PROGRAM_HAS_WIDTH_SHIFT; + if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; return key; } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index cc689bbd798c..2817df8ebabc 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -1310,7 +1310,7 @@ public class LocationManager { * @param listener GPS status listener object to register * * @return true if the listener was successfully added - * + * * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present */ public boolean addGpsStatusListener(GpsStatus.Listener listener) { @@ -1434,7 +1434,7 @@ public class LocationManager { return false; } } - + /** * Used by NetInitiatedActivity to report user response * for network initiated GPS fix requests. @@ -1449,5 +1449,5 @@ public class LocationManager { return false; } } - + } diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index a1cb23a250b9..40fa1481494f 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -41,8 +41,6 @@ #include <private/ui/android_natives_priv.h> -#include <hardware/copybit.h> - #include "context.h" #include "state.h" #include "texture.h" @@ -238,7 +236,6 @@ private: android_native_buffer_t* buffer; android_native_buffer_t* previousBuffer; gralloc_module_t const* module; - copybit_device_t* blitengine; int width; int height; void* bits; @@ -324,24 +321,6 @@ private: ssize_t count; }; - struct region_iterator : public copybit_region_t { - region_iterator(const Region& region) - : b(region.begin()), e(region.end()) { - this->next = iterate; - } - private: - static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { - region_iterator const* me = static_cast<region_iterator const*>(self); - if (me->b != me->e) { - *reinterpret_cast<Rect*>(rect) = *me->b++; - return 1; - } - return 0; - } - mutable Region::const_iterator b; - Region::const_iterator const e; - }; - void copyBlt( android_native_buffer_t* dst, void* dst_vaddr, android_native_buffer_t* src, void const* src_vaddr, @@ -357,16 +336,8 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, ANativeWindow* window) : egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0), previousBuffer(0), module(0), - blitengine(0), bits(NULL) + bits(NULL) { - hw_module_t const* pModule; - hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); - module = reinterpret_cast<gralloc_module_t const*>(pModule); - - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) { - copybit_open(pModule, &blitengine); - } - pixelFormatTable = gglGetPixelFormatTable(); // keep a reference on the window @@ -383,9 +354,6 @@ egl_window_surface_v2_t::~egl_window_surface_v2_t() { previousBuffer->common.decRef(&previousBuffer->common); } nativeWindow->common.decRef(&nativeWindow->common); - if (blitengine) { - copybit_close(blitengine); - } } EGLBoolean egl_window_surface_v2_t::connect() @@ -475,60 +443,33 @@ void egl_window_surface_v2_t::copyBlt( // FIXME: use copybit if possible // NOTE: dst and src must be the same format - status_t err = NO_ERROR; - copybit_device_t* const copybit = blitengine; - if (copybit) { - copybit_image_t simg; - simg.w = src->stride; - simg.h = src->height; - simg.format = src->format; - simg.handle = const_cast<native_handle_t*>(src->handle); - - copybit_image_t dimg; - dimg.w = dst->stride; - dimg.h = dst->height; - dimg.format = dst->format; - dimg.handle = const_cast<native_handle_t*>(dst->handle); - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - region_iterator it(clip); - err = copybit->blit(copybit, &dimg, &simg, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } - } - - if (!copybit || err) { - Region::const_iterator cur = clip.begin(); - Region::const_iterator end = clip.end(); - - const size_t bpp = pixelFormatTable[src->format].size; - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; - - uint8_t const * const src_bits = (uint8_t const *)src_vaddr; - uint8_t * const dst_bits = (uint8_t *)dst_vaddr; - - while (cur != end) { - const Rect& r(*cur++); - ssize_t w = r.right - r.left; - ssize_t h = r.bottom - r.top; - if (w <= 0 || h<=0) continue; - size_t size = w * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); + Region::const_iterator cur = clip.begin(); + Region::const_iterator end = clip.end(); + + const size_t bpp = pixelFormatTable[src->format].size; + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + uint8_t const * const src_bits = (uint8_t const *)src_vaddr; + uint8_t * const dst_bits = (uint8_t *)dst_vaddr; + + while (cur != end) { + const Rect& r(*cur++); + ssize_t w = r.right - r.left; + ssize_t h = r.bottom - r.top; + if (w <= 0 || h<=0) continue; + size_t size = w * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); } } diff --git a/opengl/libagl2/src/egl.cpp b/opengl/libagl2/src/egl.cpp index 6184644ed205..ba771c3fba33 100644 --- a/opengl/libagl2/src/egl.cpp +++ b/opengl/libagl2/src/egl.cpp @@ -1,19 +1,19 @@ /* -** -** Copyright 2007 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. -*/ + ** + ** Copyright 2007 The Android Open Source Project + ** + ** Licensed under the Apache License Version 2.0(the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing software + ** distributed under the License is distributed on an "AS IS" BASIS + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ #include <errno.h> #include <stdlib.h> @@ -30,8 +30,6 @@ #include <private/ui/android_natives_priv.h> -#include <hardware/copybit.h> - #include "gles2context.h" // ---------------------------------------------------------------------------- @@ -53,808 +51,751 @@ pthread_key_t gGLKey = -1; template<typename T> static T setError(GLint error, T returnValue) { - if (ggl_unlikely(gEGLErrorKey == -1)) { - pthread_mutex_lock(&gErrorKeyMutex); - if (gEGLErrorKey == -1) - pthread_key_create(&gEGLErrorKey, NULL); - pthread_mutex_unlock(&gErrorKeyMutex); - } - pthread_setspecific(gEGLErrorKey, (void*)error); - return returnValue; + if (ggl_unlikely(gEGLErrorKey == -1)) { + pthread_mutex_lock(&gErrorKeyMutex); + if (gEGLErrorKey == -1) + pthread_key_create(&gEGLErrorKey, NULL); + pthread_mutex_unlock(&gErrorKeyMutex); + } + pthread_setspecific(gEGLErrorKey, (void*)error); + return returnValue; } static GLint getError() { - if (ggl_unlikely(gEGLErrorKey == -1)) - return EGL_SUCCESS; - GLint error = (GLint)pthread_getspecific(gEGLErrorKey); - if (error == 0) { - // The TLS key has been created by another thread, but the value for - // this thread has not been initialized. - return EGL_SUCCESS; - } - pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); - return error; + if (ggl_unlikely(gEGLErrorKey == -1)) + return EGL_SUCCESS; + GLint error = (GLint)pthread_getspecific(gEGLErrorKey); + if (error == 0) { + // The TLS key has been created by another thread, but the value for + // this thread has not been initialized. + return EGL_SUCCESS; + } + pthread_setspecific(gEGLErrorKey, (void*)EGL_SUCCESS); + return error; } // ---------------------------------------------------------------------------- struct egl_display_t { - egl_display_t() : type(0), initialized(0) { } + egl_display_t() : type(0), initialized(0) { } - static egl_display_t& get_display(EGLDisplay dpy); + static egl_display_t& get_display(EGLDisplay dpy); - static EGLBoolean is_valid(EGLDisplay dpy) { - return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; - } + static EGLBoolean is_valid(EGLDisplay dpy) { + return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; + } - NativeDisplayType type; - volatile int32_t initialized; + NativeDisplayType type; + volatile int32_t initialized; }; static egl_display_t gDisplays[NUM_DISPLAYS]; egl_display_t& egl_display_t::get_display(EGLDisplay dpy) { - return gDisplays[uintptr_t(dpy)-1U]; + return gDisplays[uintptr_t(dpy)-1U]; } // ---------------------------------------------------------------------------- struct egl_surface_t { - enum { - PAGE_FLIP = 0x00000001, - MAGIC = 0x31415265 - }; - - uint32_t magic; - EGLDisplay dpy; - EGLConfig config; - EGLContext ctx; - - egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); - virtual ~egl_surface_t(); - bool isValid() const; - virtual bool initCheck() const = 0; - - virtual EGLBoolean bindDrawSurface(GLES2Context* gl) = 0; - virtual EGLBoolean bindReadSurface(GLES2Context* gl) = 0; - virtual EGLBoolean connect() { - return EGL_TRUE; - } - virtual void disconnect() {} - virtual EGLint getWidth() const = 0; - virtual EGLint getHeight() const = 0; - - virtual EGLint getHorizontalResolution() const; - virtual EGLint getVerticalResolution() const; - virtual EGLint getRefreshRate() const; - virtual EGLint getSwapBehavior() const; - virtual EGLBoolean swapBuffers(); - virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); + enum { + PAGE_FLIP = 0x00000001, + MAGIC = 0x31415265 + }; + + uint32_t magic; + EGLDisplay dpy; + EGLConfig config; + EGLContext ctx; + + egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); + virtual ~egl_surface_t(); + bool isValid() const; + virtual bool initCheck() const = 0; + + virtual EGLBoolean bindDrawSurface(GLES2Context* gl) = 0; + virtual EGLBoolean bindReadSurface(GLES2Context* gl) = 0; + virtual EGLBoolean connect() { + return EGL_TRUE; + } + virtual void disconnect() {} + virtual EGLint getWidth() const = 0; + virtual EGLint getHeight() const = 0; + + virtual EGLint getHorizontalResolution() const; + virtual EGLint getVerticalResolution() const; + virtual EGLint getRefreshRate() const; + virtual EGLint getSwapBehavior() const; + virtual EGLBoolean swapBuffers(); + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); protected: - GGLSurface depth; + GGLSurface depth; }; egl_surface_t::egl_surface_t(EGLDisplay dpy, - EGLConfig config, - int32_t depthFormat) - : magic(MAGIC), dpy(dpy), config(config), ctx(0) + EGLConfig config, + int32_t depthFormat) +: magic(MAGIC), dpy(dpy), config(config), ctx(0) { - depth.version = sizeof(GGLSurface); - depth.data = 0; - depth.format = (GGLPixelFormat)depthFormat; + depth.version = sizeof(GGLSurface); + depth.data = 0; + depth.format = (GGLPixelFormat)depthFormat; } egl_surface_t::~egl_surface_t() { - magic = 0; - free(depth.data); + magic = 0; + free(depth.data); } bool egl_surface_t::isValid() const { - LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this); - return magic == MAGIC; + LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this); + return magic == MAGIC; } EGLBoolean egl_surface_t::swapBuffers() { - return EGL_FALSE; + return EGL_FALSE; } EGLint egl_surface_t::getHorizontalResolution() const { - return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); + return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } EGLint egl_surface_t::getVerticalResolution() const { - return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); + return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } EGLint egl_surface_t::getRefreshRate() const { - return (60 * EGL_DISPLAY_SCALING); + return (60 * EGL_DISPLAY_SCALING); } EGLint egl_surface_t::getSwapBehavior() const { - return EGL_BUFFER_PRESERVED; + return EGL_BUFFER_PRESERVED; } EGLBoolean egl_surface_t::setSwapRectangle( - EGLint l, EGLint t, EGLint w, EGLint h) + EGLint l, EGLint t, EGLint w, EGLint h) { - return EGL_FALSE; + return EGL_FALSE; } // ---------------------------------------------------------------------------- struct egl_window_surface_v2_t : public egl_surface_t { - egl_window_surface_v2_t( - EGLDisplay dpy, EGLConfig config, - int32_t depthFormat, - ANativeWindow* window); - - ~egl_window_surface_v2_t(); - - virtual bool initCheck() const { - return true; // TODO: report failure if ctor fails - } - virtual EGLBoolean swapBuffers(); - virtual EGLBoolean bindDrawSurface(GLES2Context* gl); - virtual EGLBoolean bindReadSurface(GLES2Context* gl); - virtual EGLBoolean connect(); - virtual void disconnect(); - virtual EGLint getWidth() const { - return width; - } - virtual EGLint getHeight() const { - return height; - } - virtual EGLint getHorizontalResolution() const; - virtual EGLint getVerticalResolution() const; - virtual EGLint getRefreshRate() const; - virtual EGLint getSwapBehavior() const; - virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); + egl_window_surface_v2_t( + EGLDisplay dpy, EGLConfig config, + int32_t depthFormat, + ANativeWindow* window); + + ~egl_window_surface_v2_t(); + + virtual bool initCheck() const { + return true; // TODO: report failure if ctor fails + } + virtual EGLBoolean swapBuffers(); + virtual EGLBoolean bindDrawSurface(GLES2Context* gl); + virtual EGLBoolean bindReadSurface(GLES2Context* gl); + virtual EGLBoolean connect(); + virtual void disconnect(); + virtual EGLint getWidth() const { + return width; + } + virtual EGLint getHeight() const { + return height; + } + virtual EGLint getHorizontalResolution() const; + virtual EGLint getVerticalResolution() const; + virtual EGLint getRefreshRate() const; + virtual EGLint getSwapBehavior() const; + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); private: - status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); - status_t unlock(android_native_buffer_t* buf); - ANativeWindow* nativeWindow; - android_native_buffer_t* buffer; - android_native_buffer_t* previousBuffer; - gralloc_module_t const* module; - copybit_device_t* blitengine; - int width; - int height; - void* bits; - GGLFormat const* pixelFormatTable; - - struct Rect { - inline Rect() { }; - inline Rect(int32_t w, int32_t h) - : left(0), top(0), right(w), bottom(h) { } - inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) - : left(l), top(t), right(r), bottom(b) { } - Rect& andSelf(const Rect& r) { - left = max(left, r.left); - top = max(top, r.top); - right = min(right, r.right); - bottom = min(bottom, r.bottom); - return *this; - } - bool isEmpty() const { - return (left>=right || top>=bottom); - } - void dump(char const* what) { - LOGD("%s { %5d, %5d, w=%5d, h=%5d }", - what, left, top, right-left, bottom-top); - } - - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; - }; - - struct Region { - inline Region() : count(0) { } - typedef Rect const* const_iterator; - const_iterator begin() const { - return storage; - } - const_iterator end() const { - return storage+count; - } - static Region subtract(const Rect& lhs, const Rect& rhs) { - Region reg; - Rect* storage = reg.storage; - if (!lhs.isEmpty()) { - if (lhs.top < rhs.top) { // top rect - storage->left = lhs.left; - storage->top = lhs.top; - storage->right = lhs.right; - storage->bottom = rhs.top; - storage++; - } - const int32_t top = max(lhs.top, rhs.top); - const int32_t bot = min(lhs.bottom, rhs.bottom); - if (top < bot) { - if (lhs.left < rhs.left) { // left-side rect - storage->left = lhs.left; - storage->top = top; - storage->right = rhs.left; - storage->bottom = bot; - storage++; - } - if (lhs.right > rhs.right) { // right-side rect - storage->left = rhs.right; - storage->top = top; - storage->right = lhs.right; - storage->bottom = bot; - storage++; - } + status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); + status_t unlock(android_native_buffer_t* buf); + ANativeWindow* nativeWindow; + android_native_buffer_t* buffer; + android_native_buffer_t* previousBuffer; + gralloc_module_t const* module; + int width; + int height; + void* bits; + GGLFormat const* pixelFormatTable; + + struct Rect { + inline Rect() { }; + inline Rect(int32_t w, int32_t h) + : left(0), top(0), right(w), bottom(h) { } + inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) + : left(l), top(t), right(r), bottom(b) { } + Rect& andSelf(const Rect& r) { + left = max(left, r.left); + top = max(top, r.top); + right = min(right, r.right); + bottom = min(bottom, r.bottom); + return *this; + } + bool isEmpty() const { + return (left>=right || top>=bottom); + } + void dump(char const* what) { + LOGD("%s { %5d, %5d, w=%5d, h=%5d }", + what, left, top, right-left, bottom-top); + } + + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + }; + + struct Region { + inline Region() : count(0) { } + typedef Rect const* const_iterator; + const_iterator begin() const { + return storage; + } + const_iterator end() const { + return storage+count; + } + static Region subtract(const Rect& lhs, const Rect& rhs) { + Region reg; + Rect* storage = reg.storage; + if (!lhs.isEmpty()) { + if (lhs.top < rhs.top) { // top rect + storage->left = lhs.left; + storage->top = lhs.top; + storage->right = lhs.right; + storage->bottom = rhs.top; + storage++; + } + const int32_t top = max(lhs.top, rhs.top); + const int32_t bot = min(lhs.bottom, rhs.bottom); + if (top < bot) { + if (lhs.left < rhs.left) { // left-side rect + storage->left = lhs.left; + storage->top = top; + storage->right = rhs.left; + storage->bottom = bot; + storage++; + } + if (lhs.right > rhs.right) { // right-side rect + storage->left = rhs.right; + storage->top = top; + storage->right = lhs.right; + storage->bottom = bot; + storage++; + } + } + if (lhs.bottom > rhs.bottom) { // bottom rect + storage->left = lhs.left; + storage->top = rhs.bottom; + storage->right = lhs.right; + storage->bottom = lhs.bottom; + storage++; + } + reg.count = storage - reg.storage; } - if (lhs.bottom > rhs.bottom) { // bottom rect - storage->left = lhs.left; - storage->top = rhs.bottom; - storage->right = lhs.right; - storage->bottom = lhs.bottom; - storage++; - } - reg.count = storage - reg.storage; - } - return reg; - } - bool isEmpty() const { - return count<=0; - } -private: - Rect storage[4]; - ssize_t count; - }; - - struct region_iterator : public copybit_region_t { - region_iterator(const Region& region) - : b(region.begin()), e(region.end()) { - this->next = iterate; - } -private: - static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { - region_iterator const* me = static_cast<region_iterator const*>(self); - if (me->b != me->e) { - *reinterpret_cast<Rect*>(rect) = *me->b++; - return 1; - } - return 0; - } - mutable Region::const_iterator b; - Region::const_iterator const e; - }; - - void copyBlt( - android_native_buffer_t* dst, void* dst_vaddr, - android_native_buffer_t* src, void const* src_vaddr, - const Region& clip); - - Rect dirtyRegion; - Rect oldDirtyRegion; + return reg; + } + bool isEmpty() const { + return count<=0; + } + private: + Rect storage[4]; + ssize_t count; + }; + + void copyBlt( + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Region& clip); + + Rect dirtyRegion; + Rect oldDirtyRegion; }; egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, - EGLConfig config, - int32_t depthFormat, - ANativeWindow* window) - : egl_surface_t(dpy, config, depthFormat), - nativeWindow(window), buffer(0), previousBuffer(0), module(0), - blitengine(0), bits(NULL) + EGLConfig config, + int32_t depthFormat, + ANativeWindow* window) +: egl_surface_t(dpy, config, depthFormat), + nativeWindow(window), buffer(0), previousBuffer(0), module(0), + bits(NULL) { - hw_module_t const* pModule; - hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); - module = reinterpret_cast<gralloc_module_t const*>(pModule); - - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) { - copybit_open(pModule, &blitengine); - } + pixelFormatTable = gglGetPixelFormatTable(); - pixelFormatTable = gglGetPixelFormatTable(); - - // keep a reference on the window - nativeWindow->common.incRef(&nativeWindow->common); - nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width); - nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height); - int format = 0; - nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format); - LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format); -// assert(0); + // keep a reference on the window + nativeWindow->common.incRef(&nativeWindow->common); + nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width); + nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height); + int format = 0; + nativeWindow->query(nativeWindow, NATIVE_WINDOW_FORMAT, &format); + LOGD("agl2: egl_window_surface_v2_t format=0x%.4X", format); + // assert(0); } egl_window_surface_v2_t::~egl_window_surface_v2_t() { - if (buffer) { - buffer->common.decRef(&buffer->common); - } - if (previousBuffer) { - previousBuffer->common.decRef(&previousBuffer->common); - } - nativeWindow->common.decRef(&nativeWindow->common); - if (blitengine) { - copybit_close(blitengine); - } + if (buffer) { + buffer->common.decRef(&buffer->common); + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + } + nativeWindow->common.decRef(&nativeWindow->common); } EGLBoolean egl_window_surface_v2_t::connect() { - // we're intending to do software rendering - native_window_set_usage(nativeWindow, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - - // dequeue a buffer - if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) { - return setError(EGL_BAD_ALLOC, EGL_FALSE); - } - - // allocate a corresponding depth-buffer - width = buffer->width; - height = buffer->height; - if (depth.format) { - depth.width = width; - depth.height = height; - depth.stride = depth.width; // use the width here - assert(GGL_PIXEL_FORMAT_Z_32 == depth.format); - depth.data = (GGLubyte*)malloc(depth.stride*depth.height*4); - if (depth.data == 0) { - return setError(EGL_BAD_ALLOC, EGL_FALSE); - } - } - - // keep a reference on the buffer - buffer->common.incRef(&buffer->common); - - // Lock the buffer - nativeWindow->lockBuffer(nativeWindow, buffer); - // pin the buffer down - if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + // we're intending to do software rendering + native_window_set_usage(nativeWindow, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + + // dequeue a buffer + if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) { + return setError(EGL_BAD_ALLOC, EGL_FALSE); + } + + // allocate a corresponding depth-buffer + width = buffer->width; + height = buffer->height; + if (depth.format) { + depth.width = width; + depth.height = height; + depth.stride = depth.width; // use the width here + assert(GGL_PIXEL_FORMAT_Z_32 == depth.format); + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*4); + if (depth.data == 0) { + return setError(EGL_BAD_ALLOC, EGL_FALSE); + } + } + + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); + + // Lock the buffer + nativeWindow->lockBuffer(nativeWindow, buffer); + // pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { - LOGE("connect() failed to lock buffer %p (%ux%u)", - buffer, buffer->width, buffer->height); - return setError(EGL_BAD_ACCESS, EGL_FALSE); - // FIXME: we should make sure we're not accessing the buffer anymore - } - return EGL_TRUE; + LOGE("connect() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + return setError(EGL_BAD_ACCESS, EGL_FALSE); + // FIXME: we should make sure we're not accessing the buffer anymore + } + return EGL_TRUE; } void egl_window_surface_v2_t::disconnect() { - if (buffer && bits) { - bits = NULL; - unlock(buffer); - } - // enqueue the last frame - if (buffer) - nativeWindow->queueBuffer(nativeWindow, buffer); - if (buffer) { - buffer->common.decRef(&buffer->common); - buffer = 0; - } - if (previousBuffer) { - previousBuffer->common.decRef(&previousBuffer->common); - previousBuffer = 0; - } + if (buffer && bits) { + bits = NULL; + unlock(buffer); + } + // enqueue the last frame + if (buffer) + nativeWindow->queueBuffer(nativeWindow, buffer); + if (buffer) { + buffer->common.decRef(&buffer->common); + buffer = 0; + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + previousBuffer = 0; + } } status_t egl_window_surface_v2_t::lock( - android_native_buffer_t* buf, int usage, void** vaddr) + android_native_buffer_t* buf, int usage, void** vaddr) { - int err; + int err; - err = module->lock(module, buf->handle, - usage, 0, 0, buf->width, buf->height, vaddr); + err = module->lock(module, buf->handle, + usage, 0, 0, buf->width, buf->height, vaddr); - return err; + return err; } status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) { - if (!buf) return BAD_VALUE; - int err = NO_ERROR; + if (!buf) return BAD_VALUE; + int err = NO_ERROR; - err = module->unlock(module, buf->handle); + err = module->unlock(module, buf->handle); - return err; + return err; } void egl_window_surface_v2_t::copyBlt( - android_native_buffer_t* dst, void* dst_vaddr, - android_native_buffer_t* src, void const* src_vaddr, - const Region& clip) -{ - // FIXME: use copybit if possible - // NOTE: dst and src must be the same format - - status_t err = NO_ERROR; - copybit_device_t* const copybit = blitengine; - if (copybit) { - copybit_image_t simg; - simg.w = src->stride; - simg.h = src->height; - simg.format = src->format; - simg.handle = const_cast<native_handle_t*>(src->handle); - - copybit_image_t dimg; - dimg.w = dst->stride; - dimg.h = dst->height; - dimg.format = dst->format; - dimg.handle = const_cast<native_handle_t*>(dst->handle); - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - region_iterator it(clip); - err = copybit->blit(copybit, &dimg, &simg, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } - } - - if (!copybit || err) { - Region::const_iterator cur = clip.begin(); - Region::const_iterator end = clip.end(); - - const size_t bpp = pixelFormatTable[src->format].size; - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; - - uint8_t const * const src_bits = (uint8_t const *)src_vaddr; - uint8_t * const dst_bits = (uint8_t *)dst_vaddr; - - while (cur != end) { - const Rect& r(*cur++); - ssize_t w = r.right - r.left; - ssize_t h = r.bottom - r.top; - if (w <= 0 || h<=0) continue; - size_t size = w * bpp; - uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Region& clip) +{ + // FIXME: use copybit if possible + // NOTE: dst and src must be the same format + + Region::const_iterator cur = clip.begin(); + Region::const_iterator end = clip.end(); + + const size_t bpp = pixelFormatTable[src->format].size; + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + uint8_t const * const src_bits = (uint8_t const *)src_vaddr; + uint8_t * const dst_bits = (uint8_t *)dst_vaddr; + + while (cur != end) { + const Rect& r(*cur++); + ssize_t w = r.right - r.left; + ssize_t h = r.bottom - r.top; + if (w <= 0 || h<=0) continue; + size_t size = w * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { size *= h; h = 1; - } - do { + } + do { memcpy(d, s, size); d += dbpr; s += sbpr; - } while (--h > 0); - } - } + } while (--h > 0); + } } EGLBoolean egl_window_surface_v2_t::swapBuffers() { - if (!buffer) { - return setError(EGL_BAD_ACCESS, EGL_FALSE); - } - - /* - * Handle eglSetSwapRectangleANDROID() - * We copyback from the front buffer - */ - if (!dirtyRegion.isEmpty()) { - dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); - if (previousBuffer) { - // This was const Region copyBack, but that causes an - // internal compile error on simulator builds - /*const*/ - Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); - if (!copyBack.isEmpty()) { - void* prevBits; - if (lock(previousBuffer, - GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) { - // copy from previousBuffer to buffer - copyBlt(buffer, bits, previousBuffer, prevBits, copyBack); - unlock(previousBuffer); + if (!buffer) { + return setError(EGL_BAD_ACCESS, EGL_FALSE); + } + + /* + * Handle eglSetSwapRectangleANDROID() + * We copyback from the front buffer + */ + if (!dirtyRegion.isEmpty()) { + dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); + if (previousBuffer) { + // This was const Region copyBack, but that causes an + // internal compile error on simulator builds + /*const*/ + Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); + if (!copyBack.isEmpty()) { + void* prevBits; + if (lock(previousBuffer, + GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) { + // copy from previousBuffer to buffer + copyBlt(buffer, bits, previousBuffer, prevBits, copyBack); + unlock(previousBuffer); + } } - } - } - oldDirtyRegion = dirtyRegion; - } - - if (previousBuffer) { - previousBuffer->common.decRef(&previousBuffer->common); - previousBuffer = 0; - } - - unlock(buffer); - previousBuffer = buffer; - nativeWindow->queueBuffer(nativeWindow, buffer); - buffer = 0; - - // dequeue a new buffer - if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) { - - // TODO: lockBuffer should rather be executed when the very first - // direct rendering occurs. - nativeWindow->lockBuffer(nativeWindow, buffer); - - // reallocate the depth-buffer if needed - if ((width != buffer->width) || (height != buffer->height)) { - // TODO: we probably should reset the swap rect here - // if the window size has changed - width = buffer->width; - height = buffer->height; - if (depth.data) { - free(depth.data); - depth.width = width; - depth.height = height; - depth.stride = buffer->stride; - depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); - if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_FALSE); - return EGL_FALSE; + } + oldDirtyRegion = dirtyRegion; + } + + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + previousBuffer = 0; + } + + unlock(buffer); + previousBuffer = buffer; + nativeWindow->queueBuffer(nativeWindow, buffer); + buffer = 0; + + // dequeue a new buffer + if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) { + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + nativeWindow->lockBuffer(nativeWindow, buffer); + + // reallocate the depth-buffer if needed + if ((width != buffer->width) || (height != buffer->height)) { + // TODO: we probably should reset the swap rect here + // if the window size has changed + width = buffer->width; + height = buffer->height; + if (depth.data) { + free(depth.data); + depth.width = width; + depth.height = height; + depth.stride = buffer->stride; + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; + } } - } - } + } - // keep a reference on the buffer - buffer->common.incRef(&buffer->common); + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); - // finally pin the buffer down - if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { - LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", - buffer, buffer->width, buffer->height); - return setError(EGL_BAD_ACCESS, EGL_FALSE); - // FIXME: we should make sure we're not accessing the buffer anymore - } - } else { - return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE); - } + // finally pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { + LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + return setError(EGL_BAD_ACCESS, EGL_FALSE); + // FIXME: we should make sure we're not accessing the buffer anymore + } + } else { + return setError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE); + } - return EGL_TRUE; + return EGL_TRUE; } EGLBoolean egl_window_surface_v2_t::setSwapRectangle( - EGLint l, EGLint t, EGLint w, EGLint h) + EGLint l, EGLint t, EGLint w, EGLint h) { - dirtyRegion = Rect(l, t, l+w, t+h); - return EGL_TRUE; + dirtyRegion = Rect(l, t, l+w, t+h); + return EGL_TRUE; } EGLBoolean egl_window_surface_v2_t::bindDrawSurface(GLES2Context* gl) { - GGLSurface buffer; - buffer.version = sizeof(GGLSurface); - buffer.width = this->buffer->width; - buffer.height = this->buffer->height; - buffer.stride = this->buffer->stride; - buffer.data = (GGLubyte*)bits; - buffer.format = (GGLPixelFormat)this->buffer->format; - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer); - if (depth.data != gl->rasterizer.depthSurface.data) - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)bits; + buffer.format = (GGLPixelFormat)this->buffer->format; + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer); + if (depth.data != gl->rasterizer.depthSurface.data) + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); - return EGL_TRUE; + return EGL_TRUE; } EGLBoolean egl_window_surface_v2_t::bindReadSurface(GLES2Context* gl) { - GGLSurface buffer; - buffer.version = sizeof(GGLSurface); - buffer.width = this->buffer->width; - buffer.height = this->buffer->height; - buffer.stride = this->buffer->stride; - buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! - buffer.format = (GGLPixelFormat)this->buffer->format; - puts("agl2: readBuffer not implemented"); - //gl->rasterizer.interface.readBuffer(gl, &buffer); - return EGL_TRUE; + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! + buffer.format = (GGLPixelFormat)this->buffer->format; + puts("agl2: readBuffer not implemented"); + //gl->rasterizer.interface.readBuffer(gl, &buffer); + return EGL_TRUE; } EGLint egl_window_surface_v2_t::getHorizontalResolution() const { - return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); + return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } EGLint egl_window_surface_v2_t::getVerticalResolution() const { - return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); + return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } EGLint egl_window_surface_v2_t::getRefreshRate() const { - return (60 * EGL_DISPLAY_SCALING); // FIXME + return (60 * EGL_DISPLAY_SCALING); // FIXME } EGLint egl_window_surface_v2_t::getSwapBehavior() const { - /* - * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves - * the content of the swapped buffer. - * - * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. - * - * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED - * only applies to the area specified by eglSetSwapRectangleANDROID(), that - * is, everything outside of this area is preserved. - * - * This implementation of EGL assumes the later case. - * - */ + /* + * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves + * the content of the swapped buffer. + * + * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. + * + * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED + * only applies to the area specified by eglSetSwapRectangleANDROID(), that + * is, everything outside of this area is preserved. + * + * This implementation of EGL assumes the later case. + * + */ - return EGL_BUFFER_DESTROYED; + return EGL_BUFFER_DESTROYED; } // ---------------------------------------------------------------------------- struct egl_pixmap_surface_t : public egl_surface_t { - egl_pixmap_surface_t( - EGLDisplay dpy, EGLConfig config, - int32_t depthFormat, - egl_native_pixmap_t const * pixmap); - - virtual ~egl_pixmap_surface_t() { } - - virtual bool initCheck() const { - return !depth.format || depth.data!=0; - } - virtual EGLBoolean bindDrawSurface(GLES2Context* gl); - virtual EGLBoolean bindReadSurface(GLES2Context* gl); - virtual EGLint getWidth() const { - return nativePixmap.width; - } - virtual EGLint getHeight() const { - return nativePixmap.height; - } + egl_pixmap_surface_t( + EGLDisplay dpy, EGLConfig config, + int32_t depthFormat, + egl_native_pixmap_t const * pixmap); + + virtual ~egl_pixmap_surface_t() { } + + virtual bool initCheck() const { + return !depth.format || depth.data!=0; + } + virtual EGLBoolean bindDrawSurface(GLES2Context* gl); + virtual EGLBoolean bindReadSurface(GLES2Context* gl); + virtual EGLint getWidth() const { + return nativePixmap.width; + } + virtual EGLint getHeight() const { + return nativePixmap.height; + } private: - egl_native_pixmap_t nativePixmap; + egl_native_pixmap_t nativePixmap; }; egl_pixmap_surface_t::egl_pixmap_surface_t(EGLDisplay dpy, - EGLConfig config, - int32_t depthFormat, - egl_native_pixmap_t const * pixmap) - : egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap) -{ - if (depthFormat) { - depth.width = pixmap->width; - depth.height = pixmap->height; - depth.stride = depth.width; // use the width here - depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); - if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - } - } + EGLConfig config, + int32_t depthFormat, + egl_native_pixmap_t const * pixmap) +: egl_surface_t(dpy, config, depthFormat), nativePixmap(*pixmap) +{ + if (depthFormat) { + depth.width = pixmap->width; + depth.height = pixmap->height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + } + } } EGLBoolean egl_pixmap_surface_t::bindDrawSurface(GLES2Context* gl) { - GGLSurface buffer; - buffer.version = sizeof(GGLSurface); - buffer.width = nativePixmap.width; - buffer.height = nativePixmap.height; - buffer.stride = nativePixmap.stride; - buffer.data = nativePixmap.data; - buffer.format = (GGLPixelFormat)nativePixmap.format; + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativePixmap.width; + buffer.height = nativePixmap.height; + buffer.stride = nativePixmap.stride; + buffer.data = nativePixmap.data; + buffer.format = (GGLPixelFormat)nativePixmap.format; - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer); - if (depth.data != gl->rasterizer.depthSurface.data) - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); - return EGL_TRUE; + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &buffer); + if (depth.data != gl->rasterizer.depthSurface.data) + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); + return EGL_TRUE; } EGLBoolean egl_pixmap_surface_t::bindReadSurface(GLES2Context* gl) { - GGLSurface buffer; - buffer.version = sizeof(GGLSurface); - buffer.width = nativePixmap.width; - buffer.height = nativePixmap.height; - buffer.stride = nativePixmap.stride; - buffer.data = nativePixmap.data; - buffer.format = (GGLPixelFormat)nativePixmap.format; - puts("agl2: readBuffer not implemented"); - //gl->rasterizer.interface.readBuffer(gl, &buffer); - return EGL_TRUE; + GGLSurface buffer; + buffer.version = sizeof(GGLSurface); + buffer.width = nativePixmap.width; + buffer.height = nativePixmap.height; + buffer.stride = nativePixmap.stride; + buffer.data = nativePixmap.data; + buffer.format = (GGLPixelFormat)nativePixmap.format; + puts("agl2: readBuffer not implemented"); + //gl->rasterizer.interface.readBuffer(gl, &buffer); + return EGL_TRUE; } // ---------------------------------------------------------------------------- struct egl_pbuffer_surface_t : public egl_surface_t { - egl_pbuffer_surface_t( - EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - int32_t w, int32_t h, int32_t f); - - virtual ~egl_pbuffer_surface_t(); - - virtual bool initCheck() const { - return pbuffer.data != 0; - } - virtual EGLBoolean bindDrawSurface(GLES2Context* gl); - virtual EGLBoolean bindReadSurface(GLES2Context* gl); - virtual EGLint getWidth() const { - return pbuffer.width; - } - virtual EGLint getHeight() const { - return pbuffer.height; - } + egl_pbuffer_surface_t( + EGLDisplay dpy, EGLConfig config, int32_t depthFormat, + int32_t w, int32_t h, int32_t f); + + virtual ~egl_pbuffer_surface_t(); + + virtual bool initCheck() const { + return pbuffer.data != 0; + } + virtual EGLBoolean bindDrawSurface(GLES2Context* gl); + virtual EGLBoolean bindReadSurface(GLES2Context* gl); + virtual EGLint getWidth() const { + return pbuffer.width; + } + virtual EGLint getHeight() const { + return pbuffer.height; + } private: - GGLSurface pbuffer; + GGLSurface pbuffer; }; egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, - EGLConfig config, int32_t depthFormat, - int32_t w, int32_t h, int32_t f) - : egl_surface_t(dpy, config, depthFormat) -{ - size_t size = w*h; - switch (f) { - case GGL_PIXEL_FORMAT_A_8: - size *= 1; - break; - case GGL_PIXEL_FORMAT_RGB_565: - size *= 2; - break; - case GGL_PIXEL_FORMAT_RGBA_8888: - size *= 4; - break; - case GGL_PIXEL_FORMAT_RGBX_8888: - size *= 4; - break; - default: - LOGE("incompatible pixel format for pbuffer (format=%d)", f); - pbuffer.data = 0; - break; - } - pbuffer.version = sizeof(GGLSurface); - pbuffer.width = w; - pbuffer.height = h; - pbuffer.stride = w; - pbuffer.data = (GGLubyte*)malloc(size); - pbuffer.format = (GGLPixelFormat)f; - - if (depthFormat) { - depth.width = pbuffer.width; - depth.height = pbuffer.height; - depth.stride = depth.width; // use the width here - depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); - if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - return; - } - } + EGLConfig config, int32_t depthFormat, + int32_t w, int32_t h, int32_t f) +: egl_surface_t(dpy, config, depthFormat) +{ + size_t size = w*h; + switch (f) { + case GGL_PIXEL_FORMAT_A_8: + size *= 1; + break; + case GGL_PIXEL_FORMAT_RGB_565: + size *= 2; + break; + case GGL_PIXEL_FORMAT_RGBA_8888: + size *= 4; + break; + case GGL_PIXEL_FORMAT_RGBX_8888: + size *= 4; + break; + default: + LOGE("incompatible pixel format for pbuffer (format=%d)", f); + pbuffer.data = 0; + break; + } + pbuffer.version = sizeof(GGLSurface); + pbuffer.width = w; + pbuffer.height = h; + pbuffer.stride = w; + pbuffer.data = (GGLubyte*)malloc(size); + pbuffer.format = (GGLPixelFormat)f; + + if (depthFormat) { + depth.width = pbuffer.width; + depth.height = pbuffer.height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return; + } + } } egl_pbuffer_surface_t::~egl_pbuffer_surface_t() { - free(pbuffer.data); + free(pbuffer.data); } EGLBoolean egl_pbuffer_surface_t::bindDrawSurface(GLES2Context* gl) { - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer); - if (depth.data != gl->rasterizer.depthSurface.data) - gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); - return EGL_TRUE; + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_COLOR_BUFFER_BIT, &pbuffer); + if (depth.data != gl->rasterizer.depthSurface.data) + gl->rasterizer.interface.SetBuffer(&gl->rasterizer.interface, GL_DEPTH_BUFFER_BIT, &depth); + return EGL_TRUE; } EGLBoolean egl_pbuffer_surface_t::bindReadSurface(GLES2Context* gl) { - puts("agl2: readBuffer not implemented"); - //gl->rasterizer.interface.readBuffer(gl, &pbuffer); - return EGL_TRUE; + puts("agl2: readBuffer not implemented"); + //gl->rasterizer.interface.readBuffer(gl, &pbuffer); + return EGL_TRUE; } // ---------------------------------------------------------------------------- struct config_pair_t { - GLint key; - GLint value; + GLint key; + GLint value; }; struct configs_t { - const config_pair_t* array; - int size; + const config_pair_t* array; + int size; }; struct config_management_t { - GLint key; - bool (*match)(GLint reqValue, GLint confValue); - static bool atLeast(GLint reqValue, GLint confValue) { - return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue); - } - static bool exact(GLint reqValue, GLint confValue) { - return (reqValue == EGL_DONT_CARE) || (confValue == reqValue); - } - static bool mask(GLint reqValue, GLint confValue) { - return (confValue & reqValue) == reqValue; - } - static bool ignore(GLint reqValue, GLint confValue) { - return true; - } + GLint key; + bool (*match)(GLint reqValue, GLint confValue); + static bool atLeast(GLint reqValue, GLint confValue) { + return (reqValue == EGL_DONT_CARE) || (confValue >= reqValue); + } + static bool exact(GLint reqValue, GLint confValue) { + return (reqValue == EGL_DONT_CARE) || (confValue == reqValue); + } + static bool mask(GLint reqValue, GLint confValue) { + return (confValue & reqValue) == reqValue; + } + static bool ignore(GLint reqValue, GLint confValue) { + return true; + } }; // ---------------------------------------------------------------------------- @@ -865,62 +806,62 @@ static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "0.0 Android Driver 0.0.0"; static char const * const gClientApiString = "OpenGL ES2"; static char const * const gExtensionsString = - //"EGL_KHR_image_base " - // "KHR_image_pixmap " - //"EGL_ANDROID_image_native_buffer " - //"EGL_ANDROID_swap_rectangle " - ""; + //"EGL_KHR_image_base " + // "KHR_image_pixmap " + //"EGL_ANDROID_image_native_buffer " + //"EGL_ANDROID_swap_rectangle " + ""; // ---------------------------------------------------------------------------- struct extention_map_t { - const char * const name; - __eglMustCastToProperFunctionPointerType address; + const char * const name; + __eglMustCastToProperFunctionPointerType address; }; static const extention_map_t gExtentionMap[] = { -// { "glDrawTexsOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, -// { "glDrawTexiOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, -// { "glDrawTexfOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, -// { "glDrawTexxOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, -// { "glDrawTexsvOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, -// { "glDrawTexivOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, -// { "glDrawTexfvOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, -// { "glDrawTexxvOES", -// (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, -// { "glQueryMatrixxOES", -// (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, -// { "glEGLImageTargetTexture2DOES", -// (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, -// { "glEGLImageTargetRenderbufferStorageOES", -// (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, -// { "glClipPlanef", -// (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, -// { "glClipPlanex", -// (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, -// { "glBindBuffer", -// (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, -// { "glBufferData", -// (__eglMustCastToProperFunctionPointerType)&glBufferData }, -// { "glBufferSubData", -// (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, -// { "glDeleteBuffers", -// (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, -// { "glGenBuffers", -// (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, -// { "eglCreateImageKHR", -// (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, -// { "eglDestroyImageKHR", -// (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, -// { "eglSetSwapRectangleANDROID", -// (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, + // { "glDrawTexsOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, + // { "glDrawTexiOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, + // { "glDrawTexfOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, + // { "glDrawTexxOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, + // { "glDrawTexsvOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, + // { "glDrawTexivOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, + // { "glDrawTexfvOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, + // { "glDrawTexxvOES", + // (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, + // { "glQueryMatrixxOES", + // (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, + // { "glEGLImageTargetTexture2DOES", + // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, + // { "glEGLImageTargetRenderbufferStorageOES", + // (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, + // { "glClipPlanef", + // (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, + // { "glClipPlanex", + // (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, + // { "glBindBuffer", + // (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, + // { "glBufferData", + // (__eglMustCastToProperFunctionPointerType)&glBufferData }, + // { "glBufferSubData", + // (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, + // { "glDeleteBuffers", + // (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, + // { "glGenBuffers", + // (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, + // { "eglCreateImageKHR", + // (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, + // { "eglDestroyImageKHR", + // (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, + // { "eglSetSwapRectangleANDROID", + // (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, }; /* @@ -930,31 +871,31 @@ static const extention_map_t gExtentionMap[] = { */ static config_pair_t const config_base_attribute_list[] = { - { EGL_STENCIL_SIZE, 0 }, - { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, - { EGL_LEVEL, 0 }, - { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, - { EGL_MAX_PBUFFER_PIXELS, - GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, - { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, - { EGL_NATIVE_RENDERABLE, EGL_TRUE }, - { EGL_NATIVE_VISUAL_ID, 0 }, - { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 }, - { EGL_SAMPLES, 0 }, - { EGL_SAMPLE_BUFFERS, 0 }, - { EGL_TRANSPARENT_TYPE, EGL_NONE }, - { EGL_TRANSPARENT_BLUE_VALUE, 0 }, - { EGL_TRANSPARENT_GREEN_VALUE, 0 }, - { EGL_TRANSPARENT_RED_VALUE, 0 }, - { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE }, - { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE }, - { EGL_MIN_SWAP_INTERVAL, 1 }, - { EGL_MAX_SWAP_INTERVAL, 1 }, - { EGL_LUMINANCE_SIZE, 0 }, - { EGL_ALPHA_MASK_SIZE, 0 }, - { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER }, - { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT }, - { EGL_CONFORMANT, 0 } + { EGL_STENCIL_SIZE, 0 }, + { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, + { EGL_LEVEL, 0 }, + { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, + { EGL_MAX_PBUFFER_PIXELS, + GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, + { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, + { EGL_NATIVE_RENDERABLE, EGL_TRUE }, + { EGL_NATIVE_VISUAL_ID, 0 }, + { EGL_NATIVE_VISUAL_TYPE, GGL_PIXEL_FORMAT_RGBA_8888 }, + { EGL_SAMPLES, 0 }, + { EGL_SAMPLE_BUFFERS, 0 }, + { EGL_TRANSPARENT_TYPE, EGL_NONE }, + { EGL_TRANSPARENT_BLUE_VALUE, 0 }, + { EGL_TRANSPARENT_GREEN_VALUE, 0 }, + { EGL_TRANSPARENT_RED_VALUE, 0 }, + { EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE }, + { EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE }, + { EGL_MIN_SWAP_INTERVAL, 1 }, + { EGL_MAX_SWAP_INTERVAL, 1 }, + { EGL_LUMINANCE_SIZE, 0 }, + { EGL_ALPHA_MASK_SIZE, 0 }, + { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER }, + { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT }, + { EGL_CONFORMANT, 0 } }; // These configs can override the base attribute list @@ -962,199 +903,199 @@ static config_pair_t const config_base_attribute_list[] = { // 565 configs static config_pair_t const config_0_attribute_list[] = { - { EGL_BUFFER_SIZE, 16 }, - { EGL_ALPHA_SIZE, 0 }, - { EGL_BLUE_SIZE, 5 }, - { EGL_GREEN_SIZE, 6 }, - { EGL_RED_SIZE, 5 }, - { EGL_DEPTH_SIZE, 0 }, - { EGL_CONFIG_ID, 0 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 16 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 5 }, + { EGL_GREEN_SIZE, 6 }, + { EGL_RED_SIZE, 5 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 0 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; static config_pair_t const config_1_attribute_list[] = { - { EGL_BUFFER_SIZE, 16 }, - { EGL_ALPHA_SIZE, 0 }, - { EGL_BLUE_SIZE, 5 }, - { EGL_GREEN_SIZE, 6 }, - { EGL_RED_SIZE, 5 }, - { EGL_DEPTH_SIZE, 16 }, - { EGL_CONFIG_ID, 1 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 16 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 5 }, + { EGL_GREEN_SIZE, 6 }, + { EGL_RED_SIZE, 5 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 1 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGB_565 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; // RGB 888 configs static config_pair_t const config_2_attribute_list[] = { - { EGL_BUFFER_SIZE, 32 }, - { EGL_ALPHA_SIZE, 0 }, - { EGL_BLUE_SIZE, 8 }, - { EGL_GREEN_SIZE, 8 }, - { EGL_RED_SIZE, 8 }, - { EGL_DEPTH_SIZE, 0 }, - { EGL_CONFIG_ID, 6 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 6 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; static config_pair_t const config_3_attribute_list[] = { - { EGL_BUFFER_SIZE, 32 }, - { EGL_ALPHA_SIZE, 0 }, - { EGL_BLUE_SIZE, 8 }, - { EGL_GREEN_SIZE, 8 }, - { EGL_RED_SIZE, 8 }, - { EGL_DEPTH_SIZE, 16 }, - { EGL_CONFIG_ID, 7 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 0 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 7 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBX_8888 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; // 8888 configs static config_pair_t const config_4_attribute_list[] = { - { EGL_BUFFER_SIZE, 32 }, - { EGL_ALPHA_SIZE, 8 }, - { EGL_BLUE_SIZE, 8 }, - { EGL_GREEN_SIZE, 8 }, - { EGL_RED_SIZE, 8 }, - { EGL_DEPTH_SIZE, 0 }, - { EGL_CONFIG_ID, 2 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 2 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; static config_pair_t const config_5_attribute_list[] = { - { EGL_BUFFER_SIZE, 32 }, - { EGL_ALPHA_SIZE, 8 }, - { EGL_BLUE_SIZE, 8 }, - { EGL_GREEN_SIZE, 8 }, - { EGL_RED_SIZE, 8 }, - { EGL_DEPTH_SIZE, 16 }, - { EGL_CONFIG_ID, 3 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 32 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 8 }, + { EGL_GREEN_SIZE, 8 }, + { EGL_RED_SIZE, 8 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 3 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_RGBA_8888 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; // A8 configs static config_pair_t const config_6_attribute_list[] = { - { EGL_BUFFER_SIZE, 8 }, - { EGL_ALPHA_SIZE, 8 }, - { EGL_BLUE_SIZE, 0 }, - { EGL_GREEN_SIZE, 0 }, - { EGL_RED_SIZE, 0 }, - { EGL_DEPTH_SIZE, 0 }, - { EGL_CONFIG_ID, 4 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 8 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 0 }, + { EGL_GREEN_SIZE, 0 }, + { EGL_RED_SIZE, 0 }, + { EGL_DEPTH_SIZE, 0 }, + { EGL_CONFIG_ID, 4 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; static config_pair_t const config_7_attribute_list[] = { - { EGL_BUFFER_SIZE, 8 }, - { EGL_ALPHA_SIZE, 8 }, - { EGL_BLUE_SIZE, 0 }, - { EGL_GREEN_SIZE, 0 }, - { EGL_RED_SIZE, 0 }, - { EGL_DEPTH_SIZE, 16 }, - { EGL_CONFIG_ID, 5 }, - { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, - { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, + { EGL_BUFFER_SIZE, 8 }, + { EGL_ALPHA_SIZE, 8 }, + { EGL_BLUE_SIZE, 0 }, + { EGL_GREEN_SIZE, 0 }, + { EGL_RED_SIZE, 0 }, + { EGL_DEPTH_SIZE, 16 }, + { EGL_CONFIG_ID, 5 }, + { EGL_NATIVE_VISUAL_ID, GGL_PIXEL_FORMAT_A_8 }, + { EGL_SURFACE_TYPE, EGL_SWAP_BEHAVIOR_PRESERVED_BIT|EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT }, }; static configs_t const gConfigs[] = { - { config_0_attribute_list, NELEM(config_0_attribute_list) }, - { config_1_attribute_list, NELEM(config_1_attribute_list) }, - { config_2_attribute_list, NELEM(config_2_attribute_list) }, - { config_3_attribute_list, NELEM(config_3_attribute_list) }, - { config_4_attribute_list, NELEM(config_4_attribute_list) }, - { config_5_attribute_list, NELEM(config_5_attribute_list) }, -// { config_6_attribute_list, NELEM(config_6_attribute_list) }, -// { config_7_attribute_list, NELEM(config_7_attribute_list) }, + { config_0_attribute_list, NELEM(config_0_attribute_list) }, + { config_1_attribute_list, NELEM(config_1_attribute_list) }, + { config_2_attribute_list, NELEM(config_2_attribute_list) }, + { config_3_attribute_list, NELEM(config_3_attribute_list) }, + { config_4_attribute_list, NELEM(config_4_attribute_list) }, + { config_5_attribute_list, NELEM(config_5_attribute_list) }, + // { config_6_attribute_list, NELEM(config_6_attribute_list) }, + // { config_7_attribute_list, NELEM(config_7_attribute_list) }, }; static config_management_t const gConfigManagement[] = { - { EGL_BUFFER_SIZE, config_management_t::atLeast }, - { EGL_ALPHA_SIZE, config_management_t::atLeast }, - { EGL_BLUE_SIZE, config_management_t::atLeast }, - { EGL_GREEN_SIZE, config_management_t::atLeast }, - { EGL_RED_SIZE, config_management_t::atLeast }, - { EGL_DEPTH_SIZE, config_management_t::atLeast }, - { EGL_STENCIL_SIZE, config_management_t::atLeast }, - { EGL_CONFIG_CAVEAT, config_management_t::exact }, - { EGL_CONFIG_ID, config_management_t::exact }, - { EGL_LEVEL, config_management_t::exact }, - { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore }, - { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore }, - { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore }, - { EGL_NATIVE_RENDERABLE, config_management_t::exact }, - { EGL_NATIVE_VISUAL_ID, config_management_t::ignore }, - { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact }, - { EGL_SAMPLES, config_management_t::exact }, - { EGL_SAMPLE_BUFFERS, config_management_t::exact }, - { EGL_SURFACE_TYPE, config_management_t::mask }, - { EGL_TRANSPARENT_TYPE, config_management_t::exact }, - { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact }, - { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact }, - { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact }, - { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact }, - { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact }, - { EGL_MIN_SWAP_INTERVAL, config_management_t::exact }, - { EGL_MAX_SWAP_INTERVAL, config_management_t::exact }, - { EGL_LUMINANCE_SIZE, config_management_t::atLeast }, - { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast }, - { EGL_COLOR_BUFFER_TYPE, config_management_t::exact }, - { EGL_RENDERABLE_TYPE, config_management_t::mask }, - { EGL_CONFORMANT, config_management_t::mask } + { EGL_BUFFER_SIZE, config_management_t::atLeast }, + { EGL_ALPHA_SIZE, config_management_t::atLeast }, + { EGL_BLUE_SIZE, config_management_t::atLeast }, + { EGL_GREEN_SIZE, config_management_t::atLeast }, + { EGL_RED_SIZE, config_management_t::atLeast }, + { EGL_DEPTH_SIZE, config_management_t::atLeast }, + { EGL_STENCIL_SIZE, config_management_t::atLeast }, + { EGL_CONFIG_CAVEAT, config_management_t::exact }, + { EGL_CONFIG_ID, config_management_t::exact }, + { EGL_LEVEL, config_management_t::exact }, + { EGL_MAX_PBUFFER_HEIGHT, config_management_t::ignore }, + { EGL_MAX_PBUFFER_PIXELS, config_management_t::ignore }, + { EGL_MAX_PBUFFER_WIDTH, config_management_t::ignore }, + { EGL_NATIVE_RENDERABLE, config_management_t::exact }, + { EGL_NATIVE_VISUAL_ID, config_management_t::ignore }, + { EGL_NATIVE_VISUAL_TYPE, config_management_t::exact }, + { EGL_SAMPLES, config_management_t::exact }, + { EGL_SAMPLE_BUFFERS, config_management_t::exact }, + { EGL_SURFACE_TYPE, config_management_t::mask }, + { EGL_TRANSPARENT_TYPE, config_management_t::exact }, + { EGL_TRANSPARENT_BLUE_VALUE, config_management_t::exact }, + { EGL_TRANSPARENT_GREEN_VALUE, config_management_t::exact }, + { EGL_TRANSPARENT_RED_VALUE, config_management_t::exact }, + { EGL_BIND_TO_TEXTURE_RGBA, config_management_t::exact }, + { EGL_BIND_TO_TEXTURE_RGB, config_management_t::exact }, + { EGL_MIN_SWAP_INTERVAL, config_management_t::exact }, + { EGL_MAX_SWAP_INTERVAL, config_management_t::exact }, + { EGL_LUMINANCE_SIZE, config_management_t::atLeast }, + { EGL_ALPHA_MASK_SIZE, config_management_t::atLeast }, + { EGL_COLOR_BUFFER_TYPE, config_management_t::exact }, + { EGL_RENDERABLE_TYPE, config_management_t::mask }, + { EGL_CONFORMANT, config_management_t::mask } }; static config_pair_t const config_defaults[] = { - // attributes that are not specified are simply ignored, if a particular - // one needs not be ignored, it must be specified here, eg: - // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT }, + // attributes that are not specified are simply ignored, if a particular + // one needs not be ignored, it must be specified here, eg: + // { EGL_SURFACE_TYPE, EGL_WINDOW_BIT }, }; // ---------------------------------------------------------------------------- static status_t getConfigFormatInfo(EGLint configID, - int32_t& pixelFormat, int32_t& depthFormat) -{ - switch (configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; - depthFormat = 0; - break; - case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; - depthFormat = GGL_PIXEL_FORMAT_Z_32; - break; - case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; - depthFormat = 0; - break; - case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; - depthFormat = GGL_PIXEL_FORMAT_Z_32; - break; - case 4: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; - depthFormat = 0; - break; - case 5: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; - depthFormat = GGL_PIXEL_FORMAT_Z_32; - break; - case 6: - pixelFormat = GGL_PIXEL_FORMAT_A_8; - depthFormat = 0; - break; - case 7: - pixelFormat = GGL_PIXEL_FORMAT_A_8; - depthFormat = GGL_PIXEL_FORMAT_Z_32; - break; - default: - return NAME_NOT_FOUND; - } - return NO_ERROR; + int32_t& pixelFormat, int32_t& depthFormat) +{ + switch (configID) { + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = 0; + break; + case 1: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + depthFormat = GGL_PIXEL_FORMAT_Z_32; + break; + case 2: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = 0; + break; + case 3: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = GGL_PIXEL_FORMAT_Z_32; + break; + case 4: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = 0; + break; + case 5: + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + depthFormat = GGL_PIXEL_FORMAT_Z_32; + break; + case 6: + pixelFormat = GGL_PIXEL_FORMAT_A_8; + depthFormat = 0; + break; + case 7: + pixelFormat = GGL_PIXEL_FORMAT_A_8; + depthFormat = GGL_PIXEL_FORMAT_Z_32; + break; + default: + return NAME_NOT_FOUND; + } + return NO_ERROR; } // ---------------------------------------------------------------------------- @@ -1162,256 +1103,256 @@ static status_t getConfigFormatInfo(EGLint configID, template<typename T> static int binarySearch(T const sortedArray[], int first, int last, EGLint key) { - while (first <= last) { - int mid = (first + last) / 2; - if (key > sortedArray[mid].key) { - first = mid + 1; - } else if (key < sortedArray[mid].key) { - last = mid - 1; - } else { - return mid; - } - } - return -1; + while (first <= last) { + int mid = (first + last) / 2; + if (key > sortedArray[mid].key) { + first = mid + 1; + } else if (key < sortedArray[mid].key) { + last = mid - 1; + } else { + return mid; + } + } + return -1; } static int isAttributeMatching(int i, EGLint attr, EGLint val) { - // look for the attribute in all of our configs - config_pair_t const* configFound = gConfigs[i].array; - int index = binarySearch<config_pair_t>( - gConfigs[i].array, - 0, gConfigs[i].size-1, - attr); - if (index < 0) { - configFound = config_base_attribute_list; - index = binarySearch<config_pair_t>( - config_base_attribute_list, - 0, NELEM(config_base_attribute_list)-1, - attr); - } - if (index >= 0) { - // attribute found, check if this config could match - int cfgMgtIndex = binarySearch<config_management_t>( - gConfigManagement, - 0, NELEM(gConfigManagement)-1, - attr); - if (cfgMgtIndex >= 0) { - bool match = gConfigManagement[cfgMgtIndex].match( - val, configFound[index].value); - if (match) { - // this config matches - return 1; - } - } else { - // attribute not found. this should NEVER happen. - } - } else { - // error, this attribute doesn't exist - } - return 0; + // look for the attribute in all of our configs + config_pair_t const* configFound = gConfigs[i].array; + int index = binarySearch<config_pair_t>( + gConfigs[i].array, + 0, gConfigs[i].size-1, + attr); + if (index < 0) { + configFound = config_base_attribute_list; + index = binarySearch<config_pair_t>( + config_base_attribute_list, + 0, NELEM(config_base_attribute_list)-1, + attr); + } + if (index >= 0) { + // attribute found, check if this config could match + int cfgMgtIndex = binarySearch<config_management_t>( + gConfigManagement, + 0, NELEM(gConfigManagement)-1, + attr); + if (cfgMgtIndex >= 0) { + bool match = gConfigManagement[cfgMgtIndex].match( + val, configFound[index].value); + if (match) { + // this config matches + return 1; + } + } else { + // attribute not found. this should NEVER happen. + } + } else { + // error, this attribute doesn't exist + } + return 0; } static int makeCurrent(GLES2Context* gl) { - GLES2Context* current = (GLES2Context*)getGlThreadSpecific(); - if (gl) { - egl_context_t* c = egl_context_t::context(gl); - if (c->flags & egl_context_t::IS_CURRENT) { - if (current != gl) { - // it is an error to set a context current, if it's already - // current to another thread - return -1; - } - } else { - if (current) { + GLES2Context* current = (GLES2Context*)getGlThreadSpecific(); + if (gl) { + egl_context_t* c = egl_context_t::context(gl); + if (c->flags & egl_context_t::IS_CURRENT) { + if (current != gl) { + // it is an error to set a context current, if it's already + // current to another thread + return -1; + } + } else { + if (current) { + // mark the current context as not current, and flush + glFlush(); + egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; + } + } + if (!(c->flags & egl_context_t::IS_CURRENT)) { + // The context is not current, make it current! + setGlThreadSpecific(gl); + c->flags |= egl_context_t::IS_CURRENT; + } + } else { + if (current) { // mark the current context as not current, and flush glFlush(); egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; - } - } - if (!(c->flags & egl_context_t::IS_CURRENT)) { - // The context is not current, make it current! - setGlThreadSpecific(gl); - c->flags |= egl_context_t::IS_CURRENT; - } - } else { - if (current) { - // mark the current context as not current, and flush - glFlush(); - egl_context_t::context(current)->flags &= ~egl_context_t::IS_CURRENT; - } - // this thread has no context attached to it - setGlThreadSpecific(0); - } - return 0; + } + // this thread has no context attached to it + setGlThreadSpecific(0); + } + return 0; } static EGLBoolean getConfigAttrib(EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value) -{ - size_t numConfigs = NELEM(gConfigs); - int index = (int)config; - if (uint32_t(index) >= numConfigs) - return setError(EGL_BAD_CONFIG, EGL_FALSE); - - int attrIndex; - attrIndex = binarySearch<config_pair_t>( - gConfigs[index].array, - 0, gConfigs[index].size-1, - attribute); - if (attrIndex>=0) { - *value = gConfigs[index].array[attrIndex].value; - return EGL_TRUE; - } - - attrIndex = binarySearch<config_pair_t>( - config_base_attribute_list, - 0, NELEM(config_base_attribute_list)-1, - attribute); - if (attrIndex>=0) { - *value = config_base_attribute_list[attrIndex].value; - return EGL_TRUE; - } - return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + EGLint attribute, EGLint *value) +{ + size_t numConfigs = NELEM(gConfigs); + int index = (int)config; + if (uint32_t(index) >= numConfigs) + return setError(EGL_BAD_CONFIG, EGL_FALSE); + + int attrIndex; + attrIndex = binarySearch<config_pair_t>( + gConfigs[index].array, + 0, gConfigs[index].size-1, + attribute); + if (attrIndex>=0) { + *value = gConfigs[index].array[attrIndex].value; + return EGL_TRUE; + } + + attrIndex = binarySearch<config_pair_t>( + config_base_attribute_list, + 0, NELEM(config_base_attribute_list)-1, + attribute); + if (attrIndex>=0) { + *value = config_base_attribute_list[attrIndex].value; + return EGL_TRUE; + } + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); } static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, - NativeWindowType window, const EGLint *attrib_list) -{ - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - if (window == 0) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - - EGLint surfaceType; - if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) - return EGL_FALSE; - - if (!(surfaceType & EGL_WINDOW_BIT)) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - - if (reinterpret_cast<ANativeWindow*>(window)->common.magic != - ANDROID_NATIVE_WINDOW_MAGIC) { - return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } - - EGLint configID; - if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) - return EGL_FALSE; - - int32_t depthFormat; - int32_t pixelFormat; - if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - } - - // FIXME: we don't have access to the pixelFormat here just yet. - // (it's possible that the surface is not fully initialized) - // maybe this should be done after the page-flip - //if (EGLint(info.format) != pixelFormat) - // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - - egl_surface_t* surface; - surface = new egl_window_surface_v2_t(dpy, config, depthFormat, - reinterpret_cast<ANativeWindow*>(window)); - - if (!surface->initCheck()) { - // there was a problem in the ctor, the error - // flag has been set. - delete surface; - surface = 0; - } - return surface; + NativeWindowType window, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + if (window == 0) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; + + if (!(surfaceType & EGL_WINDOW_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + if (reinterpret_cast<ANativeWindow*>(window)->common.magic != + ANDROID_NATIVE_WINDOW_MAGIC) { + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; + + int32_t depthFormat; + int32_t pixelFormat; + if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } + + // FIXME: we don't have access to the pixelFormat here just yet. + // (it's possible that the surface is not fully initialized) + // maybe this should be done after the page-flip + //if (EGLint(info.format) != pixelFormat) + // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + + egl_surface_t* surface; + surface = new egl_window_surface_v2_t(dpy, config, depthFormat, + reinterpret_cast<ANativeWindow*>(window)); + + if (!surface->initCheck()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; } static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, - NativePixmapType pixmap, const EGLint *attrib_list) + NativePixmapType pixmap, const EGLint *attrib_list) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - if (pixmap == 0) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + if (pixmap == 0) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - EGLint surfaceType; - if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) - return EGL_FALSE; + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; - if (!(surfaceType & EGL_PIXMAP_BIT)) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + if (!(surfaceType & EGL_PIXMAP_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version != - sizeof(egl_native_pixmap_t)) { - return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); - } + if (reinterpret_cast<egl_native_pixmap_t*>(pixmap)->version != + sizeof(egl_native_pixmap_t)) { + return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); + } - EGLint configID; - if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) - return EGL_FALSE; + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; - int32_t depthFormat; - int32_t pixelFormat; - if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - } + int32_t depthFormat; + int32_t pixelFormat; + if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } - if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + if (reinterpret_cast<egl_native_pixmap_t *>(pixmap)->format != pixelFormat) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - egl_surface_t* surface = - new egl_pixmap_surface_t(dpy, config, depthFormat, - reinterpret_cast<egl_native_pixmap_t*>(pixmap)); + egl_surface_t* surface = + new egl_pixmap_surface_t(dpy, config, depthFormat, + reinterpret_cast<egl_native_pixmap_t*>(pixmap)); - if (!surface->initCheck()) { - // there was a problem in the ctor, the error - // flag has been set. - delete surface; - surface = 0; - } - return surface; + if (!surface->initCheck()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; } static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list) + const EGLint *attrib_list) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - EGLint surfaceType; - if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) - return EGL_FALSE; + EGLint surfaceType; + if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) + return EGL_FALSE; - if (!(surfaceType & EGL_PBUFFER_BIT)) - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + if (!(surfaceType & EGL_PBUFFER_BIT)) + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - EGLint configID; - if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) - return EGL_FALSE; + EGLint configID; + if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) + return EGL_FALSE; - int32_t depthFormat; - int32_t pixelFormat; - if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { - return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - } + int32_t depthFormat; + int32_t pixelFormat; + if (getConfigFormatInfo(configID, pixelFormat, depthFormat) != NO_ERROR) { + return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); + } - int32_t w = 0; - int32_t h = 0; - while (attrib_list[0]) { - if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; - if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; - attrib_list+=2; - } + int32_t w = 0; + int32_t h = 0; + while (attrib_list[0]) { + if (attrib_list[0] == EGL_WIDTH) w = attrib_list[1]; + if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1]; + attrib_list+=2; + } - egl_surface_t* surface = - new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat); + egl_surface_t* surface = + new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat); - if (!surface->initCheck()) { - // there was a problem in the ctor, the error - // flag has been set. - delete surface; - surface = 0; - } - return surface; + if (!surface->initCheck()) { + // there was a problem in the ctor, the error + // flag has been set. + delete surface; + surface = 0; + } + return surface; } // ---------------------------------------------------------------------------- @@ -1426,61 +1367,61 @@ using namespace android; EGLDisplay eglGetDisplay(NativeDisplayType display) { - puts("agl2:eglGetDisplay"); + puts("agl2:eglGetDisplay"); #ifndef HAVE_ANDROID_OS - // this just needs to be done once - if (gGLKey == -1) { - pthread_mutex_lock(&gInitMutex); - if (gGLKey == -1) - pthread_key_create(&gGLKey, NULL); - pthread_mutex_unlock(&gInitMutex); - } + // this just needs to be done once + if (gGLKey == -1) { + pthread_mutex_lock(&gInitMutex); + if (gGLKey == -1) + pthread_key_create(&gGLKey, NULL); + pthread_mutex_unlock(&gInitMutex); + } #endif - if (display == EGL_DEFAULT_DISPLAY) { - EGLDisplay dpy = (EGLDisplay)1; - egl_display_t& d = egl_display_t::get_display(dpy); - d.type = display; - return dpy; - } - return EGL_NO_DISPLAY; + if (display == EGL_DEFAULT_DISPLAY) { + EGLDisplay dpy = (EGLDisplay)1; + egl_display_t& d = egl_display_t::get_display(dpy); + d.type = display; + return dpy; + } + return EGL_NO_DISPLAY; } EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { - puts("agl2:eglInitialize"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); + puts("agl2:eglInitialize"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); - EGLBoolean res = EGL_TRUE; - egl_display_t& d = egl_display_t::get_display(dpy); + EGLBoolean res = EGL_TRUE; + egl_display_t& d = egl_display_t::get_display(dpy); - if (android_atomic_inc(&d.initialized) == 0) { - // initialize stuff here if needed - //pthread_mutex_lock(&gInitMutex); - //pthread_mutex_unlock(&gInitMutex); - } + if (android_atomic_inc(&d.initialized) == 0) { + // initialize stuff here if needed + //pthread_mutex_lock(&gInitMutex); + //pthread_mutex_unlock(&gInitMutex); + } - if (res == EGL_TRUE) { - if (major != NULL) *major = VERSION_MAJOR; - if (minor != NULL) *minor = VERSION_MINOR; - } - return res; + if (res == EGL_TRUE) { + if (major != NULL) *major = VERSION_MAJOR; + if (minor != NULL) *minor = VERSION_MINOR; + } + return res; } EGLBoolean eglTerminate(EGLDisplay dpy) { - puts("agl2:eglTerminate"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); + puts("agl2:eglTerminate"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); - EGLBoolean res = EGL_TRUE; - egl_display_t& d = egl_display_t::get_display(dpy); - if (android_atomic_dec(&d.initialized) == 1) { - // TODO: destroy all resources (surfaces, contexts, etc...) - //pthread_mutex_lock(&gInitMutex); - //pthread_mutex_unlock(&gInitMutex); - } - return res; + EGLBoolean res = EGL_TRUE; + egl_display_t& d = egl_display_t::get_display(dpy); + if (android_atomic_dec(&d.initialized) == 1) { + // TODO: destroy all resources (surfaces, contexts, etc...) + //pthread_mutex_lock(&gInitMutex); + //pthread_mutex_unlock(&gInitMutex); + } + return res; } // ---------------------------------------------------------------------------- @@ -1488,166 +1429,166 @@ EGLBoolean eglTerminate(EGLDisplay dpy) // ---------------------------------------------------------------------------- EGLBoolean eglGetConfigs( EGLDisplay dpy, - EGLConfig *configs, - EGLint config_size, EGLint *num_config) -{ - puts("agl2:eglGetConfigs"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - - GLint numConfigs = NELEM(gConfigs); - if (!configs) { - *num_config = numConfigs; - return EGL_TRUE; - } - GLint i; - for (i=0 ; i<numConfigs && i<config_size ; i++) { - *configs++ = (EGLConfig)i; - } - *num_config = i; - return EGL_TRUE; + EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + puts("agl2:eglGetConfigs"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + GLint numConfigs = NELEM(gConfigs); + if (!configs) { + *num_config = numConfigs; + return EGL_TRUE; + } + GLint i; + for (i=0 ; i<numConfigs && i<config_size ; i++) { + *configs++ = (EGLConfig)i; + } + *num_config = i; + return EGL_TRUE; } static const char * ATTRIBUTE_NAMES [] = { - "EGL_BUFFER_SIZE", - "EGL_ALPHA_SIZE", - "EGL_BLUE_SIZE", - "EGL_GREEN_SIZE", - "EGL_RED_SIZE", - "EGL_DEPTH_SIZE", - "EGL_STENCIL_SIZE", - "EGL_CONFIG_CAVEAT", - "EGL_CONFIG_ID", - "EGL_LEVEL", - "EGL_MAX_PBUFFER_HEIGHT", - "EGL_MAX_PBUFFER_PIXELS", - "EGL_MAX_PBUFFER_WIDTH", - "EGL_NATIVE_RENDERABLE", - "EGL_NATIVE_VISUAL_ID", - "EGL_NATIVE_VISUAL_TYPE", - "EGL_PRESERVED_RESOURCES", - "EGL_SAMPLES", - "EGL_SAMPLE_BUFFERS", - "EGL_SURFACE_TYPE", - "EGL_TRANSPARENT_TYPE", - "EGL_TRANSPARENT_BLUE_VALUE", - "EGL_TRANSPARENT_GREEN_VALUE", - "EGL_TRANSPARENT_RED_VALUE", - "EGL_NONE", /* Attrib list terminator */ - "EGL_BIND_TO_TEXTURE_RGB", - "EGL_BIND_TO_TEXTURE_RGBA", - "EGL_MIN_SWAP_INTERVAL", - "EGL_MAX_SWAP_INTERVAL", - "EGL_LUMINANCE_SIZE", - "EGL_ALPHA_MASK_SIZE", - "EGL_COLOR_BUFFER_TYPE", - "EGL_RENDERABLE_TYPE", - "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */ - "EGL_CONFORMANT", + "EGL_BUFFER_SIZE", + "EGL_ALPHA_SIZE", + "EGL_BLUE_SIZE", + "EGL_GREEN_SIZE", + "EGL_RED_SIZE", + "EGL_DEPTH_SIZE", + "EGL_STENCIL_SIZE", + "EGL_CONFIG_CAVEAT", + "EGL_CONFIG_ID", + "EGL_LEVEL", + "EGL_MAX_PBUFFER_HEIGHT", + "EGL_MAX_PBUFFER_PIXELS", + "EGL_MAX_PBUFFER_WIDTH", + "EGL_NATIVE_RENDERABLE", + "EGL_NATIVE_VISUAL_ID", + "EGL_NATIVE_VISUAL_TYPE", + "EGL_PRESERVED_RESOURCES", + "EGL_SAMPLES", + "EGL_SAMPLE_BUFFERS", + "EGL_SURFACE_TYPE", + "EGL_TRANSPARENT_TYPE", + "EGL_TRANSPARENT_BLUE_VALUE", + "EGL_TRANSPARENT_GREEN_VALUE", + "EGL_TRANSPARENT_RED_VALUE", + "EGL_NONE", /* Attrib list terminator */ + "EGL_BIND_TO_TEXTURE_RGB", + "EGL_BIND_TO_TEXTURE_RGBA", + "EGL_MIN_SWAP_INTERVAL", + "EGL_MAX_SWAP_INTERVAL", + "EGL_LUMINANCE_SIZE", + "EGL_ALPHA_MASK_SIZE", + "EGL_COLOR_BUFFER_TYPE", + "EGL_RENDERABLE_TYPE", + "EGL_MATCH_NATIVE_PIXMAP", /* Pseudo-attribute (not queryable) */ + "EGL_CONFORMANT", }; EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, - EGLint *num_config) -{ - puts("agl2:eglChooseConfig"); - LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - - if (ggl_unlikely(num_config==0)) { - LOGD("\n***\n***\n num_config==0 \n***\n***\n"); - return setError(EGL_BAD_PARAMETER, EGL_FALSE); - } - - if (ggl_unlikely(attrib_list==0)) { - /* - * A NULL attrib_list should be treated as though it was an empty - * one (terminated with EGL_NONE) as defined in - * section 3.4.1 "Querying Configurations" in the EGL specification. - */ - LOGD("\n***\n***\n attrib_list==0 \n***\n***\n"); - static const EGLint dummy = EGL_NONE; - attrib_list = &dummy; - } - - for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) { - LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]); - if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0]) - LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]); - } - - int numAttributes = 0; - int numConfigs = NELEM(gConfigs); - uint32_t possibleMatch = (1<<numConfigs)-1; - while (possibleMatch && *attrib_list != EGL_NONE) { - numAttributes++; - EGLint attr = *attrib_list++; - EGLint val = *attrib_list++; - for (int i=0 ; possibleMatch && i<numConfigs ; i++) { - if (!(possibleMatch & (1<<i))) - continue; - if (isAttributeMatching(i, attr, val) == 0) { - LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val); - possibleMatch &= ~(1<<i); - } - } - } - - LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch); - - // now, handle the attributes which have a useful default value - for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) { - // see if this attribute was specified, if not, apply its - // default value - if (binarySearch<config_pair_t>( - (config_pair_t const*)attrib_list, - 0, numAttributes-1, - config_defaults[j].key) < 0) { - for (int i=0 ; possibleMatch && i<numConfigs ; i++) { + EGLConfig *configs, EGLint config_size, + EGLint *num_config) +{ + puts("agl2:eglChooseConfig"); + LOGD("\n***\n***\n agl2:LOGD eglChooseConfig \n***\n***\n"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + if (ggl_unlikely(num_config==0)) { + LOGD("\n***\n***\n num_config==0 \n***\n***\n"); + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + } + + if (ggl_unlikely(attrib_list==0)) { + /* + * A NULL attrib_list should be treated as though it was an empty + * one (terminated with EGL_NONE) as defined in + * section 3.4.1 "Querying Configurations" in the EGL specification. + */ + LOGD("\n***\n***\n attrib_list==0 \n***\n***\n"); + static const EGLint dummy = EGL_NONE; + attrib_list = &dummy; + } + + for (const EGLint * attrib = attrib_list; *attrib != EGL_NONE; attrib += 2) { + LOGD("eglChooseConfig %s(%.4X): %d \n", ATTRIBUTE_NAMES[attrib[0] - EGL_BUFFER_SIZE], attrib[0], attrib[1]); + if (EGL_BUFFER_SIZE > attrib[0] || EGL_CONFORMANT < attrib[0]) + LOGD("eglChooseConfig invalid config attrib: 0x%.4X=%d \n", attrib[0], attrib[1]); + } + + int numAttributes = 0; + int numConfigs = NELEM(gConfigs); + uint32_t possibleMatch = (1<<numConfigs)-1; + while (possibleMatch && *attrib_list != EGL_NONE) { + numAttributes++; + EGLint attr = *attrib_list++; + EGLint val = *attrib_list++; + for (int i=0 ; possibleMatch && i<numConfigs ; i++) { if (!(possibleMatch & (1<<i))) - continue; - if (isAttributeMatching(i, - config_defaults[j].key, - config_defaults[j].value) == 0) { - possibleMatch &= ~(1<<i); + continue; + if (isAttributeMatching(i, attr, val) == 0) { + LOGD("!isAttributeMatching config(%d) %s=%d \n", i, ATTRIBUTE_NAMES[attr - EGL_BUFFER_SIZE], val); + possibleMatch &= ~(1<<i); + } + } + } + + LOGD("eglChooseConfig possibleMatch=%.4X \n", possibleMatch); + + // now, handle the attributes which have a useful default value + for (size_t j=0 ; possibleMatch && j<NELEM(config_defaults) ; j++) { + // see if this attribute was specified, if not, apply its + // default value + if (binarySearch<config_pair_t>( + (config_pair_t const*)attrib_list, + 0, numAttributes-1, + config_defaults[j].key) < 0) { + for (int i=0 ; possibleMatch && i<numConfigs ; i++) { + if (!(possibleMatch & (1<<i))) + continue; + if (isAttributeMatching(i, + config_defaults[j].key, + config_defaults[j].value) == 0) { + possibleMatch &= ~(1<<i); + } } - } - } - } - - // return the configurations found - int n=0; - if (possibleMatch) { - if (configs) { - for (int i=0 ; config_size && i<numConfigs ; i++) { - if (possibleMatch & (1<<i)) { - *configs++ = (EGLConfig)i; - config_size--; - n++; + } + } + + // return the configurations found + int n=0; + if (possibleMatch) { + if (configs) { + for (int i=0 ; config_size && i<numConfigs ; i++) { + if (possibleMatch & (1<<i)) { + *configs++ = (EGLConfig)i; + config_size--; + n++; + } } - } - } else { - for (int i=0 ; i<numConfigs ; i++) { - if (possibleMatch & (1<<i)) { - n++; + } else { + for (int i=0 ; i<numConfigs ; i++) { + if (possibleMatch & (1<<i)) { + n++; + } } - } - } - } - *num_config = n; - LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config); - return EGL_TRUE; + } + } + *num_config = n; + LOGD("\n***\n***\n num_config==%d \n***\n***\n", *num_config); + return EGL_TRUE; } EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value) + EGLint attribute, EGLint *value) { - puts("agl2:eglGetConfigAttrib"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); + puts("agl2:eglGetConfigAttrib"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); - return getConfigAttrib(dpy, config, attribute, value); + return getConfigAttrib(dpy, config, attribute, value); } // ---------------------------------------------------------------------------- @@ -1655,396 +1596,396 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, // ---------------------------------------------------------------------------- EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, - NativeWindowType window, - const EGLint *attrib_list) + NativeWindowType window, + const EGLint *attrib_list) { - puts("agl2:eglCreateWindowSurface"); - return createWindowSurface(dpy, config, window, attrib_list); + puts("agl2:eglCreateWindowSurface"); + return createWindowSurface(dpy, config, window, attrib_list); } EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, - NativePixmapType pixmap, - const EGLint *attrib_list) + NativePixmapType pixmap, + const EGLint *attrib_list) { - puts("agl2:eglCreatePixmapSurface"); - return createPixmapSurface(dpy, config, pixmap, attrib_list); + puts("agl2:eglCreatePixmapSurface"); + return createPixmapSurface(dpy, config, pixmap, attrib_list); } EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list) + const EGLint *attrib_list) { - puts("agl2:eglCreatePbufferSurface"); - return createPbufferSurface(dpy, config, attrib_list); + puts("agl2:eglCreatePbufferSurface"); + return createPbufferSurface(dpy, config, attrib_list); } EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) { - puts("agl2:eglDestroySurface"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (eglSurface != EGL_NO_SURFACE) { - egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); - if (!surface->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (surface->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (surface->ctx) { - // FIXME: this surface is current check what the spec says - surface->disconnect(); - surface->ctx = 0; - } - delete surface; - } - return EGL_TRUE; + puts("agl2:eglDestroySurface"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (eglSurface != EGL_NO_SURFACE) { + egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) ); + if (!surface->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (surface->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (surface->ctx) { + // FIXME: this surface is current check what the spec says + surface->disconnect(); + surface->ctx = 0; + } + delete surface; + } + return EGL_TRUE; } EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, - EGLint attribute, EGLint *value) -{ - puts("agl2:eglQuerySurface"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface); - if (!surface->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (surface->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - - EGLBoolean ret = EGL_TRUE; - switch (attribute) { - case EGL_CONFIG_ID: - ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value); - break; - case EGL_WIDTH: - *value = surface->getWidth(); - break; - case EGL_HEIGHT: - *value = surface->getHeight(); - break; - case EGL_LARGEST_PBUFFER: - // not modified for a window or pixmap surface - break; - case EGL_TEXTURE_FORMAT: - *value = EGL_NO_TEXTURE; - break; - case EGL_TEXTURE_TARGET: - *value = EGL_NO_TEXTURE; - break; - case EGL_MIPMAP_TEXTURE: - *value = EGL_FALSE; - break; - case EGL_MIPMAP_LEVEL: - *value = 0; - break; - case EGL_RENDER_BUFFER: - // TODO: return the real RENDER_BUFFER here - *value = EGL_BACK_BUFFER; - break; - case EGL_HORIZONTAL_RESOLUTION: - // pixel/mm * EGL_DISPLAY_SCALING - *value = surface->getHorizontalResolution(); - break; - case EGL_VERTICAL_RESOLUTION: - // pixel/mm * EGL_DISPLAY_SCALING - *value = surface->getVerticalResolution(); - break; - case EGL_PIXEL_ASPECT_RATIO: { - // w/h * EGL_DISPLAY_SCALING - int wr = surface->getHorizontalResolution(); - int hr = surface->getVerticalResolution(); - *value = (wr * EGL_DISPLAY_SCALING) / hr; - } - break; - case EGL_SWAP_BEHAVIOR: - *value = surface->getSwapBehavior(); - break; - default: - ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - return ret; + EGLint attribute, EGLint *value) +{ + puts("agl2:eglQuerySurface"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface); + if (!surface->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (surface->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + EGLBoolean ret = EGL_TRUE; + switch (attribute) { + case EGL_CONFIG_ID: + ret = getConfigAttrib(dpy, surface->config, EGL_CONFIG_ID, value); + break; + case EGL_WIDTH: + *value = surface->getWidth(); + break; + case EGL_HEIGHT: + *value = surface->getHeight(); + break; + case EGL_LARGEST_PBUFFER: + // not modified for a window or pixmap surface + break; + case EGL_TEXTURE_FORMAT: + *value = EGL_NO_TEXTURE; + break; + case EGL_TEXTURE_TARGET: + *value = EGL_NO_TEXTURE; + break; + case EGL_MIPMAP_TEXTURE: + *value = EGL_FALSE; + break; + case EGL_MIPMAP_LEVEL: + *value = 0; + break; + case EGL_RENDER_BUFFER: + // TODO: return the real RENDER_BUFFER here + *value = EGL_BACK_BUFFER; + break; + case EGL_HORIZONTAL_RESOLUTION: + // pixel/mm * EGL_DISPLAY_SCALING + *value = surface->getHorizontalResolution(); + break; + case EGL_VERTICAL_RESOLUTION: + // pixel/mm * EGL_DISPLAY_SCALING + *value = surface->getVerticalResolution(); + break; + case EGL_PIXEL_ASPECT_RATIO: { + // w/h * EGL_DISPLAY_SCALING + int wr = surface->getHorizontalResolution(); + int hr = surface->getVerticalResolution(); + *value = (wr * EGL_DISPLAY_SCALING) / hr; + } + break; + case EGL_SWAP_BEHAVIOR: + *value = surface->getSwapBehavior(); + break; + default: + ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + return ret; } EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) + EGLContext share_list, const EGLint *attrib_list) { - puts("agl2:eglCreateContext"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + puts("agl2:eglCreateContext"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t)); - if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + GLES2Context* gl = new GLES2Context();//ogles_init(sizeof(egl_context_t)); + if (!gl) return setError(EGL_BAD_ALLOC, EGL_NO_CONTEXT); - //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base); - egl_context_t * c = &gl->egl; - c->flags = egl_context_t::NEVER_CURRENT; - c->dpy = dpy; - c->config = config; - c->read = 0; - c->draw = 0; - - c->frame = 0; - c->lastSwapTime = clock(); - c->accumulateSeconds = 0; - return (EGLContext)gl; + //egl_context_t* c = static_cast<egl_context_t*>(gl->rasterizer.base); + egl_context_t * c = &gl->egl; + c->flags = egl_context_t::NEVER_CURRENT; + c->dpy = dpy; + c->config = config; + c->read = 0; + c->draw = 0; + + c->frame = 0; + c->lastSwapTime = clock(); + c->accumulateSeconds = 0; + return (EGLContext)gl; } EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - puts("agl2:eglDestroyContext"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - egl_context_t* c = egl_context_t::context(ctx); - if (c->flags & egl_context_t::IS_CURRENT) - setGlThreadSpecific(0); - //ogles_uninit((GLES2Context*)ctx); - delete (GLES2Context*)ctx; - return EGL_TRUE; + puts("agl2:eglDestroyContext"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_context_t* c = egl_context_t::context(ctx); + if (c->flags & egl_context_t::IS_CURRENT) + setGlThreadSpecific(0); + //ogles_uninit((GLES2Context*)ctx); + delete (GLES2Context*)ctx; + return EGL_TRUE; } EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, - EGLSurface read, EGLContext ctx) -{ - puts("agl2:eglMakeCurrent"); - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - if (draw) { - egl_surface_t* s = (egl_surface_t*)draw; - if (!s->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (s->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: check that draw is compatible with the context - } - if (read && read!=draw) { - egl_surface_t* s = (egl_surface_t*)read; - if (!s->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (s->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: check that read is compatible with the context - } - - EGLContext current_ctx = EGL_NO_CONTEXT; - - if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) - return setError(EGL_BAD_MATCH, EGL_FALSE); - - if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) - return setError(EGL_BAD_MATCH, EGL_FALSE); - - if (ctx == EGL_NO_CONTEXT) { - // if we're detaching, we need the current context - current_ctx = (EGLContext)getGlThreadSpecific(); - } else { - egl_context_t* c = egl_context_t::context(ctx); - egl_surface_t* d = (egl_surface_t*)draw; - egl_surface_t* r = (egl_surface_t*)read; - if ((d && d->ctx && d->ctx != ctx) || - (r && r->ctx && r->ctx != ctx)) { - // one of the surface is bound to a context in another thread - return setError(EGL_BAD_ACCESS, EGL_FALSE); - } - } - - GLES2Context* gl = (GLES2Context*)ctx; - if (makeCurrent(gl) == 0) { - if (ctx) { - egl_context_t* c = egl_context_t::context(ctx); - egl_surface_t* d = (egl_surface_t*)draw; - egl_surface_t* r = (egl_surface_t*)read; - - if (c->draw) { - egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw); - s->disconnect(); - } - if (c->read) { - // FIXME: unlock/disconnect the read surface too - } - - c->draw = draw; - c->read = read; - - if (c->flags & egl_context_t::NEVER_CURRENT) { - c->flags &= ~egl_context_t::NEVER_CURRENT; - GLint w = 0; - GLint h = 0; - if (draw) { - w = d->getWidth(); - h = d->getHeight(); + EGLSurface read, EGLContext ctx) +{ + puts("agl2:eglMakeCurrent"); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (draw) { + egl_surface_t* s = (egl_surface_t*)draw; + if (!s->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (s->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: check that draw is compatible with the context + } + if (read && read!=draw) { + egl_surface_t* s = (egl_surface_t*)read; + if (!s->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (s->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: check that read is compatible with the context + } + + EGLContext current_ctx = EGL_NO_CONTEXT; + + if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) + return setError(EGL_BAD_MATCH, EGL_FALSE); + + if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) + return setError(EGL_BAD_MATCH, EGL_FALSE); + + if (ctx == EGL_NO_CONTEXT) { + // if we're detaching, we need the current context + current_ctx = (EGLContext)getGlThreadSpecific(); + } else { + egl_context_t* c = egl_context_t::context(ctx); + egl_surface_t* d = (egl_surface_t*)draw; + egl_surface_t* r = (egl_surface_t*)read; + if ((d && d->ctx && d->ctx != ctx) || + (r && r->ctx && r->ctx != ctx)) { + // one of the surface is bound to a context in another thread + return setError(EGL_BAD_ACCESS, EGL_FALSE); + } + } + + GLES2Context* gl = (GLES2Context*)ctx; + if (makeCurrent(gl) == 0) { + if (ctx) { + egl_context_t* c = egl_context_t::context(ctx); + egl_surface_t* d = (egl_surface_t*)draw; + egl_surface_t* r = (egl_surface_t*)read; + + if (c->draw) { + egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw); + s->disconnect(); } - gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h); - //ogles_surfaceport(gl, 0, 0); - //ogles_viewport(gl, 0, 0, w, h); - //ogles_scissor(gl, 0, 0, w, h); - } - if (d) { - if (d->connect() == EGL_FALSE) { - return EGL_FALSE; + if (c->read) { + // FIXME: unlock/disconnect the read surface too + } + + c->draw = draw; + c->read = read; + + if (c->flags & egl_context_t::NEVER_CURRENT) { + c->flags &= ~egl_context_t::NEVER_CURRENT; + GLint w = 0; + GLint h = 0; + if (draw) { + w = d->getWidth(); + h = d->getHeight(); + } + gl->rasterizer.interface.Viewport(&gl->rasterizer.interface, 0, 0, w, h); + //ogles_surfaceport(gl, 0, 0); + //ogles_viewport(gl, 0, 0, w, h); + //ogles_scissor(gl, 0, 0, w, h); } - d->ctx = ctx; - d->bindDrawSurface(gl); - } - if (r) { - // FIXME: lock/connect the read surface too - r->ctx = ctx; - r->bindReadSurface(gl); - } - } else { - // if surfaces were bound to the context bound to this thread - // mark then as unbound. - if (current_ctx) { - egl_context_t* c = egl_context_t::context(current_ctx); - egl_surface_t* d = (egl_surface_t*)c->draw; - egl_surface_t* r = (egl_surface_t*)c->read; if (d) { - c->draw = 0; - d->ctx = EGL_NO_CONTEXT; - d->disconnect(); + if (d->connect() == EGL_FALSE) { + return EGL_FALSE; + } + d->ctx = ctx; + d->bindDrawSurface(gl); } if (r) { - c->read = 0; - r->ctx = EGL_NO_CONTEXT; - // FIXME: unlock/disconnect the read surface too + // FIXME: lock/connect the read surface too + r->ctx = ctx; + r->bindReadSurface(gl); + } + } else { + // if surfaces were bound to the context bound to this thread + // mark then as unbound. + if (current_ctx) { + egl_context_t* c = egl_context_t::context(current_ctx); + egl_surface_t* d = (egl_surface_t*)c->draw; + egl_surface_t* r = (egl_surface_t*)c->read; + if (d) { + c->draw = 0; + d->ctx = EGL_NO_CONTEXT; + d->disconnect(); + } + if (r) { + c->read = 0; + r->ctx = EGL_NO_CONTEXT; + // FIXME: unlock/disconnect the read surface too + } } - } - } - return EGL_TRUE; - } - return setError(EGL_BAD_ACCESS, EGL_FALSE); + } + return EGL_TRUE; + } + return setError(EGL_BAD_ACCESS, EGL_FALSE); } EGLContext eglGetCurrentContext(void) { - // eglGetCurrentContext returns the current EGL rendering context, - // as specified by eglMakeCurrent. If no context is current, - // EGL_NO_CONTEXT is returned. - return (EGLContext)getGlThreadSpecific(); + // eglGetCurrentContext returns the current EGL rendering context, + // as specified by eglMakeCurrent. If no context is current, + // EGL_NO_CONTEXT is returned. + return (EGLContext)getGlThreadSpecific(); } EGLSurface eglGetCurrentSurface(EGLint readdraw) { - // eglGetCurrentSurface returns the read or draw surface attached - // to the current EGL rendering context, as specified by eglMakeCurrent. - // If no context is current, EGL_NO_SURFACE is returned. - EGLContext ctx = (EGLContext)getGlThreadSpecific(); - if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE; - egl_context_t* c = egl_context_t::context(ctx); - if (readdraw == EGL_READ) { - return c->read; - } else if (readdraw == EGL_DRAW) { - return c->draw; - } - return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); + // eglGetCurrentSurface returns the read or draw surface attached + // to the current EGL rendering context, as specified by eglMakeCurrent. + // If no context is current, EGL_NO_SURFACE is returned. + EGLContext ctx = (EGLContext)getGlThreadSpecific(); + if (ctx == EGL_NO_CONTEXT) return EGL_NO_SURFACE; + egl_context_t* c = egl_context_t::context(ctx); + if (readdraw == EGL_READ) { + return c->read; + } else if (readdraw == EGL_DRAW) { + return c->draw; + } + return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } EGLDisplay eglGetCurrentDisplay(void) { - // eglGetCurrentDisplay returns the current EGL display connection - // for the current EGL rendering context, as specified by eglMakeCurrent. - // If no context is current, EGL_NO_DISPLAY is returned. - EGLContext ctx = (EGLContext)getGlThreadSpecific(); - if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY; - egl_context_t* c = egl_context_t::context(ctx); - return c->dpy; + // eglGetCurrentDisplay returns the current EGL display connection + // for the current EGL rendering context, as specified by eglMakeCurrent. + // If no context is current, EGL_NO_DISPLAY is returned. + EGLContext ctx = (EGLContext)getGlThreadSpecific(); + if (ctx == EGL_NO_CONTEXT) return EGL_NO_DISPLAY; + egl_context_t* c = egl_context_t::context(ctx); + return c->dpy; } EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, - EGLint attribute, EGLint *value) + EGLint attribute, EGLint *value) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - egl_context_t* c = egl_context_t::context(ctx); - switch (attribute) { - case EGL_CONFIG_ID: - // Returns the ID of the EGL frame buffer configuration with - // respect to which the context was created - return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value); - } - return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_context_t* c = egl_context_t::context(ctx); + switch (attribute) { + case EGL_CONFIG_ID: + // Returns the ID of the EGL frame buffer configuration with + // respect to which the context was created + return getConfigAttrib(dpy, c->config, EGL_CONFIG_ID, value); + } + return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); } EGLBoolean eglWaitGL(void) { - return EGL_TRUE; + return EGL_TRUE; } EGLBoolean eglWaitNative(EGLint engine) { - return EGL_TRUE; + return EGL_TRUE; } EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - - egl_surface_t* d = static_cast<egl_surface_t*>(draw); - if (!d->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (d->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - - // post the surface - d->swapBuffers(); - - // if it's bound to a context, update the buffer - if (d->ctx != EGL_NO_CONTEXT) { - d->bindDrawSurface((GLES2Context*)d->ctx); - // if this surface is also the read surface of the context - // it is bound to, make sure to update the read buffer as well. - // The EGL spec is a little unclear about this. - egl_context_t* c = egl_context_t::context(d->ctx); - if (c->read == draw) { - d->bindReadSurface((GLES2Context*)d->ctx); - } - clock_t time = clock(); - float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC; - c->accumulateSeconds += elapsed; - c->frame++; -// LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000); - if (20 == c->frame) { - float avg = c->accumulateSeconds / c->frame; - LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*", - c->frame, 1 / avg, avg * 1000); - c->frame = 0; - c->accumulateSeconds = 0; - } - c->lastSwapTime = time; - } - - return EGL_TRUE; + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl_surface_t* d = static_cast<egl_surface_t*>(draw); + if (!d->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + // post the surface + d->swapBuffers(); + + // if it's bound to a context, update the buffer + if (d->ctx != EGL_NO_CONTEXT) { + d->bindDrawSurface((GLES2Context*)d->ctx); + // if this surface is also the read surface of the context + // it is bound to, make sure to update the read buffer as well. + // The EGL spec is a little unclear about this. + egl_context_t* c = egl_context_t::context(d->ctx); + if (c->read == draw) { + d->bindReadSurface((GLES2Context*)d->ctx); + } + clock_t time = clock(); + float elapsed = (float)(time - c->lastSwapTime) / CLOCKS_PER_SEC; + c->accumulateSeconds += elapsed; + c->frame++; + // LOGD("agl2: eglSwapBuffers elapsed=%.2fms \n*", elapsed * 1000); + if (20 == c->frame) { + float avg = c->accumulateSeconds / c->frame; + LOGD("\n*\n* agl2: eglSwapBuffers %u frame avg fps=%.1f elapsed=%.2fms \n*", + c->frame, 1 / avg, avg * 1000); + c->frame = 0; + c->accumulateSeconds = 0; + } + c->lastSwapTime = time; + } + + return EGL_TRUE; } EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, - NativePixmapType target) + NativePixmapType target) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: eglCopyBuffers() - return EGL_FALSE; + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglCopyBuffers() + return EGL_FALSE; } EGLint eglGetError(void) { - return getError(); + return getError(); } const char* eglQueryString(EGLDisplay dpy, EGLint name) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, (const char*)0); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, (const char*)0); - switch (name) { - case EGL_VENDOR: - return gVendorString; - case EGL_VERSION: - return gVersionString; - case EGL_EXTENSIONS: - return gExtensionsString; - case EGL_CLIENT_APIS: - return gClientApiString; - } - return setError(EGL_BAD_PARAMETER, (const char *)0); + switch (name) { + case EGL_VENDOR: + return gVendorString; + case EGL_VERSION: + return gVersionString; + case EGL_EXTENSIONS: + return gExtensionsString; + case EGL_CLIENT_APIS: + return gClientApiString; + } + return setError(EGL_BAD_PARAMETER, (const char *)0); } // ---------------------------------------------------------------------------- @@ -2052,38 +1993,38 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) // ---------------------------------------------------------------------------- EGLBoolean eglSurfaceAttrib( - EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) + EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: eglSurfaceAttrib() - return setError(EGL_BAD_PARAMETER, EGL_FALSE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglSurfaceAttrib() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLBoolean eglBindTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer) + EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: eglBindTexImage() - return setError(EGL_BAD_PARAMETER, EGL_FALSE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglBindTexImage() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLBoolean eglReleaseTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer) + EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: eglReleaseTexImage() - return setError(EGL_BAD_PARAMETER, EGL_FALSE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglReleaseTexImage() + return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // TODO: eglSwapInterval() - return EGL_TRUE; + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + // TODO: eglSwapInterval() + return EGL_TRUE; } // ---------------------------------------------------------------------------- @@ -2092,36 +2033,36 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) EGLBoolean eglBindAPI(EGLenum api) { - if (api != EGL_OPENGL_ES_API) - return setError(EGL_BAD_PARAMETER, EGL_FALSE); - return EGL_TRUE; + if (api != EGL_OPENGL_ES_API) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + return EGL_TRUE; } EGLenum eglQueryAPI(void) { - return EGL_OPENGL_ES_API; + return EGL_OPENGL_ES_API; } EGLBoolean eglWaitClient(void) { - glFinish(); - return EGL_TRUE; + glFinish(); + return EGL_TRUE; } EGLBoolean eglReleaseThread(void) { - // TODO: eglReleaseThread() - return EGL_TRUE; + // TODO: eglReleaseThread() + return EGL_TRUE; } EGLSurface eglCreatePbufferFromClientBuffer( - EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list) + EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); - // TODO: eglCreatePbufferFromClientBuffer() - return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_NO_SURFACE); + // TODO: eglCreatePbufferFromClientBuffer() + return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } // ---------------------------------------------------------------------------- @@ -2129,84 +2070,84 @@ EGLSurface eglCreatePbufferFromClientBuffer( // ---------------------------------------------------------------------------- void (*eglGetProcAddress (const char *procname))() -{ - extention_map_t const * const map = gExtentionMap; - for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) { - if (!strcmp(procname, map[i].name)) { - return map[i].address; - } - } - return NULL; -} + { + extention_map_t const * const map = gExtentionMap; + for (uint32_t i=0 ; i<NELEM(gExtentionMap) ; i++) { + if (!strcmp(procname, map[i].name)) { + return map[i].address; + } + } + return NULL; + } EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, - const EGLint *attrib_list) + const EGLint *attrib_list) { - EGLBoolean result = EGL_FALSE; - return result; + EGLBoolean result = EGL_FALSE; + return result; } EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) { - EGLBoolean result = EGL_FALSE; - return result; + EGLBoolean result = EGL_FALSE; + return result; } EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, - EGLClientBuffer buffer, const EGLint *attrib_list) -{ - if (egl_display_t::is_valid(dpy) == EGL_FALSE) { - return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); - } - if (ctx != EGL_NO_CONTEXT) { - return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); - } - if (target != EGL_NATIVE_BUFFER_ANDROID) { - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - } - - android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; - - if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - - if (native_buffer->common.version != sizeof(android_native_buffer_t)) - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - - switch (native_buffer->format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_RGBX_8888: - case HAL_PIXEL_FORMAT_RGB_888: - case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_BGRA_8888: - case HAL_PIXEL_FORMAT_RGBA_5551: - case HAL_PIXEL_FORMAT_RGBA_4444: - break; - default: - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - } - - native_buffer->common.incRef(&native_buffer->common); - return (EGLImageKHR)native_buffer; + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + if (ctx != EGL_NO_CONTEXT) { + return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); + } + if (target != EGL_NATIVE_BUFFER_ANDROID) { + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + switch (native_buffer->format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + break; + default: + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + } + + native_buffer->common.incRef(&native_buffer->common); + return (EGLImageKHR)native_buffer; } EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) { - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - } + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } - android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; + android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; - if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) - return setError(EGL_BAD_PARAMETER, EGL_FALSE); + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); - if (native_buffer->common.version != sizeof(android_native_buffer_t)) - return setError(EGL_BAD_PARAMETER, EGL_FALSE); + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); - native_buffer->common.decRef(&native_buffer->common); + native_buffer->common.decRef(&native_buffer->common); - return EGL_TRUE; + return EGL_TRUE; } // ---------------------------------------------------------------------------- @@ -2214,19 +2155,19 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) // ---------------------------------------------------------------------------- EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, - EGLint left, EGLint top, EGLint width, EGLint height) + EGLint left, EGLint top, EGLint width, EGLint height) { - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); - egl_surface_t* d = static_cast<egl_surface_t*>(draw); - if (!d->isValid()) - return setError(EGL_BAD_SURFACE, EGL_FALSE); - if (d->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); + egl_surface_t* d = static_cast<egl_surface_t*>(draw); + if (!d->isValid()) + return setError(EGL_BAD_SURFACE, EGL_FALSE); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); - // post the surface - d->setSwapRectangle(left, top, width, height); + // post the surface + d->setSwapRectangle(left, top, width, height); - return EGL_TRUE; + return EGL_TRUE; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 73003c855f84..27b7e1c87419 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -2587,6 +2587,21 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) { mActionBar.initIndeterminateProgress(); } + + final boolean splitActionBar = getWindowStyle().getBoolean( + com.android.internal.R.styleable.Window_windowSplitActionBar, false); + if (splitActionBar) { + final ViewGroup splitView = (ViewGroup) findViewById( + com.android.internal.R.id.lower_action_context_bar); + if (splitView != null) { + mActionBar.setSplitActionBar(splitActionBar); + mActionBar.setSplitView(splitView); + } else { + Log.e(TAG, "Window style requested split action bar with " + + "incompatible window decor! Ignoring request."); + } + } + // Post the panel invalidate for later; avoid application onCreateOptionsMenu // being called in the middle of onCreate or similar. mDecor.post(new Runnable() { diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 9c43067363a9..f04fb020fff7 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -114,10 +114,11 @@ struct InputWindow { TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+14, + TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+17, + TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17, + TYPE_POINTER = FIRST_SYSTEM_WINDOW+18, LAST_SYSTEM_WINDOW = 2999, }; diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index d841cb3a7766..02332b7aa918 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -16,6 +16,9 @@ package com.android.server; +import com.android.internal.R; +import com.android.internal.telephony.TelephonyProperties; + import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; @@ -30,7 +33,6 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.net.INetworkManagementEventObserver; import android.net.IThrottleManager; -import android.net.SntpClient; import android.net.ThrottleManager; import android.os.Binder; import android.os.Environment; @@ -47,10 +49,9 @@ import android.os.SystemProperties; import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.NtpTrustedTime; import android.util.Slog; - -import com.android.internal.R; -import com.android.internal.telephony.TelephonyProperties; +import android.util.TrustedTime; import java.io.BufferedWriter; import java.io.File; @@ -60,11 +61,11 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Calendar; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import java.util.GregorianCalendar; import java.util.Properties; import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; // TODO - add comments - reference the ThrottleManager for public API public class ThrottleService extends IThrottleManager.Stub { @@ -84,6 +85,11 @@ public class ThrottleService extends IThrottleManager.Stub { private static final int TESTING_RESET_PERIOD_SEC = 60 * 10; private static final long TESTING_THRESHOLD = 1 * 1024 * 1024; + private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000; + private static final long MAX_NTP_FETCH_WAIT = 20 * 1000; + + private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE; + private int mPolicyPollPeriodSec; private AtomicLong mPolicyThreshold; private AtomicInteger mPolicyThrottleValue; @@ -121,10 +127,24 @@ public class ThrottleService extends IThrottleManager.Stub { private static final int THROTTLE_INDEX_UNTHROTTLED = 0; private static final String PROPERTIES_FILE = "/etc/gps.conf"; - private String mNtpServer; - private boolean mNtpActive; + + private Intent mPollStickyBroadcast; + + private TrustedTime mTime; + + private static INetworkManagementService getNetworkManagementService() { + final IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + return INetworkManagementService.Stub.asInterface(b); + } public ThrottleService(Context context) { + // TODO: move to using cached NtpTrustedTime + this(context, getNetworkManagementService(), new NtpTrustedTime(), + context.getResources().getString(R.string.config_datause_iface)); + } + + public ThrottleService(Context context, INetworkManagementService nmService, TrustedTime time, + String iface) { if (VDBG) Slog.v(TAG, "Starting ThrottleService"); mContext = context; @@ -132,17 +152,15 @@ public class ThrottleService extends IThrottleManager.Stub { mPolicyThrottleValue = new AtomicInteger(); mThrottleIndex = new AtomicInteger(); - mNtpActive = false; - - mIface = mContext.getResources().getString(R.string.config_datause_iface); + mIface = iface; mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); Intent pollIntent = new Intent(ACTION_POLL, null); mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0); Intent resetIntent = new Intent(ACTION_RESET, null); mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0); - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); + mNMService = nmService; + mTime = time; mNotificationManager = (NotificationManager)mContext.getSystemService( Context.NOTIFICATION_SERVICE); @@ -189,7 +207,7 @@ public class ThrottleService extends IThrottleManager.Stub { mMsg = msg; } - void observe(Context context) { + void register(Context context) { ContentResolver resolver = context.getContentResolver(); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.THROTTLE_POLLING_SEC), false, this); @@ -207,6 +225,11 @@ public class ThrottleService extends IThrottleManager.Stub { Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this); } + void unregister(Context context) { + final ContentResolver resolver = context.getContentResolver(); + resolver.unregisterContentObserver(this); + } + @Override public void onChange(boolean selfChange) { mHandler.obtainMessage(mMsg).sendToTarget(); @@ -220,7 +243,9 @@ public class ThrottleService extends IThrottleManager.Stub { } private long ntpToWallTime(long ntpTime) { - long bestNow = getBestTime(true); // do it quickly + // get time quickly without worrying about trusted state + long bestNow = mTime.hasCache() ? mTime.currentTimeMillis() + : System.currentTimeMillis(); long localNow = System.currentTimeMillis(); return localNow + (ntpTime - bestNow); } @@ -300,7 +325,7 @@ public class ThrottleService extends IThrottleManager.Stub { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget(); + dispatchPoll(); } }, new IntentFilter(ACTION_POLL)); @@ -308,7 +333,7 @@ public class ThrottleService extends IThrottleManager.Stub { new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget(); + dispatchReset(); } }, new IntentFilter(ACTION_RESET)); @@ -318,7 +343,10 @@ public class ThrottleService extends IThrottleManager.Stub { File file = new File(PROPERTIES_FILE); stream = new FileInputStream(file); properties.load(stream); - mNtpServer = properties.getProperty("NTP_SERVER", null); + final String ntpServer = properties.getProperty("NTP_SERVER", null); + if (mTime instanceof NtpTrustedTime) { + ((NtpTrustedTime) mTime).setNtpServer(ntpServer, MAX_NTP_FETCH_WAIT); + } } catch (IOException e) { Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE); } finally { @@ -343,9 +371,33 @@ public class ThrottleService extends IThrottleManager.Stub { } mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED); - mSettingsObserver.observe(mContext); + mSettingsObserver.register(mContext); + } + + void shutdown() { + // TODO: eventually connect with ShutdownThread to persist stats during + // graceful shutdown. + + if (mThread != null) { + mThread.quit(); + } + + if (mSettingsObserver != null) { + mSettingsObserver.unregister(mContext); + } + + if (mPollStickyBroadcast != null) { + mContext.removeStickyBroadcast(mPollStickyBroadcast); + } } + void dispatchPoll() { + mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget(); + } + + void dispatchReset() { + mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget(); + } private static final int EVENT_REBOOT_RECOVERY = 0; private static final int EVENT_POLICY_CHANGED = 1; @@ -440,15 +492,17 @@ public class ThrottleService extends IThrottleManager.Stub { mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType); - mMaxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC, MAX_NTP_CACHE_AGE_SEC); + final int maxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC, + (int) (MAX_NTP_CACHE_AGE / 1000)); + mMaxNtpCacheAge = maxNtpCacheAgeSec * 1000; if (VDBG || (mPolicyThreshold.get() != 0)) { Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" + mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold.get() + ", value=" + mPolicyThrottleValue.get() + ", resetDay=" + mPolicyResetDay + - ", noteType=" + mPolicyNotificationsAllowedMask + ", maxNtpCacheAge=" + - mMaxNtpCacheAgeSec); + ", noteType=" + mPolicyNotificationsAllowedMask + ", mMaxNtpCacheAge=" + + mMaxNtpCacheAge); } // force updates @@ -464,9 +518,15 @@ public class ThrottleService extends IThrottleManager.Stub { private void onPollAlarm() { long now = SystemClock.elapsedRealtime(); - long next = now + mPolicyPollPeriodSec*1000; + long next = now + mPolicyPollPeriodSec * 1000; - checkForAuthoritativeTime(); + // when trusted cache outdated, try refreshing + if (mTime.getCacheAge() > mMaxNtpCacheAge) { + if (mTime.forceRefresh()) { + if (VDBG) Slog.d(TAG, "updated trusted time, reseting alarm"); + dispatchReset(); + } + } long incRead = 0; long incWrite = 0; @@ -509,6 +569,7 @@ public class ThrottleService extends IThrottleManager.Stub { broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface)); broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface)); mContext.sendStickyBroadcast(broadcast); + mPollStickyBroadcast = broadcast; mAlarmManager.cancel(mPendingPollIntent); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent); @@ -538,7 +599,8 @@ public class ThrottleService extends IThrottleManager.Stub { // have we spoken with an ntp server yet? // this is controversial, but we'd rather err towards not throttling - if ((mNtpServer != null) && !mNtpActive) { + if (!mTime.hasCache()) { + Slog.w(TAG, "missing trusted time, skipping throttle check"); return; } @@ -697,9 +759,15 @@ public class ThrottleService extends IThrottleManager.Stub { " bytes read and " + mRecorder.getPeriodTx(0) + " written"); } - long now = getBestTime(false); + // when trusted cache outdated, try refreshing + if (mTime.getCacheAge() > mMaxNtpCacheAge) { + mTime.forceRefresh(); + } - if (mNtpActive || (mNtpServer == null)) { + // as long as we have a trusted time cache, we always reset alarms, + // even if the refresh above failed. + if (mTime.hasCache()) { + final long now = mTime.currentTimeMillis(); Calendar end = calculatePeriodEnd(now); Calendar start = calculatePeriodStart(end); @@ -714,56 +782,11 @@ public class ThrottleService extends IThrottleManager.Stub { SystemClock.elapsedRealtime() + offset, mPendingResetIntent); } else { - if (VDBG) Slog.d(TAG, "no authoritative time - not resetting period"); + if (VDBG) Slog.d(TAG, "no trusted time, not resetting period"); } } } - private void checkForAuthoritativeTime() { - if (mNtpActive || (mNtpServer == null)) return; - - // will try to get the ntp time and switch to it if found. - // will also cache the time so we don't fetch it repeatedly. - getBestTime(false); - } - - private static final int MAX_NTP_CACHE_AGE_SEC = 60 * 60 * 24; // 1 day - private static final int MAX_NTP_FETCH_WAIT = 20 * 1000; - private int mMaxNtpCacheAgeSec = MAX_NTP_CACHE_AGE_SEC; - private long cachedNtp; - private long cachedNtpTimestamp; - - // if the request is tied to UI and ANR's are a danger, request a fast result - // the regular polling should have updated the cached time recently using the - // slower method (!fast) - private long getBestTime(boolean fast) { - if (mNtpServer != null) { - if (mNtpActive) { - long ntpAge = SystemClock.elapsedRealtime() - cachedNtpTimestamp; - if (ntpAge < mMaxNtpCacheAgeSec * 1000 || fast) { - if (VDBG) Slog.v(TAG, "using cached time"); - return cachedNtp + ntpAge; - } - } - SntpClient client = new SntpClient(); - if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT)) { - cachedNtp = client.getNtpTime(); - cachedNtpTimestamp = SystemClock.elapsedRealtime(); - if (!mNtpActive) { - mNtpActive = true; - if (VDBG) Slog.d(TAG, "found Authoritative time - reseting alarm"); - mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget(); - } - if (VDBG) Slog.v(TAG, "using Authoritative time: " + cachedNtp); - return cachedNtp; - } - } - long time = System.currentTimeMillis(); - if (VDBG) Slog.v(TAG, "using User time: " + time); - mNtpActive = false; - return time; - } - // records bytecount data for a given time and accumulates it into larger time windows // for logging and other purposes // @@ -929,7 +952,7 @@ public class ThrottleService extends IThrottleManager.Stub { private void checkAndDeleteLRUDataFile(File dir) { File[] files = dir.listFiles(); - if (files.length <= MAX_SIMS_SUPPORTED) return; + if (files == null || files.length <= MAX_SIMS_SUPPORTED) return; if (DBG) Slog.d(TAG, "Too many data files"); do { File oldest = null; @@ -949,9 +972,11 @@ public class ThrottleService extends IThrottleManager.Stub { File newest = null; File[] files = dir.listFiles(); - for (File f : files) { - if ((newest == null) || (newest.lastModified() < f.lastModified())) { - newest = f; + if (files != null) { + for (File f : files) { + if ((newest == null) || (newest.lastModified() < f.lastModified())) { + newest = f; + } } } if (newest == null) { @@ -1126,7 +1151,7 @@ public class ThrottleService extends IThrottleManager.Stub { " seconds."); pw.println("Polling every " + mPolicyPollPeriodSec + " seconds"); pw.println("Current Throttle Index is " + mThrottleIndex.get()); - pw.println("Max NTP Cache Age is " + mMaxNtpCacheAgeSec); + pw.println("mMaxNtpCacheAge=" + mMaxNtpCacheAge); for (int i = 0; i < mRecorder.getPeriodCount(); i++) { pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" + diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java index e9ce3ce3ccf7..bb9e60f6e072 100755 --- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java +++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java @@ -56,6 +56,7 @@ import java.util.TimerTask; public class ComprehensiveCountryDetector extends CountryDetectorBase { private final static String TAG = "ComprehensiveCountryDetector"; + /* package */ static final boolean DEBUG = false; /** * The refresh interval when the location based country was used @@ -90,7 +91,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { * The listener for receiving the notification from LocationBasedCountryDetector. */ private CountryListener mLocationBasedCountryDetectionListener = new CountryListener() { + @Override public void onCountryDetected(Country country) { + if (DEBUG) Slog.d(TAG, "Country detected via LocationBasedCountryDetector"); mCountryFromLocation = country; // Don't start the LocationBasedCountryDetector. detectCountry(true, false); @@ -206,6 +209,7 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { protected void runAfterDetectionAsync(final Country country, final Country detectedCountry, final boolean notifyChange, final boolean startLocationBasedDetection) { mHandler.post(new Runnable() { + @Override public void run() { runAfterDetection( country, detectedCountry, notifyChange, startLocationBasedDetection); @@ -233,9 +237,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { if (notifyChange) { notifyIfCountryChanged(country, detectedCountry); } + if (DEBUG) { + Slog.d(TAG, "startLocationBasedDetection=" + startLocationBasedDetection + + " detectCountry=" + (detectedCountry == null ? null : + "(source: " + detectedCountry.getSource() + + ", countryISO: " + detectedCountry.getCountryIso() + ")") + + " isAirplaneModeOff()=" + isAirplaneModeOff() + + " mListener=" + mListener + + " isGeoCoderImplemnted()=" + isGeoCoderImplemented()); + } + if (startLocationBasedDetection && (detectedCountry == null || detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION) && isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) { + if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()"); // Start finding location when the source is less reliable than the // location and the airplane mode is off (as geocoder will not // work). @@ -266,12 +281,20 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { if (mLocationBasedCountryDetector != null) { return; } + if (DEBUG) { + Slog.d(TAG, "starts LocationBasedDetector to detect Country code via Location info " + + "(e.g. GPS)"); + } mLocationBasedCountryDetector = createLocationBasedCountryDetector(); mLocationBasedCountryDetector.setCountryListener(listener); mLocationBasedCountryDetector.detectCountry(); } private synchronized void stopLocationBasedDetector() { + if (DEBUG) { + Slog.d(TAG, "tries to stop LocationBasedDetector " + + "(current detector: " + mLocationBasedCountryDetector + ")"); + } if (mLocationBasedCountryDetector != null) { mLocationBasedCountryDetector.stop(); mLocationBasedCountryDetector = null; @@ -305,10 +328,17 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase { */ private synchronized void scheduleLocationRefresh() { if (mLocationRefreshTimer != null) return; + if (DEBUG) { + Slog.d(TAG, "start periodic location refresh timer. Interval: " + + LOCATION_REFRESH_INTERVAL); + } mLocationRefreshTimer = new Timer(); mLocationRefreshTimer.schedule(new TimerTask() { @Override public void run() { + if (DEBUG) { + Slog.d(TAG, "periodic location refresh event. Starts detecting Country code"); + } mLocationRefreshTimer = null; detectCountry(false, true); } diff --git a/services/java/com/android/server/location/LocationBasedCountryDetector.java b/services/java/com/android/server/location/LocationBasedCountryDetector.java index 139f05d211fd..d4fb8ee5abb0 100755 --- a/services/java/com/android/server/location/LocationBasedCountryDetector.java +++ b/services/java/com/android/server/location/LocationBasedCountryDetector.java @@ -16,12 +16,6 @@ package com.android.server.location; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; - import android.content.Context; import android.location.Address; import android.location.Country; @@ -32,6 +26,12 @@ import android.location.LocationManager; import android.os.Bundle; import android.util.Slog; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + /** * This class detects which country the user currently is in through the enabled * location providers and the GeoCoder @@ -86,24 +86,23 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { return country; } + protected boolean isAcceptableProvider(String provider) { + // We don't want to actively initiate a location fix here (with gps or network providers). + return LocationManager.PASSIVE_PROVIDER.equals(provider); + } + /** - * Register the listeners with the location providers + * Register a listener with a provider name */ - protected void registerEnabledProviders(List<LocationListener> listeners) { - int total = listeners.size(); - for (int i = 0; i< total; i++) { - mLocationManager.requestLocationUpdates( - mEnabledProviders.get(i), 0, 0, listeners.get(i)); - } + protected void registerListener(String provider, LocationListener listener) { + mLocationManager.requestLocationUpdates(provider, 0, 0, listener); } /** - * Unregister the listeners with the location providers + * Unregister an already registered listener */ - protected void unregisterProviders(List<LocationListener> listeners) { - for (LocationListener listener : listeners) { - mLocationManager.removeUpdates(listener); - } + protected void unregisterListener(LocationListener listener) { + mLocationManager.removeUpdates(listener); } /** @@ -130,14 +129,11 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { return QUERY_LOCATION_TIMEOUT; } - /** - * @return the total number of enabled location providers - */ - protected int getTotalEnabledProviders() { + protected List<String> getEnabledProviders() { if (mEnabledProviders == null) { mEnabledProviders = mLocationManager.getProviders(true); } - return mEnabledProviders.size(); + return mEnabledProviders; } /** @@ -152,27 +148,36 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { throw new IllegalStateException(); } // Request the location from all enabled providers. - int totalProviders = getTotalEnabledProviders(); + List<String> enabledProviders = getEnabledProviders(); + int totalProviders = enabledProviders.size(); if (totalProviders > 0) { mLocationListeners = new ArrayList<LocationListener>(totalProviders); for (int i = 0; i < totalProviders; i++) { - LocationListener listener = new LocationListener () { - public void onLocationChanged(Location location) { - if (location != null) { - LocationBasedCountryDetector.this.stop(); - queryCountryCode(location); + String provider = enabledProviders.get(i); + if (isAcceptableProvider(provider)) { + LocationListener listener = new LocationListener () { + @Override + public void onLocationChanged(Location location) { + if (location != null) { + LocationBasedCountryDetector.this.stop(); + queryCountryCode(location); + } } - } - public void onProviderDisabled(String provider) { - } - public void onProviderEnabled(String provider) { - } - public void onStatusChanged(String provider, int status, Bundle extras) { - } - }; - mLocationListeners.add(listener); + @Override + public void onProviderDisabled(String provider) { + } + @Override + public void onProviderEnabled(String provider) { + } + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + }; + mLocationListeners.add(listener); + registerListener(provider, listener); + } } - registerEnabledProviders(mLocationListeners); + mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override @@ -197,7 +202,9 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { @Override public synchronized void stop() { if (mLocationListeners != null) { - unregisterProviders(mLocationListeners); + for (LocationListener listener : mLocationListeners) { + unregisterListener(listener); + } mLocationListeners = null; } if (mTimer != null) { @@ -216,6 +223,7 @@ public class LocationBasedCountryDetector extends CountryDetectorBase { } if (mQueryThread != null) return; mQueryThread = new Thread(new Runnable() { + @Override public void run() { String countryIso = null; if (location != null) { diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index 186b3490e502..295f324f9582 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -7,7 +7,9 @@ LOCAL_MODULE_TAGS := tests # Include all test java files. LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_STATIC_JAVA_LIBRARIES := easymocklib +LOCAL_STATIC_JAVA_LIBRARIES := \ + easymocklib \ + guava LOCAL_JAVA_LIBRARIES := android.test.runner services diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 2fcce785178c..f8d14265217c 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -20,6 +20,10 @@ <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.BROADCAST_STICKY" /> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java new file mode 100644 index 000000000000..6f55f4600dcd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java @@ -0,0 +1,400 @@ +/* + * 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 com.android.server; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reset; +import static org.easymock.EasyMock.verify; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.AbstractFuture; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.INetworkManagementEventObserver; +import android.net.ThrottleManager; +import android.os.INetworkManagementService; +import android.provider.Settings; +import android.test.AndroidTestCase; +import android.text.format.DateUtils; +import android.util.TrustedTime; + +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Future; + +/** + * Tests for {@link ThrottleService}. + */ +public class ThrottleServiceTest extends AndroidTestCase { + private static final String TAG = "ThrottleServiceTest"; + + private static final long MB_IN_BYTES = 1024 * 1024; + + private static final int TEST_KBITPS = 222; + private static final int TEST_RESET_DAY = 11; + + private static final String TEST_IFACE = "test0"; + + private WatchingContext mWatchingContext; + private INetworkManagementService mMockNMService; + private TrustedTime mMockTime; + + private ThrottleService mThrottleService; + + @Override + public void setUp() throws Exception { + super.setUp(); + + mWatchingContext = new WatchingContext(getContext()); + + mMockNMService = createMock(INetworkManagementService.class); + mMockTime = createMock(TrustedTime.class); + + mThrottleService = new ThrottleService( + mWatchingContext, mMockNMService, mMockTime, TEST_IFACE); + } + + @Override + public void tearDown() throws Exception { + mWatchingContext = null; + mMockNMService = null; + + mThrottleService.shutdown(); + mThrottleService = null; + + clearThrottlePolicy(); + + super.tearDown(); + } + + public void testNoPolicyNotThrottled() throws Exception { + expectTimeCurrent(); + expectSystemReady(); + + // provide stats without policy, verify not throttled + expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES); + expectSetInterfaceThrottle(-1, -1); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + } + + public void testUnderLimitNotThrottled() throws Exception { + setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + expectTimeCurrent(); + expectSystemReady(); + + // provide stats under limits, and verify not throttled + expectGetInterfaceCounter(1 * MB_IN_BYTES, 2 * MB_IN_BYTES); + expectSetInterfaceThrottle(-1, -1); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + } + + public void testOverLimitThrottled() throws Exception { + setThrottlePolicy(200 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + expectTimeCurrent(); + expectSystemReady(); + + // provide stats over limits, and verify throttled + expectGetInterfaceCounter(500 * MB_IN_BYTES, 600 * MB_IN_BYTES); + expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + } + + public void testUnderThenOverLimitThrottled() throws Exception { + setThrottlePolicy(201 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + expectTimeCurrent(); + expectSystemReady(); + + // provide stats right under 201MB limit, verify not throttled + expectGetInterfaceCounter(100 * MB_IN_BYTES, 100 * MB_IN_BYTES); + expectSetInterfaceThrottle(-1, -1); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + reset(mMockTime, mMockNMService); + + expectTimeCurrent(); + + // adjust usage to bump over limit, verify throttle kicks in + expectGetInterfaceCounter(105 * MB_IN_BYTES, 100 * MB_IN_BYTES); + expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS); + + // and kick poll event which should throttle + replay(mMockTime, mMockNMService); + forceServicePoll(); + verify(mMockTime, mMockNMService); + } + + public void testUpdatedPolicyThrottled() throws Exception { + setThrottlePolicy(500 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + expectTimeCurrent(); + expectSystemReady(); + + // provide stats under limit, verify not throttled + expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES); + expectSetInterfaceThrottle(-1, -1); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + reset(mMockTime, mMockNMService); + + expectTimeCurrent(); + + // provide same stats, but verify that modified policy will throttle + expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES); + expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS); + + replay(mMockTime, mMockNMService); + + // now adjust policy to bump usage over limit + setThrottlePolicy(5 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + // and wait for policy updated broadcast + mWatchingContext.nextBroadcastIntent(ThrottleManager.POLICY_CHANGED_ACTION).get(); + + verify(mMockTime, mMockNMService); + } + + public void testWithPolicyOverLimitThrottledAndRemovedAfterCycle() throws Exception { + setThrottlePolicy(90 * MB_IN_BYTES, TEST_KBITPS, TEST_RESET_DAY); + + final long baseTime = System.currentTimeMillis(); + + expectTime(baseTime); + expectSystemReady(); + + // provide stats over limit, verify throttle kicks in + expectGetInterfaceCounter(50 * MB_IN_BYTES, 50 * MB_IN_BYTES); + expectSetInterfaceThrottle(TEST_KBITPS, TEST_KBITPS); + + replay(mMockTime, mMockNMService); + systemReady(); + verify(mMockTime, mMockNMService); + reset(mMockTime, mMockNMService); + + // pretend that time has jumped forward two months + expectTime(baseTime + DateUtils.WEEK_IN_MILLIS * 8); + + // provide slightly updated stats, but verify throttle is removed + expectGetInterfaceCounter(60 * MB_IN_BYTES, 60 * MB_IN_BYTES); + expectSetInterfaceThrottle(-1, -1); + + // and kick poll event which should throttle + replay(mMockTime, mMockNMService); + forceServiceReset(); + verify(mMockTime, mMockNMService); + } + + /** + * Persist the given {@link ThrottleService} policy into {@link Settings}. + */ + public void setThrottlePolicy(long thresholdBytes, int valueKbitps, int resetDay) { + final ContentResolver resolver = getContext().getContentResolver(); + Settings.Secure.putLong(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, thresholdBytes); + Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, valueKbitps); + Settings.Secure.putInt(resolver, Settings.Secure.THROTTLE_RESET_DAY, resetDay); + } + + /** + * Clear any {@link ThrottleService} policy from {@link Settings}. + */ + public void clearThrottlePolicy() { + final ContentResolver resolver = getContext().getContentResolver(); + Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_THRESHOLD_BYTES, null); + Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_VALUE_KBITSPS, null); + Settings.Secure.putString(resolver, Settings.Secure.THROTTLE_RESET_DAY, null); + } + + /** + * Expect any {@link TrustedTime} mock calls, and respond with + * {@link System#currentTimeMillis()}. + */ + public void expectTimeCurrent() throws Exception { + expectTime(System.currentTimeMillis()); + } + + /** + * Expect any {@link TrustedTime} mock calls, and respond with the given + * time in response to {@link TrustedTime#currentTimeMillis()}. + */ + public void expectTime(long currentTime) throws Exception { + expect(mMockTime.forceRefresh()).andReturn(false).anyTimes(); + expect(mMockTime.hasCache()).andReturn(true).anyTimes(); + expect(mMockTime.currentTimeMillis()).andReturn(currentTime).anyTimes(); + expect(mMockTime.getCacheAge()).andReturn(0L).anyTimes(); + expect(mMockTime.getCacheCertainty()).andReturn(0L).anyTimes(); + } + + /** + * Expect {@link ThrottleService#systemReady()} generated calls, such as + * connecting with {@link NetworkManagementService} mock. + */ + public void expectSystemReady() throws Exception { + mMockNMService.registerObserver(isA(INetworkManagementEventObserver.class)); + expectLastCall().atLeastOnce(); + } + + /** + * Expect {@link NetworkManagementService#getInterfaceRxCounter} mock calls, + * responding with the given counter values. + */ + public void expectGetInterfaceCounter(long rx, long tx) throws Exception { + expect(mMockNMService.getInterfaceRxCounter(isA(String.class))).andReturn(rx).atLeastOnce(); + expect(mMockNMService.getInterfaceTxCounter(isA(String.class))).andReturn(tx).atLeastOnce(); + } + + /** + * Expect {@link NetworkManagementService#setInterfaceThrottle} mock call + * with the specified parameters. + */ + public void expectSetInterfaceThrottle(int rx, int tx) throws Exception { + mMockNMService.setInterfaceThrottle(isA(String.class), eq(rx), eq(tx)); + expectLastCall().atLeastOnce(); + } + + /** + * Dispatch {@link ThrottleService#systemReady()} and block until finished. + */ + public void systemReady() throws Exception { + final Future<Intent> policyChanged = mWatchingContext.nextBroadcastIntent( + ThrottleManager.POLICY_CHANGED_ACTION); + final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent( + ThrottleManager.THROTTLE_POLL_ACTION); + + mThrottleService.systemReady(); + + // wait for everything to settle; for policy to update and for first poll + policyChanged.get(); + pollAction.get(); + } + + /** + * Dispatch {@link ThrottleService#dispatchPoll()} and block until finished. + */ + public void forceServicePoll() throws Exception { + // during systemReady() service already pushed a sticky broadcast, so we + // need to skip the immediate and wait for the updated sticky. + final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent( + ThrottleManager.THROTTLE_POLL_ACTION); + + mThrottleService.dispatchPoll(); + + pollAction.get(); + } + + /** + * Dispatch {@link ThrottleService#dispatchReset()} and block until finished. + */ + public void forceServiceReset() throws Exception { + // during systemReady() service already pushed a sticky broadcast, so we + // need to skip the immediate and wait for the updated sticky. + final Future<Intent> pollAction = mWatchingContext.nextBroadcastIntent( + ThrottleManager.THROTTLE_POLL_ACTION); + + mThrottleService.dispatchReset(); + + pollAction.get(); + } + + + /** + * {@link ContextWrapper} that can attach listeners for upcoming + * {@link Context#sendBroadcast(Intent)}. + */ + private static class WatchingContext extends ContextWrapper { + private List<LocalBroadcastReceiver> mReceivers = Lists.newArrayList(); + + public class LocalBroadcastReceiver extends AbstractFuture<Intent> { + private IntentFilter mFilter; + + public LocalBroadcastReceiver(IntentFilter filter) { + mFilter = filter; + } + + public boolean dispatchBroadcast(Intent intent) { + if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { + set(intent); + return true; + } else { + return false; + } + } + } + + public WatchingContext(Context base) { + super(base); + } + + public Future<Intent> nextBroadcastIntent(String action) { + return nextBroadcastIntent(new IntentFilter(action)); + } + + public Future<Intent> nextBroadcastIntent(IntentFilter filter) { + final LocalBroadcastReceiver receiver = new LocalBroadcastReceiver(filter); + synchronized (mReceivers) { + mReceivers.add(receiver); + } + return receiver; + } + + @Override + public void sendBroadcast(Intent intent) { + synchronized (mReceivers) { + final Iterator<LocalBroadcastReceiver> i = mReceivers.iterator(); + while (i.hasNext()) { + final LocalBroadcastReceiver receiver = i.next(); + if (receiver.dispatchBroadcast(intent)) { + i.remove(); + } + } + } + } + + @Override + public void sendStickyBroadcast(Intent intent) { + sendBroadcast(intent); + } + + @Override + public void removeStickyBroadcast(Intent intent) { + // ignored + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java index 71e8e2a62623..60677dff0d8d 100755 --- a/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java +++ b/services/tests/servicestests/src/com/android/server/location/LocationBasedCountryDetectorTest.java @@ -15,17 +15,25 @@ */ package com.android.server.location; -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; - import android.location.Country; import android.location.CountryListener; import android.location.Location; import android.location.LocationListener; +import android.location.LocationManager; import android.test.AndroidTestCase; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Timer; + public class LocationBasedCountryDetectorTest extends AndroidTestCase { + private static final List<String> sEnabledProviders = Arrays.asList( + LocationManager.GPS_PROVIDER, LocationManager.PASSIVE_PROVIDER); private class TestCountryDetector extends LocationBasedCountryDetector { public static final int TOTAL_PROVIDERS = 2; protected Object countryFoundLocker = new Object(); @@ -33,7 +41,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { private final Location mLocation; private final String mCountry; private final long mQueryLocationTimeout; - private List<LocationListener> mListeners; + private Map<String, LocationListener> mListeners; public TestCountryDetector(String country, String provider) { this(country, provider, 1000 * 60 * 5); @@ -44,7 +52,7 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { mCountry = country; mLocation = new Location(provider); mQueryLocationTimeout = queryLocationTimeout; - mListeners = new ArrayList<LocationListener>(); + mListeners = new HashMap<String, LocationListener>(); } @Override @@ -69,16 +77,40 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { return mLocation; } + private Set<String> mAcceptableProviders; + + public void setAcceptableProvider(Set<String> acceptableProviders) { + mAcceptableProviders = acceptableProviders; + } + + @Override + protected boolean isAcceptableProvider(String provider) { + if (mAcceptableProviders != null) { + return mAcceptableProviders.contains(provider); + } else { + return true; + } + } + @Override - protected void registerEnabledProviders(List<LocationListener> listeners) { - mListeners.addAll(listeners); + protected void registerListener(String provider, LocationListener listener) { + assertNotNull(provider); + mListeners.put(provider, listener); } @Override - protected void unregisterProviders(List<LocationListener> listeners) { - for (LocationListener listener : mLocationListeners) { - assertTrue(mListeners.remove(listener)); + protected void unregisterListener(LocationListener listener) { + for (Entry<String, LocationListener> entry : mListeners.entrySet()) { + if (entry.getValue().equals(listener)) { + mListeners.remove(entry.getKey()); + return; + } } + fail("Not registered"); + } + + public Map<String, LocationListener> getListeners() { + return mListeners; } @Override @@ -87,8 +119,8 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { } @Override - protected int getTotalEnabledProviders() { - return TOTAL_PROVIDERS; + protected List<String> getEnabledProviders() { + return sEnabledProviders; } public void notifyLocationFound() { @@ -140,16 +172,39 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { } public void testFindingCountry() { + testFindingCountryCommon(null); + } + + public void testFindingCountryWithAcceptableProvider() { + testFindingCountryCommon(new HashSet<String>(Arrays.asList("passive"))); + } + + private void testFindingCountryCommon(Set<String> acceptableProviders) { final String country = "us"; final String provider = "Good"; CountryListenerImpl countryListener = new CountryListenerImpl(); TestCountryDetector detector = new TestCountryDetector(country, provider); + + if (acceptableProviders != null) { + detector.setAcceptableProvider(acceptableProviders); + } + detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + + if (acceptableProviders != null) { + assertEquals(acceptableProviders.size(), detector.getListenersCount()); + Map<String, LocationListener> listeners = detector.getListeners(); + for (String acceptableProvider : acceptableProviders) { + assertTrue(listeners.containsKey(acceptableProvider)); + } + } else { + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); + } + detector.notifyLocationFound(); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); assertNull(detector.getTimer()); Thread queryThread = waitForQueryThreadLaunched(detector); detector.notifyCountryFound(); @@ -168,10 +223,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { TestCountryDetector detector = new TestCountryDetector(country, provider); detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); detector.notifyLocationFound(); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); // The time should be stopped assertNull(detector.getTimer()); Thread queryThread = waitForQueryThreadLaunched(detector); @@ -193,10 +248,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { TestCountryDetector detector = new TestCountryDetector(country, provider); detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); detector.stop(); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); // The time should be stopped assertNull(detector.getTimer()); // QueryThread should still be NULL @@ -217,10 +272,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { CountryListenerImpl countryListener = new CountryListenerImpl(); detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); waitForTimerReset(detector); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); // QueryThread should still be NULL assertNull(detector.getQueryThread()); assertTrue(countryListener.notified()); @@ -248,10 +303,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { CountryListenerImpl countryListener = new CountryListenerImpl(); detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); detector.notifyLocationFound(); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); assertNull(detector.getTimer()); Thread queryThread = waitForQueryThreadLaunched(detector); detector.notifyCountryFound(); @@ -272,10 +327,10 @@ public class LocationBasedCountryDetectorTest extends AndroidTestCase { CountryListenerImpl countryListener = new CountryListenerImpl(); detector.setCountryListener(countryListener); detector.detectCountry(); - assertEquals(detector.getListenersCount(), TestCountryDetector.TOTAL_PROVIDERS); + assertEquals(TestCountryDetector.TOTAL_PROVIDERS, detector.getListenersCount()); waitForTimerReset(detector); // All listeners should be unregistered - assertEquals(detector.getListenersCount(), 0); + assertEquals(0, detector.getListenersCount()); Thread queryThread = waitForQueryThreadLaunched(detector); detector.notifyCountryFound(); // Wait for query thread ending diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java index 5217ecd49c7c..33cc97ed12d6 100644 --- a/telephony/java/com/android/internal/telephony/cat/CatService.java +++ b/telephony/java/com/android/internal/telephony/cat/CatService.java @@ -134,6 +134,7 @@ public class CatService extends Handler implements AppInterface { static final int MSG_ID_CALL_SETUP = 4; static final int MSG_ID_REFRESH = 5; static final int MSG_ID_RESPONSE = 6; + static final int MSG_ID_SIM_READY = 7; static final int MSG_ID_RIL_MSG_DECODED = 10; @@ -171,9 +172,11 @@ public class CatService extends Handler implements AppInterface { mIccRecords = ir; // Register for SIM ready event. + mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null); + mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null); + mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null); mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null); - mCmdIf.reportStkServiceIsRunning(null); CatLog.d(this, "Is running"); } @@ -587,6 +590,10 @@ public class CatService extends Handler implements AppInterface { case MSG_ID_RESPONSE: handleCmdResponse((CatResponseMessage) msg.obj); break; + case MSG_ID_SIM_READY: + CatLog.d(this, "SIM ready. Reporting STK service running now..."); + mCmdIf.reportStkServiceIsRunning(null); + break; default: throw new AssertionError("Unrecognized CAT command: " + msg.what); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java index cd585cfcba63..e299d4a8b8a1 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java @@ -99,9 +99,9 @@ public class CdmaDataConnection extends DataConnection { @Override protected boolean isDnsOk(String[] domainNameServers) { - if ((NULL_IP.equals(domainNameServers[0]) + if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1]) - && !((CDMAPhone) phone).isDnsCheckDisabled())) { + && !phone.isDnsCheckDisabled()) { return false; } else { return true; diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java index 109daf03c642..f019487aa2bc 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java @@ -424,8 +424,8 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { : -1; if (networkType == ServiceState.RADIO_TECHNOLOGY_LTE) { lteRssi = (ints[offset + 5] >= 0) ? ints[offset + 5] : 99; - lteRsrp = (ints[offset + 6] > 0) ? -ints[offset + 7] : -1; - lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 6] : 99; + lteRsrp = (ints[offset + 6] < 0) ? ints[offset + 6] : -1; + lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 7] : 99; } if (networkType != ServiceState.RADIO_TECHNOLOGY_LTE) { diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java index 8a11ae3a3253..545ad8af6b3c 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java @@ -130,7 +130,7 @@ public class GsmDataConnection extends DataConnection { @Override protected boolean isDnsOk(String[] domainNameServers) { if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1]) - && !((GSMPhone) phone).isDnsCheckDisabled()) { + && !phone.isDnsCheckDisabled()) { // Work around a race condition where QMI does not fill in DNS: // Deactivate PDP and let DataConnectionTracker retry. // Do not apply the race condition workaround for MMS APN diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 223c8adc644d..8e675fc3f4f9 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -115,6 +115,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn"); static final String APN_ID = "apn_id"; private boolean canSetPreferApn = false; + private boolean mRadioAvailable = false; @Override protected void onActionIntentReconnectAlarm(Intent intent) { @@ -519,6 +520,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } else { if (DBG) log("return APN_ALREADY_INACTIVE"); apnContext.setEnabled(false); + apnContext.setDataConnection(null); return Phone.APN_ALREADY_INACTIVE; } @@ -1267,6 +1269,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (!apnContext.getDataConnection().isRetryNeeded()) { if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)){ // if no more retries on a secondary APN attempt, tell the world and revert. + apnContext.setDataConnection(null); notifyDataConnection(Phone.REASON_APN_FAILED); return; } @@ -1323,6 +1326,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { private void onRecordsLoaded() { if (DBG) log("onRecordsLoaded: createAllApnList"); createAllApnList(); + if (mRadioAvailable) { + if (DBG) log("onRecordsLoaded, notifying data availability"); + notifyDataAvailability(null); + } setupDataOnReadyApns(Phone.REASON_SIM_LOADED); } @@ -1434,6 +1441,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { @Override protected void onRadioAvailable() { + + mRadioAvailable = true; if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator // FIXME this can be improved @@ -1461,6 +1470,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { dc.resetRetryCount(); } mReregisterOnReconnectFailure = false; + mRadioAvailable = false; if (mPhone.getSimulatedRadioControl() != null) { // Assume data is connected on the simulator @@ -1470,6 +1480,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (DBG) log("Radio is off and clean up all connection"); cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF); } + notifyDataAvailability(null); } @Override @@ -1562,6 +1573,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { log("onDataSetupComplete: All APN's had permanent failures, stop retrying"); } apnContext.setState(State.FAILED); + apnContext.setDataConnection(null); notifyDataConnection(Phone.REASON_APN_FAILED); } else { if (DBG) log("onDataSetupComplete: Not all permanent failures, retry"); @@ -1600,6 +1612,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_APN_DISABLE) { apnContext.setEnabled(false); apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE); + apnContext.setDataConnection(null); } mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); @@ -1618,7 +1631,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (apnContext.getPendingAction() == ApnContext.PENDING_ACTION_RECONNECT) { apnContext.setPendingAction(ApnContext.PENDING_ACTION_NONE); } - trySetupData(apnContext); + // Wait a bit before trying the next APN, so that + // we're not tying up the RIL command channel. + // This also helps in any external dependency to turn off the context. + sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext),APN_DELAY_MILLIS); } } diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 31b2ddd27b50..c5c3f708b0d0 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -18,6 +18,11 @@ package="com.android.test.hwui"> <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.CAMERA" /> + + <uses-feature android:name="android.hardware.camera" /> + <uses-feature android:name="android.hardware.camera.autofocus" /> + <uses-sdk android:minSdkVersion="11" /> <application @@ -25,6 +30,15 @@ android:hardwareAccelerated="true"> <activity + android:name="TextureViewActivity" + android:label="_TextureView"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="BitmapMeshActivity" android:label="_BitmapMesh"> <intent-filter> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java new file mode 100644 index 000000000000..4726672cad84 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java @@ -0,0 +1,87 @@ +/* + * 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 com.android.test.hwui; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.app.Activity; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.os.Bundle; +import android.view.Gravity; +import android.view.TextureView; +import android.view.View; +import android.widget.FrameLayout; + +import java.io.IOException; + +@SuppressWarnings({"UnusedDeclaration"}) +public class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener { + private Camera mCamera; + private TextureView mTextureView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mTextureView = new TextureView(this); + mTextureView.setSurfaceTextureListener(this); + + setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER)); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + mCamera.stopPreview(); + mCamera.release(); + } + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface) { + mCamera = Camera.open(); + + try { + mCamera.setPreviewTexture(surface); + } catch (IOException t) { + android.util.Log.e("TextureView", "Cannot set preview texture target!", t); + } + + mCamera.startPreview(); + + mTextureView.setCameraDistance(5000); + + ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f); + animator.setRepeatMode(ObjectAnimator.REVERSE); + animator.setRepeatCount(ObjectAnimator.INFINITE); + animator.setDuration(4000); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + ((View) mTextureView.getParent()).invalidate(); + } + }); + animator.start(); + + animator = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f); + animator.setRepeatMode(ObjectAnimator.REVERSE); + animator.setRepeatCount(ObjectAnimator.INFINITE); + animator.setDuration(4000); + animator.start(); + } +} diff --git a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs index 31dd3e94ce34..d44fd2beff9d 100644 --- a/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs +++ b/tests/RenderScriptTests/FBOTest/src/com/android/fbotest/fbotest.rs @@ -184,7 +184,7 @@ static void drawOffscreenResult(int posX, int posY) { startX + width, startY, 0, 1, 1); } -int root(int launchID) { +int root(void) { rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); rsgClearDepth(1.0f); diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs index 36790686feca..f04695260f41 100644 --- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs +++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs @@ -46,7 +46,7 @@ void init() { gRotate = 0.0f; } -int root(int launchID) { +int root(void) { gGroup->transforms[1].w += 0.5f; gGroup->isDirty = 1; diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs index 4c38745574c4..809f02cecc0f 100644 --- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs +++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs @@ -130,7 +130,7 @@ void drawDescription() { rsgDrawText(gTextAlloc, 2 -left, height - 2 + bottom); } -int root(int launchID) { +int root(void) { rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f); rsgClearDepth(1.0f); diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs index a663d3525176..3fc59fcfdd64 100644 --- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs +++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs @@ -776,7 +776,7 @@ static void drawOffscreenResult(int posX, int posY, int width, int height) { startX + width, startY, 0, 1, 1); } -int root(int launchID) { +int root(void) { gRenderSurfaceW = rsgGetWidth(); gRenderSurfaceH = rsgGetHeight(); diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs index 67c2b8623c61..aeae13ff1331 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/rslist.rs @@ -35,7 +35,7 @@ void init() { int textPos = 0; -int root(int launchID) { +int root(void) { rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f); rsgClearDepth(1.0f); diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 16611d88851f..33d4e1fc489b 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -73,6 +73,7 @@ import android.util.LruCache; import com.android.internal.app.IBatteryStats; import com.android.internal.util.AsyncChannel; +import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -165,95 +166,97 @@ public class WifiStateMachine extends StateMachine { private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022; private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023; + /* The base for wifi message types */ + static final int BASE = Protocol.BASE_WIFI; /* Load the driver */ - static final int CMD_LOAD_DRIVER = 1; + static final int CMD_LOAD_DRIVER = BASE + 1; /* Unload the driver */ - static final int CMD_UNLOAD_DRIVER = 2; + static final int CMD_UNLOAD_DRIVER = BASE + 2; /* Indicates driver load succeeded */ - static final int CMD_LOAD_DRIVER_SUCCESS = 3; + static final int CMD_LOAD_DRIVER_SUCCESS = BASE + 3; /* Indicates driver load failed */ - static final int CMD_LOAD_DRIVER_FAILURE = 4; + static final int CMD_LOAD_DRIVER_FAILURE = BASE + 4; /* Indicates driver unload succeeded */ - static final int CMD_UNLOAD_DRIVER_SUCCESS = 5; + static final int CMD_UNLOAD_DRIVER_SUCCESS = BASE + 5; /* Indicates driver unload failed */ - static final int CMD_UNLOAD_DRIVER_FAILURE = 6; + static final int CMD_UNLOAD_DRIVER_FAILURE = BASE + 6; /* Start the supplicant */ - static final int CMD_START_SUPPLICANT = 11; + static final int CMD_START_SUPPLICANT = BASE + 11; /* Stop the supplicant */ - static final int CMD_STOP_SUPPLICANT = 12; + static final int CMD_STOP_SUPPLICANT = BASE + 12; /* Start the driver */ - static final int CMD_START_DRIVER = 13; + static final int CMD_START_DRIVER = BASE + 13; /* Start the driver */ - static final int CMD_STOP_DRIVER = 14; + static final int CMD_STOP_DRIVER = BASE + 14; /* Indicates DHCP succeded */ - static final int CMD_IP_CONFIG_SUCCESS = 15; + static final int CMD_IP_CONFIG_SUCCESS = BASE + 15; /* Indicates DHCP failed */ - static final int CMD_IP_CONFIG_FAILURE = 16; + static final int CMD_IP_CONFIG_FAILURE = BASE + 16; /* Start the soft access point */ - static final int CMD_START_AP = 21; + static final int CMD_START_AP = BASE + 21; /* Stop the soft access point */ - static final int CMD_STOP_AP = 22; + static final int CMD_STOP_AP = BASE + 22; - static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = 23; + static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 23; /* Supplicant events */ /* Connection to supplicant established */ - static final int SUP_CONNECTION_EVENT = 31; + static final int SUP_CONNECTION_EVENT = BASE + 31; /* Connection to supplicant lost */ - static final int SUP_DISCONNECTION_EVENT = 32; + static final int SUP_DISCONNECTION_EVENT = BASE + 32; /* Driver start completed */ - static final int DRIVER_START_EVENT = 33; + static final int DRIVER_START_EVENT = BASE + 33; /* Driver stop completed */ - static final int DRIVER_STOP_EVENT = 34; + static final int DRIVER_STOP_EVENT = BASE + 34; /* Network connection completed */ - static final int NETWORK_CONNECTION_EVENT = 36; + static final int NETWORK_CONNECTION_EVENT = BASE + 36; /* Network disconnection completed */ - static final int NETWORK_DISCONNECTION_EVENT = 37; + static final int NETWORK_DISCONNECTION_EVENT = BASE + 37; /* Scan results are available */ - static final int SCAN_RESULTS_EVENT = 38; + static final int SCAN_RESULTS_EVENT = BASE + 38; /* Supplicate state changed */ - static final int SUPPLICANT_STATE_CHANGE_EVENT = 39; + static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 39; /* Password failure and EAP authentication failure */ - static final int AUTHENTICATION_FAILURE_EVENT = 40; + static final int AUTHENTICATION_FAILURE_EVENT = BASE + 40; /* WPS overlap detected */ - static final int WPS_OVERLAP_EVENT = 41; + static final int WPS_OVERLAP_EVENT = BASE + 41; /* Supplicant commands */ /* Is supplicant alive ? */ - static final int CMD_PING_SUPPLICANT = 51; + static final int CMD_PING_SUPPLICANT = BASE + 51; /* Add/update a network configuration */ - static final int CMD_ADD_OR_UPDATE_NETWORK = 52; + static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52; /* Delete a network */ - static final int CMD_REMOVE_NETWORK = 53; + static final int CMD_REMOVE_NETWORK = BASE + 53; /* Enable a network. The device will attempt a connection to the given network. */ - static final int CMD_ENABLE_NETWORK = 54; + static final int CMD_ENABLE_NETWORK = BASE + 54; /* Enable all networks */ - static final int CMD_ENABLE_ALL_NETWORKS = 55; + static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55; /* Disable a network. The device does not attempt a connection to the given network. */ - static final int CMD_DISABLE_NETWORK = 56; + static final int CMD_DISABLE_NETWORK = BASE + 56; /* Blacklist network. De-prioritizes the given BSSID for connection. */ - static final int CMD_BLACKLIST_NETWORK = 57; + static final int CMD_BLACKLIST_NETWORK = BASE + 57; /* Clear the blacklist network list */ - static final int CMD_CLEAR_BLACKLIST = 58; + static final int CMD_CLEAR_BLACKLIST = BASE + 58; /* Save configuration */ - static final int CMD_SAVE_CONFIG = 59; + static final int CMD_SAVE_CONFIG = BASE + 59; /* Supplicant commands after driver start*/ /* Initiate a scan */ - static final int CMD_START_SCAN = 71; + static final int CMD_START_SCAN = BASE + 71; /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */ - static final int CMD_SET_SCAN_MODE = 72; + static final int CMD_SET_SCAN_MODE = BASE + 72; /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */ - static final int CMD_SET_SCAN_TYPE = 73; + static final int CMD_SET_SCAN_TYPE = BASE + 73; /* Disconnect from a network */ - static final int CMD_DISCONNECT = 74; + static final int CMD_DISCONNECT = BASE + 74; /* Reconnect to a network */ - static final int CMD_RECONNECT = 75; + static final int CMD_RECONNECT = BASE + 75; /* Reassociate to a network */ - static final int CMD_REASSOCIATE = 76; + static final int CMD_REASSOCIATE = BASE + 76; /* Controls power mode and suspend mode optimizations * * When high perf mode is enabled, power mode is set to @@ -267,19 +270,19 @@ public class WifiStateMachine extends StateMachine { * - turn off roaming * - DTIM wake up settings */ - static final int CMD_SET_HIGH_PERF_MODE = 77; + static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; /* Set the country code */ - static final int CMD_SET_COUNTRY_CODE = 80; + static final int CMD_SET_COUNTRY_CODE = BASE + 80; /* Request connectivity manager wake lock before driver stop */ - static final int CMD_REQUEST_CM_WAKELOCK = 81; + static final int CMD_REQUEST_CM_WAKELOCK = BASE + 81; /* Enables RSSI poll */ - static final int CMD_ENABLE_RSSI_POLL = 82; + static final int CMD_ENABLE_RSSI_POLL = BASE + 82; /* RSSI poll */ - static final int CMD_RSSI_POLL = 83; + static final int CMD_RSSI_POLL = BASE + 83; /* Set up packet filtering */ - static final int CMD_START_PACKET_FILTERING = 84; + static final int CMD_START_PACKET_FILTERING = BASE + 84; /* Clear packet filter */ - static final int CMD_STOP_PACKET_FILTERING = 85; + static final int CMD_STOP_PACKET_FILTERING = BASE + 85; /* Connect to a specified network (network id * or WifiConfiguration) This involves increasing * the priority of the network, enabling the network @@ -288,33 +291,33 @@ public class WifiStateMachine extends StateMachine { * an existing network. All the networks get enabled * upon a successful connection or a failure. */ - static final int CMD_CONNECT_NETWORK = 86; + static final int CMD_CONNECT_NETWORK = BASE + 86; /* Save the specified network. This involves adding * an enabled network (if new) and updating the * config and issuing a save on supplicant config. */ - static final int CMD_SAVE_NETWORK = 87; + static final int CMD_SAVE_NETWORK = BASE + 87; /* Delete the specified network. This involves * removing the network and issuing a save on * supplicant config. */ - static final int CMD_FORGET_NETWORK = 88; + static final int CMD_FORGET_NETWORK = BASE + 88; /* Start Wi-Fi protected setup */ - static final int CMD_START_WPS = 89; + static final int CMD_START_WPS = BASE + 89; /* Set the frequency band */ - static final int CMD_SET_FREQUENCY_BAND = 90; + static final int CMD_SET_FREQUENCY_BAND = BASE + 90; /* Enable background scan for configured networks */ - static final int CMD_ENABLE_BACKGROUND_SCAN = 91; + static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91; /* Commands from/to the SupplicantStateTracker */ /* Reset the supplicant state tracker */ - static final int CMD_RESET_SUPPLICANT_STATE = 111; + static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; /* Commands/events reported by WpsStateMachine */ /* Indicates the completion of WPS activity */ - static final int WPS_COMPLETED_EVENT = 121; + static final int WPS_COMPLETED_EVENT = BASE + 121; /* Reset the WPS state machine */ - static final int CMD_RESET_WPS_STATE = 122; + static final int CMD_RESET_WPS_STATE = BASE + 122; private static final int CONNECT_MODE = 1; private static final int SCAN_ONLY_MODE = 2; |