把Android原生的View渲染到OpenGL Texture

把Android原生的View渲染到OpenGL Texture
把Android原生的View渲染到OpenGL Texture

把Android原生的View渲染到OpenGL Texture

最近要把Android 原生的View渲染到OpenGL GLSurfaceView中,起初想到的是截图的方法,也就是把View截取成bitmap后,再把Bitmap 渲染到OpenGL中;但是明显这种方法是不可行的,面对一些高速动态更新的View,只有不停的对view 进行截图才能渲染出原生View的效果。

通过大量的Google终于在国外的网站找到了一个做过类似的先例。不过经过测试该方法只能渲染直接父类为View的view,也就是只能渲染一层View(如progressbar,没不能添加child的view),当该原生Android View包含很多子view时(也就是根View为FramLayout、或者linearLayout之类),无法实时的监听到View动态改变,OpenGL中只能不停的渲染该view,才能渲染出原生View的效果。但是这样一来不同的渲染会耗费大量的资源,降低应用程序的效率。理想中的话,是监听到了该View的内容或者其子view 的内容发生了变化(如:View中的字幕发生滚动)才进行渲染。

经过接近两周的努力我终于完美地实现了该效果,既然是站在别人的基础上得来的成果,那么该方法就应当被共享,所以产生了此文,不过只支持api 15以上的

步骤一:重写根View

1.设置该View 绘制自己:

[java] view plain copy 在CODE上查看代码片派生到我的代码片setWillNotDraw(false);

2.监听View的变化,重写View,用ViewTreeObServer来监听,方法如下:

[java] view plain copy 在CODE上查看代码片派生到我的代码片private void addOnPreDrawListener() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

final ViewTreeObserver mObserver = getViewTreeObserver();

if (mObserver != null) {

mObserver.addOnPreDrawListener(new OnPreDrawListener() { @Override

public boolean onPreDraw() {

if (isDirty()) {//View或者子view发生变化

invalidate();

}

return true;

}

});

}

}

}

3.重写该View的onDraw方法:

[java] view plain copy 在CODE上查看代码片派生到我的代码片@Override

protected void onDraw(Canvas canvas) {

try {

if (mSurface != null) {

Canvas surfaceCanvas = mSurface.lockCanvas(null); super.dispatchDraw(surfaceCanvas);

mSurface.unlockCanvasAndPost(surfaceCanvas);

mSurface.release();

mSurface = null;

mSurface = new Surface(mSurfaceTexture);

}

} catch (OutOfResourcesException e) {

e.printStackTrace();

}

}

步骤二:GLSurfaceView.Renderer

[java] view plain copy 在CODE上查看代码片派生到我的代码片class CustomRenderer implements GLSurfaceView.Renderer { int glSurfaceTex;

private final int GL_TEXTURE_EXTERNAL_OES = 0x8D65;

long currentTime;

long previousTime;

boolean b = false;

int frameCount = 0;

DirectDrawer mDirectDrawer;

ActivityManager activityManager;

MemoryInfo _memoryInfo;

// Fixed values

private int TEXTURE_WIDTH = 360;

private int TEXTURE_HEIGHT = 360;

Context context;

private LauncherAppWidgetHostView addedWidgetView; private SurfaceTexture surfaceTexture = null;

private Surface surface;

float fps;

public CustomRenderer(Context context, LauncherAppWidgetHostView addedWidgetView, Display mDisplay){ this.context = context;

this.addedWidgetView = addedWidgetView;

TEXTURE_WIDTH = mDisplay.getWidth();

TEXTURE_HEIGHT = mDisplay.getHeight();

_memoryInfo = new MemoryInfo();

activityManager = (ActivityManager)

context.getApplicationContext().getSystemService(Context.ACTI VITY_SERVICE);

}

@Override

public void onDrawFrame(GL10 gl) {

synchronized (this) {

surfaceTexture.updateTexImage();

}

activityManager.getMemoryInfo(_memoryInfo);

GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT |

GLES20.GL_COLOR_BUFFER_BIT);

GLES20.glEnable(GLES20.GL_BLEND);

GLES20.glBlendFunc(GLES20.GL_ONE,

GLES20.GL_ONE_MINUS_SRC_ALPHA);

float[] mtx = new float[16];

surfaceTexture.getTransformMatrix(mtx);

mDirectDrawer.draw(mtx);

calculateFps();

//getAppMemorySize();

//getRunningAppProcessInfo();

//Log.v("onDrawFrame", "FPS: " + Math.round(fps) + ", availMem: " + Math.round(_memoryInfo.availMem / 1048576) + "MB");

}

