this gralloc module is only used on the emulator or without a h/w renderer. therefore there is no synchronization to do in lock/unlock and pmem buffers are not relevant. hopefully this will remove some of the confusion about how gralloc should be implemented and make it more obvious that this implementation is not intended to be used by h/w renderers.
170 lines
4.9 KiB
C++
170 lines
4.9 KiB
C++
/*
|
|
* Copyright (C) 2008 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <cutils/log.h>
|
|
#include <cutils/atomic.h>
|
|
|
|
#include <hardware/hardware.h>
|
|
#include <hardware/gralloc.h>
|
|
|
|
#include "gralloc_priv.h"
|
|
|
|
|
|
/* desktop Linux needs a little help with gettid() */
|
|
#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
|
|
#define __KERNEL__
|
|
# include <linux/unistd.h>
|
|
pid_t gettid() { return syscall(__NR_gettid);}
|
|
#undef __KERNEL__
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
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) {
|
|
LOGE("Could not mmap %s", strerror(errno));
|
|
return -errno;
|
|
}
|
|
hnd->base = intptr_t(mappedAddress) + hnd->offset;
|
|
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
|
|
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
|
|
}
|
|
*vaddr = (void*)hnd->base;
|
|
return 0;
|
|
}
|
|
|
|
static int gralloc_unmap(gralloc_module_t const* module,
|
|
buffer_handle_t handle)
|
|
{
|
|
private_handle_t* hnd = (private_handle_t*)handle;
|
|
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
|
|
void* base = (void*)hnd->base;
|
|
size_t size = hnd->size;
|
|
//LOGD("unmapping from %p, size=%d", base, size);
|
|
if (munmap(base, size) < 0) {
|
|
LOGE("Could not unmap %s", strerror(errno));
|
|
}
|
|
}
|
|
hnd->base = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
/*****************************************************************************/
|
|
|
|
int gralloc_register_buffer(gralloc_module_t const* module,
|
|
buffer_handle_t handle)
|
|
{
|
|
if (private_handle_t::validate(handle) < 0)
|
|
return -EINVAL;
|
|
|
|
// if this handle was created in this process, then we keep it as is.
|
|
int err = 0;
|
|
private_handle_t* hnd = (private_handle_t*)handle;
|
|
if (hnd->pid != getpid()) {
|
|
void *vaddr;
|
|
err = gralloc_map(module, handle, &vaddr);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
int gralloc_unregister_buffer(gralloc_module_t const* module,
|
|
buffer_handle_t handle)
|
|
{
|
|
if (private_handle_t::validate(handle) < 0)
|
|
return -EINVAL;
|
|
|
|
// never unmap buffers that were created in this process
|
|
private_handle_t* hnd = (private_handle_t*)handle;
|
|
if (hnd->pid != getpid()) {
|
|
if (hnd->base) {
|
|
gralloc_unmap(module, handle);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int mapBuffer(gralloc_module_t const* module,
|
|
private_handle_t* hnd)
|
|
{
|
|
void* vaddr;
|
|
return gralloc_map(module, hnd, &vaddr);
|
|
}
|
|
|
|
int terminateBuffer(gralloc_module_t const* module,
|
|
private_handle_t* hnd)
|
|
{
|
|
if (hnd->base) {
|
|
// this buffer was mapped, unmap it now
|
|
gralloc_unmap(module, hnd);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int gralloc_lock(gralloc_module_t const* module,
|
|
buffer_handle_t handle, int usage,
|
|
int l, int t, int w, int h,
|
|
void** vaddr)
|
|
{
|
|
// this is called when a buffer is being locked for software
|
|
// access. in thin implementation we have nothing to do since
|
|
// not synchronization with the h/w is needed.
|
|
// typically this is used to wait for the h/w to finish with
|
|
// this buffer if relevant. the data cache may need to be
|
|
// flushed or invalidated depending on the usage bits and the
|
|
// hardware.
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
return -EINVAL;
|
|
|
|
private_handle_t* hnd = (private_handle_t*)handle;
|
|
*vaddr = (void*)hnd->base;
|
|
return 0;
|
|
}
|
|
|
|
int gralloc_unlock(gralloc_module_t const* module,
|
|
buffer_handle_t handle)
|
|
{
|
|
// we're done with a software buffer. nothing to do in this
|
|
// implementation. typically this is used to flush the data cache.
|
|
|
|
if (private_handle_t::validate(handle) < 0)
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|