gralloc: Refactor, ion support

- Add ION support
- Refactor the design

Change-Id: I5b067b0aca1235ee8c01c256e025f416bb56f560
This commit is contained in:
Naseer Ahmed 2011-11-16 13:41:37 -08:00
parent cbb0b78679
commit 9c050e95ec
26 changed files with 1316 additions and 1358 deletions

View File

@ -1 +1,7 @@
# Empty Android.mk
# Build only new gralloc
ifeq ($(TARGET_USES_ION),true)
display-hals := libgralloc
include $(call all-named-subdir-makefiles,$(display-hals))
endif

View File

@ -1,84 +0,0 @@
/*
* 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.
*/
#ifndef GRALLOC_QSD8K_GPU_H_
#define GRALLOC_QSD8K_GPU_H_
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/log.h>
#include <cutils/ashmem.h>
#include "gralloc_priv.h"
#include "pmemalloc.h"
class gpu_context_t : public alloc_device_t {
public:
class Deps {
public:
virtual ~Deps();
// ashmem
virtual int ashmem_create_region(const char *name, size_t size) = 0;
// POSIX
virtual int close(int fd) = 0;
// Framebuffer (locally defined)
virtual int mapFrameBufferLocked(struct private_module_t* module) = 0;
virtual int terminateBuffer(gralloc_module_t const* module,
private_handle_t* hnd) = 0;
};
gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
PmemAllocator& pmemAdspAllocator, const private_module_t* module);
int gralloc_alloc_framebuffer_locked(size_t size, int usage,
buffer_handle_t* pHandle);
int gralloc_alloc_framebuffer(size_t size, int usage,
buffer_handle_t* pHandle);
int gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle, int bufferType, int format,
int width, int height);
int free_impl(private_handle_t const* hnd);
int alloc_impl(int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride, int bufferSize = 0);
static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
int usage, buffer_handle_t* pHandle, int* pStride);
static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
static int gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize);
static int gralloc_close(struct hw_device_t *dev);
int get_composition_type() const { return compositionType; }
private:
Deps& deps;
PmemAllocator& pmemAllocator;
PmemAllocator& pmemAdspAllocator;
int compositionType;
int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
int* pOffset, int* pFd);
void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType);
};
#endif // GRALLOC_QSD8K_GPU_H

View File

@ -1,231 +0,0 @@
/*
* 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 <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/android_pmem.h>
#include "allocator.h"
#include "gr.h"
#include "gpu.h"
/*****************************************************************************/
static int gralloc_alloc_buffer(alloc_device_t* dev,
size_t size, int usage, buffer_handle_t* pHandle);
/*****************************************************************************/
int fb_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
static int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
extern int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
extern int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_perform(struct gralloc_module_t const* module,
int operation, ... );
/*****************************************************************************/
/* On-device dependency implementation */
class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps,
public PmemKernelAllocator::Deps {
const private_module_t* module;
virtual size_t getPmemTotalSize(int fd, size_t* size) {
int err = 0;
#ifndef TARGET_MSM7x27
pmem_region region;
err = ioctl(fd, PMEM_GET_TOTAL_SIZE, &region);
if (err == 0) {
*size = region.len;
}
#else
#ifdef USE_ASHMEM
if(module != NULL)
*size = module->info.xres * module->info.yres * 2 * 2;
else
return -ENOMEM;
#else
*size = 23<<20; //23MB for 7x27
#endif
#endif
return err;
}
virtual int connectPmem(int fd, int master_fd) {
return ioctl(fd, PMEM_CONNECT, master_fd);
}
virtual int mapPmem(int fd, int offset, size_t size) {
struct pmem_region sub = { offset, size };
return ioctl(fd, PMEM_MAP, &sub);
}
virtual int unmapPmem(int fd, int offset, size_t size) {
struct pmem_region sub = { offset, size };
return ioctl(fd, PMEM_UNMAP, &sub);
}
virtual int alignPmem(int fd, size_t size, int align) {
struct pmem_allocation allocation;
allocation.size = size;
allocation.align = align;
return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation);
}
virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) {
struct pmem_addr pmem_addr;
pmem_addr.vaddr = base;
pmem_addr.offset = offset;
pmem_addr.length = size;
return ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr);
}
virtual int getErrno() {
return errno;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
return ::mmap(start, length, prot, flags, fd, offset);
}
virtual int munmap(void* start, size_t length) {
return ::munmap(start, length);
}
virtual int open(const char* pathname, int flags, int mode) {
return ::open(pathname, flags, mode);
}
virtual int close(int fd) {
return ::close(fd);
}
public:
void setModule(const private_module_t* m) {
module = m;
}
};
class GpuContextDepsDeviceImpl : public gpu_context_t::Deps {
public:
virtual int ashmem_create_region(const char *name, size_t size) {
return ::ashmem_create_region(name, size);
}
virtual int mapFrameBufferLocked(struct private_module_t* module) {
return ::mapFrameBufferLocked(module);
}
virtual int terminateBuffer(gralloc_module_t const* module,
private_handle_t* hnd) {
return ::terminateBuffer(module, hnd);
}
virtual int close(int fd) {
return ::close(fd);
}
};
static PmemAllocatorDepsDeviceImpl pmemAllocatorDeviceDepsImpl;
static GpuContextDepsDeviceImpl gpuContextDeviceDepsImpl;
/*****************************************************************************/
static SimpleBestFitAllocator pmemAllocMgr;
static PmemUserspaceAllocator pmemAllocator(pmemAllocatorDeviceDepsImpl, pmemAllocMgr,
"/dev/pmem");
static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl);
/*****************************************************************************/
static struct hw_module_methods_t gralloc_module_methods = {
open: gralloc_device_open
};
struct private_module_t HAL_MODULE_INFO_SYM = {
base: {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: GRALLOC_HARDWARE_MODULE_ID,
name: "Graphics Memory Allocator Module",
author: "The Android Open Source Project",
methods: &gralloc_module_methods
},
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
perform: gralloc_perform,
},
framebuffer: 0,
fbFormat: 0,
flags: 0,
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
currentBuffer: 0,
};
/*****************************************************************************/
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)) {
const private_module_t* m = reinterpret_cast<const private_module_t*>(
module);
pmemAllocatorDeviceDepsImpl.setModule(m);
gpu_context_t *dev;
dev = new gpu_context_t(gpuContextDeviceDepsImpl, pmemAllocator,
pmemAdspAllocator, m);
*device = &dev->common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}

View File

