Android GUI FramebufferNativeWindow ANativeWindow
来源:互联网 发布:用eclipse写java 编辑:程序博客网 时间:2024/06/07 02:22
Android GUI FramebufferNativeWindow ANativeWindow
Android系统的GUI设计的两种本地窗口:
面向管理者(SurfaceFlinger)
SurfaceFlinger扮演了系统中所有UI界面的管理者,它需要直接或间接地持有“本地窗口”,这个窗口就是FramebufferNativeWindow
面向应用程序
—-这类窗口是SurfaceTextureClient
Window-1 是能直接显示在终端屏幕上, 它使用了帧缓冲区
Window-2 是从内存缓冲区分配的空间
OpenGL“本地窗口”(NativeWindow),Android系统通过ANativeWindow实现OpenGL ES的本地化, 而FramebufferNativeWindow是ANativeWindow子类,对应的是真实的物理屏幕。
OpenGL ES ->ANativeWindow->FramebufferNativeWindow
OpenGL ES 本质上是一个图形渲染管线的状态机
EGL
1、为 OpenGL ES 提供平台独立性而设计
2、是 OpenGL ES 和底层 Native 平台视窗系统之间的接口
3、用于监控图形渲染管线的状态以及维护 Frame buffer 和其他渲染 Surface 的外部层
—-OpenGL ES 图形管线的状态被存储于 EGL 管理的一个 Context 中。 Frame Buffers 和其他绘制 Surfaces 通过 EGL API 创建、管理和销毁。 EGL 同时也控制和提供了对设备显示和可能的设备渲染配置的访问
EGL 应用:
EGLDisplay mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); // 1、获取显示设备 //EGLDisplay eglGetDisplay (NativeDisplayType display); //display 参数是native系统的窗口显示ID值 eglInitialize(mEglDisplay, &major, &minor); // 2、初始化显示设备、获取EGL版本号EGLint config_attribs[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_RENDERABLE_TYPE, //指定渲染api类别, 这里或者是硬编码的4 EGL_OPENGL_ES2_BIT, //或者是EGL14.EGL_OPENGL_ES2_BIT EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE};int num_configs = 0;EGLConfig eglConfig;//3、获取满足attributes的所有config, EGLConfig---描述EGLSurface配置信息的数据类型(绘制目标framebuffer的配置属性)eglChooseConfig(mEglDisplay, config_attribs, &eglConfig, 1, &num_configs)) //通过ANativeWindow 创建本地surface---EGLSurface,它是系统窗口或frame buffer句柄,可以理解为一个后端的渲染目标窗口// 4、将Surface转换为本地窗口EGLSurface mEglSurface = eglCreateWindowSurface(mEglDisplay, eglConfig, mWin, NULL); eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &mSurfaceWidth); // 5、查询高宽eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &mSurfaceHeight);EGLint context_attrib[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};//创建EGL环境, EGLContext: OpenGL ES图形上下文,它代表了OpenGL状态机EGLContext mEglContext = eglCreateContext(mEglDisplay, eglConfig, EGL_NO_CONTEXT, context_attrib); // 6、根据EGLConfig、context_attrib创建EGLContext//7、将EGLDisplay、EGLSurface和EGLContext进行绑定(渲染上下文绑定到渲染面,指定当前的环境为绘制环境 EGLContext->context)//eglMakeCurrent后生成的surface就可以利用opengl画图了eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); render: //双缓冲刷新 front buffer 和 back buffer //eglSwapBuffers会去触发queuebuffer,dequeuebuffer, //queuebuffer将画好的buffer(back->front)交给surfaceflinger处理, //dequeuebuffer新创建一个buffer用来画图 eglSwapBuffers(mEglDisplay, mEglSurface);//release流程: eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); //1、 eglDestroyContext(mEglDisplay, mEglContext); // 2、 eglDestroySurface(mEglDisplay, mEglSurface); // 3、 eglTerminate(mEglDisplay); // 4、mEglDisplay = EGL_NO_DISPLAY; // 5、 mEglContext = EGL_NO_CONTEXT; mEglSurface = EGL_NO_SURFACE;
1、
ANativeWindow
EGL创建一个Window Surface函数原型列出如下:
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowType window, const EGLint *attrib_list);
frameworks/base/opengl/include/egl/Eglplatform.h
#ifndef __eglplatform_h_#define __eglplatform_h_#include <KHR/khrplatform.h>#ifndef EGLAPI#define EGLAPI KHRONOS_APICALL#endif#ifndef EGLAPIENTRY#define EGLAPIENTRY KHRONOS_APIENTRY#endif#define EGLAPIENTRYP EGLAPIENTRY*#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */#ifndef WIN32_LEAN_AND_MEAN#define WIN32_LEAN_AND_MEAN 1#endif#include <windows.h>typedef HDC EGLNativeDisplayType;typedef HBITMAP EGLNativePixmapType;typedef HWND EGLNativeWindowType;#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */typedef int EGLNativeDisplayType;typedef void *EGLNativeWindowType;typedef void *EGLNativePixmapType;#elif defined(__ANDROID__) || defined(ANDROID) //针对android平台,关键定义项#include <android/native_window.h>struct egl_native_pixmap_t;typedef struct ANativeWindow* EGLNativeWindowType;typedef struct egl_native_pixmap_t* EGLNativePixmapType;typedef void* EGLNativeDisplayType;#elif defined(__unix__)/* X11 (tentative) */#include <X11/Xlib.h>#include <X11/Xutil.h>typedef Display *EGLNativeDisplayType;typedef Pixmap EGLNativePixmapType;typedef Window EGLNativeWindowType;#else#error "Platform not recognized"#endif/* EGL 1.2 types, renamed for consistency in EGL 1.3 */typedef EGLNativeDisplayType NativeDisplayType;typedef EGLNativePixmapType NativePixmapType;typedef EGLNativeWindowType NativeWindowType;typedef khronos_int32_t EGLint;#endif /* __eglplatform_h */
ANativeWindow
system/core/include/system/Window.h
...typedef const native_handle_t* buffer_handle_t;typedef struct android_native_base_t{ /* a magic value defined by the actual EGL native type */ int magic; /* the sizeof() of the actual EGL native type */ int version; void* reserved[4]; /* reference-counting interface */ void (*incRef)(struct android_native_base_t* base); void (*decRef)(struct android_native_base_t* base);} android_native_base_t;typedef struct ANativeWindowBuffer{#ifdef __cplusplus ANativeWindowBuffer() { common.magic = ANDROID_NATIVE_BUFFER_MAGIC; common.version = sizeof(ANativeWindowBuffer); memset(common.reserved, 0, sizeof(common.reserved)); } // Implement the methods that sp<ANativeWindowBuffer> expects so that it // can be used to automatically refcount ANativeWindowBuffer's. void incStrong(const void* id) const { common.incRef(const_cast<android_native_base_t*>(&common)); } void decStrong(const void* id) const { common.decRef(const_cast<android_native_base_t*>(&common)); }#endif struct android_native_base_t common; int width; int height; int stride; int format; int usage; void* reserved[2]; buffer_handle_t handle; void* reserved_proc[8];} ANativeWindowBuffer_t;// Old typedef for backwards compatibility.typedef ANativeWindowBuffer_t android_native_buffer_t;...struct ANativeWindow{#ifdef __cplusplus ANativeWindow() : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) { common.magic = ANDROID_NATIVE_WINDOW_MAGIC; common.version = sizeof(ANativeWindow); memset(common.reserved, 0, sizeof(common.reserved)); } /* Implement the methods that sp<ANativeWindow> expects so that it can be used to automatically refcount ANativeWindow's. */ void incStrong(const void* id) const { common.incRef(const_cast<android_native_base_t*>(&common)); } void decStrong(const void* id) const { common.decRef(const_cast<android_native_base_t*>(&common)); }#endif struct android_native_base_t common; /* flags describing some attributes of this surface or its updater */ const uint32_t flags; /* min swap interval supported by this updated */ const int minSwapInterval; /* max swap interval supported by this updated */ const int maxSwapInterval; /* horizontal and vertical resolution in DPI */ const float xdpi; const float ydpi; /* Some storage reserved for the OEM's driver. */ intptr_t oem[4]; //设置交换间隔时间 int (*setSwapInterval)(struct ANativeWindow* window, int interval); //EGL通过这个dequeueBuffer来申请一个buffer。本地窗口所提供的buffer分别来自于帧缓冲区和内存空间。 int (*dequeueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer** buffer); int (*lockBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); //当EGL对一块buffer渲染完成后,调用queueBuffer来unlock和post buffer int (*queueBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); int (*query)(const struct ANativeWindow* window, int what, int* value); /* * hook used to perform various operations on the surface. * (*perform)() is a generic mechanism to add functionality to * ANativeWindow while keeping backward binary compatibility. * * DO NOT CALL THIS HOOK DIRECTLY. Instead, use the helper functions * defined below. * * (*perform)() returns -ENOENT if the 'what' parameter is not supported * by the surface's implementation. * * The valid operations are: * NATIVE_WINDOW_SET_USAGE * NATIVE_WINDOW_CONNECT (deprecated) * NATIVE_WINDOW_DISCONNECT (deprecated) * NATIVE_WINDOW_SET_CROP * NATIVE_WINDOW_SET_BUFFER_COUNT * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY (deprecated) * NATIVE_WINDOW_SET_BUFFERS_TRANSFORM * NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS * NATIVE_WINDOW_SET_BUFFERS_FORMAT * NATIVE_WINDOW_SET_SCALING_MODE * NATIVE_WINDOW_LOCK (private) * NATIVE_WINDOW_UNLOCK_AND_POST (private) * NATIVE_WINDOW_API_CONNECT (private) * NATIVE_WINDOW_API_DISCONNECT (private) * */ int (*perform)(struct ANativeWindow* window, int operation, ... ); int (*cancelBuffer)(struct ANativeWindow* window, struct ANativeWindowBuffer* buffer); void* reserved_proc[2];};
native_handle_t代表一块内存块
system/core/include/cutils/native_handle.h
typedef struct native_handle{ int version; /* sizeof(native_handle_t) */ int numFds; /* number of file-descriptors at &data[0] */ int numInts; /* number of ints at &data[numFds] */ int data[0]; /* numFds + numInts ints */} native_handle_t;
2、
FramebufferNativeWindow对应的是真实的物理屏幕
frameworks/base/include/ui/FramebufferNativeWindow.h
...#define NUM_FRAME_BUFFERS 2class FramebufferNativeWindow : public EGLNativeBase< ANativeWindow, FramebufferNativeWindow, LightRefBase<FramebufferNativeWindow> >{public: FramebufferNativeWindow(); framebuffer_device_t const * getDevice() const { return fbDev; } bool isUpdateOnDemand() const { return mUpdateOnDemand; } status_t setUpdateRectangle(const Rect& updateRect); status_t compositionComplete(); void dump(String8& result); // for debugging only int getCurrentBufferIndex() const;private: friend class LightRefBase<FramebufferNativeWindow>; ~FramebufferNativeWindow(); // this class cannot be overloaded static int setSwapInterval(ANativeWindow* window, int interval); static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer); static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer); static int query(const ANativeWindow* window, int what, int* value); static int perform(ANativeWindow* window, int operation, ...); framebuffer_device_t* fbDev; alloc_device_t* grDev; sp<NativeBuffer> buffers[NUM_FRAME_BUFFERS]; sp<NativeBuffer> front; mutable Mutex mutex; Condition mCondition; int32_t mNumBuffers; //FramebufferNativeWindow管理的buffer总数 int32_t mNumFreeBuffers; // 空闲的buffer数 int32_t mBufferHead; int32_t mCurrentBufferIndex; bool mUpdateOnDemand;#if defined(BOARD_USES_HDMI) SecHdmiClient *mHdmiClient;#endif};
frameworks/base/libs/ui/FramebufferNativeWindow.cpp
...class NativeBuffer : public EGLNativeBase< ANativeWindowBuffer, NativeBuffer, LightRefBase<NativeBuffer> >{public: NativeBuffer(int w, int h, int f, int u) : BASE() { ANativeWindowBuffer::width = w; ANativeWindowBuffer::height = h; ANativeWindowBuffer::format = f; ANativeWindowBuffer::usage = u; }private: friend class LightRefBase<NativeBuffer>; ~NativeBuffer() { }; // this class cannot be overloaded};FramebufferNativeWindow::FramebufferNativeWindow() : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false){ hw_module_t const* module;#if defined(BOARD_USES_HDMI) mHdmiClient = android::SecHdmiClient::getInstance();#endif //1\将指定的模块加载到内存来 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { int stride; int err; int i; //2\打开Gralloc模块中的gralloc设备和fb设备 //Gralloc模块负责注册图形缓冲区,gralloc设备负责分配图形缓冲区,fb设备负责渲染图形缓冲区 //framebuffer_open()\gralloc_open()实际都调用gralloc.cpp中的gralloc_device_open()打开实际的设备 err = framebuffer_open(module, &fbDev); //打开framebuffer设备 LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); err = gralloc_open(module, &grDev); //grallo设备 LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err)); // bail out if we can't initialize the modules if (!fbDev || !grDev) return; mUpdateOnDemand = (fbDev->setUpdateRect != 0); // initialize the buffer FIFO mNumBuffers = NUM_FRAME_BUFFERS; mNumFreeBuffers = NUM_FRAME_BUFFERS; mBufferHead = mNumBuffers-1; for (i = 0; i < mNumBuffers; i++) { //向HAL层的Gralloc申请缓冲空间 buffers[i] = new NativeBuffer( fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); } for (i = 0; i < mNumBuffers; i++) { //hardware/libhardware/include/hardware/Gralloc.h 函数原型: // int (*alloc)(struct alloc_device_t* dev, // int w, int h, int format, int usage, // buffer_handle_t* handle, int* stride); //通过 gralloc_device_open()函数的 dev->device.alloc = gralloc_alloc;进行一步步函数调用实现分配图形缓冲区 err = grDev->alloc(grDev, fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride); LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s", i, fbDev->width, fbDev->height, strerror(-err)); if (err) { mNumBuffers = i; mNumFreeBuffers = i; mBufferHead = mNumBuffers-1; break; } } const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi; const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi; const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval; const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval; } else { LOGE("Couldn't get gralloc module"); } //FramebufferNativeWindow将其setSwapInterval/dequeueBuffer等成员函数填充 到ANativeWindow中的函数指针中,OpenGL ES才能通过一个ANativeWindow来正确地与本地窗口建立真正的连接 ANativeWindow::setSwapInterval = setSwapInterval; ANativeWindow::dequeueBuffer = dequeueBuffer; ANativeWindow::lockBuffer = lockBuffer; ANativeWindow::queueBuffer = queueBuffer; ANativeWindow::query = query; ANativeWindow::perform = perform;}
hardware/libhardware/include/hardware/FB.h
...static inline int framebuffer_open(const struct hw_module_t* module, struct framebuffer_device_t** device) { return module->methods->open(module, GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);}
hardware/libhardware/include/hardware/Gralloc.h
...static inline int gralloc_open(const struct hw_module_t* module, struct alloc_device_t** device) { return module->methods->open(module, GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);}
3、
用户空间的应用程序在使用帧缓冲区之前,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。
有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。最后,用户空间中的应用程序就通过fb设备来将前面已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。
当用户空间中的应用程序不再需要使用一块图形缓冲区的时候,就可以通过gralloc设备来释放它,并且将它从地址空间中解除映射。
分配图形缓冲区: grDev->alloc()
gralloc_device_open() =>gralloc_alloc()
=>gralloc_alloc_framebuffer()=>gralloc_alloc_framebuffer_locked()
=>mapFrameBufferLocked()=>mapFrameBuffer()//帧缓冲区分配
gralloc_device_open() =>gralloc_alloc()=>gralloc_alloc_buffer()
=>ashmem_create_region()
//创建一块匿名共享内存,接着再在这块匿名共享内存上分配一个图形缓冲区
=>mapBuffer()
//把从匿名共享内存中分配的图形缓冲区映射到进程的地址空间,然后才可以使用,通过调用函数mapBuffer实现映射
=>gralloc_map(module, hnd, &vaddr);
//将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间
framebuffer设备渲染:fb_post()
framebuffer_open() => gralloc_device_open() => fb_device_open() => fb_post() 将图形缓冲区渲染到系统帧缓冲区中去,把画面绘制到设备显示屏中
hardware/libhardware/module/gralloc/gralloc.cpp
int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device){ int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { gralloc_context_t *dev; dev = (gralloc_context_t*)malloc(sizeof(*dev)); /* initialize our state here */ memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = gralloc_close; dev->device.alloc = gralloc_alloc; // dev->device.free = gralloc_free; *device = &dev->device.common; status = 0; } else { status = fb_device_open(module, name, device); } return status;}分配图形缓冲区//用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_alloc来分配static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride){ if (!pHandle || !pStride) return -EINVAL; size_t size, stride; int align = 4; int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: bpp = 4; break; case HAL_PIXEL_FORMAT_RGB_888: bpp = 3; break; case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_RGBA_5551: case HAL_PIXEL_FORMAT_RGBA_4444: bpp = 2; break; default: return -EINVAL; } size_t bpr = (w*bpp + (align-1)) & ~(align-1); size = bpr * h; stride = bpr / bpp; int err; //系统帧缓冲区中分配还是在内存中分配缓冲,内存中分配的图形缓冲区,最终是需要拷贝到系统帧缓冲区去的 if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); } else { err = gralloc_alloc_buffer(dev, size, usage, pHandle); } if (err < 0) { return err; } *pStride = stride; return 0;}//函数gralloc_alloc_framebuffer用来在系统帧缓冲区中分配图形缓冲区static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module); pthread_mutex_lock(&m->lock); //函数gralloc_alloc_framebuffer_locked才是真正用来分配图形缓冲区 int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); pthread_mutex_unlock(&m->lock); return err; } static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module); // allocate the framebuffer if (m->framebuffer == NULL) { // initialize the framebuffer, the framebuffer is mapped once // and forever. int err = mapFrameBufferLocked(m); if (err < 0) { return err; } } const uint32_t bufferMask = m->bufferMask; const uint32_t numBuffers = m->numBuffers; const size_t bufferSize = m->finfo.line_length * m->info.yres; if (numBuffers == 1) { // If we have only one buffer, we never use page-flipping. Instead, // we return a regular buffer which will be memcpy'ed to the main // screen when post is called. int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle); } if (bufferMask >= ((1LU<<numBuffers)-1)) { // We ran out of buffers. return -ENOMEM; } // create a "fake" handles for it intptr_t vaddr = intptr_t(m->framebuffer->base); private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, private_handle_t::PRIV_FLAGS_FRAMEBUFFER); // find a free slot for (uint32_t i=0 ; i<numBuffers ; i++) { if ((bufferMask & (1LU<<i)) == 0) { m->bufferMask |= (1LU<<i); break; } vaddr += bufferSize; } hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); *pHandle = hnd; return 0; }//函数gralloc_alloc_buffer用来在内存在分配图形缓冲区static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle){ int err = 0; int fd = -1; size = roundUpToPageSize(size); //创建一块匿名共享内存,接着再在这块匿名共享内存上分配一个图形缓冲区 fd = ashmem_create_region("gralloc-buffer", size); if (fd < 0) { LOGE("couldn't create ashmem (%s)", strerror(-errno)); err = -errno; } if (err == 0) { private_handle_t* hnd = new private_handle_t(fd, size, 0); gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( dev->common.module); //把从匿名共享内存中分配的图形缓冲区映射到进程的地址空间,然后才可以使用,通过调用函数mapBuffer实现映射 err = mapBuffer(module, hnd); if (err == 0) { *pHandle = hnd; } } LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); return err;}
函数mapBuffer实现在文件hardware/libhardware/modules/gralloc/mapper.cpp
int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd) { void* vaddr; return gralloc_map(module, hnd, &vaddr); //将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间 }
hardware/libhardware/modules/gralloc/framebuffer.cpp
int fb_device_open(hw_module_t const* module, const char* name, hw_device_t** device){ int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { alloc_device_t* gralloc_device; status = gralloc_open(module, &gralloc_device); if (status < 0) return status; /* initialize our state here */ fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = fb_close; dev->device.setSwapInterval = fb_setSwapInterval; dev->device.post = fb_post; dev->device.setUpdateRect = 0; private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); if (status >= 0) { int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); int format = (m->info.bits_per_pixel == 32) ? HAL_PIXEL_FORMAT_RGBX_8888 : HAL_PIXEL_FORMAT_RGB_565; const_cast<uint32_t&>(dev->device.flags) = 0; const_cast<uint32_t&>(dev->device.width) = m->info.xres; const_cast<uint32_t&>(dev->device.height) = m->info.yres; const_cast<int&>(dev->device.stride) = stride; const_cast<int&>(dev->device.format) = format; const_cast<float&>(dev->device.xdpi) = m->xdpi; const_cast<float&>(dev->device.ydpi) = m->ydpi; const_cast<float&>(dev->device.fps) = m->fps; const_cast<int&>(dev->device.minSwapInterval) = 1; const_cast<int&>(dev->device.maxSwapInterval) = 1; *device = &dev->device.common; } } return status;}//将图形缓冲区渲染到系统帧缓冲区中去,把画面绘制到设备显示屏中static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer){ if (private_handle_t::validate(buffer) < 0) return -EINVAL; fb_context_t* ctx = (fb_context_t*)dev; private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module); if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { const size_t offset = hnd->base - m->framebuffer->base; m->info.activate = FB_ACTIVATE_VBL; m->info.yoffset = offset / m->finfo.line_length; if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { LOGE("FBIOPUT_VSCREENINFO failed"); m->base.unlock(&m->base, buffer); return -errno; } m->currentBuffer = buffer; } else { // If we can't do the page_flip, just copy the buffer to the front // FIXME: use copybit HAL instead of memcpy void* fb_vaddr; void* buffer_vaddr; m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, 0, 0, m->info.xres, m->info.yres, &fb_vaddr); m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY, 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); m->base.unlock(&m->base, buffer); m->base.unlock(&m->base, m->framebuffer); } return 0;}
- Android GUI FramebufferNativeWindow ANativeWindow
- GUI系统之SurfaceFlinger(3)Android中的本地窗口FramebufferNativewindow
- GUI系统之SurfaceFlinger(3)Android中的本地窗口FramebufferNativewindow
- GUI系统之SurfaceFlinger(3)Android中的本地窗口FramebufferNativewindow
- GUI系统之SurfaceFlinger(3)Android中的本地窗口FramebufferNativewindow
- Android Dev Intro - ANativeWindow
- FramebufferNativeWindow
- Android服务端本地窗口FramebufferNativeWindow
- Android服务端本地窗口FramebufferNativeWindow
- ANativeWindow
- Android Camera Preview ANativeWindow的处理
- Android Camera Preview ANativeWindow的处理
- Android Camera Preview ANativeWindow的处理
- Android+FFmpeg+ANativeWindow视频解码播放
- android :ffmpeg+anativewindow做视频播放
- Android Camera Preview ANativeWindow的处理
- Android+FFmpeg+ANativeWindow视频解码播放
- Android中native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface的关系
- vue-cli安装规范
- 杭电多校 1011 Regular polygon! 题解报告
- 使用 acl 库编写多线程应用程序
- Spark编程之基本的RDD算子coalesce, repartition, checkpoint
- MongoDB四(插入文档)
- Android GUI FramebufferNativeWindow ANativeWindow
- Win32 SOCKET之UDP
- 目前为止最全的微信小程序项目实例
- 理解RESTful架构
- OpenGL ES应用开发实践指南(android 卷)笔记 第一章
- HDU2333(二分答案)
- C++ 虚函数表解析
- Trailing Zeroes
- tensorflow安装记录