private void getAppMemorySize(){

ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

android.os.Debug.MemoryInfo[] memoryInfos = mActivityManager.getProcessMemoryInfo(new

int[]{android.os.Process.myPid()});

int size = memoryInfos[0].dalvikPrivateDirty;

Log.w("getAppMemorySize", size / 1024 + " MB");

}

private void getRunningAppProcessInfo() {

ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

//获得系统里正在运行的所有进程

List runningAppProcessesList = mActivityManager.getRunningAppProcesses();

for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcessesList) {

// 进程ID号

int pid = runningAppProcessInfo.pid;

// 用户ID

int uid = runningAppProcessInfo.uid;

// 进程名

String processName = runningAppProcessInfo.processName;

// 占用的内存

int[] pids = new int[] {pid};

Debug.MemoryInfo[] memoryInfo =

mActivityManager.getProcessMemoryInfo(pids);

int memorySize = memoryInfo[0].dalvikPrivateDirty;

System.out.println("processName="+processName+",currentPid: "+ "pid= "

+android.os.Process.myPid()+"----------->"+pid+",uid="+uid+", memorySize="+memorySize+"kb");

}

}

@Override

public void onSurfaceCreated(GL10 gl, EGLConfig config) { surface = null;

surfaceTexture = null;

glSurfaceTex = Engine_CreateSurfaceTexture(TEXTURE_WIDTH, TEXTURE_HEIGHT);

Log.d("GLES20Ext", "glSurfaceTex" + glSurfaceTex);

if (glSurfaceTex > 0) {

surfaceTexture = new SurfaceTexture(glSurfaceTex);

surfaceTexture.setDefaultBufferSize(TEXTURE_WIDTH, TEXTURE_HEIGHT);

surface = new Surface(surfaceTexture);

addedWidgetView.setSurface(surface);

addedWidgetView.setSurfaceTexture(surfaceTexture);

//addedWidgetView.setSurfaceTexture(surfaceTexture);

mDirectDrawer = new DirectDrawer(glSurfaceTex);

}

}

float calculateFps() {

frameCount++;

if (!b) {

b = true;

previousTime = System.currentTimeMillis();

}

long intervalTime = System.currentTimeMillis() - previousTime;

if (intervalTime >= 1000) {

b = false;

fps = frameCount / (intervalTime / 1000f);

frameCount = 0;

Log.w("calculateFps", "FPS: " + fps);

}

return fps;

}

int Engine_CreateSurfaceTexture(int width, int height) {

/*

* Create our texture. This has to be done each time the surface is

* created.

*/

int[] textures = new int[1];

GLES20.glGenTextures(1, textures, 0);

glSurfaceTex = textures[0];

if (glSurfaceTex > 0) {

GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, glSurfaceTex);

// Notice the use of GL_TEXTURE_2D for texture creation

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width, height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);

GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,

GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);

GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,

GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,

GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);

GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,

GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

}

return glSurfaceTex;

}

@Override

public void onSurfaceChanged(GL10 gl, int width, int height) {

}

}

[java] view plain copy 在CODE上查看代码片派生到我的代码片public class DirectDrawer {

private final String vertexShaderCode =

"attribute vec4 vPosition;" +

"attribute vec2 inputTextureCoordinate;" +

"varying vec2 textureCoordinate;" +

"void main()" +

"{"+

"gl_Position = vPosition;"+

"textureCoordinate = inputTextureCoordinate;" +

"}";

private final String fragmentShaderCode =

"#extension GL_OES_EGL_image_external : require\n"+

"precision mediump float;" +

"varying vec2 textureCoordinate;\n" +

"uniform samplerExternalOES s_texture;\n" +

"void main() {" +

" gl_FragColor = texture2D( s_texture,

textureCoordinate );\n" +

"}";

private FloatBuffer vertexBuffer, textureVerticesBuffer;

private ShortBuffer drawListBuffer;

private final int mProgram;

private int mPositionHandle;

private int mTextureCoordHandle;

private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

// number of coordinates per vertex in this array

private static final int COORDS_PER_VERTEX = 2;

private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

static float squareCoords[] = {

-1.0f, 0.0f,

-1.0f, -2.2f,

1.0f, -

2.2f,

1.0f, 0.0f,

};

static float textureVertices[] = {

0f, 0f,

0f, 1f,

1f, 1f,

1f, 0f,

};

private int texture;

public DirectDrawer(int texture)