@ -1,55 +0,0 @@
# 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.
LOCAL_PATH := $(call my-dir)
# you can use EXTRA_CFLAGS to indicate additional CFLAGS to use
# in the build. The variables will be cleaned on exit
#
#
libgralloc_test_includes:= \
bionic/libstdc++/include \
external/astl/include \
external/gtest/include \
$(LOCAL_PATH)/..
libgralloc_test_static_libs := \
libgralloc_qsd8k_host \
libgtest_main_host \
libgtest_host \
libastl_host \
liblog
define host-test
$(foreach file,$(1), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_CPP_EXTENSION := .cpp) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_C_INCLUDES := $(libgralloc_test_includes)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
$(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
$(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \
$(eval LOCAL_STATIC_LIBRARIES := $(libgralloc_test_static_libs)) \
$(eval LOCAL_MODULE_TAGS := eng tests) \
$(eval include $(BUILD_HOST_EXECUTABLE)) \
) \
$(eval EXTRA_CFLAGS :=) \
$(eval EXTRA_LDLIBS :=)
endef
TEST_SRC_FILES := \
pmemalloc_test.cpp
$(call host-test, $(TEST_SRC_FILES))

View File

@ -1,601 +0,0 @@
/*
* Copyright (C) 2010 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 <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "pmemalloc.h"
class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps {
public:
virtual size_t getPmemTotalSize(int fd, size_t* size) {
return 0;
}
virtual int connectPmem(int fd, int master_fd) {
return 0;
}
virtual int mapPmem(int fd, int offset, size_t size) {
return 0;
}
virtual int unmapPmem(int fd, int offset, size_t size) {
return 0;
}
virtual int getErrno() {
return 0;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
return 0;
}
virtual int munmap(void* start, size_t length) {
return 0;
}
virtual int open(const char* pathname, int flags, int mode) {
return 0;
}
virtual int close(int fd) {
return 0;
}
};
/******************************************************************************/
class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator {
virtual ssize_t setSize(size_t size) {
return 0;
}
virtual size_t size() const {
return 0;
}
virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
return 0;
}
virtual ssize_t deallocate(size_t offset) {
return 0;
}
};
/******************************************************************************/
static const char* fakePmemDev = "/foo/bar";
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub {
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags);
EXPECT_EQ(0, mode);
return 1234;
}
virtual size_t getPmemTotalSize(int fd, size_t* size) {
EXPECT_EQ(1234, fd);
*size = 16 << 20;
return 0;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
EXPECT_EQ(1234, fd);
return (void*)0x87654321;
}
};
struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub {
virtual ssize_t setSize(size_t size) {
EXPECT_EQ(size_t(16 << 20), size);
return 0;
}
};
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) {
Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock;
Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
int result = pma.init_pmem_area_locked();
ASSERT_EQ(0, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub {
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags);
EXPECT_EQ(0, mode);
return 1234;
}
virtual size_t getPmemTotalSize(int fd, size_t* size) {
EXPECT_EQ(1234, fd);
*size = 16 << 20;
return 0;
}
virtual int getErrno() {
return ENOMEM;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
return (void*)MAP_FAILED;
}
};
struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub {
virtual ssize_t setSize(size_t size) {
EXPECT_EQ(size_t(16 << 20), size);
return 0;
}
};
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) {
Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock;
Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
int result = pma.init_pmem_area_locked();
ASSERT_EQ(-ENOMEM, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub {
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags);
EXPECT_EQ(0, mode);
return 1234;
}
virtual size_t getPmemTotalSize(int fd, size_t* size) {
EXPECT_EQ(1234, fd);
return -EACCES;
}
};
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) {
Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
int result = pma.init_pmem_area_locked();
ASSERT_EQ(-EACCES, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub {
virtual int getErrno() {
return EACCES;
}
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags);
EXPECT_EQ(0, mode);
return -1;
}
};
TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) {
Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
int result = pma.init_pmem_area_locked();
ASSERT_EQ(-EACCES, result);
}
/******************************************************************************/
typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion;
TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) {
Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
int result = pma.init_pmem_area();
ASSERT_EQ(0, result);
}
/******************************************************************************/
typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked;
TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) {
Deps_InitPmemAreaWithEaccesOnInitLocked depsMock;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
int result = pma.init_pmem_area();
ASSERT_EQ(-EACCES, result);
}
/******************************************************************************/
TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) {
DepsStub depsStub;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd
int result = pma.init_pmem_area();
ASSERT_EQ(0, result);
//XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed
}
/******************************************************************************/
TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) {
DepsStub depsStub;
AllocatorStub allocStub;
PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init
int result = pma.init_pmem_area();
ASSERT_EQ(-EACCES, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub {
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags & O_RDWR);
EXPECT_EQ(0, mode);
return 5678;
}
virtual int connectPmem(int fd, int master_fd) {
EXPECT_EQ(5678, fd);
EXPECT_EQ(1234, master_fd);
return 0;
}
virtual int mapPmem(int fd, int offset, size_t size) {
EXPECT_EQ(5678, fd);
EXPECT_EQ(0x300, offset);
EXPECT_EQ(size_t(0x100), size);
return 0;
}
};
struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub {
virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
EXPECT_EQ(size_t(0x100), size);
EXPECT_EQ(uint32_t(0x0), flags);
return 0x300;
}
};
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock;
Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = 0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(0, result);
ASSERT_EQ(0x300, offset);
ASSERT_EQ(5678, fd);
for (int i = 0x300; i < 0x400; ++i) {
ASSERT_EQ(uint8_t(0), buf[i]);
}
}
/******************************************************************************/
typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags;
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags;
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock;
Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(0, result);
ASSERT_EQ(0x300, offset);
ASSERT_EQ(5678, fd);
for (int i = 0x300; i < 0x400; ++i) {
ASSERT_EQ(0, buf[i]);
}
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
virtual int getErrno() {
return ENODEV;
}
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags & O_RDWR);
EXPECT_EQ(0, mode);
return -1;
}
};
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen;
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) {
Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock;
Allocator_AllocPmemBufferWithEnodevOnOpen allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(-ENODEV, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
virtual int getErrno() {
return ENOMEM;
}
virtual int connectPmem(int fd, int master_fd) {
EXPECT_EQ(5678, fd);
EXPECT_EQ(1234, master_fd);
return -1;
}
};
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem;
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) {
Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock;
Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(-ENOMEM, result);
}
/******************************************************************************/
struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
virtual int getErrno() {
return ENOMEM;
}
virtual int mapPmem(int fd, int offset, size_t size) {
EXPECT_EQ(5678, fd);
EXPECT_EQ(0x300, offset);
EXPECT_EQ(size_t(0x100), size);
return -1;
}
};
typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem;
TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) {
Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock;
Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock;
PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(-ENOMEM, result);
}
/******************************************************************************/
struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub {
void* mmapResult;
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) :
mmapResult(mmapResult) {}
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags & O_RDWR);
EXPECT_EQ(0, mode);
return 5678;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
EXPECT_EQ(5678, fd);
return mmapResult;
}
};
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
uint8_t buf[0x100]; // Create a buffer to get memzero'd
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf);
PmemKernelAllocator pma(depsMock, fakePmemDev);
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = 0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(0, result);
ASSERT_EQ(buf, base);
ASSERT_EQ(0, offset);
ASSERT_EQ(5678, fd);
for (int i = 0; i < 0x100; ++i) {
ASSERT_EQ(0, buf[i]);
}
}
/******************************************************************************/
typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags;
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
uint8_t buf[0x100]; // Create a buffer to get memzero'd
Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf);
PmemKernelAllocator pma(depsMock, fakePmemDev);
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(0, result);
ASSERT_EQ(buf, base);
ASSERT_EQ(0, offset);
ASSERT_EQ(5678, fd);
for (int i = 0; i < 0x100; ++i) {
ASSERT_EQ(0, buf[i]);
}
}
/******************************************************************************/
struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub {
virtual int getErrno() {
return EPERM;
}
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags & O_RDWR);
EXPECT_EQ(0, mode);
return -1;
}
};
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) {
Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock;
PmemKernelAllocator pma(depsMock, fakePmemDev);
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(-EPERM, result);
ASSERT_EQ(0, base);
ASSERT_EQ(0, offset);
ASSERT_EQ(-1, fd);
}
/******************************************************************************/
struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub {
virtual int open(const char* pathname, int flags, int mode) {
EXPECT_EQ(fakePmemDev, pathname);
EXPECT_EQ(O_RDWR, flags & O_RDWR);
EXPECT_EQ(0, mode);
return 5678;
}
virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
off_t offset) {
return (void*)MAP_FAILED;
}
virtual int getErrno() {
return ENOMEM;
}
};
TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) {
Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock;
PmemKernelAllocator pma(depsMock, fakePmemDev);
void* base = 0;
int offset = -9182, fd = -9182;
int size = 0x100;
int flags = ~0;
int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
ASSERT_EQ(-ENOMEM, result);
ASSERT_EQ(0, base);
ASSERT_EQ(0, offset);
ASSERT_EQ(-1, fd);
}
/******************************************************************************/

