GLSurefaceView继承自SurfaceView,同时也拥有了OpenGL ES所提供的的强大的3D图形处理功能。目前主流的移动游戏引擎都使用该View。
GLSurefaceView的主要特性:
1、管理EGLDisplay,它表示一个显示屏
2、管理Surface(本质上就是一块内存区域)
3、GLSurefaceView会创建新的线程,以使整个渲染过程不至于阻塞UI主线程
4、用户可以自定义渲染方式,如通过setRender()设置一个Render。
使用基本步骤:
1、创建GLSurefaceView
2、初始化OpenGL ES环境
环境可以自己设置,ex:

     setEGLConfigChooser(boolean);setGLWrapper(GLWrapper);getHolder().setFormat(PixelFormat,TRANSLUCENT)setDebugFlag(int)

3、设置Renderer,setRender()可以将用户自定义的一个Renderer加入实际的渲染流程中

 setRenderer(Renderer renderer);

4、设置Rendering Mode,默认情况下采用的是连续的渲染方式。

   setRenderMode(RENDERMODE_WHEN_DIRTY);

5、状态处理
注意处理程序的声明周期,例如Activity的暂停和恢复情况下的处理,在pause触发时,调用GLSurefaceView的onPause(),恢复时再调用onResume。

上述步骤发现,我们主要关注Renderer的实现,而EGL的创建过程,Surface的分配以及OpenGL ES的一些调用细节等都会被隐藏起来了。

实现原理:
其构造函数除了调用了其父类的方法就直接进入了init()方法

private void init() {SurfaceHolder holder = getHolder();holder.addCallback(this);}

该方法先通过父类获取当前的SurefaceHolder,然后添加自身为回调函数(自身实现了SurfaceHolder.Callback2,CallBack2继承自SurfaceHolder.Callback),这样每当Surface有变化时,就能收到通知了。

     //当成功申请到一个Surface时调用,正常情况下只会发生一次public void surfaceCreated(SurfaceHolder holder);//当Surface改变时调用,如format,size的变动public void surfaceChanged(SurfaceHolder holder, int format, int width,int height);//当Surface销毁时调用public void surfaceDestroyed(SurfaceHolder holder);

SurfaceHolder如何被创建
SurfaceView.java

 private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {....}

他是一个全局变量,在一开始就已经创建了实例。
Surface如何创建
SurfaceView继承于View,View树在ViewRoot创建时会申请到一个Surface。而SurfaceView的这个SurfaceView并非和ViewRoot的Surface是同一个。

@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();mParent.requestTransparentRegion(this);//SurfaceView没有必要自己在创建一个ViewRoot,直接通过ViewRoot获取一个IWindowSessionmSession = getWindowSession();mLayout.token = getWindowToken();mLayout.setTitle("SurfaceView");mViewVisibility = getVisibility() == VISIBLE;if (!mGlobalListenersAdded) {ViewTreeObserver observer = getViewTreeObserver();observer.addOnScrollChangedListener(mScrollChangedListener);observer.addOnPreDrawListener(mDrawListener);mGlobalListenersAdded = true;}}