{

this.texture = texture;

// initialize vertex byte buffer for shape coordinates

ByteBuffer bb =

ByteBuffer.allocateDirect(squareCoords.length * 4);

bb.order(ByteOrder.nativeOrder());

vertexBuffer = bb.asFloatBuffer();

vertexBuffer.put(squareCoords);

vertexBuffer.position(0);

// initialize byte buffer for the draw list

ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);

dlb.order(ByteOrder.nativeOrder());

drawListBuffer = dlb.asShortBuffer();

drawListBuffer.put(drawOrder);

drawListBuffer.position(0);

ByteBuffer bb2 =

ByteBuffer.allocateDirect(textureVertices.length * 4);

bb2.order(ByteOrder.nativeOrder());

textureVerticesBuffer = bb2.asFloatBuffer();

textureVerticesBuffer.put(textureVertices);

textureVerticesBuffer.position(0);

int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);

int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program

GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program

GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program

GLES20.glLinkProgram(mProgram); //

creates OpenGL ES program executables

}

public void draw(float[] mtx)

{

GLES20.glUseProgram(mProgram);

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture);

// get handle to vertex shader's vPosition member

mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

// Enable a handle to the triangle vertices

GLES20.glEnableVertexAttribArray(mPositionHandle);

// Prepare the coordinate data

GLES20.glVertexAttribPointer(mPositionHandle,

COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);

mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");

GLES20.glEnableVertexAttribArray(mTextureCoordHandle);

// textureVerticesBuffer.clear();

// textureVerticesBuffer.put( transformTextureCoordinates( // textureVertices, mtx ));

// textureVerticesBuffer.position(0);

GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, textureVerticesBuffer);

GLES20.glDrawElements(GLES20.GL_TRIANGLES,

drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

// Disable vertex array

GLES20.glDisableVertexAttribArray(mPositionHandle);

GLES20.glDisableVertexAttribArray(mTextureCoordHandle);

}

private int loadShader(int type, String shaderCode){

// create a vertex shader type (GLES20.GL_VERTEX_SHADER)

// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)

int shader = GLES20.glCreateShader(type);

// add the source code to the shader and compile it

GLES20.glShaderSource(shader, shaderCode);

GLES20.glCompileShader(shader);

return shader;

}

private float[] transformTextureCoordinates( float[] coords, float[] matrix)

{

float[] result = new float[ coords.length ];

float[] vt = new float[4];

for ( int i = 0 ; i < coords.length ; i += 2 ) {

float[] v = { coords[i], coords[i+1], 0 , 1 };

Matrix.multiplyMV(vt, 0, matrix, 0, v, 0);

result[i] = vt[0];

result[i+1] = vt[1];

}

return result;

}

}

步骤三:配置GLSurfaceView:

[java] view plain copy 在CODE上查看代码片派生到我的代码片GLSurfaceView glSurfaceView = new

GLSurfaceView(getApplicationContext());

// Setup the surface view for drawing to

glSurfaceView.setEGLContextClientVersion(2);

glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

glSurfaceView.setRenderer(renderer);

//glSurfaceView.setZOrderOnTop(true);

// Add our WebView to the Android View hierarchy

