07.显示系统:第003课_最简单的Surface测试程序:第01节_最简单的Surface测试程序

在前面的章节中,简单的分析了android显示系统的框架,我们知道一个应用程序之中,存在一个或者多个buffer用来存放界面的数据,单应用程序构造好这些buffer之后,他会把这些buffer发送给surfaceFlinger,由surfaceFlinger决定在合适的时候把buffer中的数据拷贝到framebuffer,这样才能在屏幕上显示界面。应用程序的buffer需要向surfaceFlinger进行申请。

surfaceFlinger管理着两个驱动程序,一个为ashmem(匿名共享内存),其中应用程序的buffer来自ashmem(匿名共享内存)。同时还管理者多个应用程序发送过来的buffer,由他决定如何把这多个应用程序的数据叠加起来,最终发送给framebuffer。下面我们编写一个Surface测试程序。

Surface测试程序流程

编写改程序,最核心的东西就是如何得到buffer,写buffer,最后再提交buffer。
在这里插入图片描述
上图的APP是我们的引用程序,存在一个或者多个buf(用来存放界面数据),多个buf合成一个surface(APP的界面)。这些buf是想surfaceFlinger申请的。

编写Surface测试程序流程如下:
1.获得surfacelinger服务
2.创建surface。
3.得到buffer
4.写buffer
5.提交buffer
其中3,4,5是一个循环的过程,如上图中的3个buffer,提交完第一个buf的时候,APP可以构建第二个buf,当第二个构建成功然后提交,紧接着构造第三个buffer,这样进行循环。

Surface测试程序编写

从头到尾写一个测试程序是十分困难的,在安卓5.0的源码中android-5.0.2\frameworks\native\services\surfaceflinger\tests\resize目录下存在文件Android.mk,与resize.cpp。我们把其拷贝到RK3399安卓源码7.1,frameworks\native\services\surfaceflinger\tests\APP_0010_Surfacetest(自己创建),并且修改resize.cpp为SurfaceTest.cpp。可惜的是,该测试程序并不能直接使用 mmm命令编译通过。还要做一些修改,修改之后代码如下:
SurfaceTest.cpp:

#include <cutils/memory.h>

#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <android/native_window.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>

using namespace android;


int main()
{
    // set up the thread-pool
    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    // create a client to surfaceflinger
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
            160, 240, PIXEL_FORMAT_RGB_565, 0);

    sp<Surface> surface = surfaceControl->getSurface();

    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setLayer(100000);
    SurfaceComposerClient::closeGlobalTransaction();

    ANativeWindow_Buffer outBuffer;
    surface->lock(&outBuffer, NULL);
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
    surface->unlockAndPost();

    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
    surface->unlockAndPost();

    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setSize(320, 240);
    SurfaceComposerClient::closeGlobalTransaction();

    
    IPCThreadState::self()->joinThreadPool();
    
    return 0;
}

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	SurfaceTest.cpp

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
    libui \
    libgui \
	libbinder

LOCAL_MODULE:= SurfaceTest

LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)

编写完成上面两个文件之后,使用mmm命令编译,然后重新生生system.img烧写到开发板。

启动开发板之后,执行命令SurfaceTest,可以看到屏幕的做上角出现一块绿色的区域。我们把这个版本的代码保存下来为APP_0010_Surfacetest-v1,

下面是我们APP_0010_Surfacetest-v2版本

#include <cutils/memory.h>

#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <android/native_window.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>

using namespace android;


int main()
{
    // set up the thread-pool
    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    // create a client to surfaceflinger
	/*获得SurfaceComposerClient服务*/
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    
	/*创建Surface*/
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
            160, 240, PIXEL_FORMAT_RGB_565, 0);

    sp<Surface> surface = surfaceControl->getSurface();

    SurfaceComposerClient::openGlobalTransaction();
	/*设置Z轴高度*/
    surfaceControl->setLayer(100000);
    SurfaceComposerClient::closeGlobalTransaction();


    ANativeWindow_Buffer outBuffer;
	/*获得这个surface的一个buf*/
    surface->lock(&outBuffer, NULL);
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
	/*填充buf*/
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
	/*提交buf给surfaceflinger,让其显示*/
    surface->unlockAndPost();
	/*增加一个休眠时间*/
	sleep(3);
	
    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
    surface->unlockAndPost();
	sleep(3);

    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x001F, bpr*outBuffer.height);
    surface->unlockAndPost();
	sleep(3);

    SurfaceComposerClient::openGlobalTransaction();
    surfaceControl->setSize(320, 240);
    SurfaceComposerClient::closeGlobalTransaction();

    
    IPCThreadState::self()->joinThreadPool();
    
    return 0;
}

编译之后可以看三种颜色以一定时间间隔不停的交换。

最后是编写我们的APP_0010_Surfacetest-v3版本:

#include <cutils/memory.h>

#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <android/native_window.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>

using namespace android;


int main()
{
    // set up the thread-pool
    sp<ProcessState> proc(ProcessState::self());
    ProcessState::self()->startThreadPool();

    // create a client to surfaceflinger
	/*获得SurfaceComposerClient服务*/
    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
    
	/*创建Surface*/
    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
            160, 240, PIXEL_FORMAT_RGB_565, 0);

    sp<Surface> surface = surfaceControl->getSurface();

    SurfaceComposerClient::openGlobalTransaction();
	/*设置Z轴高度*/
    surfaceControl->setLayer(100000);
    SurfaceComposerClient::closeGlobalTransaction();


    ANativeWindow_Buffer outBuffer;
	/*获得这个surface的一个buf*/
    surface->lock(&outBuffer, NULL);
    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
	/*填充buf*/
    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
	/*提交buf给surfaceflinger,让其显示*/
    surface->unlockAndPost();
	/*增加一个休眠时间*/
	sleep(3);
	
    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
    surface->unlockAndPost();
	sleep(3);

    surface->lock(&outBuffer,NULL);
    android_memset16((uint16_t*)outBuffer.bits, 0x001F, bpr*outBuffer.height);
    surface->unlockAndPost();
	sleep(3);

	for(int i = 0; i <100; i++){
		surface->lock(&outBuffer,NULL);
		printf("%03d buff addr = 0x%x\n",i,(unsigned long)outBuffer.bits);
		surface->unlockAndPost();
	}

    
    IPCThreadState::self()->joinThreadPool();
    
    return 0;
}

在这个版本中,我们打印了outBuffer.bits的地址,在开发板运行之后,打印信息如下:

000 buff addr = 0x5844000
000 buff addr = 0x5831000
000 buff addr = 0x581e000
000 buff addr = 0x5e87000

000 buff addr = 0x5844000
000 buff addr = 0x5831000
000 buff addr = 0x581e000
000 buff addr = 0x5e87000

000 buff addr = 0x5844000
000 buff addr = 0x5831000
000 buff addr = 0x581e000
000 buff addr = 0x5e87000

000 buff addr = 0x5844000
000 buff addr = 0x5831000
000 buff addr = 0x581e000
000 buff addr = 0x5e87000
......
......

我们可以发现,其使用了四个buf,后面都是重复使用。这样我们知道对于同一个应用程序。他分配了3个buf。

如果我们在上面的程序添加代码 surfaceControl->setLayer(100000),改变其z轴高度,我们可以实现对显示的隐藏或者遮挡。

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/88815592