View File

@ -11,7 +11,9 @@
# 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.
ifneq ($(TARGET_USES_ION),true)
# Use this flag until pmem/ashmem is implemented in the new gralloc
ifeq ($(TARGET_USES_ION),true)
LOCAL_PATH := $(call my-dir)
# HAL module implemenation, not prelinked and stored in
@ -19,48 +21,50 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
hardware/qcom/display/libgralloc
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SRC_FILES := \
allocator.cpp \
framebuffer.cpp \
gpu.cpp \
gralloc.cpp \
mapper.cpp \
pmemalloc.cpp
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
LOCAL_SRC_FILES := framebuffer.cpp \
gpu.cpp \
gralloc.cpp \
mapper.cpp \
pmemalloc.cpp \
pmem_bestfit_alloc.cpp
ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT)))
LOCAL_CFLAGS += -DTARGET_MSM7x27
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS -DUSE_ION
ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true)
LOCAL_CFLAGS += -DTARGET_MSM7x27
endif
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../liboverlay
LOCAL_SHARED_LIBRARIES += liboverlay
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
LOCAL_C_INCLUDES += hardware/msm7k/liboverlay
LOCAL_SHARED_LIBRARIES += liboverlay
endif
ifeq ($(TARGET_USES_SF_BYPASS),true)
LOCAL_CFLAGS += -DSF_BYPASS
endif
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
LOCAL_CFLAGS += -DUSE_ASHMEM
LOCAL_CFLAGS += -DUSE_ASHMEM
endif
include $(BUILD_SHARED_LIBRARY)
# Build a host library for testing
ifeq ($(HOST_OS),linux)
#MemAlloc Library
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
gpu.cpp \
pmemalloc.cpp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := libgralloc_qsd8k_host
LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\"
include $(BUILD_HOST_STATIC_LIBRARY)
endif
endif
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
LOCAL_SRC_FILES := ionalloc.cpp \
ashmemalloc.cpp \
alloc_controller.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\" -DLOG_NDDEBUG=0 -DUSE_ION
LOCAL_MODULE := libmemalloc
include $(BUILD_SHARED_LIBRARY)
endif #TARGET_USES_ION

View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cutils/log.h>
#include <utils/RefBase.h>
#include "gralloc_priv.h"
#include "alloc_controller.h"
#include "memalloc.h"
#include "ionalloc.h"
using namespace gralloc;
using android::sp;
sp<IAllocController> IAllocController::sController = NULL;
sp<IAllocController> IAllocController::getInstance(void)
{
if(sController == NULL) {
#ifdef USE_ION
sController = new IonController();
#else
// XXX: Return pmem/ashmem controller when completed
#endif
}
return sController;
}
IonController::IonController()
{
mIonAlloc = new IonAlloc();
}
static bool canFallback(int compositionType, int usage, int flags)
{
// Fallback to system heap when alloc fails unless
// 1. Composition type is MDP
// 2. Earlier alloc attempt was from system heap
// 3. Contiguous heap requsted explicitly
if(compositionType == MDP_COMPOSITION)
return false;
if(flags & ION_HEAP_SYSTEM_ID)
return false;
if(usage &(GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
GRALLOC_USAGE_PRIVATE_EBI_HEAP |
GRALLOC_USAGE_PRIVATE_SMI_HEAP))
return false;
//Return true by default
return true;
}
int IonController::allocate(alloc_data& data, int usage,
int compositionType)
{
int ionFlags = 0;
int ret;
//System heap cannot be uncached
if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED &&
!(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP))
data.uncached = true;
else
data.uncached = false;
if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
ionFlags |= 1 << ION_HEAP_ADSP_ID;
if(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)
ionFlags |= 1 << ION_HEAP_SMI_ID;
if(usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP)
ionFlags |= 1 << ION_HEAP_EBI_ID;
if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
ionFlags |= 1 << ION_HEAP_SYSTEM_ID;
// if no flags are set, default to
// EBI heap, so that bypass can work
// we can fall back to system heap if
// we run out.
if(!ionFlags)
ionFlags = 1 << ION_HEAP_EBI_ID;
data.flags = ionFlags;
ret = mIonAlloc->alloc_buffer(data);
// Fallback
if(ret < 0 && canFallback(compositionType, usage, ionFlags)) {
LOGW("Falling back to system heap");
data.flags = 1 << ION_HEAP_SYSTEM_ID;
ret = mIonAlloc->alloc_buffer(data);
}
if(ret >= 0 )
data.allocType = private_handle_t::PRIV_FLAGS_USES_ION;
return ret;
}
sp<IMemAlloc> IonController::getAllocator(int flags)
{
sp<IMemAlloc> memalloc;
if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
memalloc = mIonAlloc;
} else {
LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
}
return memalloc;
}
int PmemAshmemController::allocate(alloc_data& data, int usage,
int compositionType)
{
//XXX PMEM with ashmem fallback strategy
return 0;
}
sp<IMemAlloc> PmemAshmemController::getAllocator(int flags)
{
sp<IMemAlloc> memalloc;
if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
// XXX Return right allocator based on flags
memalloc = NULL;
} else {
LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
memalloc = NULL;
}
return memalloc;
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GRALLOC_ALLOCCONTROLLER_H
#define GRALLOC_ALLOCCONTROLLER_H
#include <utils/RefBase.h>
namespace gralloc {
struct alloc_data;
class IMemAlloc;
class IonAlloc;
class IAllocController : public android::RefBase {
public:
/* Allocate using a suitable method
* Returns the type of buffer allocated
*/
virtual int allocate(alloc_data& data, int usage,
int compositionType) = 0;
virtual android::sp<IMemAlloc> getAllocator(int flags) = 0;
virtual ~IAllocController() {};
static android::sp<IAllocController> getInstance(void);
private:
static android::sp<IAllocController> sController;
};
class IonController : public IAllocController {
public:
virtual int allocate(alloc_data& data, int usage,
int compositionType);
virtual android::sp<IMemAlloc> getAllocator(int flags);
IonController();
private:
android::sp<IonAlloc> mIonAlloc;
};
class PmemAshmemController : public IAllocController {
public:
virtual int allocate(alloc_data& data, int usage,
int compositionType);
virtual android::sp<IMemAlloc> getAllocator(int flags);
// XXX: Pmem and ashmem alloc objects
};
} //end namespace gralloc
#endif // GRALLOC_ALLOCCONTROLLER_H