glSurfaceView.setLayoutParams(new

https://www.360docs.net/doc/3e5392015.html,youtParams(https://www.360docs.net/doc/3e5392015.html,youtParams.MATCH_PAREN T, https://www.360docs.net/doc/3e5392015.html,youtParams.MATCH_PARENT));

android 自定义圆角头像以及使用declare-styleable进行配置属性解析

android 自定义圆角头像以及使用declare-styleable进行配置属性解析由于最新项目中正在检查UI是否与效果图匹配,结果关于联系人模块给的默认图片是四角稍带弧度的圆角,而我们截取的图片是正方形的,现在要给应用统一替换。应用中既用到大圆角头像(即整个头像是圆的)又用到四角稍带弧度的圆角头像,封装一下以便重用。以下直接见代码 [java] view plain copy 在CODE上查看代码片派生到我的代码片 package com.test.demo; import com.test.demo.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.widget.ImageView; /** * 圆角imageview */ public class RoundImageView extends ImageView { private static final String TAG = "RoundImageView"; /** * 图片的类型,圆形or圆角 */ private int type; public static final int TYPE_CIRCLE = 0; public static final int TYPE_ROUND = 1; /** * 圆角大小的默认值

高通android平台开发

问题描述: 对于有过开发高通android系统的人来说,获取代码构建开发环境并不是难事,但对于刚刚接触这一块内容的人,如果没有详细的说明很容易走弯路,本文档就是根据本人的实践总结的一些经验教训。 1.代码获取 高通的android代码分为两部分,一部分是开源的,可以从网站https://https://www.360docs.net/doc/3e5392015.html,/xwiki/bin/QAEP/下载,需要知道要下载的代码的分支及build id。另一部分是非开源的,需要从高通的另一个网站https://https://www.360docs.net/doc/3e5392015.html,/login/上下载,这个下载是有权限限制的,晓光的帐号可以下载代码。后面这部分代码需要放到第一部分代码的vendor指定目录下,可能是vendor/qcom-proprietary或vendor/qcom/proprietary,根据版本的不同有所区别。 高通平台相关的东西基本都在vendor/qcom/proprietary下或device/qcom下 2.编译环境构建(ubuntu 10.04 64位) Android2.3.x后的版本需要在64位下进行编译 更新ubuntu源,要加上deb https://www.360docs.net/doc/3e5392015.html,/ lucid partner 这个 源用来安装java。 apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev x11proto-core-dev libx11-dev libxml-simple-perl sun-java6-jdk gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs lib32z-dev lib32readline5-dev 研发主机不能更新java,需要让IT安装sun-java6-jdk。 在命令行执行sudo dpkg-reconfigure dash 选择no,否则编译时会报一下脚本语法错误 编译的过程中https://https://www.360docs.net/doc/3e5392015.html,/xwiki/bin/QAEP/和版本的 release notes中都有介绍,首先source build/envsetup.sh,然后choosecombo选择需要的选项,最后make或make –j4。-j4用来指定参与编译的cpu个数,指定了编译会快些。编译单个模块的时候只需要在make后面跟 上模块的名字 为了简化可以使用以下脚本 export TARGET_SIMULATOR=fasle export TARGET_BUILD_TYPE=release export TARGET_PRODUCT=msm7627a export TARGET_BUILD_VARIANT=eng set_stuff_for_environment make $1 编译的中间结果在out/target/product/平台/obj目录下,有时候为了完全

A20_Android开发手册_V1[1].0

C o n f i d e n t i a l A20Android 开发手册 V 1.0 2013-02013-03 3-15

C o n f i d e n t i a l Revision History Version Date Section/Page Changes 1.0 2013-03-15 初始版本

C o n f i d e n t i a l 目录 一、A20概述 (4) 1.1A20主控介绍.....................................................................................................................51.2外围设备介绍.....................................................................................................................51.3软件资源介绍.....................................................................................................................5二、建立开发环境. (5) 2.1硬件资源............................................................................................................................62.2软件资源. (6) 2.2.1安装JDK (ubuntu12.04).....................................................................................62.2.2安装平台支持软件(ubuntu12.04).....................................................................62.2.3安装编译工具链(ubuntu12.04).........................................................................62.2.4安装phoenixSuit (windows xp )........................................................................72.2.5其他软件(windows xp ).. (7) 三、源码下载 (8) 3.1wing 源码下载....................................................................................................................83.2仓库的目录树.. (8) 3.2.1android 目录树.........................................................................................................83.2.2lichee 目录结构.. (9) 3.2.2.1buildroot 目录结构........................................................................................93.2.2.2linux-3.3目录结构......................................................................................103.2.2.3u-boot 目录结构..........................................................................................113.2.2.4tools 目录结构............................................................................................123.2.2.5boot 目录结构 (12) 四、编译和打包 (13) 4.1源码编译 (13) 4.1.1lichee 源码编译......................................................................................................134.1.2android 源码编译...................................................................................................134.2打包固件.. (13) 4.2.1完全打包...............................................................................................................134.2.2局部打包 (14) 五、固件烧写 (14) 5.1使用PhoenixSuit 烧写固件.............................................................................................145.2使用fastboot 更新系统 (14) 5.2.1进入fastboot 模式.................................................................................................145.2.2fastboot 命令使用.. (15) 六、recovery 功能使用 (15) 6.1键值的查看......................................................................................................................156.2按键选择..........................................................................................................................166.3功能使用..........................................................................................................................16七、调试 (17) 7.1调试apk...........................................................................................................................177.2调试linux 内核. (17)

Android平台我的日记设计文档

Android平台我的日记 设计文档 项目名称:mydiray 项目结构示意: 阶段任务名称(一)布局的设计 开始时间: 结束时间: 设计者: 梁凌旭 一、本次任务完成的功能 1、各控件的显示 二、最终功能及效果 三、涉及知识点介绍 四、代码设计 activity_main.xml:

android:layout_centerHorizontal="true" android:layout_marginTop="88dp" android:text="@string/wo" android:textSize="35sp"/>

相关文档
最新文档