Android GLSurfaceView笔记

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是同一个。

@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mParent.requestTransparentRegion(this);
        //SurfaceView没有必要自己在创建一个ViewRoot,直接通过ViewRoot获取一个IWindowSession
        mSession = 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);

					//重新申请一个Surface
                    relayoutResult = 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内核设计思想》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值