140
libgralloc/ashmemalloc.cpp Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <cutils/log.h>
#include <linux/ashmem.h>
#include <cutils/ashmem.h>
#include <errno.h>
#include "ashmemalloc.h"
using gralloc::AshmemAlloc;
int AshmemAlloc::alloc_buffer(alloc_data& data)
{
int err = 0;
int fd = -1;
void* base = 0;
int offset = 0;
char name[ASHMEM_NAME_LEN];
snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", data.pHandle);
int prot = PROT_READ | PROT_WRITE;
fd = ashmem_create_region(name, data.size);
if (fd < 0) {
LOGE("couldn't create ashmem (%s)", strerror(errno));
err = -errno;
} else {
if (ashmem_set_prot_region(fd, prot) < 0) {
LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
fd, prot, strerror(errno));
close(fd);
err = -errno;
} else {
base = mmap(0, data.size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0);
if (base == MAP_FAILED) {
LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
fd, data.size, prot, strerror(errno));
close(fd);
err = -errno;
} else {
memset((char*)base + offset, 0, data.size);
}
}
}
if(err == 0) {
data.fd = fd;
data.base = base;
data.offset = offset;
clean_buffer(base, data.size, offset, fd);
}
return err;
}
int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
LOGD("%s:Freeing buffer size=%d base=%p fd=%d PID=%d",
__FUNCTION__, size, base, fd, getpid());
int err = 0;
if(!base) {
LOGE("Invalid free");
return -EINVAL;
}
err = unmap_buffer(base, size, offset);
close(fd);
return err;
}
int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
{
LOGD("%s: Mapping buffer fd=%d size=%d PID=%d", __FUNCTION__,
fd, size, getpid());
int err = 0;
void *base = 0;
if (err)
return err;
base = mmap(0, size, PROT_READ| PROT_WRITE,
MAP_SHARED, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
LOGD("%s: Failed to map memory in the client: %s",
__FUNCTION__, strerror(errno));
err = -errno;
} else {
LOGD("%s: Successfully mapped %d bytes", __FUNCTION__, size);
}
return err;
}
int AshmemAlloc::unmap_buffer(void *base, size_t size, int offset)
{
LOGD("%s: Unmapping buffer at address %p", __FUNCTION__, base);
int err = munmap(base, size);
if(err) {
LOGE("%s: Failed to unmap memory at %p: %s",
__FUNCTION__, base, strerror(errno));
}
return err;
}
int AshmemAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
{
// LOGD("%s: Clean buffer fd=%d base = %p size=%d PID=%d", __FUNCTION__,
// fd, base, size, getpid());
int err = 0;
if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) {
LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd);
}
return err;
}

56
libgralloc/ashmemalloc.h Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GRALLOC_ASHMEMALLOC_H
#define GRALLOC_ASHMEMALLOC_H
#include "memalloc.h"
#include <linux/ion.h>
namespace gralloc {
class AshmemAlloc : public IMemAlloc {
public:
virtual int alloc_buffer(alloc_data& data);
virtual int free_buffer(void *base, size_t size,
int offset, int fd);
virtual int map_buffer(void **pBase, size_t size,
int offset, int fd);
virtual int unmap_buffer(void *base, size_t size,
int offset);
virtual int clean_buffer(void*base, size_t size,
int offset, int fd);
};
}
#endif /* GRALLOC_ASHMEMALLOC_H */

View File

