概述
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
2
class 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的全部内容,希望文章能够帮你解决Android GUI FramebufferNativeWindow ANativeWindow所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复