Merge new display HAL
Change-Id: Ia937a122d5d22df243e31d7eef8762a532094684
This commit is contained in:
commit
c2b402de13
Android.mkgpu.cppgpu.hgralloc.cpp
libcopybit
libgralloc
Android.mkMODULE_LICENSE_APACHE2NOTICEalloc_controller.cppalloc_controller.hashmemalloc.cppashmemalloc.hframebuffer.cppgpu.cppgpu.hgr.hgralloc.cppgralloc_priv.hionalloc.cppionalloc.hmapper.cppmemalloc.hpmem_bestfit_alloc.cpppmem_bestfit_alloc.hpmemalloc.cpppmemalloc.h
libhwcomposer
liboverlay
tests
71
Android.mk
71
Android.mk
@ -1,70 +1,7 @@
|
||||
# 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.
|
||||
# Build only new gralloc
|
||||
|
||||
ifeq ($(TARGET_USES_ION),true)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils
|
||||
|
||||
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_MODULE_TAGS := optional
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
|
||||
|
||||
ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true)
|
||||
LOCAL_CFLAGS += -DTARGET_MSM7x27
|
||||
display-hals := libgralloc
|
||||
include $(call all-named-subdir-makefiles,$(display-hals))
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../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
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
||||
# Build a host library for testing
|
||||
ifeq ($(HOST_OS),linux)
|
||||
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
|
||||
|
429
gpu.cpp
429
gpu.cpp
@ -1,429 +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 <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef HOST
|
||||
#include <linux/ashmem.h>
|
||||
#endif
|
||||
|
||||
#include "gr.h"
|
||||
#include "gpu.h"
|
||||
|
||||
gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
|
||||
PmemAllocator& pmemAdspAllocator, const private_module_t* module) :
|
||||
deps(deps),
|
||||
pmemAllocator(pmemAllocator),
|
||||
pmemAdspAllocator(pmemAdspAllocator),
|
||||
isMDPComposition(false)
|
||||
{
|
||||
// Zero out the alloc_device_t
|
||||
memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
|
||||
|
||||
// Initialize the procs
|
||||
common.tag = HARDWARE_DEVICE_TAG;
|
||||
common.version = 0;
|
||||
common.module = const_cast<hw_module_t*>(&module->base.common);
|
||||
common.close = gralloc_close;
|
||||
alloc = gralloc_alloc;
|
||||
free = gralloc_free;
|
||||
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
if((property_get("debug.composition.type", property, NULL) > 0) &&
|
||||
(strncmp(property, "mdp", 3) == 0))
|
||||
isMDPComposition = true;
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
|
||||
// we don't support allocations with both the FB and PMEM_ADSP flags
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t bufferMask = m->bufferMask;
|
||||
const uint32_t numBuffers = m->numBuffers;
|
||||
const size_t bufferSize = m->finfo.line_length * m->info.yres;
|
||||
if (numBuffers == 1) {
|
||||
// If we have only one buffer, we never use page-flipping. Instead,
|
||||
// we return a regular buffer which will be memcpy'ed to the main
|
||||
// screen when post is called.
|
||||
int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
|
||||
return gralloc_alloc_buffer(bufferSize, newUsage, pHandle);
|
||||
}
|
||||
|
||||
if (bufferMask >= ((1LU<<numBuffers)-1)) {
|
||||
// We ran out of buffers.
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// create a "fake" handles for it
|
||||
intptr_t vaddr = intptr_t(m->framebuffer->base);
|
||||
private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), bufferSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
|
||||
|
||||
// find a free slot
|
||||
for (uint32_t i=0 ; i<numBuffers ; i++) {
|
||||
if ((bufferMask & (1LU<<i)) == 0) {
|
||||
m->bufferMask |= (1LU<<i);
|
||||
break;
|
||||
}
|
||||
vaddr += bufferSize;
|
||||
}
|
||||
|
||||
hnd->base = vaddr;
|
||||
hnd->offset = vaddr - intptr_t(m->framebuffer->base);
|
||||
*pHandle = hnd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
pthread_mutex_lock(&m->lock);
|
||||
int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
|
||||
pthread_mutex_unlock(&m->lock);
|
||||
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 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
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP){
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
|
||||
// Enable use of PMEM only when MDP composition is used (and other conditions apply).
|
||||
// Else fall back on using ASHMEM
|
||||
if (isMDPComposition &&
|
||||
((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
|
||||
}
|
||||
#endif
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
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;
|
||||
|
||||
// Allocate the buffer from pmem
|
||||
err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd);
|
||||
if (err < 0) {
|
||||
if (((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) &&
|
||||
((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0) &&
|
||||
!isMDPComposition) {
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
private_handle_t* hnd = new private_handle_t(fd, size, flags);
|
||||
hnd->offset = offset;
|
||||
hnd->base = int(base)+offset;
|
||||
hnd->lockState = lockState;
|
||||
*pHandle = hnd;
|
||||
}
|
||||
|
||||
LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline size_t ALIGN(size_t x, size_t align) {
|
||||
return (x + align-1) & ~(align-1);
|
||||
}
|
||||
|
||||
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
|
||||
buffer_handle_t* pHandle, int* pStride) {
|
||||
if (!pHandle || !pStride)
|
||||
return -EINVAL;
|
||||
|
||||
size_t size, alignedw, alignedh;
|
||||
|
||||
alignedw = ALIGN(w, 32);
|
||||
alignedh = ALIGN(h, 32);
|
||||
switch (format) {
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888:
|
||||
case HAL_PIXEL_FORMAT_RGBX_8888:
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
size = alignedw * alignedh * 4;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_888:
|
||||
size = alignedw * alignedh * 3;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_565:
|
||||
case HAL_PIXEL_FORMAT_RGBA_5551:
|
||||
case HAL_PIXEL_FORMAT_RGBA_4444:
|
||||
size = alignedw * alignedh * 2;
|
||||
break;
|
||||
|
||||
// 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);
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12
|
||||
// The chroma plane is subsampled,
|
||||
// but the pitch in bytes is unchanged
|
||||
// The GPU needs 4K alignment, but the video decoder needs 8K
|
||||
alignedw = ALIGN(w, 128);
|
||||
size = ALIGN( alignedw * alignedh, 8192);
|
||||
size += ALIGN( alignedw * ALIGN(h/2, 32), 4096);
|
||||
break;
|
||||
|
||||
case HAL_PIXEL_FORMAT_YV12:
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
if ((w&1) || (h&1)) {
|
||||
LOGE("w or h is odd for HAL_PIXEL_FORMAT_YV12");
|
||||
return -EINVAL;
|
||||
}
|
||||
alignedw = ALIGN(w, 16);
|
||||
alignedh = h;
|
||||
size = alignedw*alignedh +
|
||||
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGE("unrecognized pixel format: %d", format);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ssize_t)size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
int err;
|
||||
if (usage & GRALLOC_USAGE_HW_FB) {
|
||||
err = gralloc_alloc_framebuffer(size, usage, pHandle);
|
||||
} else {
|
||||
err = gralloc_alloc_buffer(size, usage, pHandle);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*pStride = alignedw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpu_context_t::free_impl(private_handle_t const* hnd) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||
// 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);
|
||||
} 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));
|
||||
}
|
||||
|
||||
deps.close(hnd->fd);
|
||||
delete hnd; // XXX JMG: move this to the deps
|
||||
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)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->alloc_impl(w, h, format, usage, pHandle, pStride);
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_free(alloc_device_t* dev,
|
||||
buffer_handle_t handle)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->free_impl(hnd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gpu_context_t::gralloc_close(struct hw_device_t *dev)
|
||||
{
|
||||
gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
|
||||
if (ctx) {
|
||||
/* TODO: keep a list of all buffer_handle_t created, and free them
|
||||
* all here.
|
||||
*/
|
||||
delete ctx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
gpu_context_t::Deps::~Deps() {}
|
79
gpu.h
79
gpu.h
@ -1,79 +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 free_impl(private_handle_t const* hnd);
|
||||
int alloc_impl(int w, int h, int format, int usage,
|
||||
buffer_handle_t* pHandle, int* pStride);
|
||||
|
||||
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_close(struct hw_device_t *dev);
|
||||
|
||||
private:
|
||||
|
||||
Deps& deps;
|
||||
PmemAllocator& pmemAllocator;
|
||||
PmemAllocator& pmemAdspAllocator;
|
||||
bool isMDPComposition;
|
||||
int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
|
||||
int* pOffset, int* pFd);
|
||||
};
|
||||
|
||||
#endif // GRALLOC_QSD8K_GPU_H
|
236
gralloc.cpp
236
gralloc.cpp
@ -1,236 +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 <cutils/properties.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, ®ion);
|
||||
if (err == 0) {
|
||||
*size = region.len;
|
||||
}
|
||||
#else
|
||||
#ifdef USE_ASHMEM
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
bool isMDPComposition = false;
|
||||
if((property_get("debug.composition.type", property, NULL) > 0) &&
|
||||
(strncmp(property, "mdp", 3) == 0))
|
||||
isMDPComposition = true;
|
||||
|
||||
if (isMDPComposition) {
|
||||
*size = 23<<20; //23MB for 7x27
|
||||
} else {
|
||||
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 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,
|
||||
"/dev/pmem_adsp");
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
73
libcopybit/Android.mk
Normal file
73
libcopybit/Android.mk
Normal file
@ -0,0 +1,73 @@
|
||||
# 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)
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
|
||||
|
||||
ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libdl
|
||||
LOCAL_SRC_FILES := copybit_c2d.cpp
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
ifneq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630"
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
ifeq "$(findstring msm7627,$(TARGET_PRODUCT))" "msm7627"
|
||||
LOCAL_CFLAGS += -DTARGET_7x27
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SRC_FILES := copybit.cpp
|
||||
LOCAL_MODULE := copybit.msm7k
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),qsd8k)
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SRC_FILES := copybit.cpp
|
||||
LOCAL_MODULE := copybit.qsd8k
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
endif
|
190
libcopybit/NOTICE
Normal file
190
libcopybit/NOTICE
Normal file
@ -0,0 +1,190 @@
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
618
libcopybit/c2d2.h
Normal file
618
libcopybit/c2d2.h
Normal file
@ -0,0 +1,618 @@
|
||||
/* Copyright (c) 2010, 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 __c2d2_h_
|
||||
#define __c2d2_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <EGL/egl.h> /* for EGL surfaces */
|
||||
|
||||
#ifndef C2D_API
|
||||
#define C2D_API /* define API export as needed */
|
||||
#endif
|
||||
#ifndef int32
|
||||
typedef int int32;
|
||||
#endif
|
||||
#ifndef uint32
|
||||
typedef unsigned int uint32;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/*********************** Blit definitions *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Status codes, returned by any blit function */
|
||||
typedef enum {
|
||||
C2D_STATUS_OK = 0,
|
||||
C2D_STATUS_NOT_SUPPORTED = 1,
|
||||
C2D_STATUS_OUT_OF_MEMORY = 2,
|
||||
C2D_STATUS_INVALID_PARAM = 3,
|
||||
C2D_STATUS_SURFACE_IN_USE = 4,
|
||||
} C2D_STATUS;
|
||||
|
||||
|
||||
/* Definitions of color format modes, used together with color formats */
|
||||
typedef enum {
|
||||
C2D_FORMAT_PACK_INTO_32BIT = (1 << 8), /* pack into dword if set */
|
||||
C2D_FORMAT_SWAP_ENDIANNESS = (1 << 9), /* swaps the order */
|
||||
C2D_FORMAT_LINEAR_SPACE = (1 << 10), /* linear color space */
|
||||
C2D_FORMAT_PREMULTIPLIED = (1 << 11), /* alpha premultiplied */
|
||||
C2D_FORMAT_INVERT_ALPHA = (1 << 12), /* inverts alpha */
|
||||
C2D_FORMAT_DISABLE_ALPHA = (1 << 13), /* disables alpha */
|
||||
C2D_FORMAT_INTERLACED = (1 << 14), /* YUV line-interlaced */
|
||||
C2D_FORMAT_TRANSPARENT = (1 << 15), /* YUV 1-bit alpha in Y */
|
||||
C2D_FORMAT_MACROTILED = (1 << 16), /* tiled in macro level */
|
||||
C2D_FORMAT_TILED_4x4 = (1 << 17), /* 4x4 tiled format */
|
||||
C2D_FORMAT_SWAP_RB = (1 << 18), /* Swap R & B color components */
|
||||
} C2D_FORMAT_MODE;
|
||||
|
||||
/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
|
||||
* The bits of each color channel are packed into a machine word
|
||||
* representing a single pixel from left to right (MSB to LSB) in the
|
||||
* order indicated by format name. For the sub-byte formats the pixels
|
||||
* are packed into bytes from left to right (MSbit to LSBit).
|
||||
* If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal
|
||||
* machine word used for pixel storage is 32-bit and the whole word
|
||||
* is reversed if endianness is swapped.
|
||||
* If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a
|
||||
* minimal machine word representing a pixel
|
||||
* is reversed for both sub-byte and multi-byte formats.
|
||||
* If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of
|
||||
* the formats below is considered linear, if applicable.
|
||||
* If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels
|
||||
* are premultiplied with the alpha, if applicable.
|
||||
* If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation
|
||||
* is inverted: 0 - opaque, 1 - transparent, if applicable.
|
||||
* If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves
|
||||
* as a placeholder and is ignored during blit, if applicable.
|
||||
* If the COMP_FORMAT_MACROTILED bit is set, the surface is in the
|
||||
* tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats */
|
||||
typedef enum {
|
||||
C2D_COLOR_FORMAT_1 = 0, /* 1-bit alpha/color expansion */
|
||||
|
||||
C2D_COLOR_FORMAT_2_PALETTE = 1, /* 2-bit indices for palette */
|
||||
C2D_COLOR_FORMAT_4_PALETTE = 2, /* 4-bit indices for palette */
|
||||
C2D_COLOR_FORMAT_8_PALETTE = 3, /* 8-bit indices for palette */
|
||||
|
||||
C2D_COLOR_FORMAT_2_L = 4, /* 2-bit grayscale */
|
||||
C2D_COLOR_FORMAT_4_L = 5, /* 4-bit grayscale */
|
||||
C2D_COLOR_FORMAT_8_L = 6, /* 8-bit grayscale */
|
||||
|
||||
C2D_COLOR_FORMAT_2_A = 7, /* 2-bit alpha only */
|
||||
C2D_COLOR_FORMAT_4_A = 8, /* 4-bit alpha only */
|
||||
C2D_COLOR_FORMAT_8_A = 9, /* 8-bit alpha only */
|
||||
|
||||
C2D_COLOR_FORMAT_444_RGB = 10, /* 12-bit colors */
|
||||
C2D_COLOR_FORMAT_565_RGB = 11, /* 16-bit colors */
|
||||
C2D_COLOR_FORMAT_888_RGB = 12, /* 24-bit colors */
|
||||
|
||||
C2D_COLOR_FORMAT_1555_ARGB = 13, /* 16-bit colors (1-bit alpha) */
|
||||
C2D_COLOR_FORMAT_4444_ARGB = 14, /* 16-bit colors (4-bit alpha) */
|
||||
C2D_COLOR_FORMAT_8565_ARGB = 15, /* 24-bit colors (8-bit alpha) */
|
||||
C2D_COLOR_FORMAT_8888_ARGB = 16, /* 32-bit colors (8-bit alpha) */
|
||||
|
||||
C2D_COLOR_FORMAT_5551_RGBA = 17, /* 16-bit colors (1-bit alpha) */
|
||||
C2D_COLOR_FORMAT_4444_RGBA = 18, /* 16-bit colors (4-bit alpha) */
|
||||
C2D_COLOR_FORMAT_5658_RGBA = 19, /* 24-bit colors (8-bit alpha) */
|
||||
C2D_COLOR_FORMAT_8888_RGBA = 20, /* 32-bit colors (8-bit alpha) */
|
||||
|
||||
/* derived RGB color formats (base format + mode bits) */
|
||||
|
||||
} C2D_RGB_FORMAT;
|
||||
|
||||
/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF.
|
||||
* Each of Y,U,V channels usually takes 1 byte and therefore is
|
||||
* individually addressable. The definitions below show how Y,U,V
|
||||
* channels are packed into macropixels for each particular format.
|
||||
* The order is from left (smaller byte addresses) to right (larger
|
||||
* byte addresses). The first three digits (4xx) denote the chroma
|
||||
* subsampling in standard YUV notation. The digits in the macropixel
|
||||
* denote that the whole block (from the previous digit or from the
|
||||
* beginning) has to be repeated the number of times. Underscores
|
||||
* between Y,U,V channels are used to describe separate planes for
|
||||
* planar YUV formats. Formats are mapped to numbers so that future
|
||||
* versions with various YUV permutations are easy to add.
|
||||
* If the C2D_FORMAT_INTERLACED bit is set, the line order is
|
||||
* interlaced: 0,2,4,...1,3,5... if applicable.
|
||||
* If the C2D_FORMAT_TRANSPARENT bit is set, the least significant
|
||||
* bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */
|
||||
typedef enum {
|
||||
C2D_COLOR_FORMAT_411_YYUYYV = 110, /* packed, 12-bit */
|
||||
C2D_COLOR_FORMAT_411_YUYYVY = 111, /* packed, 12-bit */
|
||||
C2D_COLOR_FORMAT_411_UYYVYY = 112, /* packed, 12-bit, "Y411" */
|
||||
C2D_COLOR_FORMAT_411_YUYV2Y4 = 116, /* packed, 12-bit */
|
||||
C2D_COLOR_FORMAT_411_UYVY2Y4 = 117, /* packed, 12-bit, "Y41P" */
|
||||
|
||||
C2D_COLOR_FORMAT_422_YUYV = 120, /* packed, 16-bit, "YUY2" */
|
||||
C2D_COLOR_FORMAT_422_UYVY = 121, /* packed, 16-bit, "UYVY" */
|
||||
C2D_COLOR_FORMAT_422_YVYU = 122, /* packed, 16-bit, "YVYU" */
|
||||
C2D_COLOR_FORMAT_422_VYUY = 123, /* packed, 16-bit */
|
||||
|
||||
C2D_COLOR_FORMAT_444_YUV = 130, /* packed, 24-bit */
|
||||
C2D_COLOR_FORMAT_444_UYV = 131, /* packed, 24-bit, "IYU2" */
|
||||
C2D_COLOR_FORMAT_444_AYUV = 136, /* packed, 24-bit, "AYUV" */
|
||||
|
||||
C2D_COLOR_FORMAT_410_Y_UV = 150, /* planar, Y + interleaved UV */
|
||||
C2D_COLOR_FORMAT_411_Y_UV = 151, /* planar, Y + interleaved UV */
|
||||
C2D_COLOR_FORMAT_420_Y_UV = 152, /* planar, Y + interleaved UV */
|
||||
C2D_COLOR_FORMAT_422_Y_UV = 153, /* planar, Y + interleaved UV */
|
||||
C2D_COLOR_FORMAT_444_Y_UV = 154, /* planar, Y + interleaved UV */
|
||||
|
||||
C2D_COLOR_FORMAT_410_Y_VU = 160, /* planar, Y + interleaved VU */
|
||||
C2D_COLOR_FORMAT_411_Y_VU = 161, /* planar, Y + interleaved VU */
|
||||
C2D_COLOR_FORMAT_420_Y_VU = 162, /* planar, Y + interleaved VU */
|
||||
C2D_COLOR_FORMAT_422_Y_VU = 163, /* planar, Y + interleaved VU */
|
||||
C2D_COLOR_FORMAT_444_Y_VU = 164, /* planar, Y + interleaved VU */
|
||||
|
||||
C2D_COLOR_FORMAT_410_Y_U_V = 170, /* planar, Y + U + V separate */
|
||||
C2D_COLOR_FORMAT_411_Y_U_V = 171, /* planar, Y + U + V separate */
|
||||
C2D_COLOR_FORMAT_420_Y_V_U = 172, /* planar, Y + V + U separate */
|
||||
C2D_COLOR_FORMAT_420_Y_U_V = 173, /* planar, Y + U + V separate */
|
||||
C2D_COLOR_FORMAT_422_Y_U_V = 174, /* planar, Y + U + V separate */
|
||||
C2D_COLOR_FORMAT_444_Y_U_V = 175, /* planar, Y + U + V separate */
|
||||
|
||||
C2D_COLOR_FORMAT_800_Y = 190, /* planar, Y only, grayscale */
|
||||
|
||||
/* derived YUV color formats (base format + mode bits), FOURCC */
|
||||
|
||||
C2D_COLOR_FORMAT_411_Y411 = 112,
|
||||
C2D_COLOR_FORMAT_411_Y41P = 117,
|
||||
C2D_COLOR_FORMAT_411_IY41 = 117 | (1 << 14),
|
||||
C2D_COLOR_FORMAT_411_Y41T = 117 | (1 << 15),
|
||||
|
||||
C2D_COLOR_FORMAT_422_YUY2 = 120,
|
||||
C2D_COLOR_FORMAT_422_IUYV = 121 | (1 << 14),
|
||||
C2D_COLOR_FORMAT_422_Y42T = 121 | (1 << 15),
|
||||
C2D_COLOR_FORMAT_444_IYU2 = 131,
|
||||
|
||||
C2D_COLOR_FORMAT_420_NV12 = 152,
|
||||
C2D_COLOR_FORMAT_420_NV21 = 162,
|
||||
|
||||
C2D_COLOR_FORMAT_410_YUV9 = 170,
|
||||
C2D_COLOR_FORMAT_410_YVU9 = 170,
|
||||
C2D_COLOR_FORMAT_411_Y41B = 171,
|
||||
C2D_COLOR_FORMAT_420_YV12 = 172,
|
||||
C2D_COLOR_FORMAT_420_IYUV = 173,
|
||||
C2D_COLOR_FORMAT_420_I420 = 173,
|
||||
C2D_COLOR_FORMAT_422_YV16 = 174,
|
||||
C2D_COLOR_FORMAT_422_Y42B = 174,
|
||||
|
||||
C2D_COLOR_FORMAT_800_Y800 = 190,
|
||||
|
||||
} C2D_YUV_FORMAT;
|
||||
|
||||
|
||||
/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
|
||||
typedef enum {
|
||||
C2D_SOURCE_RECT_BIT = (1 << 0), /* enables source_rect field */
|
||||
C2D_MIRROR_H_BIT = (1 << 1), /* enables horizontal flipping */
|
||||
C2D_MIRROR_V_BIT = (1 << 2), /* enables vertical flipping */
|
||||
C2D_SOURCE_TILE_BIT = (1 << 3), /* enables source surface tiling */
|
||||
C2D_TARGET_RECT_BIT = (1 << 4), /* enables target_rect field */
|
||||
C2D_ROTATE_BIT = (1 << 5), /* enables all rotation fields */
|
||||
C2D_SCISSOR_RECT_BIT = (1 << 6), /* enables scissor_rect field */
|
||||
C2D_MASK_SURFACE_BIT = (1 << 7), /* enables mask_surface_id field */
|
||||
C2D_MASK_ALIGN_BIT = (1 << 8), /* aligns mask to source_rect */
|
||||
C2D_MASK_SCALE_BIT = (1 << 9), /* enables mask surface scaling */
|
||||
C2D_MASK_TILE_BIT = (1 << 10), /* enables mask surface tiling */
|
||||
C2D_GLOBAL_ALPHA_BIT = (1 << 11), /* enables global_alpha field */
|
||||
C2D_COLOR_KEY_BIT = (1 << 12), /* enables color_key field */
|
||||
C2D_NO_PIXEL_ALPHA_BIT = (1 << 13), /* disables source alpha channel */
|
||||
C2D_NO_BILINEAR_BIT = (1 << 14), /* disables bilinear on scaling */
|
||||
C2D_NO_ANTIALIASING_BIT = (1 << 15), /* disables antialiasing on edges */
|
||||
C2D_DRAW_LINE_BIT = (1 << 16), /* enables line drawing with source rectangle */
|
||||
C2D_DRAW_LINE_NOLAST = (1 << 17), /* disable last pixel draw for line */
|
||||
} C2D_SOURCE_CONFIG;
|
||||
|
||||
/* Target configuration bits, defines rotation + mirroring.
|
||||
* Mirror is applied prior to rotation if enabled. */
|
||||
typedef enum {
|
||||
C2D_TARGET_MIRROR_H = (1 << 0), /* horizontal flip */
|
||||
C2D_TARGET_MIRROR_V = (1 << 1), /* vertical flip */
|
||||
C2D_TARGET_ROTATE_0 = (0 << 2), /* no rotation */
|
||||
C2D_TARGET_ROTATE_90 = (1 << 2), /* 90 degree rotation */
|
||||
C2D_TARGET_ROTATE_180 = (2 << 2), /* 180 degree rotation */
|
||||
C2D_TARGET_ROTATE_270 = (3 << 2), /* 270 degree rotation, 90 + 180 */
|
||||
C2D_TARGET_MASK_ALIGN = (1 << 4), /* aligns mask to target scissor */
|
||||
C2D_TARGET_MASK_SCALE = (1 << 5), /* enables mask scaling */
|
||||
C2D_TARGET_MASK_TILE = (1 << 6), /* enables mask tiling */
|
||||
C2D_TARGET_COLOR_KEY = (1 << 7), /* enables target_color_key */
|
||||
C2D_TARGET_NO_PIXEL_ALPHA = (1 << 8), /* disables target alpha channel */
|
||||
} C2D_TARGET_CONFIG;
|
||||
|
||||
#define C2D_TARGET_ROTATION_MASK (C2D_TARGET_ROTATE_90*3)
|
||||
|
||||
/* Additional blend modes, can be used with both source and target configs.
|
||||
If none of the below is set, the default "SRC over DST" is applied. */
|
||||
typedef enum {
|
||||
C2D_ALPHA_BLEND_SRC_OVER = (0 << 20), /* Default, Porter-Duff "SRC over DST" */
|
||||
C2D_ALPHA_BLEND_SRC = (1 << 20), /* Porter-Duff "SRC" */
|
||||
C2D_ALPHA_BLEND_SRC_IN = (2 << 20), /* Porter-Duff "SRC in DST" */
|
||||
C2D_ALPHA_BLEND_DST_IN = (3 << 20), /* Porter-Duff "DST in SRC" */
|
||||
C2D_ALPHA_BLEND_SRC_OUT = (4 << 20), /* Porter-Duff "SRC out DST" */
|
||||
C2D_ALPHA_BLEND_DST_OUT = (5 << 20), /* Porter-Duff "DST out SRC" */
|
||||
C2D_ALPHA_BLEND_DST_OVER = (6 << 20), /* Porter-Duff "DST over SRC" */
|
||||
C2D_ALPHA_BLEND_SRC_ATOP = (7 << 20), /* Porter-Duff "SRC ATOP" */
|
||||
C2D_ALPHA_BLEND_DST_ATOP = (8 << 20), /* Porter-Duff "DST ATOP" */
|
||||
C2D_ALPHA_BLEND_XOR = (9 << 20), /* Xor */
|
||||
C2D_ALPHA_BLEND_MULTIPLY = (10 << 20), /* OpenVG "MULTIPLY" */
|
||||
C2D_ALPHA_BLEND_SCREEN = (11 << 20), /* OpenVG "SCREEN" */
|
||||
C2D_ALPHA_BLEND_DARKEN = (12 << 20), /* OpenVG "DARKEN" */
|
||||
C2D_ALPHA_BLEND_LIGHTEN = (13 << 20), /* OpenVG "LIGHTEN" */
|
||||
C2D_ALPHA_BLEND_ADDITIVE = (14 << 20), /* OpenVG "ADDITIVE" */
|
||||
C2D_ALPHA_BLEND_DIRECT = (15 << 20), /* Direct alpha blitting */
|
||||
C2D_ALPHA_BLEND_INVERTC = (16 << 20), /* Invert color */
|
||||
C2D_ALPHA_BLEND_NONE = (1 << 25), /* disables alpha blending */
|
||||
} C2D_ALPHA_BLEND_MODE;
|
||||
|
||||
|
||||
/* Surface caps enumeration */
|
||||
typedef enum {
|
||||
C2D_SOURCE = (1 << 0), /* allows to use as a source */
|
||||
C2D_TARGET = (1 << 1), /* allows to use as a target */
|
||||
C2D_MASK = (1 << 2), /* allows to use as a mask */
|
||||
C2D_PALETTE = (1 << 3), /* allows to use as a palette */
|
||||
} C2D_SURFACE_BITS;
|
||||
|
||||
/* Surface type enumeration */
|
||||
typedef enum {
|
||||
C2D_SURFACE_EGL = 0, /* Arbitrary EGL surface */
|
||||
C2D_SURFACE_RGB_HOST = 1, /* Host memory RGB surface */
|
||||
C2D_SURFACE_RGB_EXT = 2, /* External memory RGB surface */
|
||||
C2D_SURFACE_YUV_HOST = 3, /* Host memory YUV surface */
|
||||
C2D_SURFACE_YUV_EXT = 4, /* External memory YUV surface */
|
||||
C2D_SURFACE_WITH_PHYS = (1<<3), /* physical address allready mapped */
|
||||
/* this bit is valid with HOST types */
|
||||
} C2D_SURFACE_TYPE;
|
||||
|
||||
/* Structure for registering an EGL surface as a blit surface */
|
||||
typedef struct {
|
||||
EGLDisplay display; /* EGL display */
|
||||
EGLContext context; /* EGL context, reserved - pass EGL_NO_CONTEXT */
|
||||
EGLSurface surface; /* EGL surface */
|
||||
} C2D_EGL_SURFACE_DEF;
|
||||
|
||||
/* Structure for registering a RGB buffer as a blit surface */
|
||||
typedef struct {
|
||||
uint32 format; /* RGB color format plus additional mode bits */
|
||||
uint32 width; /* defines width in pixels */
|
||||
uint32 height; /* defines height in pixels */
|
||||
void *buffer; /* pointer to the RGB buffer */
|
||||
void *phys; /* physical address */
|
||||
int32 stride; /* defines stride in bytes, negative stride is allowed */
|
||||
} C2D_RGB_SURFACE_DEF;
|
||||
|
||||
/* Structure for registering a YUV plane(s) as a blit surface */
|
||||
typedef struct {
|
||||
uint32 format; /* YUV color format plus additional mode bits */
|
||||
uint32 width; /* defines width in pixels */
|
||||
uint32 height; /* defines height in pixels */
|
||||
void *plane0; /* holds the whole buffer if YUV format is not planar */
|
||||
void *phys0; /* physical address */
|
||||
int32 stride0; /* stride in bytes if YUV format is not planar */
|
||||
void *plane1; /* holds UV or VU plane for planar interleaved */
|
||||
void *phys1; /* physical address */
|
||||
int32 stride1; /* stride for UV or VU plane for planar interleaved */
|
||||
void *plane2; /* holds the 3. plane, ignored if YUV format is not planar */
|
||||
void *phys2; /* physical address */
|
||||
int32 stride2; /* stride for the 3. plane, ignored if YUV format is not planar */
|
||||
} C2D_YUV_SURFACE_DEF;
|
||||
|
||||
|
||||
/* Rectangle definition */
|
||||
typedef struct {
|
||||
int32 x; /* upper-left x */
|
||||
int32 y; /* upper-left y */
|
||||
int32 width; /* width */
|
||||
int32 height; /* height */
|
||||
} C2D_RECT;
|
||||
|
||||
/* C2D_OBJECT encapsulates the blit parameters for a source surface.
|
||||
* The fg_color defines color in target format for bits equal to 1
|
||||
* in the source C2D_COLOR_FORMAT_1 format. It also defines rendering
|
||||
* color for all alpha-only source formats. If the surface_id is 0
|
||||
* the fg_color defines a constant fill color used instead of the surface.
|
||||
* The bg_color defines color in target format for bits equal to 0
|
||||
* in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored.
|
||||
* The palette_id is used for all palette source formats, otherwise ignored.
|
||||
|
||||
* The source_rect first defines the content of the source surface,
|
||||
* it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set,
|
||||
* then scaled with bilinear interpolation to exactly fit target_rect
|
||||
* or repeated across target_rect if C2D_SOURCE_TILE_BIT is set,
|
||||
* target_rect is then rotated clockwise by an arbitrary angle in degrees
|
||||
* around the rot_orig_x/y, defined relative to target_rect's top left point,
|
||||
* and then clipped to scissor_rect defined in target coordinate system.
|
||||
|
||||
* Finally alpha blending is applied before pixels get written into the target.
|
||||
* Surface's pixel alpha is combined with mask alpha and with global alpha.
|
||||
* Mask surface follows all transformations applied to the source surface.
|
||||
* Source color key defines transparent color, applied together with alpha. */
|
||||
typedef struct C2D_OBJECT_STR {
|
||||
uint32 surface_id; /* source surface */
|
||||
|
||||
uint32 fg_color; /* foreground color */
|
||||
uint32 bg_color; /* background color */
|
||||
uint32 palette_id; /* one-dimensional horizontal palette surface */
|
||||
|
||||
uint32 config_mask; /* defines which fields below are enabled */
|
||||
|
||||
C2D_RECT source_rect; /* region of the source surface, 16.16 fp */
|
||||
C2D_RECT target_rect; /* position and scaling in target, 16.16 fp */
|
||||
|
||||
int32 rot_orig_x; /* rotation origin relative to target_rect's... */
|
||||
int32 rot_orig_y; /* ...top left point, both are 16.16 fp */
|
||||
int32 rotation; /* clock-wise rotation in degrees, 16.16 fp */
|
||||
|
||||
C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */
|
||||
|
||||
uint32 mask_surface_id; /* source alpha-mask surface */
|
||||
uint32 global_alpha; /* 0 = fully transparent, 255 = fully opaque */
|
||||
uint32 color_key; /* transparent color for the source surface */
|
||||
|
||||
struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
|
||||
} C2D_OBJECT;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**************************** C2D API 2.0 ********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Functions to create/destroy surfaces */
|
||||
|
||||
/* Creates a generic blit surface according to its type.
|
||||
* Pass a combination of desired surface bits according to planned usage.
|
||||
* Accepted values for surface_bits may include bits from C2D_SURFACE_BITS,
|
||||
* and also from C2D_DISPLAY for compatibility with HW display controller.
|
||||
* For host memory types the memory is preallocated outside the API
|
||||
* and should remain valid until surface is destroyed.
|
||||
* For external memory types the memory is allocated within API.
|
||||
* On success, the non-zero surface identifier is returned.
|
||||
* All numbers greater that 0 are valid surface identifiers, 0 is invalid.
|
||||
|
||||
* arbitrary EGL surface (including proprietary Command List Surface):
|
||||
* surface_type = C2D_SURFACE_EGL
|
||||
* surface_definition = C2D_EGL_SURFACE_DEF
|
||||
* all fields in definition structure should be set
|
||||
* context field is reserved and can be ignored
|
||||
|
||||
* Host memory RGB surface:
|
||||
* surface_type = C2D_SURFACE_RGB_HOST
|
||||
* surface_definition = C2D_RGB_SURFACE_DEF
|
||||
* all fields in definition structure should be set
|
||||
|
||||
* External memory RGB surface:
|
||||
* surface_type = C2D_SURFACE_RGB_EXT
|
||||
* surface_definition = C2D_RGB_SURFACE_DEF
|
||||
* buffer field in definition structure is ignored
|
||||
|
||||
* Host memory YUV surface:
|
||||
* surface_type = C2D_SURFACE_YUV_HOST
|
||||
* surface_definition = C2D_YUV_SURFACE_DEF
|
||||
* one or all plane and stride fields in definition structure
|
||||
* should be set depending on whether the format is planar or not
|
||||
|
||||
* External memory YUV surface:
|
||||
* surface_type = C2D_SURFACE_YUV_EXT
|
||||
* surface_definition = C2D_YUV_SURFACE_DEF
|
||||
* all plane and stride fields in definition structure are ignored */
|
||||
C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id,
|
||||
uint32 surface_bits,
|
||||
C2D_SURFACE_TYPE surface_type,
|
||||
void *surface_definition );
|
||||
|
||||
/* Requests properties of the specified surface. */
|
||||
C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id,
|
||||
uint32 *surface_bits,
|
||||
C2D_SURFACE_TYPE *surface_type,
|
||||
uint32 *width, uint32 *height,
|
||||
uint32 *format );
|
||||
|
||||
/* Destroys a generic blit surface.
|
||||
* For external memory surfaces also deallocates the memory.
|
||||
* It is safe to free any external resources associated with a given
|
||||
* surface on c2dCreateSurface call after this function returns. */
|
||||
C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Functions to modify/exchange surface data */
|
||||
|
||||
/* The format of fill_color is the same as color format being used
|
||||
* for specified surface. If fill_rect is NULL the whole surface is filled.
|
||||
* Alpha-blending is not performed while filling.
|
||||
* The operation is complete when function returns. */
|
||||
C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id,
|
||||
uint32 fill_color,
|
||||
C2D_RECT *fill_rect );
|
||||
|
||||
/* Writes data located in host memory into the specified surface.
|
||||
* The chunk of host memory is identified with surface_type and
|
||||
* surface_definition, no surface registration needed in this case.
|
||||
* Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
|
||||
* If only part of the host memory buffer should be loaded, it should
|
||||
* be configured in surface_definition using width, height and stride.
|
||||
* The x and y are defined in target surface coordinate space.
|
||||
* Color conversion has to be done, if color formats differ.
|
||||
* Alpha-blending is not performed while writing.
|
||||
* The operation is complete when function returns. */
|
||||
C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id,
|
||||
C2D_SURFACE_TYPE surface_type,
|
||||
void *surface_definition,
|
||||
int32 x, int32 y );
|
||||
|
||||
/* Reads data from the specified surface into the host memory.
|
||||
* The chunk of host memory is identified with surface_type and
|
||||
* surface_definition, no surface registration needed in this case.
|
||||
* Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
|
||||
* If only part of the surface should be read, it should
|
||||
* be configured in surface_definition using width, height and stride.
|
||||
* The x and y are defined in source surface coordinate space.
|
||||
* Color conversion has to be done, if color formats differ.
|
||||
* Alpha-blending is not performed while reading.
|
||||
* The operation is complete when function returns. */
|
||||
C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id,
|
||||
C2D_SURFACE_TYPE surface_type,
|
||||
void *surface_definition,
|
||||
int32 x, int32 y );
|
||||
|
||||
/* Notifies c2d imlementation that surface has been updated from outside the API,
|
||||
* if updated_rect is NULL then the whole surface has been updated. */
|
||||
C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id,
|
||||
C2D_RECT *updated_rect );
|
||||
|
||||
/* Updates surface information.
|
||||
* Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS".
|
||||
* Count for surface planes have to be same than for already allocated surface */
|
||||
C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id,
|
||||
uint32 surface_bits,
|
||||
C2D_SURFACE_TYPE surface_type,
|
||||
void *surface_definition );
|
||||
|
||||
/******************************************************************************
|
||||
* Functions to do actual blit */
|
||||
|
||||
/* Draw a list of blit objects into the given target.
|
||||
* The target_config is a bitwise OR of values from C2D_TARGET_CONFIG.
|
||||
* The target transformation creates the effect that target surface
|
||||
* is transformed before the blit and then transformed back
|
||||
* after blit, however no physical target transform is performed.
|
||||
* The objects_list is a linked list of blit objects, no more
|
||||
* than num_objects is drawn from the given list.
|
||||
* If num_objects is 0, the whole list is drawn.
|
||||
* The blit is not guaranteed to complete after function returns. */
|
||||
C2D_API C2D_STATUS c2dDraw( uint32 target_id,
|
||||
uint32 target_config, C2D_RECT *target_scissor,
|
||||
uint32 target_mask_id, uint32 target_color_key,
|
||||
C2D_OBJECT *objects_list, uint32 num_objects );
|
||||
|
||||
|
||||
/* timstamp set in the blit commands flush */
|
||||
typedef void* c2d_ts_handle;
|
||||
|
||||
/* Forces any pending blit to complete for a given target.
|
||||
* Non-blocking. All input surfaces for this target except those
|
||||
* which are shared with other targets are expected to be immediately
|
||||
* writable after client has been waiting returned timestamp with
|
||||
* c2dWaitTimestamp funtion or c2dFinish has been called for same target */
|
||||
C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp);
|
||||
|
||||
|
||||
/* Waits the pending timestamp */
|
||||
C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp );
|
||||
|
||||
|
||||
/* Forces any pending blit to complete for a given target.
|
||||
* Blocking version, returns when blit is done.
|
||||
* All input surfaces for this target except those which are shared with
|
||||
* other targets are expected to be immediately
|
||||
* writable after this function returns. */
|
||||
C2D_API C2D_STATUS c2dFinish( uint32 target_id );
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Display API **********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/* Display input enumeration */
|
||||
typedef enum {
|
||||
C2D_DISPLAY_INPUT_0 = 0, /*!< default input */
|
||||
C2D_DISPLAY_INPUT_1 = (1<<16), /*!< Overlay 1 */
|
||||
C2D_DISPLAY_INPUT_2 = (1<<17), /*!< Overlay 2... */
|
||||
} C2D_DISPLAY_INPUT;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Functions for display output. */
|
||||
|
||||
/* Functionality described in this section is optional and is
|
||||
* provided only for the cases when blit HW
|
||||
* is tightly bound to the display controller. */
|
||||
|
||||
/* Display enumeration, may also be used in surface caps */
|
||||
typedef enum {
|
||||
C2D_DISPLAY_MAIN = (1 << 10), /* main display */
|
||||
C2D_DISPLAY_SECONDARY = (1 << 11), /* secondary display */
|
||||
C2D_DISPLAY_TV_OUT = (1 << 12), /* tv-out */
|
||||
} C2D_DISPLAY;
|
||||
|
||||
/* Display window enumeration */
|
||||
typedef enum {
|
||||
C2D_DISPLAY_OVERLAY = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input.
|
||||
When defined the surface is set on the overlay window
|
||||
otherwise the surface is set on the background window. */
|
||||
} C2D_DISPLAY_WINDOW; /*!< Window bit set with display parameter */
|
||||
|
||||
|
||||
/* Display update modes */
|
||||
typedef enum {
|
||||
C2D_DISPLAY_MODE_TEAR_SYNC = (1 << 0), /* enables tearing sync */
|
||||
C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */
|
||||
} C2D_DISPLAY_MODE;
|
||||
|
||||
|
||||
/* Sets the given surface as a current display front buffer.
|
||||
* Several displays can be specified as an output if supported.
|
||||
* Still only one input can be specified at a time fro display/displays.
|
||||
* The surface remains shown until it gets replaced with another one. */
|
||||
C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display,
|
||||
uint32 surface_id, uint32 mode );
|
||||
|
||||
/* Returns the current surface for a particular display.
|
||||
* Only one display can be specified at a time.
|
||||
* The latest surface set with compDisplaySetSurface or
|
||||
* the default pre-allocated surface is returned. */
|
||||
C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display,
|
||||
uint32 *surface_id );
|
||||
|
||||
/* Returns the properties for a particular display.
|
||||
* Only one display can be specified at a time. */
|
||||
C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display,
|
||||
uint32 *width, uint32 *height,
|
||||
uint32 *format );
|
||||
|
||||
/* Sets the properties for a particular display input.
|
||||
* Only one display + input can be specified at a time.
|
||||
* C2D_OBJECT used to set input rect(target rect),
|
||||
* blending operations, rotation...etc for display source */
|
||||
C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display,
|
||||
uint32 target_config, uint32 target_color_key,
|
||||
C2D_OBJECT * c2dObject, uint32 mode);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __c2d2_h_ */
|
498
libcopybit/copybit.cpp
Normal file
498
libcopybit/copybit.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#define LOG_TAG "copybit"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <linux/msm_mdp.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <hardware/copybit.h>
|
||||
|
||||
#include "gralloc_priv.h"
|
||||
|
||||
#define DEBUG_MDP_ERRORS 1
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined(COPYBIT_MSM7K)
|
||||
#define MAX_SCALE_FACTOR (4)
|
||||
#define MAX_DIMENSION (4096)
|
||||
#elif defined(COPYBIT_QSD8K)
|
||||
#define MAX_SCALE_FACTOR (8)
|
||||
#define MAX_DIMENSION (2048)
|
||||
#else
|
||||
#error "Unsupported MDP version"
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/** State information for each device instance */
|
||||
struct copybit_context_t {
|
||||
struct copybit_device_t device;
|
||||
int mFD;
|
||||
uint8_t mAlpha;
|
||||
uint8_t mFlags;
|
||||
};
|
||||
|
||||
/**
|
||||
* Common hardware methods
|
||||
*/
|
||||
|
||||
static int open_copybit(const struct hw_module_t* module, const char* name,
|
||||
struct hw_device_t** device);
|
||||
|
||||
static struct hw_module_methods_t copybit_module_methods = {
|
||||
open: open_copybit
|
||||
};
|
||||
|
||||
/*
|
||||
* The COPYBIT Module
|
||||
*/
|
||||
struct copybit_module_t HAL_MODULE_INFO_SYM = {
|
||||
common: {
|
||||
tag: HARDWARE_MODULE_TAG,
|
||||
version_major: 1,
|
||||
version_minor: 0,
|
||||
id: COPYBIT_HARDWARE_MODULE_ID,
|
||||
name: "QCT MSM7K COPYBIT Module",
|
||||
author: "Google, Inc.",
|
||||
methods: ©bit_module_methods
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/** min of int a, b */
|
||||
static inline int min(int a, int b) {
|
||||
return (a<b) ? a : b;
|
||||
}
|
||||
|
||||
/** max of int a, b */
|
||||
static inline int max(int a, int b) {
|
||||
return (a>b) ? a : b;
|
||||
}
|
||||
|
||||
/** scale each parameter by mul/div. Assume div isn't 0 */
|
||||
static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
|
||||
if (mul != div) {
|
||||
*a = (mul * *a) / div;
|
||||
*b = (mul * *b) / div;
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine the intersection of lhs & rhs store in out */
|
||||
static void intersect(struct copybit_rect_t *out,
|
||||
const struct copybit_rect_t *lhs,
|
||||
const struct copybit_rect_t *rhs) {
|
||||
out->l = max(lhs->l, rhs->l);
|
||||
out->t = max(lhs->t, rhs->t);
|
||||
out->r = min(lhs->r, rhs->r);
|
||||
out->b = min(lhs->b, rhs->b);
|
||||
}
|
||||
|
||||
/** convert COPYBIT_FORMAT to MDP format */
|
||||
static int get_format(int format) {
|
||||
switch (format) {
|
||||
case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565;
|
||||
case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888;
|
||||
case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888;
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888: return MDP_RGBA_8888;
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888: return MDP_BGRA_8888;
|
||||
case HAL_PIXEL_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1;
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** convert from copybit image to mdp image structure */
|
||||
static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)
|
||||
{
|
||||
private_handle_t* hnd = (private_handle_t*)rhs->handle;
|
||||
img->width = rhs->w;
|
||||
img->height = rhs->h;
|
||||
img->format = get_format(rhs->format);
|
||||
img->offset = hnd->offset;
|
||||
#if defined(COPYBIT_MSM7K)
|
||||
#if defined(USE_ASHMEM) && (TARGET_7x27)
|
||||
img->memory_id = hnd->fd;
|
||||
#else //USE_ASHMEM not defined
|
||||
img->memory_id = hnd->fd;
|
||||
#endif //end USE_ASHMEM
|
||||
#else
|
||||
img->memory_id = hnd->fd;
|
||||
#endif
|
||||
}
|
||||
/** setup rectangles */
|
||||
static void set_rects(struct copybit_context_t *dev,
|
||||
struct mdp_blit_req *e,
|
||||
const struct copybit_rect_t *dst,
|
||||
const struct copybit_rect_t *src,
|
||||
const struct copybit_rect_t *scissor,
|
||||
uint32_t horiz_padding,
|
||||
uint32_t vert_padding) {
|
||||
struct copybit_rect_t clip;
|
||||
intersect(&clip, scissor, dst);
|
||||
|
||||
e->dst_rect.x = clip.l;
|
||||
e->dst_rect.y = clip.t;
|
||||
e->dst_rect.w = clip.r - clip.l;
|
||||
e->dst_rect.h = clip.b - clip.t;
|
||||
|
||||
uint32_t W, H;
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.x = (clip.t - dst->t) + src->t;
|
||||
e->src_rect.y = (dst->r - clip.r) + src->l;
|
||||
e->src_rect.w = (clip.b - clip.t);
|
||||
e->src_rect.h = (clip.r - clip.l);
|
||||
W = dst->b - dst->t;
|
||||
H = dst->r - dst->l;
|
||||
} else {
|
||||
e->src_rect.x = (clip.l - dst->l) + src->l;
|
||||
e->src_rect.y = (clip.t - dst->t) + src->t;
|
||||
e->src_rect.w = (clip.r - clip.l);
|
||||
e->src_rect.h = (clip.b - clip.t);
|
||||
W = dst->r - dst->l;
|
||||
H = dst->b - dst->t;
|
||||
}
|
||||
MULDIV(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W);
|
||||
MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H);
|
||||
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
|
||||
}else{
|
||||
e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
|
||||
if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
|
||||
e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
|
||||
}else{
|
||||
e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** setup mdp request */
|
||||
static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req, int flags) {
|
||||
req->alpha = dev->mAlpha;
|
||||
req->transp_mask = MDP_TRANSP_NOP;
|
||||
req->flags = dev->mFlags | flags;
|
||||
#if defined(COPYBIT_QSD8K)
|
||||
req->flags |= MDP_BLEND_FG_PREMULT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** copy the bits */
|
||||
static int msm_copybit(struct copybit_context_t *dev, void const *list)
|
||||
{
|
||||
int err = ioctl(dev->mFD, MSMFB_BLIT,
|
||||
(struct mdp_blit_req_list const*)list);
|
||||
LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
|
||||
if (err == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
#if DEBUG_MDP_ERRORS
|
||||
struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list;
|
||||
for (int i=0 ; i<l->count ; i++) {
|
||||
LOGD("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
|
||||
" dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
|
||||
" flags=%08lx"
|
||||
,
|
||||
i,
|
||||
l->req[i].src.width,
|
||||
l->req[i].src.height,
|
||||
l->req[i].src.format,
|
||||
l->req[i].src_rect.x,
|
||||
l->req[i].src_rect.y,
|
||||
l->req[i].src_rect.w,
|
||||
l->req[i].src_rect.h,
|
||||
l->req[i].dst.width,
|
||||
l->req[i].dst.height,
|
||||
l->req[i].dst.format,
|
||||
l->req[i].dst_rect.x,
|
||||
l->req[i].dst_rect.y,
|
||||
l->req[i].dst_rect.w,
|
||||
l->req[i].dst_rect.h,
|
||||
l->req[i].flags
|
||||
);
|
||||
}
|
||||
#endif
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Set a parameter to value */
|
||||
static int set_parameter_copybit(
|
||||
struct copybit_device_t *dev,
|
||||
int name,
|
||||
int value)
|
||||
{
|
||||
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
|
||||
int status = 0;
|
||||
if (ctx) {
|
||||
switch(name) {
|
||||
case COPYBIT_ROTATION_DEG:
|
||||
switch (value) {
|
||||
case 0:
|
||||
ctx->mFlags &= ~0x7;
|
||||
break;
|
||||
case 90:
|
||||
ctx->mFlags &= ~0x7;
|
||||
ctx->mFlags |= MDP_ROT_90;
|
||||
break;
|
||||
case 180:
|
||||
ctx->mFlags &= ~0x7;
|
||||
ctx->mFlags |= MDP_ROT_180;
|
||||
break;
|
||||
case 270:
|
||||
ctx->mFlags &= ~0x7;
|
||||
ctx->mFlags |= MDP_ROT_270;
|
||||
break;
|
||||
default:
|
||||
LOGE("Invalid value for COPYBIT_ROTATION_DEG");
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case COPYBIT_PLANE_ALPHA:
|
||||
if (value < 0) value = 0;
|
||||
if (value >= 256) value = 255;
|
||||
ctx->mAlpha = value;
|
||||
break;
|
||||
case COPYBIT_DITHER:
|
||||
if (value == COPYBIT_ENABLE) {
|
||||
ctx->mFlags |= MDP_DITHER;
|
||||
} else if (value == COPYBIT_DISABLE) {
|
||||
ctx->mFlags &= ~MDP_DITHER;
|
||||
}
|
||||
break;
|
||||
case COPYBIT_BLUR:
|
||||
if (value == COPYBIT_ENABLE) {
|
||||
ctx->mFlags |= MDP_BLUR;
|
||||
} else if (value == COPYBIT_DISABLE) {
|
||||
ctx->mFlags &= ~MDP_BLUR;
|
||||
}
|
||||
break;
|
||||
case COPYBIT_TRANSFORM:
|
||||
ctx->mFlags &= ~0x7;
|
||||
ctx->mFlags |= value & 0x7;
|
||||
break;
|
||||
default:
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
status = -EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Get a static info value */
|
||||
static int get(struct copybit_device_t *dev, int name)
|
||||
{
|
||||
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
|
||||
int value;
|
||||
if (ctx) {
|
||||
switch(name) {
|
||||
case COPYBIT_MINIFICATION_LIMIT:
|
||||
value = MAX_SCALE_FACTOR;
|
||||
break;
|
||||
case COPYBIT_MAGNIFICATION_LIMIT:
|
||||
value = MAX_SCALE_FACTOR;
|
||||
break;
|
||||
case COPYBIT_SCALING_FRAC_BITS:
|
||||
value = 32;
|
||||
break;
|
||||
case COPYBIT_ROTATION_STEP_DEG:
|
||||
value = 90;
|
||||
break;
|
||||
default:
|
||||
value = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
value = -EINVAL;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/** do a stretch blit type operation */
|
||||
static int stretch_copybit(
|
||||
struct copybit_device_t *dev,
|
||||
struct copybit_image_t const *dst,
|
||||
struct copybit_image_t const *src,
|
||||
struct copybit_rect_t const *dst_rect,
|
||||
struct copybit_rect_t const *src_rect,
|
||||
struct copybit_region_t const *region)
|
||||
{
|
||||
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
|
||||
int status = 0;
|
||||
if (ctx) {
|
||||
struct {
|
||||
uint32_t count;
|
||||
struct mdp_blit_req req[12];
|
||||
} list;
|
||||
|
||||
if (ctx->mAlpha < 255) {
|
||||
switch (src->format) {
|
||||
// we don't support plane alpha with RGBA formats
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888:
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
case HAL_PIXEL_FORMAT_RGBA_5551:
|
||||
case HAL_PIXEL_FORMAT_RGBA_4444:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (src_rect->l < 0 || src_rect->r > src->w ||
|
||||
src_rect->t < 0 || src_rect->b > src->h) {
|
||||
// this is always invalid
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION)
|
||||
return -EINVAL;
|
||||
|
||||
if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION)
|
||||
return -EINVAL;
|
||||
|
||||
const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
|
||||
const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
|
||||
struct copybit_rect_t clip;
|
||||
list.count = 0;
|
||||
status = 0;
|
||||
while ((status == 0) && region->next(region, &clip)) {
|
||||
intersect(&clip, &bounds, &clip);
|
||||
mdp_blit_req* req = &list.req[list.count];
|
||||
int flags = 0;
|
||||
|
||||
set_infos(ctx, req, flags);
|
||||
set_image(&req->dst, dst);
|
||||
set_image(&req->src, src);
|
||||
set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
|
||||
|
||||
if (req->src_rect.w<=0 || req->src_rect.h<=0)
|
||||
continue;
|
||||
|
||||
if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
|
||||
continue;
|
||||
|
||||
if (++list.count == maxCount) {
|
||||
status = msm_copybit(ctx, &list);
|
||||
list.count = 0;
|
||||
}
|
||||
}
|
||||
if ((status == 0) && list.count) {
|
||||
status = msm_copybit(ctx, &list);
|
||||
}
|
||||
} else {
|
||||
status = -EINVAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Perform a blit type operation */
|
||||
static int blit_copybit(
|
||||
struct copybit_device_t *dev,
|
||||
struct copybit_image_t const *dst,
|
||||
struct copybit_image_t const *src,
|
||||
struct copybit_region_t const *region)
|
||||
{
|
||||
struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
|
||||
struct copybit_rect_t sr = { 0, 0, src->w, src->h };
|
||||
return stretch_copybit(dev, dst, src, &dr, &sr, region);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Close the copybit device */
|
||||
static int close_copybit(struct hw_device_t *dev)
|
||||
{
|
||||
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
|
||||
if (ctx) {
|
||||
close(ctx->mFD);
|
||||
free(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Open a new instance of a copybit device using name */
|
||||
static int open_copybit(const struct hw_module_t* module, const char* name,
|
||||
struct hw_device_t** device)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
copybit_context_t *ctx;
|
||||
ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||
ctx->device.common.version = 1;
|
||||
ctx->device.common.module = const_cast<hw_module_t*>(module);
|
||||
ctx->device.common.close = close_copybit;
|
||||
ctx->device.set_parameter = set_parameter_copybit;
|
||||
ctx->device.get = get;
|
||||
ctx->device.blit = blit_copybit;
|
||||
ctx->device.stretch = stretch_copybit;
|
||||
ctx->mAlpha = MDP_ALPHA_NOP;
|
||||
ctx->mFlags = 0;
|
||||
ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
|
||||
|
||||
if (ctx->mFD < 0) {
|
||||
status = errno;
|
||||
LOGE("Error opening frame buffer errno=%d (%s)",
|
||||
status, strerror(status));
|
||||
status = -status;
|
||||
} else {
|
||||
struct fb_fix_screeninfo finfo;
|
||||
if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
|
||||
if (strncmp(finfo.id, "msmfb", 5) == 0) {
|
||||
/* Success */
|
||||
status = 0;
|
||||
} else {
|
||||
LOGE("Error not msm frame buffer");
|
||||
status = -EINVAL;
|
||||
}
|
||||
} else {
|
||||
LOGE("Error executing ioctl for screen info");
|
||||
status = -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
*device = &ctx->device.common;
|
||||
} else {
|
||||
close_copybit(&ctx->device.common);
|
||||
}
|
||||
return status;
|
||||
}
|
1036
libcopybit/copybit_c2d.cpp
Normal file
1036
libcopybit/copybit_c2d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
70
libgralloc/Android.mk
Normal file
70
libgralloc/Android.mk
Normal file
@ -0,0 +1,70 @@
|
||||
# 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.
|
||||
|
||||
# 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
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc
|
||||
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_SRC_FILES := framebuffer.cpp \
|
||||
gpu.cpp \
|
||||
gralloc.cpp \
|
||||
mapper.cpp \
|
||||
pmemalloc.cpp \
|
||||
pmem_bestfit_alloc.cpp
|
||||
|
||||
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 += 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
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
#MemAlloc Library
|
||||
include $(CLEAR_VARS)
|
||||
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
|
0
libgralloc/MODULE_LICENSE_APACHE2
Normal file
0
libgralloc/MODULE_LICENSE_APACHE2
Normal file
158
libgralloc/alloc_controller.cpp
Normal file
158
libgralloc/alloc_controller.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
87
libgralloc/alloc_controller.h
Normal file
87
libgralloc/alloc_controller.h
Normal 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
140
libgralloc/ashmemalloc.cpp
Normal 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
56
libgralloc/ashmemalloc.h
Normal 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 */
|
@ -63,7 +63,6 @@
|
||||
#define HEIGHT_480P 480
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
using overlay::Overlay;
|
||||
using overlay::ActionSafe;
|
||||
/** min of int a, b */
|
||||
static inline int min(int a, int b) {
|
||||
return (a<b) ? a : b;
|
||||
@ -87,6 +86,20 @@ char framebufferStateName[] = {'S', 'R', 'A'};
|
||||
#define MAX_DEBUG_FPS_LEVEL 2
|
||||
|
||||
struct debug_fps_metadata_t {
|
||||
/*fps calculation based on time or number of frames*/
|
||||
enum DfmType {
|
||||
DFM_FRAMES = 0,
|
||||
DFM_TIME = 1,
|
||||
};
|
||||
|
||||
DfmType type;
|
||||
|
||||
/* indicates how much time do we wait till we calculate FPS */
|
||||
unsigned long time_period;
|
||||
|
||||
/*indicates how much time elapsed since we report fps*/
|
||||
float time_elapsed;
|
||||
|
||||
/* indicates how many frames do we wait till we calculate FPS */
|
||||
unsigned int period;
|
||||
/* current frame, will go upto period, and then reset */
|
||||
@ -161,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);
|
||||
@ -177,9 +189,21 @@ static void populate_debug_fps_metadata(void)
|
||||
{
|
||||
char prop[PROPERTY_VALUE_MAX];
|
||||
|
||||
/*defaults calculation of fps to based on number of frames*/
|
||||
property_get("debug.gr.calcfps.type", prop, "0");
|
||||
debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
|
||||
|
||||
/*defaults to 1000ms*/
|
||||
property_get("debug.gr.calcfps.timeperiod", prop, "1000");
|
||||
debug_fps_metadata.time_period = atoi(prop);
|
||||
|
||||
property_get("debug.gr.calcfps.period", prop, "10");
|
||||
debug_fps_metadata.period = atoi(prop);
|
||||
|
||||
if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
|
||||
debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
|
||||
}
|
||||
|
||||
/* default ignorethresh_us: 500 milli seconds */
|
||||
property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
|
||||
debug_fps_metadata.ignorethresh_us = atoi(prop);
|
||||
@ -203,6 +227,41 @@ static void populate_debug_fps_metadata(void)
|
||||
LOGE("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
|
||||
}
|
||||
|
||||
static void print_fps(float fps)
|
||||
{
|
||||
if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
|
||||
LOGE("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
|
||||
else
|
||||
LOGE("FPS for last (%f ms, %d frames): %3.2f",
|
||||
debug_fps_metadata.time_elapsed,
|
||||
debug_fps_metadata.curr_frame, fps);
|
||||
|
||||
debug_fps_metadata.curr_frame = 0;
|
||||
debug_fps_metadata.time_elapsed = 0.0;
|
||||
|
||||
if (debug_fps_level > 1) {
|
||||
LOGE("Frame Arrival Distribution:");
|
||||
for (unsigned int i = 0;
|
||||
i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
|
||||
i++) {
|
||||
LOGE("%lld %lld %lld %lld %lld %lld",
|
||||
debug_fps_metadata.accum_framearrivals[i*6],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+1],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+2],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+3],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+4],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+5]);
|
||||
}
|
||||
|
||||
/* We are done with displaying, now clear the stats */
|
||||
for (unsigned int i = 0;
|
||||
i < debug_fps_metadata.framearrival_steps;
|
||||
i++)
|
||||
debug_fps_metadata.accum_framearrivals[i] = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void calc_fps(nsecs_t currtime_us)
|
||||
{
|
||||
static nsecs_t oldtime_us = 0;
|
||||
@ -211,41 +270,15 @@ static void calc_fps(nsecs_t currtime_us)
|
||||
|
||||
oldtime_us = currtime_us;
|
||||
|
||||
if (diff > debug_fps_metadata.ignorethresh_us) {
|
||||
if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
|
||||
diff > debug_fps_metadata.ignorethresh_us) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
|
||||
/* time to calculate and display FPS */
|
||||
nsecs_t sum = 0;
|
||||
for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
|
||||
sum += debug_fps_metadata.framearrivals[i];
|
||||
LOGE("FPS for last %d frames: %3.2f", debug_fps_metadata.period,
|
||||
(debug_fps_metadata.period * float(1000000))/float(sum));
|
||||
|
||||
debug_fps_metadata.curr_frame = 0;
|
||||
if (debug_fps_level > 1) {
|
||||
LOGE("Frame Arrival Distribution:");
|
||||
for (unsigned int i = 0;
|
||||
i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
|
||||
i++) {
|
||||
LOGE("%lld %lld %lld %lld %lld %lld",
|
||||
debug_fps_metadata.accum_framearrivals[i*6],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+1],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+2],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+3],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+4],
|
||||
debug_fps_metadata.accum_framearrivals[i*6+5]);
|
||||
}
|
||||
|
||||
/* We are done with displaying, now clear the stats */
|
||||
for (unsigned int i = 0; i < debug_fps_metadata.framearrival_steps; i++)
|
||||
debug_fps_metadata.accum_framearrivals[i] = 0;
|
||||
}
|
||||
if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
|
||||
debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame++] = diff;
|
||||
}
|
||||
|
||||
debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame++] = diff;
|
||||
|
||||
if (debug_fps_level > 1) {
|
||||
unsigned int currstep = (diff + debug_fps_metadata.margin_us) / 16666;
|
||||
|
||||
@ -253,6 +286,25 @@ static void calc_fps(nsecs_t currtime_us)
|
||||
debug_fps_metadata.accum_framearrivals[currstep-1]++;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
|
||||
if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
|
||||
/* time to calculate and display FPS */
|
||||
nsecs_t sum = 0;
|
||||
for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
|
||||
sum += debug_fps_metadata.framearrivals[i];
|
||||
print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
|
||||
}
|
||||
}
|
||||
else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
|
||||
debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
|
||||
if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
|
||||
float fps = (1000.0 * debug_fps_metadata.curr_frame)/
|
||||
(float)debug_fps_metadata.time_elapsed;
|
||||
print_fps(fps);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // DEBUG_CALC_FPS
|
||||
@ -299,23 +351,6 @@ static void *disp_loop(void *ptr)
|
||||
if (debug_fps_level > 0) calc_fps(ns2us(systemTime()));
|
||||
#endif
|
||||
|
||||
#if defined(SF_BYPASS)
|
||||
/*
|
||||
* Comp. bypass sepcific.
|
||||
* Close the bypass channel if PENDING_CLOSE.
|
||||
* We require this code here because -
|
||||
* disp_loop can only guarantee push of FB
|
||||
*/
|
||||
pthread_mutex_lock(&m->overlayui_lock);
|
||||
if (m->bypassChannelState == BYPASS_OV_CHANNEL_PENDING_CLOSE) {
|
||||
if (m->pobjOverlayUI) {
|
||||
m->pobjOverlayUI->closeChannel();
|
||||
}
|
||||
m->bypassChannelState = BYPASS_OV_CHANNEL_CLOSED;
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayui_lock);
|
||||
#endif
|
||||
|
||||
if (cur_buf == -1) {
|
||||
int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
|
||||
pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
|
||||
@ -350,16 +385,11 @@ static void *disp_loop(void *ptr)
|
||||
}
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
static int postOrigResHDMI(private_module_t *);
|
||||
static void *hdmi_ui_loop(void *ptr)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ptr);
|
||||
while (1) {
|
||||
if(m->isOrigResStarted) {
|
||||
postOrigResHDMI(m);
|
||||
continue;
|
||||
}
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
while(!(m->hdmiStateChanged))
|
||||
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
|
||||
@ -368,19 +398,27 @@ static void *hdmi_ui_loop(void *ptr)
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return NULL;
|
||||
}
|
||||
float asWidthRatio = ActionSafe::getWidthRatio() / 100.0f;
|
||||
float asHeightRatio = ActionSafe::getHeightRatio() / 100.0f;
|
||||
float asWidthRatio = m->actionsafeWidthRatio/100.0f;
|
||||
float asHeightRatio = m->actionsafeHeightRatio/100.0f;
|
||||
|
||||
if (m->pobjOverlay) {
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if (!m->enableHDMIOutput)
|
||||
pTemp->closeChannel();
|
||||
else if (m->enableHDMIOutput && !m->videoOverlay &&
|
||||
!(m->isOrigResStarted)) {
|
||||
else if (m->enableHDMIOutput && !m->videoOverlay) {
|
||||
if (!pTemp->isChannelUP()) {
|
||||
int alignedW = ALIGN(m->info.xres, 32);
|
||||
if (pTemp->startChannel(alignedW, m->info.yres,
|
||||
m->fbFormat, 1, false, true, 0, VG0_PIPE, true)) {
|
||||
int alignedW = ALIGN(m->info.xres, 32);
|
||||
|
||||
private_handle_t const* hnd =
|
||||
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
||||
overlay_buffer_info info;
|
||||
info.width = alignedW;
|
||||
info.height = hnd->height;
|
||||
info.format = hnd->format;
|
||||
info.size = hnd->size;
|
||||
|
||||
if (pTemp->startChannel(info, 1,
|
||||
false, true, 0, VG0_PIPE, true)) {
|
||||
pTemp->setFd(m->framebuffer->fd);
|
||||
pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
|
||||
} else
|
||||
@ -523,18 +561,34 @@ static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable)
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
m->enableHDMIOutput = enable;
|
||||
if(m->isOrigResStarted) {
|
||||
m->ts.isHDMIExitPending = !enable;
|
||||
} else if (!enable && pTemp) {
|
||||
if (!enable && pTemp)
|
||||
pTemp->closeChannel();
|
||||
}
|
||||
m->enableHDMIOutput = enable;
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->actionsafeWidthRatio = asWidthRatio;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->actionsafeHeightRatio = asHeightRatio;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
@ -544,215 +598,6 @@ static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientati
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Posts buffers in their original resolution to secondary.
|
||||
*/
|
||||
static int postOrigResHDMI(private_module_t* m) {
|
||||
int w, h, format;
|
||||
buffer_handle_t buffer;
|
||||
int ret = NO_ERROR;
|
||||
|
||||
//Wait for new buffer call and read values
|
||||
pthread_mutex_lock(&m->ts.newBufferMutex);
|
||||
while(m->ts.isNewBuffer == false) {
|
||||
pthread_cond_wait(&m->ts.newBufferCond, &m->ts.newBufferMutex);
|
||||
}
|
||||
m->ts.get(w,h,format,buffer);
|
||||
m->ts.isNewBuffer = false;
|
||||
pthread_mutex_unlock(&m->ts.newBufferMutex);
|
||||
|
||||
//Post them to secondary
|
||||
if(m->enableHDMIOutput) {
|
||||
const int orientation = 0;
|
||||
ret = m->pOrigResTV->setSource(w, h, format, orientation);
|
||||
if(ret == NO_ERROR) {
|
||||
m->pOrigResTV->setPosition();
|
||||
ret = m->pOrigResTV->queueBuffer(buffer);
|
||||
}
|
||||
if(ret != NO_ERROR)
|
||||
LOGE("Posting original resolution surface to secondary failed");
|
||||
}
|
||||
//Signal that we posted the buffer
|
||||
pthread_mutex_lock(&m->ts.bufferPostedMutex);
|
||||
m->ts.isBufferPosted = true;
|
||||
pthread_cond_signal(&m->ts.bufferPostedCond);
|
||||
pthread_mutex_unlock(&m->ts.bufferPostedMutex);
|
||||
if(m->ts.isExitPending || m->ts.isHDMIExitPending) {
|
||||
m->pOrigResTV->closeChannel();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Posts buffers in their original resolution to primary.
|
||||
*/
|
||||
static int fb_postOrigResBuffer(struct framebuffer_device_t* dev,
|
||||
buffer_handle_t buffer, int w,
|
||||
int h, int format, int orientation) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
int ret = NO_ERROR;
|
||||
if (m->isOrigResStarted) {
|
||||
//Share new values
|
||||
pthread_mutex_lock(&m->ts.newBufferMutex);
|
||||
m->ts.set(w,h,format,buffer);
|
||||
m->ts.isNewBuffer = true;
|
||||
pthread_cond_signal(&m->ts.newBufferCond);
|
||||
pthread_mutex_unlock(&m->ts.newBufferMutex);
|
||||
|
||||
ret = m->pOrigResPanel->setSource(w, h, format, orientation);
|
||||
if(ret == NO_ERROR) {
|
||||
ret = m->pOrigResPanel->queueBuffer(buffer);
|
||||
}
|
||||
if(ret != NO_ERROR)
|
||||
LOGE("Posting original resolution surface to primary failed");
|
||||
|
||||
//Wait for HDMI to post buffers
|
||||
pthread_mutex_lock(&m->ts.bufferPostedMutex);
|
||||
while(m->ts.isBufferPosted == false) {
|
||||
pthread_cond_wait(&m->ts.bufferPostedCond,
|
||||
&m->ts.bufferPostedMutex);
|
||||
}
|
||||
m->ts.isBufferPosted = false;
|
||||
pthread_mutex_unlock(&m->ts.bufferPostedMutex);
|
||||
}
|
||||
if(m->ts.isExitPending) {
|
||||
m->pOrigResPanel->closeChannel();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fb_startOrigResDisplay(struct framebuffer_device_t* dev) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
int ret = NO_ERROR;
|
||||
dev->videoOverlayStarted(dev, true);
|
||||
m->ts.clear();
|
||||
m->isOrigResStarted = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fb_stopOrigResDisplay(struct framebuffer_device_t* dev) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
int ret = NO_ERROR;
|
||||
m->isOrigResStarted = false;
|
||||
m->ts.isExitPending = true;
|
||||
//Free the threads
|
||||
m->ts.isNewBuffer = true;
|
||||
m->ts.isBufferPosted = true;
|
||||
pthread_cond_signal(&m->ts.newBufferCond);
|
||||
pthread_cond_signal(&m->ts.bufferPostedCond);
|
||||
m->pOrigResPanel->closeChannel();
|
||||
m->pOrigResTV->closeChannel();
|
||||
dev->videoOverlayStarted(dev, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(SF_BYPASS)
|
||||
/*
|
||||
* function: fb_postBypassBuffer
|
||||
* Input: framebuffer device pointer, buffer handle, width
|
||||
* height, format, orientation and HPD state
|
||||
* Return Value: Result of posting the bypass buffer.
|
||||
* NO_ERROR - Success in pushing the buffer
|
||||
* Works as following:
|
||||
* Currently, if HPD is on, bypass feature is disabled.
|
||||
* If Bypass channel state is PENDING CLOSE, dont push the buffer
|
||||
* Else, push the buffer with following two steps
|
||||
* 1) Set the source geometery
|
||||
* 2) queue the buffer
|
||||
* Set the bypass channel state as OPEN if we try to push the buffer
|
||||
*/
|
||||
static int fb_postBypassBuffer(struct framebuffer_device_t* dev,
|
||||
buffer_handle_t buffer, int w,
|
||||
int h, int format, int orientation, int isHPDON)
|
||||
{
|
||||
if (isHPDON)
|
||||
return -EINVAL;
|
||||
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
if (m->pobjOverlayUI) {
|
||||
|
||||
pthread_mutex_lock(&m->overlayui_lock);
|
||||
if (m->bypassChannelState == BYPASS_OV_CHANNEL_PENDING_CLOSE) {
|
||||
pthread_mutex_unlock(&m->overlayui_lock);
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&m->overlayui_lock);
|
||||
|
||||
OverlayUI* pobjOverlay = m->pobjOverlayUI;
|
||||
if (buffer == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
bool useVGPipe = false;
|
||||
|
||||
status_t ret = pobjOverlay->setSource(w, h, format, orientation, useVGPipe);
|
||||
if (ret != NO_ERROR)
|
||||
return ret;
|
||||
|
||||
ret = pobjOverlay->queueBuffer(buffer);
|
||||
|
||||
if (ret != NO_ERROR)
|
||||
LOGE("error in queue.. ");
|
||||
m->bypassChannelState = BYPASS_OV_CHANNEL_OPEN;
|
||||
return ret;
|
||||
}
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* function: fb_closeBypass
|
||||
* Input: Framebuffer device pointer
|
||||
* Its only job is to set the bypassChannelState to PENDING_CLOSE.
|
||||
* so that disp_loop could close the channel when a post happens
|
||||
*/
|
||||
|
||||
static int fb_closeBypass(struct framebuffer_device_t* dev)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
if (m->pobjOverlayUI) {
|
||||
pthread_mutex_lock(&m->overlayui_lock);
|
||||
m->bypassChannelState = BYPASS_OV_CHANNEL_PENDING_CLOSE;
|
||||
pthread_mutex_unlock(&m->overlayui_lock);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* function: fb_copyBypassBuffer
|
||||
* Input: Framebuffer device pointer
|
||||
* This function is to copy the bypass buffer.
|
||||
* This function is required because:
|
||||
* Before closing the bypass channel
|
||||
* MDP read buffer pointer need to be changed
|
||||
* so that application buffer could be released
|
||||
* It calls on to OverlayUI::copyBuffer for the same
|
||||
*/
|
||||
|
||||
static int fb_copyBypassBuffer(struct framebuffer_device_t* dev)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
status_t ret = NO_ERROR;
|
||||
if (m->pobjOverlayUI) {
|
||||
pthread_mutex_lock(&m->overlayui_lock);
|
||||
if (m->bypassChannelState != BYPASS_OV_CHANNEL_PENDING_CLOSE) {
|
||||
OverlayUI* pobjOverlay = m->pobjOverlayUI;
|
||||
ret = pobjOverlay->copyBuffer();
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayui_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
@ -817,26 +662,11 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
pthread_cond_signal(&(m->qpost));
|
||||
pthread_mutex_unlock(&(m->qlock));
|
||||
|
||||
// LCDC: after new buffer grabbed by MDP can unlock previous
|
||||
// (current) buffer
|
||||
if (m->currentBuffer) {
|
||||
if (m->swapInterval != 0) {
|
||||
pthread_mutex_lock(&(m->avail[futureIdx].lock));
|
||||
//while (! m->avail[futureIdx].is_avail) {
|
||||
while (m->avail[futureIdx].state != AVL) {
|
||||
pthread_cond_wait(&(m->avail[futureIdx].cond),
|
||||
&(m->avail[futureIdx].lock));
|
||||
//m->avail[futureIdx].is_avail = true;
|
||||
}
|
||||
pthread_mutex_unlock(&(m->avail[futureIdx].lock));
|
||||
}
|
||||
if (m->currentBuffer)
|
||||
m->base.unlock(&m->base, m->currentBuffer);
|
||||
}
|
||||
|
||||
m->currentBuffer = buffer;
|
||||
m->currentIdx = nxtIdx;
|
||||
if (m->avail[futureIdx].state != AVL) {
|
||||
LOGE_IF(m->swapInterval != 0, "[%d] != AVL!", futureIdx);
|
||||
}
|
||||
} else {
|
||||
if (m->currentBuffer)
|
||||
m->base.unlock(&m->base, m->currentBuffer);
|
||||
@ -849,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);
|
||||
|
||||
@ -868,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",
|
||||
@ -887,7 +716,7 @@ static int fb_compositionComplete(struct framebuffer_device_t* dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_dequeueBuffer(struct framebuffer_device_t* dev, int index)
|
||||
static int fb_lockBuffer(struct framebuffer_device_t* dev, int index)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
@ -914,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",
|
||||
@ -956,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)
|
||||
@ -1125,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;
|
||||
@ -1139,8 +967,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
|
||||
int err;
|
||||
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
|
||||
module->framebuffer = new private_handle_t(fd, fbSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM);
|
||||
module->framebuffer = new private_handle_t(dup(fd), fbSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_UI, module->fbFormat, info.xres, info.yres);
|
||||
|
||||
module->numBuffers = info.yres_virtual / info.yres;
|
||||
module->bufferMask = 0;
|
||||
@ -1163,16 +991,6 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
module->hdmiStateChanged = false;
|
||||
pthread_t hdmiUIThread;
|
||||
pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
|
||||
module->pOrigResPanel = new OverlayOrigRes<OverlayUI::FB0>();
|
||||
module->pOrigResTV = new OverlayOrigRes<OverlayUI::FB1>();
|
||||
module->isOrigResStarted = false;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(SF_BYPASS)
|
||||
module->pobjOverlayUI = new OverlayUI();
|
||||
module->bypassChannelState = BYPASS_OV_CHANNEL_CLOSED;
|
||||
pthread_mutex_init(&(module->overlayui_lock), NULL);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@ -1198,13 +1016,6 @@ static int fb_close(struct hw_device_t *dev)
|
||||
m->exitHDMIUILoop = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
delete m->pOrigResPanel;
|
||||
delete m->pOrigResTV;
|
||||
#endif
|
||||
|
||||
#if defined(SF_BYPASS)
|
||||
delete m->pobjOverlayUI;
|
||||
m->pobjOverlayUI = 0;
|
||||
#endif
|
||||
if (ctx) {
|
||||
free(ctx);
|
||||
@ -1235,20 +1046,13 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
||||
dev->device.post = fb_post;
|
||||
dev->device.setUpdateRect = 0;
|
||||
dev->device.compositionComplete = fb_compositionComplete;
|
||||
dev->device.dequeueBuffer = fb_dequeueBuffer;
|
||||
dev->device.lockBuffer = fb_lockBuffer;
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
dev->device.orientationChanged = fb_orientationChanged;
|
||||
dev->device.videoOverlayStarted = fb_videoOverlayStarted;
|
||||
dev->device.enableHDMIOutput = fb_enableHDMIOutput;
|
||||
dev->device.postOrigResBuffer = fb_postOrigResBuffer;
|
||||
dev->device.startOrigResDisplay = fb_startOrigResDisplay;
|
||||
dev->device.stopOrigResDisplay = fb_stopOrigResDisplay;
|
||||
#endif
|
||||
|
||||
#if defined(SF_BYPASS)
|
||||
dev->device.postBypassBuffer = fb_postBypassBuffer;
|
||||
dev->device.closeBypass = fb_closeBypass;
|
||||
dev->device.copyBypassBuffer = fb_copyBypassBuffer;
|
||||
dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio;
|
||||
dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio;
|
||||
#endif
|
||||
|
||||
private_module_t* m = (private_module_t*)module;
|
||||
@ -1310,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;
|
358
libgralloc/gpu.cpp
Normal file
358
libgralloc/gpu.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cutils/properties.h>
|
||||
#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;
|
||||
|
||||
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));
|
||||
|
||||
char property[PROPERTY_VALUE_MAX];
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0) {
|
||||
if(atoi(property) == 0) {
|
||||
//debug.sf.hw = 0
|
||||
compositionType = CPU_COMPOSITION;
|
||||
} else { //debug.sf.hw = 1
|
||||
// Get the composition type
|
||||
property_get("debug.composition.type", property, NULL);
|
||||
if (property == NULL) {
|
||||
compositionType = GPU_COMPOSITION;
|
||||
} else if ((strncmp(property, "mdp", 3)) == 0) {
|
||||
compositionType = MDP_COMPOSITION;
|
||||
} else if ((strncmp(property, "c2d", 3)) == 0) {
|
||||
compositionType = C2D_COMPOSITION;
|
||||
} else {
|
||||
compositionType = GPU_COMPOSITION;
|
||||
}
|
||||
}
|
||||
} else { //debug.sf.hw is not set. Use cpu composition
|
||||
compositionType = CPU_COMPOSITION;
|
||||
}
|
||||
|
||||
// Initialize the procs
|
||||
common.tag = HARDWARE_DEVICE_TAG;
|
||||
common.version = 0;
|
||||
common.module = const_cast<hw_module_t*>(&module->base.common);
|
||||
common.close = gralloc_close;
|
||||
alloc = gralloc_alloc;
|
||||
allocSize = gralloc_alloc_size;
|
||||
free = gralloc_free;
|
||||
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
|
||||
// we don't support allocations with both the FB and PMEM_ADSP flags
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (m->framebuffer == NULL) {
|
||||
LOGE("%s: Invalid framebuffer", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const uint32_t bufferMask = m->bufferMask;
|
||||
const uint32_t numBuffers = m->numBuffers;
|
||||
const size_t bufferSize = m->finfo.line_length * m->info.yres;
|
||||
if (numBuffers == 1) {
|
||||
// If we have only one buffer, we never use page-flipping. Instead,
|
||||
// we return a regular buffer which will be memcpy'ed to the main
|
||||
// screen when post is called.
|
||||
int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
|
||||
return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI,
|
||||
m->fbFormat, m->info.xres, m->info.yres);
|
||||
}
|
||||
|
||||
if (bufferMask >= ((1LU<<numBuffers)-1)) {
|
||||
// We ran out of buffers.
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// find a free slot
|
||||
for (uint32_t i=0 ; i<numBuffers ; i++) {
|
||||
if ((bufferMask & (1LU<<i)) == 0) {
|
||||
m->bufferMask |= (1LU<<i);
|
||||
break;
|
||||
}
|
||||
vaddr += bufferSize;
|
||||
}
|
||||
|
||||
hnd->base = vaddr;
|
||||
hnd->offset = vaddr - intptr_t(m->framebuffer->base);
|
||||
*pHandle = hnd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
|
||||
buffer_handle_t* pHandle)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
pthread_mutex_lock(&m->lock);
|
||||
int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
|
||||
pthread_mutex_unlock(&m->lock);
|
||||
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 err = 0;
|
||||
int flags = 0;
|
||||
size = roundUpToPageSize(size);
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
*bufferType = BUFFER_TYPE_VIDEO;
|
||||
*colorFormat = inputFormat;
|
||||
|
||||
if (inputFormat == HAL_PIXEL_FORMAT_YV12) {
|
||||
*bufferType = BUFFER_TYPE_VIDEO;
|
||||
} else if (inputFormat & S3D_FORMAT_MASK) {
|
||||
// S3D format
|
||||
*colorFormat = COLOR_FORMAT(inputFormat);
|
||||
} else if (inputFormat & INTERLACE_MASK) {
|
||||
// Interlaced
|
||||
*colorFormat = inputFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
|
||||
} else if (inputFormat < 0x7) {
|
||||
// RGB formats
|
||||
*colorFormat = inputFormat;
|
||||
*bufferType = BUFFER_TYPE_UI;
|
||||
} else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
|
||||
(inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
|
||||
*colorFormat = inputFormat;
|
||||
*bufferType = BUFFER_TYPE_UI;
|
||||
}
|
||||
}
|
||||
|
||||
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
|
||||
buffer_handle_t* pHandle, int* pStride, size_t bufferSize) {
|
||||
if (!pHandle || !pStride)
|
||||
return -EINVAL;
|
||||
|
||||
size_t size, alignedw, alignedh;
|
||||
|
||||
alignedw = ALIGN(w, 32);
|
||||
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:
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
size = alignedw * alignedh * 4;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_888:
|
||||
size = alignedw * alignedh * 3;
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_RGB_565:
|
||||
case HAL_PIXEL_FORMAT_RGBA_5551:
|
||||
case HAL_PIXEL_FORMAT_RGBA_4444:
|
||||
size = alignedw * alignedh * 2;
|
||||
break;
|
||||
|
||||
// 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);
|
||||
break;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12
|
||||
// The chroma plane is subsampled,
|
||||
// but the pitch in bytes is unchanged
|
||||
// The GPU needs 4K alignment, but the video decoder needs 8K
|
||||
alignedw = ALIGN(w, 128);
|
||||
size = ALIGN( alignedw * alignedh, 8192);
|
||||
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_YV12:
|
||||
if ((w&1) || (h&1)) {
|
||||
LOGE("w or h is odd for the YUV format");
|
||||
return -EINVAL;
|
||||
}
|
||||
alignedw = ALIGN(w, 16);
|
||||
alignedh = h;
|
||||
size = alignedw*alignedh +
|
||||
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
|
||||
size = ALIGN(size, 4096);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGE("unrecognized pixel format: %d", format);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ssize_t)size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
size = (bufferSize >= size)? bufferSize : size;
|
||||
|
||||
// All buffers marked as protected or for external
|
||||
// display need to go to overlay
|
||||
if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
||||
(usage & GRALLOC_USAGE_PROTECTED)) {
|
||||
bufferType = BUFFER_TYPE_VIDEO;
|
||||
}
|
||||
int err;
|
||||
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);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*pStride = alignedw;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpu_context_t::free_impl(private_handle_t const* hnd) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||
// 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);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
// XXX any additional cleanup.
|
||||
delete hnd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
|
||||
int usage, buffer_handle_t* pHandle, int* pStride)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
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)
|
||||
{
|
||||
if (private_handle_t::validate(handle) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
|
||||
gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
|
||||
return gpu->free_impl(hnd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int gpu_context_t::gralloc_close(struct hw_device_t *dev)
|
||||
{
|
||||
gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
|
||||
if (ctx) {
|
||||
/* TODO: keep a list of all buffer_handle_t created, and free them
|
||||
* all here.
|
||||
*/
|
||||
delete ctx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
81
libgralloc/gpu.h
Normal file
81
libgralloc/gpu.h
Normal 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
|
@ -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
113
libgralloc/gralloc.cpp
Normal 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;
|
||||
}
|
@ -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.
|
||||
@ -32,24 +32,31 @@
|
||||
|
||||
#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
|
||||
#include "overlayLib.h"
|
||||
#include "overlayLibUI.h"
|
||||
using namespace overlay;
|
||||
/*
|
||||
* BYPASS_OV_CHANNEL_OPEN - bypass channel is open
|
||||
* BYPASS_OV_CHANNEL_PENDING_CLOSE - disp_loop to close bypass channel
|
||||
* BYPASS_OV_CHANNEL_CLOSED - bypass channel is closed
|
||||
*/
|
||||
enum { BYPASS_OV_CHANNEL_OPEN,
|
||||
BYPASS_OV_CHANNEL_PENDING_CLOSE, BYPASS_OV_CHANNEL_CLOSED };
|
||||
#endif
|
||||
|
||||
enum {
|
||||
/* gralloc usage bit indicating the type
|
||||
/* gralloc usage bits indicating the type
|
||||
* of allocation that should be used */
|
||||
GRALLOC_USAGE_PRIVATE_ADSP_HEAP = GRALLOC_USAGE_PRIVATE_0,
|
||||
GRALLOC_USAGE_PRIVATE_EBI_HEAP = GRALLOC_USAGE_PRIVATE_1,
|
||||
GRALLOC_USAGE_PRIVATE_SMI_HEAP = GRALLOC_USAGE_PRIVATE_2,
|
||||
GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_3,
|
||||
/* 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 {
|
||||
GPU_COMPOSITION,
|
||||
C2D_COMPOSITION,
|
||||
MDP_COMPOSITION,
|
||||
CPU_COMPOSITION,
|
||||
};
|
||||
|
||||
/* numbers of max buffers for page flipping */
|
||||
@ -60,8 +67,14 @@ enum {
|
||||
#define NUM_DEF_FRAME_BUFFERS 2
|
||||
#define NO_SURFACEFLINGER_SWAPINTERVAL
|
||||
#define INTERLACE_MASK 0x80
|
||||
#define S3D_FORMAT_MASK 0xFF000
|
||||
#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
|
||||
#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
|
||||
#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
|
||||
{
|
||||
@ -172,6 +185,10 @@ enum {
|
||||
HAL_3D_OUT_MONOSCOPIC = 0x8000
|
||||
};
|
||||
|
||||
enum {
|
||||
BUFFER_TYPE_UI = 0,
|
||||
BUFFER_TYPE_VIDEO
|
||||
};
|
||||
/*****************************************************************************/
|
||||
|
||||
struct private_module_t;
|
||||
@ -198,57 +215,6 @@ struct avail_t {
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* Store for shared data and synchronization */
|
||||
struct ThreadShared {
|
||||
int w;
|
||||
int h;
|
||||
int format;
|
||||
buffer_handle_t buffer;
|
||||
bool isNewBuffer;
|
||||
bool isBufferPosted;
|
||||
bool isExitPending; //Feature close
|
||||
bool isHDMIExitPending; //Only HDMI close
|
||||
//New buffer arrival condition
|
||||
pthread_mutex_t newBufferMutex;
|
||||
pthread_cond_t newBufferCond;
|
||||
//Buffer posted to display condition, used instead of barrier
|
||||
pthread_mutex_t bufferPostedMutex;
|
||||
pthread_cond_t bufferPostedCond;
|
||||
|
||||
ThreadShared():w(0),h(0),format(0),buffer(0),isNewBuffer(false),
|
||||
isBufferPosted(false), isExitPending(false),
|
||||
isHDMIExitPending(false) {
|
||||
pthread_mutex_init(&newBufferMutex, NULL);
|
||||
pthread_mutex_init(&bufferPostedMutex, NULL);
|
||||
pthread_cond_init(&newBufferCond, NULL);
|
||||
pthread_cond_init(&bufferPostedCond, NULL);
|
||||
}
|
||||
|
||||
void set(int w, int h, int format, buffer_handle_t buffer) {
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->format = format;
|
||||
this->buffer = buffer;
|
||||
}
|
||||
|
||||
void get(int& w, int& h, int& format, buffer_handle_t& buffer) {
|
||||
w = this->w;
|
||||
h = this->h;
|
||||
format = this->format;
|
||||
buffer = this->buffer;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
w = h = format = 0;
|
||||
buffer = 0;
|
||||
isNewBuffer = isBufferPosted = isExitPending = \
|
||||
isHDMIExitPending = false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct private_module_t {
|
||||
gralloc_module_t base;
|
||||
|
||||
@ -267,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];
|
||||
@ -287,30 +253,11 @@ struct private_module_t {
|
||||
uint32_t currentOffset;
|
||||
bool enableHDMIOutput;
|
||||
bool exitHDMIUILoop;
|
||||
float actionsafeWidthRatio;
|
||||
float actionsafeHeightRatio;
|
||||
bool hdmiStateChanged;
|
||||
pthread_mutex_t overlayLock;
|
||||
pthread_cond_t overlayPost;
|
||||
OverlayOrigRes<OverlayUI::FB0>* pOrigResPanel;
|
||||
OverlayOrigRes<OverlayUI::FB1>* pOrigResTV;
|
||||
bool isOrigResStarted;
|
||||
ThreadShared ts;
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && defined(SF_BYPASS)
|
||||
/*
|
||||
* Comp. bypass specific variables
|
||||
* pobjOverlayUI - UI overlay channel for comp. bypass.
|
||||
* overlayui_lock - mutex lock for synchronization between
|
||||
* disp_loop and main thread to modify
|
||||
* bypassChannelState
|
||||
* bypassChannelState - Current Channel State
|
||||
* - OPEN - bypass channel is open
|
||||
* - PENDING_CLOSE - close channel pending
|
||||
* - CLOSED - bypass channel is closed
|
||||
*/
|
||||
OverlayUI* pobjOverlayUI;
|
||||
pthread_mutex_t overlayui_lock;
|
||||
int bypassChannelState;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -322,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,
|
||||
@ -346,7 +292,7 @@ struct private_handle_t {
|
||||
int flags;
|
||||
int size;
|
||||
int offset;
|
||||
int gpu_fd; // stored as an int, b/c we don't want it marshalled
|
||||
int bufferType;
|
||||
|
||||
// FIXME: the attributes below should be out-of-line
|
||||
int base;
|
||||
@ -354,15 +300,19 @@ struct private_handle_t {
|
||||
int writeOwner;
|
||||
int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care
|
||||
int pid;
|
||||
int format;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
#ifdef __cplusplus
|
||||
static const int sNumInts = 10;
|
||||
static const int sNumInts = 13;
|
||||
static const int sNumFds = 1;
|
||||
static const int sMagic = 'gmsm';
|
||||
|
||||
private_handle_t(int fd, int size, int flags) :
|
||||
fd(fd), magic(sMagic), flags(flags), size(size), offset(0), gpu_fd(-1),
|
||||
base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid())
|
||||
private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) :
|
||||
fd(fd), magic(sMagic), flags(flags), size(size), offset(0), bufferType(bufferType),
|
||||
base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()), format(format), width(width),
|
||||
height(height)
|
||||
{
|
||||
version = sizeof(native_handle);
|
||||
numInts = sNumInts;
|
||||
@ -380,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
249
libgralloc/ionalloc.cpp
Normal 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
71
libgralloc/ionalloc.h
Normal 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 */
|
||||
|
@ -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);
|
||||
@ -179,8 +190,9 @@ int terminateBuffer(gralloc_module_t const* module,
|
||||
|
||||
if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
|
||||
// this buffer was mapped, unmap it now
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM ||
|
||||
hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
|
||||
if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
|
||||
private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
|
||||
if (hnd->pid != getpid()) {
|
||||
// ... unless it's a "master" pmem buffer, that is a buffer
|
||||
// mapped in the process it's been allocated.
|
||||
@ -188,6 +200,7 @@ int terminateBuffer(gralloc_module_t const* module,
|
||||
gralloc_unmap(module, hnd);
|
||||
}
|
||||
} else {
|
||||
LOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", hnd->flags);
|
||||
gralloc_unmap(module, hnd);
|
||||
}
|
||||
}
|
||||
@ -213,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) {
|
||||
@ -223,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)));
|
||||
}
|
||||
}
|
||||
@ -235,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);
|
||||
|
||||
@ -272,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)
|
||||
@ -283,17 +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) {
|
||||
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;
|
||||
@ -318,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;
|
||||
}
|
||||
@ -334,158 +339,66 @@ 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*);
|
||||
|
||||
native_handle_t** handle = va_arg(args, native_handle_t**);
|
||||
int memoryFlags = va_arg(args, int);
|
||||
if (memoryFlags == GRALLOC_USAGE_PRIVATE_EBI_HEAP) {
|
||||
// validate that it's indeed a pmem buffer
|
||||
pmem_region region;
|
||||
if (ioctl(fd, PMEM_GET_SIZE, ®ion) < 0) {
|
||||
break;
|
||||
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, ®ion) < 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;
|
||||
|
||||
}
|
||||
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 = (memoryFlags == GRALLOC_USAGE_PRIVATE_EBI_HEAP) ?
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM |
|
||||
private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH:
|
||||
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;
|
||||
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;
|
||||
}
|
||||
case GRALLOC_MODULE_PERFORM_DECIDE_PUSH_BUFFER_HANDLING: {
|
||||
int format = va_arg(args, int);
|
||||
int width = va_arg(args, int);
|
||||
int height = va_arg(args, int);
|
||||
char *compositionUsed = va_arg(args, char*);
|
||||
int hasBlitEngine = va_arg(args, int);
|
||||
int *needConversion = va_arg(args, int*);
|
||||
int *useBufferDirectly = va_arg(args, int*);
|
||||
size_t *size = va_arg(args, size_t*);
|
||||
*size = calculateBufferSize(width, height, format);
|
||||
int conversion = 0;
|
||||
int direct = 0;
|
||||
res = decideBufferHandlingMechanism(format, compositionUsed, hasBlitEngine,
|
||||
needConversion, useBufferDirectly);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
int decideBufferHandlingMechanism(int format, const char *compositionUsed, int hasBlitEngine,
|
||||
int *needConversion, int *useBufferDirectly)
|
||||
{
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = FALSE;
|
||||
if(compositionUsed == NULL) {
|
||||
LOGE("null pointer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(format == HAL_PIXEL_FORMAT_RGB_565) {
|
||||
// Software video renderer gives the output in RGB565 format.
|
||||
// This can be handled by all compositors
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = TRUE;
|
||||
} else if(strncmp(compositionUsed, "cpu", 3) == 0){
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = FALSE;
|
||||
} else if(strncmp(compositionUsed, "gpu", 3) == 0) {
|
||||
if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED ||
|
||||
format == HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO ||
|
||||
format == HAL_PIXEL_FORMAT_YV12) {
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = TRUE;
|
||||
} else if(hasBlitEngine) {
|
||||
*needConversion = TRUE;
|
||||
*useBufferDirectly = FALSE;
|
||||
}
|
||||
} else if ((strncmp(compositionUsed, "mdp", 3) == 0) ||
|
||||
(strncmp(compositionUsed, "c2d", 3) == 0)){
|
||||
if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP ||
|
||||
format == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
|
||||
format == HAL_PIXEL_FORMAT_YV12) {
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = TRUE;
|
||||
} else if((strncmp(compositionUsed, "c2d", 3) == 0) &&
|
||||
format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
|
||||
*needConversion = FALSE;
|
||||
*useBufferDirectly = TRUE;
|
||||
} else if(hasBlitEngine) {
|
||||
*needConversion = TRUE;
|
||||
*useBufferDirectly = FALSE;
|
||||
}
|
||||
} else {
|
||||
LOGE("Invalid composition type %s", compositionUsed);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t calculateBufferSize(int width, int height, int format)
|
||||
{
|
||||
if(!width || !height)
|
||||
return 0;
|
||||
|
||||
size_t size = 0;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
|
||||
int aligned_height = (height + 31) & ~31;
|
||||
int pitch = (width + 127) & ~127;
|
||||
size = pitch * aligned_height;
|
||||
size = (size + 8191) & ~8191;
|
||||
int secondPlaneOffset = size;
|
||||
|
||||
aligned_height = ((height >> 1) + 31) & ~31;
|
||||
size += pitch * aligned_height;
|
||||
size = (size + 8191) & ~8191;
|
||||
break;
|
||||
}
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: {
|
||||
int aligned_height = (height + 31) & ~31;
|
||||
int pitch = (width + 31) & ~31;
|
||||
size = pitch * aligned_height;
|
||||
size = (size + 4095) & ~4095;
|
||||
int secondPlaneOffset = size;
|
||||
|
||||
pitch = 2 * (((width >> 1) + 31) & ~31);
|
||||
aligned_height = ((height >> 1) + 31) & ~31;
|
||||
size += pitch * aligned_height;
|
||||
size = (size + 4095) & ~4095;
|
||||
break;
|
||||
}
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YV12: {
|
||||
/* Camera and video YUV 420 semi-planar buffers are allocated with
|
||||
size equal to w * h * 1.5 */
|
||||
int aligned_width = (width + 15) & ~15;
|
||||
int aligned_chroma_width = ((width/2) + 15) & ~15;
|
||||
size = (aligned_width * height) + ((aligned_chroma_width * height/2) *2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
85
libgralloc/memalloc.h
Normal file
85
libgralloc/memalloc.h
Normal 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
|
@ -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;
|
@ -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;
|
@ -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),
|
||||
@ -143,7 +144,7 @@ int PmemUserspaceAllocator::init_pmem_area()
|
||||
|
||||
|
||||
int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
|
||||
void** pBase, int* pOffset, int* pFd)
|
||||
void** pBase, int* pOffset, int* pFd, int format)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
int err = init_pmem_area();
|
||||
@ -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;
|
||||
@ -232,9 +234,8 @@ PmemUserspaceAllocator::Deps::~Deps()
|
||||
END_FUNC;
|
||||
}
|
||||
|
||||
PmemKernelAllocator::PmemKernelAllocator(Deps& deps, const char* pmemdev):
|
||||
deps(deps),
|
||||
pmemdev(pmemdev)
|
||||
PmemKernelAllocator::PmemKernelAllocator(Deps& deps):
|
||||
deps(deps)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
END_FUNC;
|
||||
@ -267,7 +268,7 @@ static unsigned clp2(unsigned x) {
|
||||
|
||||
|
||||
int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
|
||||
void** pBase,int* pOffset, int* pFd)
|
||||
void** pBase,int* pOffset, int* pFd, int format)
|
||||
{
|
||||
BEGIN_FUNC;
|
||||
|
||||
@ -275,28 +276,55 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
|
||||
*pOffset = 0;
|
||||
*pFd = -1;
|
||||
|
||||
int err;
|
||||
int err, offset = 0;
|
||||
int openFlags = get_open_flags(usage);
|
||||
int fd = deps.open(pmemdev, openFlags, 0);
|
||||
const char *device;
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
|
||||
device = DEVICE_PMEM_ADSP;
|
||||
} else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) {
|
||||
device = DEVICE_PMEM_SMIPOOL;
|
||||
} else if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
|
||||
(usage & GRALLOC_USAGE_PROTECTED)) {
|
||||
int tempFd = deps.open(DEVICE_PMEM_SMIPOOL, openFlags, 0);
|
||||
if (tempFd < 0) {
|
||||
device = DEVICE_PMEM_ADSP;
|
||||
} else {
|
||||
close(tempFd);
|
||||
device = DEVICE_PMEM_SMIPOOL;
|
||||
}
|
||||
} else {
|
||||
LOGE("Invalid device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int fd = deps.open(device, openFlags, 0);
|
||||
if (fd < 0) {
|
||||
err = -deps.getErrno();
|
||||
END_FUNC;
|
||||
LOGE("Error opening %s", device);
|
||||
return err;
|
||||
}
|
||||
|
||||
// The size should already be page aligned, now round it up to a power of 2.
|
||||
size = clp2(size);
|
||||
//size = clp2(size);
|
||||
|
||||
if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
|
||||
// Tile format buffers need physical alignment to 8K
|
||||
err = deps.alignPmem(fd, size, 8192);
|
||||
if (err < 0) {
|
||||
LOGE("alignPmem failed");
|
||||
}
|
||||
}
|
||||
|
||||
void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
LOGE("%s: failed to map pmem fd: %s", pmemdev,
|
||||
LOGE("%s: failed to map pmem fd: %s", device,
|
||||
strerror(deps.getErrno()));
|
||||
err = -deps.getErrno();
|
||||
deps.close(fd);
|
||||
END_FUNC;
|
||||
return err;
|
||||
}
|
||||
|
||||
memset(base, 0, size);
|
||||
|
||||
*pBase = base;
|
||||
@ -308,19 +336,22 @@ 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);
|
||||
//size = clp2(size);
|
||||
|
||||
int err = deps.munmap(base, size);
|
||||
if (err < 0) {
|
||||
err = deps.getErrno();
|
||||
LOGW("%s: error unmapping pmem fd: %s", pmemdev, strerror(err));
|
||||
LOGW("error unmapping pmem fd: %s", strerror(err));
|
||||
return -err;
|
||||
}
|
||||
|
||||
END_FUNC;
|
||||
return 0;
|
||||
}
|
@ -36,7 +36,7 @@ class PmemAllocator {
|
||||
virtual void* get_base_address() = 0;
|
||||
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd) = 0;
|
||||
int* pOffset, int* pFd, int format) = 0;
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0;
|
||||
};
|
||||
|
||||
@ -90,7 +90,7 @@ class PmemUserspaceAllocator: public PmemAllocator {
|
||||
virtual int init_pmem_area_locked();
|
||||
virtual int init_pmem_area();
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd);
|
||||
int* pOffset, int* pFd, int format);
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
|
||||
|
||||
#ifndef ANDROID_OS
|
||||
@ -140,23 +140,22 @@ class PmemKernelAllocator: public PmemAllocator {
|
||||
virtual int munmap(void* start, size_t length) = 0;
|
||||
virtual int open(const char* pathname, int flags, int mode) = 0;
|
||||
virtual int close(int fd) = 0;
|
||||
virtual int alignPmem(int fd, size_t size, int align) = 0;
|
||||
};
|
||||
|
||||
PmemKernelAllocator(Deps& deps, const char* pmemdev);
|
||||
PmemKernelAllocator(Deps& deps);
|
||||
virtual ~PmemKernelAllocator();
|
||||
|
||||
// Only valid after init_pmem_area() has completed successfully.
|
||||
virtual void* get_base_address();
|
||||
|
||||
virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
|
||||
int* pOffset, int* pFd);
|
||||
int* pOffset, int* pFd, int format);
|
||||
virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
|
||||
|
||||
private:
|
||||
|
||||
Deps& deps;
|
||||
|
||||
const char* pmemdev;
|
||||
};
|
||||
|
||||
#endif // GRALLOC_QSD8K_PMEMALLOC_H
|
28
libhwcomposer/Android.mk
Normal file
28
libhwcomposer/Android.mk
Normal file
@ -0,0 +1,28 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
hwcomposer.cpp
|
||||
|
||||
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\"
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/liboverlay
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||
endif
|
||||
ifeq ($(TARGET_HAVE_BYPASS),true)
|
||||
LOCAL_CFLAGS += -DCOMPOSITION_BYPASS
|
||||
endif
|
||||
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
|
||||
LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1162
libhwcomposer/hwcomposer.cpp
Normal file
1162
libhwcomposer/hwcomposer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
53
liboverlay/Android.mk
Normal file
53
liboverlay/Android.mk
Normal file
@ -0,0 +1,53 @@
|
||||
# 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
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_SRC_FILES := \
|
||||
overlayLib.cpp \
|
||||
overlayLibUI.cpp \
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
|
||||
|
||||
ifeq ($(TARGET_USES_ION),true)
|
||||
LOCAL_CFLAGS += -DUSE_ION
|
||||
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
|
||||
LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
|
||||
endif
|
||||
LOCAL_MODULE := liboverlay
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog liboverlay libcutils
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_SRC_FILES := overlay.cpp
|
||||
LOCAL_MODULE := overlay.default
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1197
liboverlay/overlay.cpp
Normal file
1197
liboverlay/overlay.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1799
liboverlay/overlayLib.cpp
Normal file
1799
liboverlay/overlayLib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
306
liboverlay/overlayLib.h
Normal file
306
liboverlay/overlayLib.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (c) 2010-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 INCLUDE_OVERLAY_LIB
|
||||
#define INCLUDE_OVERLAY_LIB
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/atomic.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/msm_mdp.h>
|
||||
#include <linux/msm_rotator.h>
|
||||
#include <linux/android_pmem.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <hardware/overlay.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <alloc_controller.h>
|
||||
#include <memalloc.h>
|
||||
|
||||
#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
|
||||
#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
|
||||
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
#define VG0_PIPE 0
|
||||
#define VG1_PIPE 1
|
||||
#define NUM_CHANNELS 2
|
||||
#define FRAMEBUFFER_0 0
|
||||
#define FRAMEBUFFER_1 1
|
||||
|
||||
enum {
|
||||
HDMI_OFF,
|
||||
HDMI_ON
|
||||
};
|
||||
|
||||
enum {
|
||||
OVERLAY_CHANNEL_DOWN,
|
||||
OVERLAY_CHANNEL_UP
|
||||
};
|
||||
|
||||
enum {
|
||||
NEW_REQUEST,
|
||||
UPDATE_REQUEST
|
||||
};
|
||||
/* ------------------------------- 3D defines ---------------------------------------*/
|
||||
// The compound format passed to the overlay is
|
||||
// ABCCC where A is the input 3D format,
|
||||
// B is the output 3D format
|
||||
// CCC is the color format e.g YCbCr420SP YCrCb420SP etc.
|
||||
#define FORMAT_3D(x) (x & 0xFF000)
|
||||
#define COLOR_FORMAT(x) (x & 0xFFF)
|
||||
// in the final 3D format, the MSB 2Bytes are the input format and the
|
||||
// LSB 2bytes are the output format. Shift the output byte 12 bits.
|
||||
#define SHIFT_OUTPUT_3D 12
|
||||
#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> SHIFT_OUTPUT_3D)
|
||||
#define FORMAT_3D_INPUT(x) (x & 0xF0000)
|
||||
#define INPUT_MASK_3D 0xFFFF0000
|
||||
#define OUTPUT_MASK_3D 0x0000FFFF
|
||||
#define SHIFT_3D 16
|
||||
// The output format is the 2MSB bytes. Shift the format by 12 to reflect this
|
||||
#define HAL_3D_OUT_SIDE_BY_SIDE_MASK (HAL_3D_OUT_SIDE_BY_SIDE >> SHIFT_OUTPUT_3D)
|
||||
#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> SHIFT_OUTPUT_3D)
|
||||
#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> SHIFT_OUTPUT_3D)
|
||||
#define HAL_3D_OUT_MONOSCOPIC_MASK (HAL_3D_OUT_MONOSCOPIC >> SHIFT_OUTPUT_3D)
|
||||
|
||||
// 3D panel barrier orientation
|
||||
#define BARRIER_LANDSCAPE 1
|
||||
#define BARRIER_PORTRAIT 2
|
||||
|
||||
#ifdef HDMI_AS_PRIMARY
|
||||
#define FORMAT_3D_FILE "/sys/class/graphics/fb0/format_3d"
|
||||
#define EDID_3D_INFO_FILE "/sys/class/graphics/fb0/3d_present"
|
||||
#else
|
||||
#define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d"
|
||||
#define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present"
|
||||
#endif
|
||||
#define BARRIER_FILE "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier"
|
||||
/* -------------------------- end 3D defines ----------------------------------------*/
|
||||
|
||||
// Struct to hold the buffer info: geometry and size
|
||||
struct overlay_buffer_info {
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
int size;
|
||||
};
|
||||
|
||||
namespace overlay {
|
||||
|
||||
enum {
|
||||
OV_UI_MIRROR_TV = 0,
|
||||
OV_2D_VIDEO_ON_PANEL,
|
||||
OV_2D_VIDEO_ON_TV,
|
||||
OV_3D_VIDEO_2D_PANEL,
|
||||
OV_3D_VIDEO_2D_TV,
|
||||
OV_3D_VIDEO_3D_PANEL,
|
||||
OV_3D_VIDEO_3D_TV
|
||||
};
|
||||
bool isHDMIConnected();
|
||||
bool is3DTV();
|
||||
bool isPanel3D();
|
||||
bool usePanel3D();
|
||||
bool send3DInfoPacket(unsigned int format3D);
|
||||
bool enableBarrier(unsigned int orientation);
|
||||
unsigned int getOverlayConfig (unsigned int format3D, bool poll = true,
|
||||
bool isHDMI = false);
|
||||
int getColorFormat(int format);
|
||||
int get_mdp_format(int format);
|
||||
int get_size(int format, int w, int h);
|
||||
int get_rot_output_format(int format);
|
||||
int get_mdp_orientation(int value);
|
||||
void normalize_crop(uint32_t& xy, uint32_t& wh);
|
||||
|
||||
/* Print values being sent to driver in case of ioctl failures
|
||||
These logs are enabled only if DEBUG_OVERLAY is true */
|
||||
void dump(msm_rotator_img_info& mRotInfo);
|
||||
void dump(mdp_overlay& mOvInfo);
|
||||
const char* getFormatString(int format);
|
||||
|
||||
const int max_num_buffers = 3;
|
||||
typedef struct mdp_rect overlay_rect;
|
||||
|
||||
class OverlayControlChannel {
|
||||
|
||||
bool mNoRot;
|
||||
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
int mFBbpp;
|
||||
int mFBystride;
|
||||
int mFormat;
|
||||
int mFD;
|
||||
int mRotFD;
|
||||
int mSize;
|
||||
int mOrientation;
|
||||
unsigned int mFormat3D;
|
||||
bool mUIChannel;
|
||||
mdp_overlay mOVInfo;
|
||||
msm_rotator_img_info mRotInfo;
|
||||
msmfb_overlay_3d m3DOVInfo;
|
||||
bool mIsChannelUpdated;
|
||||
bool openDevices(int fbnum = -1);
|
||||
bool setOverlayInformation(const overlay_buffer_info& info,
|
||||
int flags, int orientation, int zorder = 0, bool ignoreFB = false,
|
||||
int requestType = NEW_REQUEST);
|
||||
bool startOVRotatorSessions(const overlay_buffer_info& info, int orientation, int requestType);
|
||||
void swapOVRotWidthHeight();
|
||||
|
||||
public:
|
||||
OverlayControlChannel();
|
||||
~OverlayControlChannel();
|
||||
bool startControlChannel(int w, int h, int format,
|
||||
int fbnum, bool norot = false,
|
||||
bool uichannel = false,
|
||||
unsigned int format3D = 0, int zorder = 0,
|
||||
bool ignoreFB = false);
|
||||
bool closeControlChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, int value, bool fetch = true);
|
||||
void setSize (int size) { mSize = size; }
|
||||
bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
|
||||
bool getOvSessionID(int& sessionID) const;
|
||||
bool getRotSessionID(int& sessionID) const;
|
||||
bool getSize(int& size) const;
|
||||
bool isChannelUP() const { return (mFD > 0); }
|
||||
int getFBWidth() const { return mFBWidth; }
|
||||
int getFBHeight() const { return mFBHeight; }
|
||||
int getFormat3D() const { return mFormat3D; }
|
||||
bool getOrientation(int& orientation) const;
|
||||
bool updateWaitForVsyncFlags(bool waitForVsync);
|
||||
bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
|
||||
bool getPositionS3D(int channel, int format, overlay_rect *rect);
|
||||
bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
|
||||
bool getFormat() const { return mFormat; }
|
||||
bool useVirtualFB ();
|
||||
int getOverlayFlags() const { return mOVInfo.flags; }
|
||||
};
|
||||
|
||||
class OverlayDataChannel {
|
||||
|
||||
bool mNoRot;
|
||||
int mFD;
|
||||
int mRotFD;
|
||||
int mPmemFD;
|
||||
void* mPmemAddr;
|
||||
uint32_t mPmemOffset;
|
||||
uint32_t mNewPmemOffset;
|
||||
msmfb_overlay_data mOvData;
|
||||
msmfb_overlay_data mOvDataRot;
|
||||
msm_rotator_data_info mRotData;
|
||||
int mRotOffset[max_num_buffers];
|
||||
int mCurrentItem;
|
||||
int mNumBuffers;
|
||||
int mUpdateDataChannel;
|
||||
android::sp<gralloc::IAllocController> mAlloc;
|
||||
int mBufferType;
|
||||
|
||||
bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2);
|
||||
bool mapRotatorMemory(int num_buffers, bool uiChannel, int requestType);
|
||||
bool queue(uint32_t offset);
|
||||
|
||||
public:
|
||||
OverlayDataChannel();
|
||||
~OverlayDataChannel();
|
||||
bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel,
|
||||
int fbnum, bool norot = false,
|
||||
bool uichannel = false, int num_buffers = 2);
|
||||
bool startDataChannel(int ovid, int rotid, int size,
|
||||
int fbnum, bool norot = false, bool uichannel = false,
|
||||
int num_buffers = 2);
|
||||
bool closeDataChannel();
|
||||
bool setFd(int fd);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
bool getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect);
|
||||
bool isChannelUP() const { return (mFD > 0); }
|
||||
bool updateDataChannel(int updateStatus, int size);
|
||||
};
|
||||
|
||||
/*
|
||||
* Overlay class for single thread application
|
||||
* A multiple thread/process application need to use Overlay HAL
|
||||
*/
|
||||
class Overlay {
|
||||
|
||||
bool mChannelUP;
|
||||
bool mHDMIConnected;
|
||||
unsigned int mS3DFormat;
|
||||
//Actual cropped source width and height of overlay
|
||||
int mCroppedSrcWidth;
|
||||
int mCroppedSrcHeight;
|
||||
overlay_buffer_info mOVBufferInfo;
|
||||
int mState;
|
||||
OverlayControlChannel objOvCtrlChannel[2];
|
||||
OverlayDataChannel objOvDataChannel[2];
|
||||
|
||||
public:
|
||||
Overlay();
|
||||
~Overlay();
|
||||
|
||||
static bool sHDMIAsPrimary;
|
||||
bool startChannel(const overlay_buffer_info& info, int fbnum, bool norot = false,
|
||||
bool uichannel = false, unsigned int format3D = 0,
|
||||
int channel = 0, bool ignoreFB = false,
|
||||
int num_buffers = 2);
|
||||
bool closeChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, int value);
|
||||
bool setOrientation(int value, int channel = 0);
|
||||
bool setFd(int fd, int channel = 0);
|
||||
bool queueBuffer(uint32_t offset, int channel = 0);
|
||||
bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel = 0);
|
||||
bool isChannelUP() const { return mChannelUP; }
|
||||
int getFBWidth(int channel = 0) const;
|
||||
int getFBHeight(int channel = 0) const;
|
||||
bool getOrientation(int& orientation, int channel = 0) const;
|
||||
bool queueBuffer(buffer_handle_t buffer);
|
||||
bool setSource(const overlay_buffer_info& info, int orientation, bool hdmiConnected,
|
||||
bool ignoreFB = false, int numBuffers = 2);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
|
||||
void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; }
|
||||
int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); }
|
||||
|
||||
private:
|
||||
bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0);
|
||||
bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel);
|
||||
bool queueBuffer(int fd, uint32_t offset, int channel);
|
||||
bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
|
||||
int getS3DFormat(int format);
|
||||
};
|
||||
|
||||
struct overlay_shared_data {
|
||||
volatile bool isControlSetup;
|
||||
unsigned int state;
|
||||
int rotid[2];
|
||||
int ovid[2];
|
||||
};
|
||||
};
|
||||
#endif
|
524
liboverlay/overlayLibUI.cpp
Normal file
524
liboverlay/overlayLibUI.cpp
Normal file
@ -0,0 +1,524 @@
|
||||
/*
|
||||
* 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 "overlayLibUI.h"
|
||||
#include "gralloc_priv.h"
|
||||
#define LOG_TAG "OverlayUI"
|
||||
|
||||
using android::sp;
|
||||
using gralloc::IMemAlloc;
|
||||
using gralloc::alloc_data;
|
||||
|
||||
namespace {
|
||||
/* helper functions */
|
||||
bool checkOVState(int w, int h, int format, int orientation,
|
||||
int zorder, const mdp_overlay& ov) {
|
||||
switch(orientation) {
|
||||
case OVERLAY_TRANSFORM_ROT_90:
|
||||
case OVERLAY_TRANSFORM_ROT_270: {
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int srcw = (w + 31) & ~31;
|
||||
int srch = (h + 31) & ~31;
|
||||
bool displayAttrsCheck = ((srcw == ov.src.width) && (srch == ov.src.height) &&
|
||||
(format == ov.src.format));
|
||||
bool zOrderCheck = (ov.z_order == zorder);
|
||||
|
||||
if (displayAttrsCheck && zorder == overlay::NO_INIT)
|
||||
return true;
|
||||
|
||||
if (displayAttrsCheck && zorder != overlay::NO_INIT
|
||||
&& ov.z_order == zorder)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void swapOVRotWidthHeight(msm_rotator_img_info& rotInfo,
|
||||
mdp_overlay& ovInfo) {
|
||||
int srcWidth = ovInfo.src.width;
|
||||
ovInfo.src.width = ovInfo.src.height;
|
||||
ovInfo.src.height = srcWidth;
|
||||
|
||||
int srcRectWidth = ovInfo.src_rect.w;
|
||||
ovInfo.src_rect.w = ovInfo.src_rect.h;
|
||||
ovInfo.src_rect.h = srcRectWidth;
|
||||
|
||||
int dstWidth = rotInfo.dst.width;
|
||||
rotInfo.dst.width = rotInfo.dst.height;
|
||||
rotInfo.dst.height = dstWidth;
|
||||
}
|
||||
|
||||
void setupOvRotInfo(int w, int h, int format, int orientation,
|
||||
mdp_overlay& ovInfo, msm_rotator_img_info& rotInfo) {
|
||||
memset(&ovInfo, 0, sizeof(ovInfo));
|
||||
memset(&rotInfo, 0, sizeof(rotInfo));
|
||||
ovInfo.id = MSMFB_NEW_REQUEST;
|
||||
int srcw = (w + 31) & ~31;
|
||||
int srch = (h + 31) & ~31;
|
||||
ovInfo.src.width = srcw;
|
||||
ovInfo.src.height = srch;
|
||||
ovInfo.src.format = format;
|
||||
ovInfo.src_rect.w = w;
|
||||
ovInfo.src_rect.h = h;
|
||||
ovInfo.alpha = 0xff;
|
||||
ovInfo.transp_mask = 0xffffffff;
|
||||
rotInfo.src.format = format;
|
||||
rotInfo.dst.format = format;
|
||||
rotInfo.src.width = srcw;
|
||||
rotInfo.src.height = srch;
|
||||
rotInfo.src_rect.w = srcw;
|
||||
rotInfo.src_rect.h = srch;
|
||||
rotInfo.dst.width = srcw;
|
||||
rotInfo.dst.height = srch;
|
||||
|
||||
int rot = orientation;
|
||||
switch(rot) {
|
||||
case 0:
|
||||
case HAL_TRANSFORM_FLIP_H:
|
||||
case HAL_TRANSFORM_FLIP_V:
|
||||
rot = 0;
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
|
||||
case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): {
|
||||
int tmp = ovInfo.src_rect.x;
|
||||
ovInfo.src_rect.x = ovInfo.src.height -
|
||||
(ovInfo.src_rect.y + ovInfo.src_rect.h);
|
||||
ovInfo.src_rect.y = tmp;
|
||||
swapOVRotWidthHeight(rotInfo, ovInfo);
|
||||
rot = HAL_TRANSFORM_ROT_90;
|
||||
break;
|
||||
}
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_270: {
|
||||
int tmp = ovInfo.src_rect.y;
|
||||
ovInfo.src_rect.y = ovInfo.src.width -
|
||||
(ovInfo.src_rect.x + ovInfo.src_rect.w);
|
||||
ovInfo.src_rect.x = tmp;
|
||||
swapOVRotWidthHeight(rotInfo, ovInfo);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int mdp_rotation = overlay::get_mdp_orientation(rot);
|
||||
if (mdp_rotation < 0)
|
||||
mdp_rotation = 0;
|
||||
ovInfo.user_data[0] = mdp_rotation;
|
||||
rotInfo.rotations = ovInfo.user_data[0];
|
||||
if (mdp_rotation)
|
||||
rotInfo.enable = 1;
|
||||
ovInfo.dst_rect.w = ovInfo.src_rect.w;
|
||||
ovInfo.dst_rect.h = ovInfo.src_rect.h;
|
||||
}
|
||||
|
||||
bool isRGBType(int format) {
|
||||
bool ret = false;
|
||||
switch(format) {
|
||||
case MDP_RGBA_8888:
|
||||
case MDP_BGRA_8888:
|
||||
case MDP_RGBX_8888:
|
||||
case MDP_RGB_565:
|
||||
ret = true;
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getRGBBpp(int format) {
|
||||
int ret = -1;
|
||||
switch(format) {
|
||||
case MDP_RGBA_8888:
|
||||
case MDP_BGRA_8888:
|
||||
case MDP_RGBX_8888:
|
||||
ret = 4;
|
||||
break;
|
||||
case MDP_RGB_565:
|
||||
ret = 2;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool turnOFFVSync() {
|
||||
static int swapIntervalPropVal = -1;
|
||||
if (swapIntervalPropVal == -1) {
|
||||
char pval[PROPERTY_VALUE_MAX];
|
||||
property_get("debug.gr.swapinterval", pval, "1");
|
||||
swapIntervalPropVal = atoi(pval);
|
||||
}
|
||||
return (swapIntervalPropVal == 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace overlay {
|
||||
|
||||
status_t Display::openDisplay(int fbnum) {
|
||||
if (mFD != NO_INIT)
|
||||
return ALREADY_EXISTS;
|
||||
|
||||
status_t ret = NO_INIT;
|
||||
char const * const device_template =
|
||||
"/dev/graphics/fb%u";
|
||||
char dev_name[64];
|
||||
snprintf(dev_name, 64, device_template, fbnum);
|
||||
|
||||
mFD = open(dev_name, O_RDWR, 0);
|
||||
if (mFD < 0) {
|
||||
LOGE("Failed to open FB %d", fbnum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fb_var_screeninfo vinfo;
|
||||
if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo)) {
|
||||
LOGE("FBIOGET_VSCREENINFO on failed on FB %d", fbnum);
|
||||
close(mFD);
|
||||
mFD = NO_INIT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mFBWidth = vinfo.xres;
|
||||
mFBHeight = vinfo.yres;
|
||||
mFBBpp = vinfo.bits_per_pixel;
|
||||
ret = NO_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OVHelper::startOVSession(mdp_overlay& ovInfo, int fbnum) {
|
||||
status_t ret = NO_INIT;
|
||||
|
||||
if (mSessionID == NO_INIT) {
|
||||
ret = mobjDisplay.openDisplay(fbnum);
|
||||
if (ret != NO_ERROR)
|
||||
return ret;
|
||||
|
||||
if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
|
||||
LOGE("OVerlay set failed..");
|
||||
mobjDisplay.closeDisplay();
|
||||
ret = BAD_VALUE;
|
||||
}
|
||||
else {
|
||||
mSessionID = ovInfo.id;
|
||||
mOVInfo = ovInfo;
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = ALREADY_EXISTS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OVHelper::queueBuffer(msmfb_overlay_data ovData) {
|
||||
if (mSessionID == NO_INIT)
|
||||
return NO_INIT;
|
||||
|
||||
ovData.id = mSessionID;
|
||||
if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData))
|
||||
return BAD_VALUE;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OVHelper::closeOVSession() {
|
||||
if (mSessionID != NO_INIT) {
|
||||
ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID);
|
||||
mobjDisplay.closeDisplay();
|
||||
}
|
||||
|
||||
mSessionID = NO_INIT;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OVHelper::setPosition(int x, int y, int w, int h) {
|
||||
status_t ret = BAD_VALUE;
|
||||
if (mSessionID != NO_INIT) {
|
||||
int fd = mobjDisplay.getFD();
|
||||
if (x < 0 || y < 0 || ((x + w) > getFBWidth())) {
|
||||
LOGE("set position failed, invalid argument");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mSessionID;
|
||||
if (!ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
|
||||
if (x != ov.dst_rect.x || y != ov.dst_rect.y ||
|
||||
w != ov.dst_rect.w || h != ov.dst_rect.h) {
|
||||
ov.dst_rect.x = x;
|
||||
ov.dst_rect.y = y;
|
||||
ov.dst_rect.w = w;
|
||||
ov.dst_rect.h = h;
|
||||
if (ioctl(fd, MSMFB_OVERLAY_SET, &ov)) {
|
||||
LOGE("set position failed");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
mOVInfo = ov;
|
||||
return NO_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
status_t OVHelper::getOVInfo(mdp_overlay& ovInfo) {
|
||||
if (mSessionID == NO_INIT)
|
||||
return NO_INIT;
|
||||
ovInfo = mOVInfo;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
|
||||
int size, int numBuffers) {
|
||||
status_t ret = ALREADY_EXISTS;
|
||||
if (mSessionID == NO_INIT && mFD == NO_INIT) {
|
||||
mNumBuffers = numBuffers;
|
||||
mFD = open("/dev/msm_rotator", O_RDWR, 0);
|
||||
if (mFD < 0) {
|
||||
LOGE("Couldnt open rotator device");
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
if (int check = ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
|
||||
close(mFD);
|
||||
mFD = NO_INIT;
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
#ifdef USE_ION
|
||||
alloc_data data;
|
||||
data.base = 0;
|
||||
data.fd = -1;
|
||||
data.offset = 0;
|
||||
data.size = mSize * mNumBuffers;
|
||||
data.align = getpagesize();
|
||||
data.uncached = true;
|
||||
|
||||
int err = mAlloc->allocate(data, GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
|
||||
GRALLOC_USAGE_PRIVATE_SMI_HEAP, 0);
|
||||
|
||||
if(err) {
|
||||
LOGE("Cant allocate from ION");
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
mPmemFD = data.fd;
|
||||
mPmemAddr = data.base;
|
||||
mBufferType = data.allocType;
|
||||
#else
|
||||
mSessionID = rotInfo.session_id;
|
||||
mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC);
|
||||
if (mPmemFD < 0) {
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
mSize = size;
|
||||
mPmemAddr = (void *) mmap(NULL, mSize* mNumBuffers, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, mPmemFD, 0);
|
||||
if (mPmemAddr == MAP_FAILED) {
|
||||
closeRotSession();
|
||||
return NO_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
mCurrentItem = 0;
|
||||
for (int i = 0; i < mNumBuffers; i++)
|
||||
mRotOffset[i] = i * mSize;
|
||||
ret = NO_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t Rotator::closeRotSession() {
|
||||
if (mSessionID != NO_INIT && mFD != NO_INIT) {
|
||||
ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID);
|
||||
close(mFD);
|
||||
#ifdef USE_ION
|
||||
sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
|
||||
memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
|
||||
#else
|
||||
munmap(mPmemAddr, mSize * mNumBuffers);
|
||||
close(mPmemFD);
|
||||
#endif
|
||||
close(mPmemFD);
|
||||
}
|
||||
|
||||
mFD = NO_INIT;
|
||||
mSessionID = NO_INIT;
|
||||
mPmemFD = NO_INIT;
|
||||
mPmemAddr = MAP_FAILED;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t Rotator::rotateBuffer(msm_rotator_data_info& rotData) {
|
||||
status_t ret = NO_INIT;
|
||||
if (mSessionID != NO_INIT) {
|
||||
rotData.dst.memory_id = mPmemFD;
|
||||
rotData.dst.offset = mRotOffset[mCurrentItem];
|
||||
rotData.session_id = mSessionID;
|
||||
mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
|
||||
if (ioctl(mFD, MSM_ROTATOR_IOCTL_ROTATE, &rotData)) {
|
||||
LOGE("Rotator failed to rotate");
|
||||
return BAD_VALUE;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OverlayUI::closeChannel() {
|
||||
mobjOVHelper.closeOVSession();
|
||||
mobjRotator.closeRotSession();
|
||||
mChannelState = CLOSED;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t OverlayUI::setSource(const overlay_buffer_info& info, int orientation,
|
||||
bool useVGPipe, bool ignoreFB,
|
||||
int fbnum, int zorder) {
|
||||
status_t ret = NO_INIT;
|
||||
|
||||
int format3D = FORMAT_3D(info.format);
|
||||
int colorFormat = COLOR_FORMAT(info.format);
|
||||
int format = get_mdp_format(colorFormat);
|
||||
|
||||
if (format3D || !isRGBType(format))
|
||||
return ret;
|
||||
|
||||
if (mChannelState == PENDING_CLOSE)
|
||||
closeChannel();
|
||||
|
||||
if (mChannelState == UP) {
|
||||
mdp_overlay ov;
|
||||
if (mobjOVHelper.getOVInfo(ov) == NO_ERROR) {
|
||||
if (mOrientation == orientation &&
|
||||
mFBNum == fbnum &&
|
||||
checkOVState(info.width, info.height, format, orientation, zorder, ov))
|
||||
return NO_ERROR;
|
||||
else
|
||||
mChannelState = PENDING_CLOSE;
|
||||
}
|
||||
else
|
||||
mChannelState = PENDING_CLOSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mOrientation = orientation;
|
||||
mdp_overlay ovInfo;
|
||||
msm_rotator_img_info rotInfo;
|
||||
setupOvRotInfo(info.width, info.height, format, orientation, ovInfo, rotInfo);
|
||||
|
||||
int flags = 0;
|
||||
if (ignoreFB)
|
||||
ovInfo.is_fg = 1;
|
||||
else
|
||||
flags |= MDP_OV_PLAY_NOWAIT;
|
||||
|
||||
if (turnOFFVSync())
|
||||
flags |= MDP_OV_PLAY_NOWAIT;
|
||||
|
||||
if (useVGPipe ||
|
||||
(fbnum == FB0 && getRGBBpp(format) != mobjOVHelper.getFBBpp()))
|
||||
flags |= MDP_OV_PIPE_SHARE;
|
||||
|
||||
ovInfo.flags = flags;
|
||||
if (zorder != NO_INIT)
|
||||
ovInfo.z_order = zorder;
|
||||
|
||||
ret = startChannel(fbnum, ovInfo, rotInfo, info.size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OverlayUI::startChannel(int fbnum, mdp_overlay& ovInfo,
|
||||
msm_rotator_img_info& rotInfo, int size) {
|
||||
status_t ret = BAD_VALUE;
|
||||
if (mChannelState == UP)
|
||||
return ret;
|
||||
|
||||
ret = mobjOVHelper.startOVSession(ovInfo, fbnum);
|
||||
if (ret == NO_ERROR && mOrientation) {
|
||||
ret = mobjRotator.startRotSession(rotInfo, size);
|
||||
}
|
||||
|
||||
if (ret == NO_ERROR) {
|
||||
mChannelState = UP;
|
||||
mFBNum = fbnum;
|
||||
}
|
||||
else
|
||||
LOGE("start channel failed.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
status_t OverlayUI::queueBuffer(buffer_handle_t buffer) {
|
||||
status_t ret = NO_INIT;
|
||||
|
||||
if (mChannelState != UP)
|
||||
return ret;
|
||||
|
||||
msmfb_overlay_data ovData;
|
||||
memset(&ovData, 0, sizeof(ovData));
|
||||
|
||||
private_handle_t const* hnd = reinterpret_cast
|
||||
<private_handle_t const*>(buffer);
|
||||
ovData.data.memory_id = hnd->fd;
|
||||
ovData.data.offset = hnd->offset;
|
||||
if (mOrientation) {
|
||||
msm_rotator_data_info rotData;
|
||||
memset(&rotData, 0, sizeof(rotData));
|
||||
rotData.src.memory_id = hnd->fd;
|
||||
rotData.src.offset = hnd->offset;
|
||||
if (mobjRotator.rotateBuffer(rotData) != NO_ERROR) {
|
||||
LOGE("Rotator failed.. ");
|
||||
return BAD_VALUE;
|
||||
}
|
||||
ovData.data.memory_id = rotData.dst.memory_id;
|
||||
ovData.data.offset = rotData.dst.offset;
|
||||
}
|
||||
|
||||
ret = mobjOVHelper.queueBuffer(ovData);
|
||||
if (ret != NO_ERROR)
|
||||
LOGE("Queuebuffer failed ");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
160
liboverlay/overlayLibUI.h
Normal file
160
liboverlay/overlayLibUI.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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 INCLUDE_OVERLAY_LIB_UI
|
||||
#define INCLUDE_OVERLAY_LIB_UI
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "overlayLib.h"
|
||||
|
||||
namespace overlay {
|
||||
|
||||
enum channel_state_t { UP, CLOSED, PENDING_CLOSE };
|
||||
enum status_t {
|
||||
NO_ERROR,
|
||||
INVALID_OPERATION = -ENOSYS,
|
||||
BAD_VALUE = -EINVAL,
|
||||
NO_INIT = -ENODEV,
|
||||
ALREADY_EXISTS = -EEXIST
|
||||
};
|
||||
|
||||
/*
|
||||
* Display class provides following services
|
||||
* Open FB
|
||||
* FB information (Width, Height and Bpp)
|
||||
*/
|
||||
|
||||
class Display {
|
||||
int mFD;
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
int mFBBpp;
|
||||
Display(const Display& objDisplay);
|
||||
Display& operator=(const Display& objDisplay);
|
||||
|
||||
public:
|
||||
explicit Display() : mFD(NO_INIT) { };
|
||||
~Display() { close(mFD); };
|
||||
int getFD() const { return mFD; };
|
||||
int getFBWidth() const { return mFBWidth; };
|
||||
int getFBHeight() const { return mFBHeight; };
|
||||
int getFBBpp() const { return mFBBpp; };
|
||||
status_t openDisplay(int fbnum);
|
||||
void closeDisplay() { close(mFD); mFD = NO_INIT; };
|
||||
};
|
||||
|
||||
/*
|
||||
* OVHelper class, provides apis related to Overlay
|
||||
* It communicates with MDP driver, provides following services
|
||||
* Start overlay session
|
||||
* Set position of the destination on to display
|
||||
*/
|
||||
|
||||
class OVHelper {
|
||||
int mSessionID;
|
||||
Display mobjDisplay;
|
||||
mdp_overlay mOVInfo;
|
||||
OVHelper(const OVHelper& objOVHelper);
|
||||
OVHelper& operator=(const OVHelper& objOVHelper);
|
||||
|
||||
public:
|
||||
explicit OVHelper() : mSessionID(NO_INIT) { };
|
||||
~OVHelper() { closeOVSession(); };
|
||||
status_t startOVSession(mdp_overlay& ovInfo, int fbnum);
|
||||
status_t closeOVSession();
|
||||
status_t queueBuffer(msmfb_overlay_data ovData);
|
||||
int getFBWidth() const { return mobjDisplay.getFBWidth(); };
|
||||
int getFBHeight() const { return mobjDisplay.getFBHeight(); };
|
||||
int getFBBpp() const { return mobjDisplay.getFBBpp(); };
|
||||
status_t setPosition(int x, int y, int w, int h);
|
||||
status_t getOVInfo(mdp_overlay& ovInfo);
|
||||
};
|
||||
|
||||
/*
|
||||
* Rotator class, manages rotation of the buffers
|
||||
* It communicates with Rotator driver, provides following services
|
||||
* Start rotator session
|
||||
* Rotate buffer
|
||||
*/
|
||||
|
||||
class Rotator {
|
||||
int mFD;
|
||||
int mSessionID;
|
||||
int mPmemFD;
|
||||
void* mPmemAddr;
|
||||
int mRotOffset[max_num_buffers];
|
||||
int mCurrentItem;
|
||||
int mNumBuffers;
|
||||
int mSize;
|
||||
android::sp<gralloc::IAllocController> mAlloc;
|
||||
int mBufferType;
|
||||
Rotator(const Rotator& objROtator);
|
||||
Rotator& operator=(const Rotator& objRotator);
|
||||
|
||||
public:
|
||||
explicit Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1)
|
||||
{
|
||||
#ifdef USE_ION
|
||||
mAlloc = gralloc::IAllocController::getInstance();
|
||||
#endif
|
||||
}
|
||||
~Rotator() { closeRotSession(); }
|
||||
status_t startRotSession(msm_rotator_img_info& rotInfo, int size,
|
||||
int numBuffers = max_num_buffers);
|
||||
status_t closeRotSession();
|
||||
status_t rotateBuffer(msm_rotator_data_info& rotData);
|
||||
};
|
||||
|
||||
/*
|
||||
* Overlay class for Comp. Bypass
|
||||
* We merge control and data channel classes.
|
||||
*/
|
||||
|
||||
class OverlayUI {
|
||||
channel_state_t mChannelState;
|
||||
int mOrientation;
|
||||
int mFBNum;
|
||||
OVHelper mobjOVHelper;
|
||||
Rotator mobjRotator;
|
||||
|
||||
OverlayUI(const OverlayUI& objOverlay);
|
||||
OverlayUI& operator=(const OverlayUI& objOverlay);
|
||||
|
||||
status_t startChannel(int fbnum, mdp_overlay& ovInfo,
|
||||
msm_rotator_img_info& rotInfo, int size);
|
||||
public:
|
||||
|
||||
enum fbnum_t { FB0, FB1 };
|
||||
|
||||
explicit OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT), mFBNum(NO_INIT) { };
|
||||
~OverlayUI() { closeChannel(); };
|
||||
status_t setSource(const overlay_buffer_info& info, int orientation,
|
||||
bool useVGPipe = false, bool ignoreFB = true,
|
||||
int fbnum = FB0, int zorder = NO_INIT);
|
||||
status_t setPosition(int x, int y, int w, int h) {
|
||||
return mobjOVHelper.setPosition(x, y, w, h);
|
||||
};
|
||||
status_t closeChannel();
|
||||
channel_state_t isChannelUP() const { return mChannelState; };
|
||||
int getFBWidth() const { return mobjOVHelper.getFBWidth(); };
|
||||
int getFBHeight() const { return mobjOVHelper.getFBHeight(); };
|
||||
status_t queueBuffer(buffer_handle_t buffer);
|
||||
};
|
||||
|
||||
};
|
||||
#endif
|
1109
liboverlay/overlayState.cpp
Normal file
1109
liboverlay/overlayState.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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))
|
@ -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);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
Loading…
x
Reference in New Issue
Block a user