@ -174,7 +174,6 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev,
{
if (((w|h) <= 0) || ((l|t)<0))
return -EINVAL;
fb_context_t* ctx = (fb_context_t*)dev;
private_module_t* m = reinterpret_cast<private_module_t*>(
dev->common.module);
@ -680,14 +679,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
} else {
void* fb_vaddr;
void* buffer_vaddr;
m->base.lock(&m->base, m->framebuffer,
GRALLOC_USAGE_SW_WRITE_RARELY,
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,
m->base.lock(&m->base, buffer,
GRALLOC_USAGE_SW_READ_RARELY,
0, 0, m->info.xres, m->info.yres,
&buffer_vaddr);
@ -699,8 +697,8 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
m->info.xoffset, m->info.yoffset,
m->info.width, m->info.height);
m->base.unlock(&m->base, buffer);
m->base.unlock(&m->base, m->framebuffer);
m->base.unlock(&m->base, buffer);
m->base.unlock(&m->base, m->framebuffer);
}
LOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c",
@ -745,7 +743,6 @@ int mapFrameBufferLocked(struct private_module_t* module)
if (module->framebuffer) {
return 0;
}
char const * const device_template[] = {
"/dev/graphics/fb%u",
"/dev/fb%u",
@ -787,42 +784,42 @@ int mapFrameBufferLocked(struct private_module_t* module)
*/
if(info.bits_per_pixel == 32) {
/*
* Explicitly request RGBA_8888
*/
info.bits_per_pixel = 32;
info.red.offset = 24;
info.red.length = 8;
info.green.offset = 16;
info.green.length = 8;
info.blue.offset = 8;
info.blue.length = 8;
info.transp.offset = 0;
info.transp.length = 8;
/*
* Explicitly request RGBA_8888
*/
info.bits_per_pixel = 32;
info.red.offset = 24;
info.red.length = 8;
info.green.offset = 16;
info.green.length = 8;
info.blue.offset = 8;
info.blue.length = 8;
info.transp.offset = 0;
info.transp.length = 8;
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
* not use the MDP for composition (i.e. hw composition == 0), ask for
* RGBA instead of RGBX. */
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
else
module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
* not use the MDP for composition (i.e. hw composition == 0), ask for
* RGBA instead of RGBX. */
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
else
module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
} else {
/*
* Explicitly request 5/6/5
*/
info.bits_per_pixel = 16;
info.red.offset = 11;
info.red.length = 5;
info.green.offset = 5;
info.green.length = 6;
info.blue.offset = 0;
info.blue.length = 5;
info.transp.offset = 0;
info.transp.length = 0;
module->fbFormat = HAL_PIXEL_FORMAT_RGB_565;
/*
* Explicitly request 5/6/5
*/
info.bits_per_pixel = 16;
info.red.offset = 11;
info.red.length = 5;
info.green.offset = 5;
info.green.length = 6;
info.blue.offset = 0;
info.blue.length = 5;
info.transp.offset = 0;
info.transp.length = 0;
module->fbFormat = HAL_PIXEL_FORMAT_RGB_565;
}
/*
* Request NUM_BUFFERS screens (at lest 2 for page flipping)
@ -956,7 +953,7 @@ int mapFrameBufferLocked(struct private_module_t* module)
pthread_cond_init(&(module->avail[i].cond), NULL);
module->avail[i].is_avail = true;
module->avail[i].state = AVL;
}
}
/* create display update thread */
pthread_t thread1;
@ -1117,7 +1114,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd,
blit.req.dst.width = width;
blit.req.dst.height = height;
blit.req.dst.offset = 0;
blit.req.dst.memory_id = fd;
blit.req.dst.memory_id = fd;
blit.req.dst.format = format;
blit.req.src_rect.x = blit.req.dst_rect.x = x;

265
libgralloc-qsd8k/gpu.cpp → libgralloc/gpu.cpp Executable file → Normal file
View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,27 +18,25 @@
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <cutils/properties.h>
#ifdef HOST
#include <linux/ashmem.h>
#endif
#include <sys/mman.h>
#include "gr.h"
#include "gpu.h"
#include "memalloc.h"
#include "alloc_controller.h"
static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
static const int QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
static const int QOMX_INTERLACE_FLAG = 0x49283654;
static const int QOMX_3D_VIDEO_FLAG = 0x23784238;
gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
PmemAllocator& pmemAdspAllocator, const private_module_t* module) :
deps(deps),
pmemAllocator(pmemAllocator),
pmemAdspAllocator(pmemAdspAllocator)
using namespace gralloc;
using android::sp;
gpu_context_t::gpu_context_t(const private_module_t* module,
sp<IAllocController> alloc_ctrl ) :
mAllocCtrl(alloc_ctrl)
{
// Zero out the alloc_device_t
memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
@ -72,6 +71,7 @@ gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
alloc = gralloc_alloc;
allocSize = gralloc_alloc_size;
free = gralloc_free;
}
int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
@ -84,14 +84,9 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
return -EINVAL;
}
// allocate the framebuffer
if (m->framebuffer == NULL) {
// initialize the framebuffer, the framebuffer is mapped once
// and forever.
int err = deps.mapFrameBufferLocked(m);
if (err < 0) {
return err;
}
LOGE("%s: Invalid framebuffer", __FUNCTION__);
return -EINVAL;
}
const uint32_t bufferMask = m->bufferMask;
@ -102,7 +97,8 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
// 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(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI,
m->fbFormat, m->info.xres, m->info.yres);
}
if (bufferMask >= ((1LU<<numBuffers)-1)) {
@ -111,11 +107,14 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
}
// create a "fake" handles for it
// Set the PMEM flag as well, since adreno
// treats the FB memory as pmem
intptr_t vaddr = intptr_t(m->framebuffer->base);
private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), bufferSize,
private_handle_t::PRIV_FLAGS_USES_PMEM |
private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
BUFFER_TYPE_UI, m->fbFormat, m->info.xres,
m->info.yres);
// find a free slot
for (uint32_t i=0 ; i<numBuffers ; i++) {
@ -129,7 +128,6 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
hnd->base = vaddr;
hnd->offset = vaddr - intptr_t(m->framebuffer->base);
*pHandle = hnd;
return 0;
}
@ -144,161 +142,38 @@ int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
return err;
}
int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
int* pOffset, int* pFd)
{
int err = 0;
int fd = -1;
void* base = 0;
int offset = 0;
char name[ASHMEM_NAME_LEN];
snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", postfix);
int prot = PROT_READ | PROT_WRITE;
fd = ashmem_create_region(name, size);
if (fd < 0) {
LOGE("couldn't create ashmem (%s)", strerror(errno));
err = -errno;
} else {
if (ashmem_set_prot_region(fd, prot) < 0) {
LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
fd, prot, strerror(errno));
close(fd);
err = -errno;
} else {
base = mmap(0, size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0);
if (base == MAP_FAILED) {
LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
fd, size, prot, strerror(errno));
close(fd);
err = -errno;
} else {
memset((char*)base + offset, 0, size);
}
}
}
if(err == 0) {
*pFd = fd;
*pBase = base;
*pOffset = offset;
#ifdef HOST
if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) {
LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd);
}
#endif
}
return err;
}
int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle,
int bufferType, int format, int width, int height)
int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
buffer_handle_t* pHandle, int bufferType,
int format, int width, int height)
{
int err = 0;
int flags = 0;
int fd = -1;
void* base = 0; // XXX JMG: This should change to just get an address from
// the PmemAllocator rather than getting the base & offset separately
int offset = 0;
int lockState = 0;
size = roundUpToPageSize(size);
#ifndef USE_ASHMEM
if (usage & GRALLOC_USAGE_HW_TEXTURE) {
// enable pmem in that case, so our software GL can fallback to
// the copybit module.
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
}
if (usage & GRALLOC_USAGE_HW_2D) {
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
}
#else
// Enable use of PMEM only when MDP composition is used (and other conditions apply).
// Else fall back on using ASHMEM
if ((get_composition_type() == MDP_COMPOSITION) &&
((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) {
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
}
if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) {
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
}
#endif
if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)
|| (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) {
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
}
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
if((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0 &&
(flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) == 0) {
flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
if(err >= 0)
lockState |= private_handle_t::LOCK_STATE_MAPPED;
}
else if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 ||
(flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
PmemAllocator* pma = 0;
if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0) {
if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
LOGE("attempting to allocate a gralloc buffer with both the "
"USES_PMEM and USES_PMEM_ADSP flags. Unsetting the "
"USES_PMEM_ADSP flag.");
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
}
pma = &pmemAllocator;
} else { // (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0
pma = &pmemAdspAllocator;
}
// PMEM buffers are always mmapped
lockState |= private_handle_t::LOCK_STATE_MAPPED;
err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format);
if (err < 0) {
// Pmem allocation failed. Try falling back to ashmem iff we are:
// a. not using MDP composition
// b. not allocating memory for a buffer to be used by overlays
// c. The client has not explicitly requested a PMEM buffer
if ((get_composition_type() != MDP_COMPOSITION) &&
(bufferType != BUFFER_TYPE_VIDEO) &&
((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) &&
((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0)) {
// the caller didn't request PMEM, so we can try something else
flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
err = 0;
LOGE("Pmem allocation failed. Trying ashmem");
goto try_ashmem;
} else {
LOGE("couldn't open pmem (%s)", strerror(errno));
}
}
} else {
try_ashmem:
err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
if (err >= 0) {
lockState |= private_handle_t::LOCK_STATE_MAPPED;
flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
} else {
LOGE("Ashmem fallback failed");
}
}
alloc_data data;
data.offset = 0;
data.fd = -1;
data.base = 0;
data.size = size;
if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED)
data.align = 8192;
else
data.align = getpagesize();
data.pHandle = (unsigned int) pHandle;
data.bufferType = bufferType;
err = mAllocCtrl->allocate(data, usage, compositionType);
if (err == 0) {
private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType, format, width, height);
hnd->offset = offset;
hnd->base = int(base)+offset;
hnd->lockState = lockState;
flags |= data.allocType;
private_handle_t* hnd = new private_handle_t(data.fd, size, flags,
bufferType, format, width, height);
hnd->offset = data.offset;
hnd->base = int(data.base) + data.offset;
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
*pHandle = hnd;
}
LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
return err;
}
@ -306,7 +181,9 @@ static inline size_t ALIGN(size_t x, size_t align) {
return (x + align-1) & ~(align-1);
}
void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType)
void gpu_context_t::getGrallocInformationFromFormat(int inputFormat,
int *colorFormat,
int *bufferType)
{
*bufferType = BUFFER_TYPE_VIDEO;
*colorFormat = inputFormat;
@ -331,7 +208,7 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorF
}
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride, int bufferSize) {
buffer_handle_t* pHandle, int* pStride, size_t bufferSize) {
if (!pHandle || !pStride)
return -EINVAL;
@ -341,7 +218,6 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
alignedh = ALIGN(h, 32);
int colorFormat, bufferType;
getGrallocInformationFromFormat(format, &colorFormat, &bufferType);
switch (colorFormat) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
@ -357,7 +233,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
size = alignedw * alignedh * 2;
break;
// adreno formats
// adreno formats
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21
size = ALIGN(alignedw*alignedh, 4096);
size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096);
@ -371,7 +247,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
size += ALIGN( alignedw * ALIGN(h/2, 32), 8192);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
if ((w&1) || (h&1)) {
LOGE("w or h is odd for the YUV format");
@ -404,7 +280,8 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
if (usage & GRALLOC_USAGE_HW_FB) {
err = gralloc_alloc_framebuffer(size, usage, pHandle);
} else {
err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, alignedw, alignedh);
err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
format, alignedw, alignedh);
}
if (err < 0) {
@ -421,41 +298,19 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) {
// free this buffer
const size_t bufferSize = m->finfo.line_length * m->info.yres;
int index = (hnd->base - m->framebuffer->base) / bufferSize;
m->bufferMask &= ~(1<<index);
m->bufferMask &= ~(1<<index);
} else {
PmemAllocator* pmem_allocator = 0;
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
pmem_allocator = &pmemAllocator;
} else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) {
pmem_allocator = &pmemAdspAllocator;
} else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
// free ashmem
if (hnd->fd >= 0) {
if (hnd->base) {
int err = munmap((void*)hnd->base, hnd->size);
LOGE_IF(err<0, "ASHMEM_UNMAP failed (%s), "
"fd=%d, sub.offset=%d, sub.size=%d",
strerror(errno), hnd->fd, hnd->offset, hnd->size);
}
}
}
if (pmem_allocator) {
pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base,
hnd->offset, hnd->fd);
}
deps.terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
sp<IMemAlloc> memalloc = mAllocCtrl->getAllocator(hnd->flags);
int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
hnd->offset, hnd->fd);
if(err)
return err;
}
deps.close(hnd->fd);
delete hnd; // XXX JMG: move this to the deps
// XXX any additional cleanup.
delete hnd;
return 0;
}
/******************************************************************************
* Static functions
*****************************************************************************/
int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
int usage, buffer_handle_t* pHandle, int* pStride)
{
@ -465,7 +320,6 @@ int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
}
int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize)
{
@ -476,8 +330,9 @@ int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int for
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize);
}
int gpu_context_t::gralloc_free(alloc_device_t* dev,
buffer_handle_t handle)
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
@ -501,5 +356,3 @@ int gpu_context_t::gralloc_close(struct hw_device_t *dev)
return 0;
}
gpu_context_t::Deps::~Deps() {}