onAttachedToWindow为updateWindow提供触发 源码链接

 /** @hide */protected void updateWindow(boolean force, boolean redrawNeeded) {if (!mHaveFrame) {return;}ViewRootImpl viewRoot = getViewRootImpl();if (viewRoot != null) {mTranslator = viewRoot.mTranslator;}if (mTranslator != null) {mSurface.setCompatibilityTranslator(mTranslator);}....................if (force || creating || formatChanged || sizeChanged || visibleChanged|| mLeft != mLocation[0] || mTop != mLocation[1]|| mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) {try {final boolean visible = mVisible = mRequestedVisible;mLeft = mLocation[0];mTop = mLocation[1];mWidth = myWidth;mHeight = myHeight;mFormat = mRequestedFormat;mLayout.x = mLeft;mLayout.y = mTop;mLayout.width = getWidth();mLayout.height = getHeight();if (mTranslator != null) {mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);}mLayout.format = mRequestedFormat;mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS| WindowManager.LayoutParams.FLAG_SCALED| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {mLayout.privateFlags |=WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;}mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;if (mWindow == null) {Display display = getDisplay();mWindow = new MyWindow(this);mLayout.type = mWindowType;mLayout.gravity = Gravity.START|Gravity.TOP;mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets,mStableInsets);}boolean realSizeChanged;boolean reportDrawNeeded;int relayoutResult;mSurfaceLock.lock();try {mUpdateWindowNeeded = false;reportDrawNeeded = mReportDrawNeeded;mReportDrawNeeded = false;mDrawingStopped = !visible;if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);//重新申请一个SurfacerelayoutResult = mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,visible ? VISIBLE : GONE,WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,mWinFrame, mOverscanInsets, mContentInsets,mVisibleInsets, mStableInsets, mOutsets, mConfiguration,mNewSurface);if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {reportDrawNeeded = true;}mSurfaceFrame.left = 0;mSurfaceFrame.top = 0;if (mTranslator == null) {mSurfaceFrame.right = mWinFrame.width();mSurfaceFrame.bottom = mWinFrame.height();} else {float appInvertedScale = mTranslator.applicationInvertedScale;mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);}final int surfaceWidth = mSurfaceFrame.right;final int surfaceHeight = mSurfaceFrame.bottom;realSizeChanged = mLastSurfaceWidth != surfaceWidth|| mLastSurfaceHeight != surfaceHeight;mLastSurfaceWidth = surfaceWidth;mLastSurfaceHeight = surfaceHeight;} finally {mSurfaceLock.unlock();}try {redrawNeeded |= creating | reportDrawNeeded;SurfaceHolder.Callback callbacks[] = null;final boolean surfaceChanged = (relayoutResult& WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {mSurfaceCreated = false;if (mSurface.isValid()) {if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");callbacks = getSurfaceCallbacks();for (SurfaceHolder.Callback c : callbacks) {c.surfaceDestroyed(mSurfaceHolder);}}}mSurface.transferFrom(mNewSurface);if (visible && mSurface.isValid()) {if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {mSurfaceCreated = true;mIsCreating = true;if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");if (callbacks == null) {callbacks = getSurfaceCallbacks();}for (SurfaceHolder.Callback c : callbacks) {c.surfaceCreated(mSurfaceHolder);}}if (creating || formatChanged || sizeChanged|| visibleChanged || realSizeChanged) {if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat+ " w=" + myWidth + " h=" + myHeight);if (callbacks == null) {callbacks = getSurfaceCallbacks();}for (SurfaceHolder.Callback c : callbacks) {c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);}}if (redrawNeeded) {//申请了全新的Surface后,会通知到所有注册了callback函数的对象。if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");if (callbacks == null) {callbacks = getSurfaceCallbacks();}for (SurfaceHolder.Callback c : callbacks) {if (c instanceof SurfaceHolder.Callback2) {((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(mSurfaceHolder);}}}}} finally {mIsCreating = false;if (redrawNeeded) {if (DEBUG) Log.i(TAG, "finishedDrawing");mSession.finishDrawing(mWindow);}mSession.performDeferredDestroy(mWindow);}} catch (RemoteException ex) {}}}

GLSurfaceView将会启动一个新线程来完后渲染,以防止程序阻塞UI线程(GLThread),其在setRenderer时启动,然后不断等待和处理事件,同时还负责开展Render工作

  public void surfaceCreated() {synchronized(sGLThreadManager) {if (LOG_THREADS) {Log.i("GLThread", "surfaceCreated tid=" + getId());}mHasSurface = true;mFinishedCreatingEglSurface = false;sGLThreadManager.notifyAll();while (mWaitingForSurface&& !mFinishedCreatingEglSurface&& !mExited) {try {sGLThreadManager.wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}

参考:
《深入理解Android内核设计思想》

Android GLSurfaceView笔记相关推荐

  1. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  2. Android开发笔记(一百五十六)通过渲染纹理展示地球仪

    上一篇文章介绍了如何使用GL10描绘三维物体的线段框架,后面给出的立方体和球体效果图,虽然看起来具备立体的轮廓,可离真实的物体还差得远.因为现实生活中的物体不仅仅有个骨架,还有花纹有光泽(比如衣服), ...

  3. Android开发笔记(一百五十四)OpenGL的画笔工具GL10

    上一篇文章介绍了OpenGL绘制三维图形的流程,其实没有传说中的那么玄乎,只要放平常心把它当作一个普通控件就好了,接下来继续介绍OpenGL具体的绘图操作,这项工作得靠三维图形的画笔GL10来完成了. ...

  4. Android开发笔记(一百五十三)OpenGL绘制三维图形的流程

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...

  5. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  6. Android学习笔记三

    大神博客(必看)http://blog.csdn.net/huachao1001/article/list/1 1.Android校招笔记 http://huachao1001.github.io/i ...

  7. Android学习笔记:Android基础知识点(不断更新中)

    1.Android学习笔记:OkHttp 2.Android学习笔记:更新UI的方法(UI线程和非UI线程) 3.Android学习笔记:Volley 4.Android学习笔记:Handler 5. ...

  8. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  9. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

最新文章

  1. WEB程序代码优化入手的几方面
  2. (转载博文)VC++API速查
  3. python程序多次运行_[Python]在一段Python程序中使用多次事件循环
  4. uniGUI 实操感受
  5. Matlab | 数字信号处理:双线性变换法设计IIR数字滤波器
  6. React state和props使用场景
  7. 手机qq2008触屏版_[进行中]数码手机周年庆
  8. WPF框架教程 | 从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器
  9. python形参中的:*args和**kwargs区别
  10. 使用ajax获取后台数据怎么打印,我用ajax获取后台数据并展示在前端页面的方法【源码】...
  11. 三个 CSS 预处理器(框架):Sass、LESS 和 Stylus
  12. 将.sql文件导入数据库
  13. C语言题目:平均成绩,已知某个同学的语文、数学、英语成绩,计算该同学的平均分
  14. 辣椒app软件测试,testflight辣椒视频APP
  15. 青春树儿童摄影网网页
  16. POI Excel插入行,下面的行动态移动
  17. 微信小程序(登录、分享、支付)
  18. Chrome浏览器上传图片或图片另存时浏览器无响应
  19. 华为nova 3e,重新编译内核文件,解除ptrace限制,以使用Frida
  20. UML设计——网上信用卡管理系统分析与设计(新手)

热门文章

  1. C#委托之如何理解委托面试常见题:
  2. 宇文成 Python 第七章 字符串与正则表达式
  3. 分析手提电子秤芯片方案CSU8RP1186
  4. ostringstream >>> string >>> char *
  5. 算法实战应用案例精讲-【图像处理】数字图像处理从原理到应用(python代码实战)
  6. (附源码)SSM萌宠宠物网店的设计与实现 毕业设计 011042
  7. java里localtime,java 时间转换之LocalDate,LocalTime ,LocalDateTime
  8. ComboBox隐藏三角符号
  9. c语言白盒测试笔试题,软件测试笔试题目第2套共8套
  10. 谁来阻击腾讯?(转载)