Allocating from system memory

When the usage bit is not set to GRALLOC_USAGE_HW_FB or the system cannot support double buffering, we have to allocate the buffer from system memory using gralloc_alloc_buffer. Let's look at the implementation of 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) {
ALOGE("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);
err = mapBuffer(module, hnd);
if (err == 0) {
*pHandle = hnd;
}
}

ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));

return err;
}

In gralloc_alloc_buffer, it rounds up the buffer size to the page size first. Then it creates an anonymous shared memory region using ashmem_create_region. It creates a new private_handle_t instance to represent this shared memory region.

This shared memory region is described as a file descriptor. To use it, we need to map it to the current process address space. This is done with the mapBuffer function:

int mapBuffer(gralloc_module_t const* module, 
private_handle_t* hnd)
{
void* vaddr;
return gralloc_map(module, hnd, &vaddr);
}

mapBuffer calls to another function, gralloc_map, to do the memory mapping:

static int gralloc_map(gralloc_module_t const* /*module*/, 
buffer_handle_t handle,
void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
size_t size = hnd->size;
void* mappedAddress = mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
if (mappedAddress == MAP_FAILED) {
ALOGE("Could not mmap %s", strerror(errno));
return -errno;
}
hnd->base = uintptr_t(mappedAddress) + hnd->offset;
//ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
}
*vaddr = (void*)hnd->base;
return 0;
}

In grallo_map, if the file descriptor in private_handle_t is a framebuffer device, we don't have to do the mapping again, since the framebuffer is initialized and mapped to the SurfaceFlinger address space in fb_device_open, as we analyzed before.

If it is a shared memory region, it needs to be mapped to the current process address space using the mmap system function.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.1.156