81
libgralloc/gpu.h Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* 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.
*/
#ifndef GRALLOC_GPU_H_
#define GRALLOC_GPU_H_
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/log.h>
#include <cutils/ashmem.h>
#include <utils/RefBase.h>
#include "gralloc_priv.h"
namespace gralloc {
class IAllocController;
class gpu_context_t : public alloc_device_t {
public:
gpu_context_t(const private_module_t* module,
android::sp<IAllocController>alloc_ctrl);
int gralloc_alloc_framebuffer_locked(size_t size, int usage,
buffer_handle_t* pHandle);
int gralloc_alloc_framebuffer(size_t size, int usage,
buffer_handle_t* pHandle);
int gralloc_alloc_buffer(size_t size, int usage,
buffer_handle_t* pHandle,
int bufferType, int format,
int width, int height);
int free_impl(private_handle_t const* hnd);
int alloc_impl(int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride,
size_t bufferSize = 0);
static int gralloc_alloc(alloc_device_t* dev, int w, int h,
int format, int usage,
buffer_handle_t* pHandle,
int* pStride);
static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
static int gralloc_alloc_size(alloc_device_t* dev,
int w, int h, int format,
int usage, buffer_handle_t* pHandle,
int* pStride, int bufferSize);
static int gralloc_close(struct hw_device_t *dev);
int get_composition_type() const { return compositionType; }
private:
android::sp<IAllocController> mAllocCtrl;
int compositionType;
void getGrallocInformationFromFormat(int inputFormat,
int *colorFormat,
int *bufferType);
};
}
#endif // GRALLOC_GPU_H

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

