Merge "New widget: TextureView Bug #4343984"
This commit is contained in:
@@ -21010,6 +21010,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
abstract class GLES20Layer extends HardwareLayer {
|
||||
int mLayer;
|
||||
Finalizer mFinalizer;
|
||||
|
||||
private int mLayerWidth;
|
||||
private int mLayerHeight;
|
||||
GLES20Layer() {
|
||||
}
|
||||
|
||||
private final GLES20Canvas mCanvas;
|
||||
|
||||
@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];
|
||||
|
||||
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) {
|
||||
|
||||
91
core/java/android/view/GLES20RenderLayer.java
Normal file
91
core/java/android/view/GLES20RenderLayer.java
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
76
core/java/android/view/GLES20TextureLayer.java
Normal file
76
core/java/android/view/GLES20TextureLayer.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,23 @@ 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.
|
||||
|
||||
@@ -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;
|
||||
@@ -165,6 +166,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.
|
||||
*
|
||||
@@ -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) {
|
||||
|
||||
299
core/java/android/view/TextureView.java
Normal file
299
core/java/android/view/TextureView.java
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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;
|
||||
*
|
||||
* @Override
|
||||
* protected void onCreate(Bundle savedInstanceState) {
|
||||
* super.onCreate(savedInstanceState);
|
||||
*
|
||||
* mTextureView = new TextureView(this);
|
||||
* mTextureView.setSurfaceTextureListener(this);
|
||||
*
|
||||
* setContentView(mTextureView);
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void onDestroy() {
|
||||
* super.onDestroy();
|
||||
*
|
||||
* mCamera.stopPreview();
|
||||
* mCamera.release();
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
@@ -386,6 +388,14 @@ private:
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,26 @@
|
||||
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
|
||||
android:label="HwUi"
|
||||
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">
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user