113
libgralloc/gralloc.cpp Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2008, The Android Open Source Project
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* 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 <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <cutils/properties.h>
#include <utils/RefBase.h>
#include <linux/android_pmem.h>
#include "gr.h"
#include "gpu.h"
#include "memalloc.h"
#include "alloc_controller.h"
using namespace gralloc;
using android::sp;
int fb_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
static int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
extern int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
extern int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle);
extern int gralloc_perform(struct gralloc_module_t const* module,
int operation, ... );
// HAL module methods
static struct hw_module_methods_t gralloc_module_methods = {
open: gralloc_device_open
};
// HAL module initialize
struct private_module_t HAL_MODULE_INFO_SYM = {
base: {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: GRALLOC_HARDWARE_MODULE_ID,
name: "Graphics Memory Allocator Module",
author: "The Android Open Source Project",
methods: &gralloc_module_methods,
dso: 0,
reserved: {0},
},
registerBuffer: gralloc_register_buffer,
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
perform: gralloc_perform,
reserved_proc: {0},
},
framebuffer: 0,
fbFormat: 0,
flags: 0,
numBuffers: 0,
bufferMask: 0,
lock: PTHREAD_MUTEX_INITIALIZER,
currentBuffer: 0,
};
// Open Gralloc device
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)) {
const private_module_t* m = reinterpret_cast<const private_module_t*>(
module);
gpu_context_t *dev;
sp<IAllocController> alloc_ctrl = IAllocController::getInstance();
dev = new gpu_context_t(m, alloc_ctrl);
*device = &dev->common;
status = 0;
} else {
status = fb_device_open(module, name, device);
}
return status;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -45,6 +45,11 @@ enum {
/* Set this for allocating uncached memory (using O_DSYNC)
* cannot be used with the system heap */
GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00010000,
/* This flag needs to be set when using a system heap
* from ION. If not set, the system heap is assumed
* to be coming from ashmem
*/
GRALLOC_USAGE_PRIVATE_ION = 0x00020000,
};
enum {
@ -68,6 +73,8 @@ enum {
#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
/*****************************************************************************/
#ifdef __cplusplus
//XXX: Remove framebuffer specific classes and defines to a different header
template <class T>
struct Node
{
@ -226,7 +233,7 @@ struct private_module_t {
float fps;
int swapInterval;
#ifdef __cplusplus
Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display
Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display
#endif
int currentIdx;
struct avail_t avail[NUM_FRAMEBUFFERS_MAX];
@ -262,7 +269,6 @@ struct private_handle_t : public native_handle {
struct private_handle_t {
native_handle_t nativeHandle;
#endif
enum {
PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
PRIV_FLAGS_USES_PMEM = 0x00000002,
@ -324,7 +330,7 @@ struct private_handle_t {
const private_handle_t* hnd = (const private_handle_t*)h;
if (!h || h->version != sizeof(native_handle) ||
h->numInts != sNumInts || h->numFds != sNumFds ||
hnd->magic != sMagic)
hnd->magic != sMagic)
{
LOGE("invalid gralloc handle (at %p)", h);
return -EINVAL;

249
libgralloc/ionalloc.cpp Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <fcntl.h>
#include <cutils/log.h>
#include <errno.h>
#include "ionalloc.h"
using gralloc::IonAlloc;
#define ION_DEVICE "/dev/ion"
int IonAlloc::open_device()
{
if(mIonFd == FD_INIT)
mIonFd = open(ION_DEVICE, O_RDONLY);
if(mIonFd < 0 ) {
LOGE("%s: Failed to open ion device - %s",
__FUNCTION__, strerror(errno));
mIonFd = FD_INIT;
return -errno;
}
return 0;
}
void IonAlloc::close_device()
{
if(mIonFd > 0)
close(mIonFd);
mIonFd = FD_INIT;
}
int IonAlloc::alloc_buffer(alloc_data& data)
{
int err = 0;
int ionSyncFd = FD_INIT;
int iFd = FD_INIT;
struct ion_handle_data handle_data;
struct ion_fd_data fd_data;
struct ion_allocation_data ionAllocData;
void *base = 0;
ionAllocData.len = data.size;
ionAllocData.align = data.align;
ionAllocData.flags = data.flags;
err = open_device();
if (err)
return err;
if(data.uncached) {
// Use the sync FD to alloc and map
// when we need uncached memory
ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC);
if(ionSyncFd < 0) {
LOGE("%s: Failed to open ion device - %s",
__FUNCTION__, strerror(errno));
close_device();
return -errno;
}
iFd = ionSyncFd;
} else {
iFd = mIonFd;
}
err = ioctl(iFd, ION_IOC_ALLOC, &ionAllocData);
if(err) {
LOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
close_device();
if(ionSyncFd >= 0)
close(ionSyncFd);
ionSyncFd = FD_INIT;
return err;
}
fd_data.handle = ionAllocData.handle;
handle_data.handle = ionAllocData.handle;
LOGD("%s: Trying ION_IOC_MAP pid=%d handle=%p size=%d mIonFd=%d flags=%x",
__FUNCTION__, getpid(), ionAllocData.handle,
ionAllocData.len, mIonFd, ionAllocData.flags);
err = ioctl(iFd, ION_IOC_MAP, &fd_data);
if(err) {
LOGE("%s: ION_IOC_MAP failed with error - %s",
__FUNCTION__, strerror(errno));
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
close_device();
if(ionSyncFd >= 0)
close(ionSyncFd);
ionSyncFd = FD_INIT;
return err;
}
base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
MAP_SHARED, fd_data.fd, 0);
if(base == MAP_FAILED) {
LOGD("%s: Failed to map the allocated memory: %s",
__FUNCTION__, strerror(errno));
err = -errno;
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
close_device();
ionSyncFd = FD_INIT;
return err;
}
//Close the uncached FD since we no longer need it;
if(ionSyncFd >= 0)
close(ionSyncFd);
ionSyncFd = FD_INIT;
// Not doing memset for ION, uncomment if needed
// memset(base, 0, ionAllocData.len);
// Clean cache after memset
// clean_buffer(base, data.size, data.offset, fd_data.fd);
data.base = base;
data.fd = fd_data.fd;
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
LOGD("%s: ION alloc succeeded - mIonFd=%d, SharedFD=%d PID=%d size=%d"
" ionHandle=%p", __FUNCTION__, mIonFd, fd_data.fd, getpid(),
ionAllocData.len, ionAllocData.handle);
return err;
}
int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
{
LOGD("%s:Freeing buffer size=%d base=%p mIonFd=%d fd=%d PID=%d",
__FUNCTION__, size, base, mIonFd, fd, getpid());
int err = 0;
err = open_device();
if (err)
return err;
if(!base) {
LOGE("Invalid free");
return -EINVAL;
}
err = unmap_buffer(base, size, offset);
close(fd);
return err;
}
int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
{
LOGD("%s: Mapping buffer fd=%d size=%d PID=%d", __FUNCTION__,
fd, size, getpid());
int err = 0;
void *base = 0;
// It is a (quirky) requirement of ION to have opened the
// ion fd in the process that is doing the mapping
err = open_device();
if (err)
return err;
base = mmap(0, size, PROT_READ| PROT_WRITE,
MAP_SHARED, fd, 0);
*pBase = base;
if(base == MAP_FAILED) {
LOGD("%s: Failed to map memory in the client: %s",
__FUNCTION__, strerror(errno));
err = -errno;
} else {
LOGD("%s: Successfully mapped %d bytes", __FUNCTION__, size);
}
return err;
}
int IonAlloc::unmap_buffer(void *base, size_t size, int offset)
{
LOGD("%s: Unmapping buffer at address %p", __FUNCTION__, base);
int err = munmap(base, size);
if(err) {
LOGE("%s: Failed to unmap memory at %p: %s",
__FUNCTION__, base, strerror(errno));
}
return err;
}
int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd)
{
// LOGD("%s: Clean buffer fd=%d base = %p size=%d PID=%d", __FUNCTION__,
// fd, base, size, getpid());
struct ion_flush_data flush_data;
struct ion_fd_data fd_data;
struct ion_handle_data handle_data;
struct ion_handle* handle;
int err = 0;
err = open_device();
if (err)
return err;
fd_data.fd = fd;
err = ioctl(mIonFd, ION_IOC_IMPORT, &fd_data);
if(err) {
LOGE("%s: ION_IOC_IMPORT failed with error - %s",
__FUNCTION__, strerror(errno));
close_device();
return err;
}
handle_data.handle = fd_data.handle;
flush_data.handle = fd_data.handle;
flush_data.vaddr = base;
flush_data.offset = offset;
flush_data.length = size;
err = ioctl(mIonFd, ION_IOC_CLEAN_INV_CACHES, &flush_data);
if(err) {
LOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",
__FUNCTION__, strerror(errno));
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
close_device();
return err;
}
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
return err;
}

71
libgralloc/ionalloc.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GRALLOC_IONALLOC_H
#define GRALLOC_IONALLOC_H
#include "memalloc.h"
#include <linux/ion.h>
namespace gralloc {
class IonAlloc : public IMemAlloc {
public:
virtual int alloc_buffer(alloc_data& data);
virtual int free_buffer(void *base, size_t size,
int offset, int fd);
virtual int map_buffer(void **pBase, size_t size,
int offset, int fd);
virtual int unmap_buffer(void *base, size_t size,
int offset);
virtual int clean_buffer(void*base, size_t size,
int offset, int fd);
IonAlloc() { mIonFd = FD_INIT; }
~IonAlloc() { close_device(); }
private:
int mIonFd;
int open_device();
void close_device();
};
}
#endif /* GRALLOC_IONALLOC_H */

194
libgralloc-qsd8k/mapper.cpp → libgralloc/mapper.cpp Executable file → Normal file
View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,20 +39,31 @@
#include "gralloc_priv.h"
#include "gr.h"
#include "ionalloc.h"
#include "ashmemalloc.h"
// we need this for now because pmem cannot mmap at an offset
#define PMEM_HACK 1
/* 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
using gralloc::IMemAlloc;
using gralloc::IonAlloc;
using gralloc::AshmemAlloc;
using android::sp;
/*****************************************************************************/
// Return the type of allocator -
// these are used for mapping/unmapping
static sp<IMemAlloc> getAllocator(int flags)
{
sp<IMemAlloc> memalloc;
if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
memalloc = new IonAlloc();
}
if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
memalloc = new AshmemAlloc();
}
// XXX Return allocator for pmem
return memalloc;
}
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle,
void** vaddr)
@ -60,16 +72,16 @@ static int gralloc_map(gralloc_module_t const* module,
void *mappedAddress;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
size_t size = hnd->size;
#if PMEM_HACK
size += hnd->offset;
#endif
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
mappedAddress = mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED | MAP_POPULATE, hnd->fd, 0);
} else {
mappedAddress = mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
int err = memalloc->map_buffer(&mappedAddress, size,
hnd->offset, hnd->fd);
if(err) {
LOGE("Could not mmap handle %p, fd=%d (%s)",
handle, hnd->fd, strerror(errno));
hnd->base = 0;
return -errno;
}
if (mappedAddress == MAP_FAILED) {
LOGE("Could not mmap handle %p, fd=%d (%s)",
handle, hnd->fd, strerror(errno));
@ -77,7 +89,7 @@ static int gralloc_map(gralloc_module_t const* module,
return -errno;
}
hnd->base = intptr_t(mappedAddress) + hnd->offset;
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
//LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
// hnd->fd, hnd->offset, hnd->size, mappedAddress);
}
*vaddr = (void*)hnd->base;
@ -89,15 +101,14 @@ static int gralloc_unmap(gralloc_module_t const* module,
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
int err = -EINVAL;
void* base = (void*)hnd->base;
size_t size = hnd->size;
#if PMEM_HACK
base = (void*)(intptr_t(base) - hnd->offset);
size += hnd->offset;
#endif
//LOGD("unmapping from %p, size=%d", base, size);
if (munmap(base, size) < 0) {
LOGE("Could not unmap %s", strerror(errno));
sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
if(memalloc != NULL)
err = memalloc->unmap_buffer(base, size, hnd->offset);
if (err) {
LOGE("Could not unmap memory at address %p", base);
}
}
hnd->base = 0;
@ -106,7 +117,7 @@ static int gralloc_unmap(gralloc_module_t const* module,
/*****************************************************************************/
static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
/*****************************************************************************/
@ -121,9 +132,9 @@ int gralloc_register_buffer(gralloc_module_t const* module,
/* NOTE: we need to initialize the buffer as not mapped/not locked
* because it shouldn't when this function is called the first time
* in a new process. Ideally these flags shouldn't be part of the
* handle, but instead maintained in the kernel or at least
* handle, but instead maintained in the kernel or at least
* out-of-line
*/
*/
// if this handle was created in this process, then we keep it as is.
private_handle_t* hnd = (private_handle_t*)handle;
@ -148,7 +159,7 @@ int gralloc_unregister_buffer(gralloc_module_t const* module,
*/
private_handle_t* hnd = (private_handle_t*)handle;
LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
"[unregister] handle %p still locked (state=%08x)",
hnd, hnd->lockState);
@ -215,7 +226,7 @@ int gralloc_lock(gralloc_module_t const* module,
new_value = current_value;
if (current_value & private_handle_t::LOCK_STATE_WRITE) {
// already locked for write
// already locked for write
LOGE("handle %p already locked for write", handle);
return -EBUSY;
} else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
@ -225,7 +236,7 @@ int gralloc_lock(gralloc_module_t const* module,
return -EBUSY;
} else {
// this is not an error
//LOGD("%p already locked for read... count = %d",
//LOGD("%p already locked for read... count = %d",
// handle, (current_value & ~(1<<31)));
}
}
@ -237,7 +248,7 @@ int gralloc_lock(gralloc_module_t const* module,
}
new_value++;
retry = android_atomic_cmpxchg(current_value, new_value,
retry = android_atomic_cmpxchg(current_value, new_value,
(volatile int32_t*)&hnd->lockState);
} while (retry);
@ -274,7 +285,7 @@ int gralloc_lock(gralloc_module_t const* module,
return err;
}
int gralloc_unlock(gralloc_module_t const* module,
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
@ -285,18 +296,9 @@ int gralloc_unlock(gralloc_module_t const* module,
if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
int err;
if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) {
struct pmem_addr pmem_addr;
pmem_addr.vaddr = hnd->base;
pmem_addr.offset = hnd->offset;
pmem_addr.length = hnd->size;
err = ioctl( hnd->fd, PMEM_CLEAN_CACHES, &pmem_addr);
} else if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
unsigned long addr = hnd->base + hnd->offset;
err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL);
}
sp<IMemAlloc> memalloc = getAllocator(hnd->flags) ;
err = memalloc->clean_buffer((void*)hnd->base,
hnd->size, hnd->offset, hnd->fd);
LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
@ -321,8 +323,8 @@ int gralloc_unlock(gralloc_module_t const* module,
new_value--;
} while (android_atomic_cmpxchg(current_value, new_value,
(volatile int32_t*)&hnd->lockState));
} while (android_atomic_cmpxchg(current_value, new_value,
(volatile int32_t*)&hnd->lockState));
return 0;
}
@ -337,48 +339,64 @@ int gralloc_perform(struct gralloc_module_t const* module,
va_start(args, operation);
switch (operation) {
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
int fd = va_arg(args, int);
size_t size = va_arg(args, size_t);
size_t offset = va_arg(args, size_t);
void* base = va_arg(args, void*);
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
{
int fd = va_arg(args, int);
size_t size = va_arg(args, size_t);
size_t offset = va_arg(args, size_t);
void* base = va_arg(args, void*);
// validate that it's indeed a pmem buffer
pmem_region region;
if (ioctl(fd, PMEM_GET_SIZE, &region) < 0) {
native_handle_t** handle = va_arg(args, native_handle_t**);
int memoryFlags = va_arg(args, int);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts);
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
unsigned int contigFlags = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
GRALLOC_USAGE_PRIVATE_EBI_HEAP |
GRALLOC_USAGE_PRIVATE_SMI_HEAP;
if (memoryFlags & contigFlags) {
// check if the buffer is a pmem buffer
pmem_region region;
if (ioctl(fd, PMEM_GET_SIZE, &region) < 0)
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
else
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM |
private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
} else {
if (memoryFlags & GRALLOC_USAGE_PRIVATE_ION)
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
else
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ASHMEM;
}
hnd->size = size;
hnd->offset = offset;
hnd->base = intptr_t(base) + offset;
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
hnd->gpuaddr = 0;
*handle = (native_handle_t *)hnd;
res = 0;
break;
}
case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE:
{
native_handle_t* handle = va_arg(args, native_handle_t*);
int w = va_arg(args, int);
int h = va_arg(args, int);
int f = va_arg(args, int);
private_handle_t* hnd = (private_handle_t*)handle;
hnd->width = w;
hnd->height = h;
if (hnd->format != f) {
hnd->format = f;
}
break;
}
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts);
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
hnd->size = size;
hnd->offset = offset;
hnd->base = intptr_t(base) + offset;
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
hnd->gpuaddr = 0;
*handle = (native_handle_t *)hnd;
res = 0;
default:
break;
}
case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: {
native_handle_t* handle = va_arg(args, native_handle_t*);
int w = va_arg(args, int);
int h = va_arg(args, int);
int f = va_arg(args, int);
private_handle_t* hnd = (private_handle_t*)handle;
hnd->width = w;
hnd->height = h;
if (hnd->format != f) {
hnd->format = f;
}
break;
}
default:
break;
}
va_end(args);

85
libgralloc/memalloc.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GRALLOC_MEMALLOC_H
#define GRALLOC_MEMALLOC_H
#include <stdlib.h>
#include <utils/RefBase.h>
namespace gralloc {
struct alloc_data {
void *base;
int fd;
int offset;
size_t size;
size_t align;
unsigned int pHandle;
bool uncached;
unsigned int flags;
int bufferType;
int allocType;
};
class IMemAlloc : public android::RefBase {
public:
// Allocate buffer - fill in the alloc_data
// structure and pass it in. Mapped address
// and fd are returned in the alloc_data struct
virtual int alloc_buffer(alloc_data& data) = 0;
// Free buffer
virtual int free_buffer(void *base, size_t size,
int offset, int fd) = 0;
// Map buffer
virtual int map_buffer(void **pBase, size_t size,
int offset, int fd) = 0;
// Unmap buffer
virtual int unmap_buffer(void *base, size_t size,
int offset) = 0;
// Clean and invalidate
virtual int clean_buffer(void *base, size_t size,
int offset, int fd) = 0;
// Destructor
virtual ~IMemAlloc() {};
enum {
FD_INIT = -1,
};
};
} // end gralloc namespace
#endif // GRALLOC_MEMALLOC_H

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +17,7 @@
#include <cutils/log.h>
#include "allocator.h"
#include "pmem_bestfit_alloc.h"
// align all the memory blocks on a cache-line boundary
@ -50,8 +51,7 @@ ssize_t SimpleBestFitAllocator::setSize(size_t size)
mList.insertHead(node);
return size;
}
size_t SimpleBestFitAllocator::size() const
{
return mHeapSize;

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -71,7 +72,7 @@ public:
mFirst = newNode;
}
}
void insertTail(NODE* newNode) {
if (mLast == 0) {
insertHead(newNode);
@ -108,7 +109,7 @@ public:
private:
struct chunk_t {
chunk_t(size_t start, size_t size)
chunk_t(size_t start, size_t size)
: start(start), size(size), free(1), prev(0), next(0) {
}
size_t start;

View File

@ -54,7 +54,8 @@ PmemAllocator::~PmemAllocator()
}
PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev):
PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps,
Deps::Allocator& allocator, const char* pmemdev):
deps(deps),
allocator(allocator),
pmemdev(pmemdev),
@ -201,7 +202,8 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
}
int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base,
int offset, int fd)
{
BEGIN_FUNC;
int err = 0;
@ -277,7 +279,6 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
int err, offset = 0;
int openFlags = get_open_flags(usage);
const char *device;
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
device = DEVICE_PMEM_ADSP;
} else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) {
@ -335,10 +336,12 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
}
int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base,
int offset, int fd)
{
BEGIN_FUNC;
// The size should already be page aligned, now round it up to a power of 2
// The size should already be page aligned,
// now round it up to a power of 2
// like we did when allocating.
//size = clp2(size);

View File