From c8998259fd683e7cc7c6dee88067baa9af477a03 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 17:08:40 +0100 Subject: Initial import Signed-off-by: Laurent Pinchart --- .../0001-hardware-renesas-DRM-gralloc-module.patch | 1006 ++++++++++++++++++++ 1 file changed, 1006 insertions(+) create mode 100644 hardware/renesas/0001-hardware-renesas-DRM-gralloc-module.patch (limited to 'hardware') diff --git a/hardware/renesas/0001-hardware-renesas-DRM-gralloc-module.patch b/hardware/renesas/0001-hardware-renesas-DRM-gralloc-module.patch new file mode 100644 index 0000000..dcecb0b --- /dev/null +++ b/hardware/renesas/0001-hardware-renesas-DRM-gralloc-module.patch @@ -0,0 +1,1006 @@ +From a559a2fd009a33aafdf0f6a6e3fd83a8f55c71e4 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Sat, 15 Sep 2012 04:36:43 +0200 +Subject: [PATCH] hardware/renesas: DRM gralloc module + +Signed-off-by: Laurent Pinchart +--- + libgralloc/Android.mk | 34 ++++ + libgralloc/framebuffer.cpp | 393 ++++++++++++++++++++++++++++++++++++++++++ + libgralloc/gralloc.cpp | 412 ++++++++++++++++++++++++++++++++++++++++++++ + libgralloc/gralloc_priv.h | 123 +++++++++++++ + 4 files changed, 962 insertions(+), 0 deletions(-) + create mode 100644 libgralloc/Android.mk + create mode 100644 libgralloc/framebuffer.cpp + create mode 100644 libgralloc/gralloc.cpp + create mode 100644 libgralloc/gralloc_priv.h + +diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk +new file mode 100644 +index 0000000..ee81ca3 +--- /dev/null ++++ b/libgralloc/Android.mk +@@ -0,0 +1,34 @@ ++# 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 stored in ++# hw/..so ++include $(CLEAR_VARS) ++ ++LOCAL_MODULE_TAGS := optional ++LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw ++LOCAL_SHARED_LIBRARIES := liblog libcutils libdrm libkms ++ ++LOCAL_SRC_FILES := \ ++ gralloc.cpp \ ++ framebuffer.cpp ++ ++LOCAL_MODULE := gralloc.drm ++LOCAL_CFLAGS := -DLOG_TAG=\"gralloc\" ++LOCAL_C_INCLUDES := external/drm/include/drm ++ ++include $(BUILD_SHARED_LIBRARY) +diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp +new file mode 100644 +index 0000000..b81e540 +--- /dev/null ++++ b/libgralloc/framebuffer.cpp +@@ -0,0 +1,393 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#if HAVE_ANDROID_OS ++#include ++#include ++#include ++#include ++#endif ++ ++#include "gralloc_priv.h" ++ ++// Numbers of buffers for page flipping. ++#define FB_NUM_BUFFERS 2 ++#define FB_FORMAT DRM_FORMAT_RGB565 ++ ++enum { ++ PAGE_FLIP = 0x00000001, ++ LOCKED = 0x00000002 ++}; ++ ++struct fb_context_t { ++ framebuffer_device_t device; ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * ++ */ ++ ++static int fb_setSwapInterval(struct framebuffer_device_t *dev, int interval) ++{ ++ fb_context_t *ctx = (fb_context_t *)dev; ++ ++ if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) ++ return -EINVAL; ++ ++ // FIXME: implement fb_setSwapInterval ++ return 0; ++} ++ ++static int fb_post(struct framebuffer_device_t *dev, buffer_handle_t buffer) ++{ ++ if (private_handle_t::validate(buffer) < 0) ++ return -EINVAL; ++ ++ fb_context_t *ctx = (fb_context_t *)dev; ++ ++ private_handle_t const *hnd = ++ static_cast(buffer); ++ private_module_t *m = ++ reinterpret_cast(dev->common.module); ++ ++ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { ++ int err = drmModePageFlip(m->fd, m->crtc, ++ m->buffers[hnd->index].fb, ++ 0 /* DRM_MODE_PAGE_FLIP_EVENT */, 0); ++ if (err < 0) { ++ LOGE("drmModePageFlip failed (%d)", err); ++ m->base.unlock(&m->base, buffer); ++ return err; ++ } ++ } else { ++ /* If we can't do the page_flip, just copy the buffer to the ++ * front. ++ * FIXME: use copybit HAL instead of memcpy ++ */ ++ void *buffer_vaddr; ++ ++ m->base.lock(&m->base, buffer, ++ GRALLOC_USAGE_SW_READ_RARELY, 0, 0, ++ m->mode->hdisplay, m->mode->vdisplay, ++ &buffer_vaddr); ++ ++ memcpy(m->buffers[0].vaddr, buffer_vaddr, ++ m->stride * m->mode->vdisplay); ++ ++ m->base.unlock(&m->base, buffer); ++ } ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * ++ */ ++ ++static void fb_free_buffer(struct private_module_t *module, ++ struct private_buffer_t *buffer) ++{ ++ if (buffer->fb) { ++ drmModeRmFB(module->fd, buffer->fb); ++ buffer->fb = 0; ++ } ++ if (buffer->vaddr) { ++ kms_bo_unmap(buffer->bo); ++ buffer->vaddr = 0; ++ } ++ if (buffer->bo) ++ kms_bo_destroy(&buffer->bo); ++} ++ ++static int fb_alloc_buffer(struct private_module_t *module, ++ struct private_buffer_t *buffer, ++ const drmModeModeInfo *mode) ++{ ++ unsigned int bo_attrs[] = { ++ KMS_WIDTH, mode->hdisplay, ++ KMS_HEIGHT, mode->vdisplay, ++ KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, ++ KMS_TERMINATE_PROP_LIST, ++ }; ++ uint32_t handles[4] = { 0 }; ++ uint32_t pitches[4] = { 0 }; ++ uint32_t offsets[4] = { 0 }; ++ int err; ++ ++ err = kms_bo_create(module->kms, bo_attrs, &buffer->bo); ++ if (err < 0) ++ goto done; ++ ++ err = kms_bo_map(buffer->bo, &buffer->vaddr); ++ if (err < 0) ++ goto done; ++ ++ kms_bo_get_prop(buffer->bo, KMS_HANDLE, &buffer->handle); ++ ++ handles[0] = buffer->handle; ++ pitches[0] = mode->hdisplay * 2; ++ err = drmModeAddFB2(module->fd, mode->hdisplay, mode->vdisplay, ++ FB_FORMAT, handles, pitches, offsets, &buffer->fb, ++ 0); ++ ++done: ++ if (err < 0) ++ fb_free_buffer(module, buffer); ++ ++ return err; ++} ++ ++int fb_map_locked(struct private_module_t *module) ++{ ++ int err; ++ ++ // already initialized... ++ if (module->num_buffers) ++ return 0; ++ ++ int fd = drmOpen("shmob-drm", 0); ++ if (fd < 0) ++ return -errno; ++ ++ module->fd = fd; ++ ++ drmModeModeInfo *mode = 0; ++ drmVersion *version = 0; ++ drmModeRes *resources = 0; ++ drmModeConnector *connector = 0; ++ drmModeEncoder *encoder = 0; ++ ++ version = drmGetVersion(fd); ++ if (!version) { ++ err = -errno; ++ goto done; ++ } ++ ++ resources = drmModeGetResources(fd); ++ if (!resources) { ++ err = -errno; ++ goto done; ++ } ++ ++ /* Get the default mode associated with the first connector. */ ++ if (resources->count_connectors == 0) { ++ err = -EINVAL; ++ goto done; ++ } ++ ++ connector = drmModeGetConnector(fd, resources->connectors[0]); ++ if (!connector) { ++ err = -errno; ++ goto done; ++ } ++ ++ if (connector->count_modes == 0) { ++ err = -EINVAL; ++ goto done; ++ } ++ ++ if (connector->count_encoders == 0) { ++ err = -EINVAL; ++ goto done; ++ } ++ ++ encoder = drmModeGetEncoder(fd, *connector->encoders); ++ if (!encoder) { ++ err = -errno; ++ goto done; ++ } ++ ++ for (int i = 0; i < resources->count_crtcs; ++i) { ++ if (encoder->possible_crtcs & (1U << i)) { ++ module->crtc = resources->crtcs[i]; ++ break; ++ } ++ } ++ ++ if (module->crtc == 0) { ++ err = -EINVAL; ++ goto done; ++ } ++ ++ float xdpi; ++ float ydpi; ++ float fps; ++ ++ mode = &connector->modes[0]; ++ ++ if (connector->mmWidth == 0 || connector->mmHeight == 0) { ++ /* The driver doesn't return that information, default to ++ * 160 dpi. ++ */ ++ xdpi = 160; ++ ydpi = 160; ++ } else { ++ xdpi = (mode->hdisplay * 25.4f) / connector->mmWidth; ++ ydpi = (mode->vdisplay * 25.4f) / connector->mmHeight; ++ } ++ ++ if (mode->htotal && mode->vtotal) ++ fps = mode->clock * 1000.0f / (mode->htotal * mode->vtotal); ++ else ++ fps = 60.0; ++ ++ /* Create two frame buffers. */ ++ module->buffers = new private_buffer_t[FB_NUM_BUFFERS]; ++ if (!module->buffers) { ++ err = -ENOMEM; ++ goto done; ++ } ++ ++ memset(module->buffers, 0, FB_NUM_BUFFERS * sizeof *module->buffers); ++ ++ err = kms_create(fd, &module->kms); ++ if (err < 0) ++ goto done; ++ ++ for (unsigned int i = 0; i < FB_NUM_BUFFERS; ++i) { ++ err = fb_alloc_buffer(module, &module->buffers[i], mode); ++ if (err < 0) ++ goto done; ++ } ++ ++ err = drmModeSetCrtc(fd, module->crtc, module->buffers[0].fb, 0, 0, ++ &connector->connector_id, 1, mode); ++ if (err < 0) ++ goto done; ++ ++ LOGI("using (fd=%d)\n" ++ "desc = %s\n" ++ "hdisplay = %u px\n" ++ "vdisplay = %u px\n" ++ "format = 0x%08x\n", ++ fd, version->desc, ++ mode->hdisplay, mode->vdisplay, ++ FB_FORMAT); ++ ++ LOGI("width = %d mm (%f dpi)\n" ++ "height = %d mm (%f dpi)\n" ++ "refresh rate = %.2f Hz\n", ++ connector->mmWidth, xdpi, connector->mmHeight, ydpi, fps); ++ ++ module->flags = PAGE_FLIP; ++ module->num_buffers = FB_NUM_BUFFERS; ++ module->mode = mode; ++ module->xdpi = xdpi; ++ module->ydpi = ydpi; ++ module->fps = fps; ++ module->stride = mode->hdisplay * 2; ++ ++done: ++ if (encoder) ++ drmModeFreeEncoder(encoder); ++ if (resources) ++ drmModeFreeResources(resources); ++ if (version) ++ drmFreeVersion(version); ++ ++ if (err < 0) { ++ if (module->buffers) { ++ for (unsigned int i = 0; i < FB_NUM_BUFFERS; ++i) ++ fb_free_buffer(module, &module->buffers[i]); ++ delete[] module->buffers; ++ } ++ if (connector) ++ drmModeFreeConnector(connector); ++ if (fd != -1) ++ drmClose(fd); ++ } ++ ++ return err; ++} ++ ++static int fb_map(struct private_module_t *module) ++{ ++ pthread_mutex_lock(&module->lock); ++ int err = fb_map_locked(module); ++ pthread_mutex_unlock(&module->lock); ++ return err; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * ++ */ ++ ++static int fb_close(struct hw_device_t *dev) ++{ ++ fb_context_t *ctx = (fb_context_t*)dev; ++ free(ctx); ++ return 0; ++} ++ ++int fb_device_open(hw_module_t const *module, const char *name, ++ hw_device_t **device) ++{ ++ alloc_device_t *gralloc_device; ++ int err; ++ ++ err = gralloc_open(module, &gralloc_device); ++ if (err < 0) ++ return err; ++ ++ /* Initialize our state here */ ++ fb_context_t *dev = (fb_context_t *)malloc(sizeof *dev); ++ memset(dev, 0, sizeof *dev); ++ ++ /* Initialize the procs */ ++ dev->device.common.tag = HARDWARE_DEVICE_TAG; ++ dev->device.common.version = 0; ++ dev->device.common.module = const_cast(module); ++ dev->device.common.close = fb_close; ++ dev->device.setSwapInterval = fb_setSwapInterval; ++ dev->device.post = fb_post; ++ dev->device.setUpdateRect = 0; ++ ++ private_module_t *m = (private_module_t*)module; ++ err = fb_map(m); ++ if (err < 0) ++ return err; ++ ++ const_cast(dev->device.flags) = 0; ++ const_cast(dev->device.width) = m->mode->hdisplay; ++ const_cast(dev->device.height) = m->mode->vdisplay; ++ const_cast(dev->device.stride) = m->stride; ++ const_cast(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565; ++ const_cast(dev->device.xdpi) = m->xdpi; ++ const_cast(dev->device.ydpi) = m->ydpi; ++ const_cast(dev->device.fps) = m->fps; ++ const_cast(dev->device.minSwapInterval) = 1; ++ const_cast(dev->device.maxSwapInterval) = 1; ++ ++ *device = &dev->device.common; ++ ++ return 0; ++} +diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp +new file mode 100644 +index 0000000..03282b3 +--- /dev/null ++++ b/libgralloc/gralloc.cpp +@@ -0,0 +1,412 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define ++# include ++#else ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "gralloc_priv.h" ++ ++struct gralloc_context_t { ++ alloc_device_t device; ++ /* our private data here */ ++}; ++ ++static size_t roundUpToPageSize(size_t x) ++{ ++ return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Map/unmap ++ */ ++ ++static int gralloc_map(gralloc_module_t const *module, private_handle_t *hnd, ++ void **vaddr) ++{ ++ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { ++ void *addr; ++ ++ addr = mmap(0, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, ++ hnd->fd, 0); ++ if (addr == MAP_FAILED) { ++ LOGE("Could not mmap %s", strerror(errno)); ++ return -errno; ++ } ++ ++ hnd->base = intptr_t(addr); ++ } ++ ++ *vaddr = (void *)hnd->base; ++ return 0; ++} ++ ++static int gralloc_unmap(gralloc_module_t const *module, private_handle_t *hnd) ++{ ++ if (hnd->base == 0) ++ return 0; ++ ++ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { ++ if (munmap((void *)hnd->base, hnd->size) < 0) ++ LOGE("Could not unmap %s", strerror(errno)); ++ } ++ ++ hnd->base = 0; ++ return 0; ++} ++/* ----------------------------------------------------------------------------- ++ * Buffer registration ++ */ ++ ++static int gralloc_register_buffer(gralloc_module_t const *module, ++ buffer_handle_t handle) ++{ ++ if (private_handle_t::validate(handle) < 0) ++ return -EINVAL; ++ ++ private_handle_t *hnd = ++ const_cast( ++ static_cast(handle)); ++ ++ /* If this handle was created in this process, then we keep it as is. */ ++ if (hnd->pid == getpid()) ++ return 0; ++ ++ void *vaddr; ++ return gralloc_map(module, hnd, &vaddr); ++} ++ ++static int gralloc_unregister_buffer(gralloc_module_t const *module, ++ buffer_handle_t handle) ++{ ++ if (private_handle_t::validate(handle) < 0) ++ return -EINVAL; ++ ++ private_handle_t *hnd = ++ const_cast( ++ static_cast(handle)); ++ ++ /* Never unmap buffers that were created in this process. */ ++ if (hnd->pid == getpid()) ++ return 0; ++ ++ gralloc_unmap(module, hnd); ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Lock/unlock ++ */ ++ ++static int gralloc_lock(gralloc_module_t const *module, ++ buffer_handle_t handle, int usage, int l, int t, ++ int w, int h, void **vaddr) ++{ ++ /* This is called when a buffer is being locked for software access. In ++ * this implementation we have nothing to do since not synchronization ++ * with the h/w is needed. Typically this is used to wait for the h/w to ++ * finish with this buffer if relevant. The data cache may need to be ++ * flushed or invalidated depending on the usage bits and the hardware. ++ */ ++ if (private_handle_t::validate(handle) < 0) ++ return -EINVAL; ++ ++ private_handle_t *hnd = ++ const_cast( ++ static_cast(handle)); ++ *vaddr = (void*)hnd->base; ++ return 0; ++} ++ ++static int gralloc_unlock(gralloc_module_t const *module, ++ buffer_handle_t handle) ++{ ++ /* We're done with a software buffer. Nothing to do in this ++ * implementation. Typically this is used to flush the data cache. ++ */ ++ if (private_handle_t::validate(handle) < 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Alloc/free ++ */ ++ ++/* Allocate a buffer from system memory through ashmem. */ ++static int gralloc_alloc_buffer(alloc_device_t *dev, size_t size, int usage, ++ buffer_handle_t *handle) ++{ ++ void *vaddr; ++ int err; ++ int fd; ++ ++ size = roundUpToPageSize(size); ++ ++ fd = ashmem_create_region("gralloc-buffer", size); ++ if (fd < 0) { ++ LOGE("couldn't create ashmem (%s)", strerror(-errno)); ++ return -errno; ++ } ++ ++ private_handle_t *hnd = new private_handle_t(fd, size, 0); ++ gralloc_module_t *module = ++ reinterpret_cast(dev->common.module); ++ err = gralloc_map(module, hnd, &vaddr); ++ if (err < 0) { ++ LOGE("gralloc failed err=%s", strerror(-err)); ++ close(fd); ++ delete hnd; ++ return err; ++ } ++ ++ *handle = hnd; ++ return 0; ++} ++ ++/* Allocate a buffer from display memory. */ ++static int gralloc_alloc_framebuffer_locked(alloc_device_t *dev, size_t size, ++ int usage, buffer_handle_t *handle) ++{ ++ private_module_t *m = ++ reinterpret_cast(dev->common.module); ++ ++ /* Allocate the framebuffer if not done already. The frame buffer is ++ * mapped once and forever. ++ */ ++ int err = fb_map_locked(m); ++ if (err < 0) ++ return err; ++ ++ if (m->num_buffers == 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. ++ */ ++ usage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; ++ return gralloc_alloc_buffer(dev, m->stride * m->mode->vdisplay, ++ usage, handle); ++ } ++ ++ unsigned int index; ++ ++ // Find a free slot. ++ for (index = 0; index < m->num_buffers ; index++) { ++ if (!m->buffers[index].busy) { ++ m->buffers[index].busy = true; ++ break; ++ } ++ } ++ ++ if (index == m->num_buffers) ++ return -ENOMEM; ++ ++ // Create a "fake" handle for it. ++ private_handle_t *hnd = ++ new private_handle_t(dup(m->fd), size, ++ private_handle_t::PRIV_FLAGS_FRAMEBUFFER); ++ ++ hnd->index = index; ++ hnd->base = (int)m->buffers[index].vaddr; ++ *handle = hnd; ++ ++ return 0; ++} ++ ++static int gralloc_alloc_framebuffer(alloc_device_t *dev, size_t size, ++ int usage, buffer_handle_t *handle) ++{ ++ private_module_t *m = ++ reinterpret_cast(dev->common.module); ++ ++ pthread_mutex_lock(&m->lock); ++ int err = gralloc_alloc_framebuffer_locked(dev, size, usage, handle); ++ pthread_mutex_unlock(&m->lock); ++ ++ return err; ++} ++ ++static int gralloc_alloc(alloc_device_t *dev, int w, int h, int format, ++ int usage, buffer_handle_t *handle, int *stride) ++{ ++ if (!handle || !stride) ++ return -EINVAL; ++ ++ unsigned int align = 4; ++ unsigned int bpp; ++ size_t size; ++ ++ switch (format) { ++ case HAL_PIXEL_FORMAT_RGBA_8888: ++ case HAL_PIXEL_FORMAT_RGBX_8888: ++ case HAL_PIXEL_FORMAT_BGRA_8888: ++ bpp = 4; ++ break; ++ case HAL_PIXEL_FORMAT_RGB_888: ++ bpp = 3; ++ break; ++ case HAL_PIXEL_FORMAT_RGB_565: ++ case HAL_PIXEL_FORMAT_RGBA_5551: ++ case HAL_PIXEL_FORMAT_RGBA_4444: ++ bpp = 2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ size_t bpr = (w*bpp + (align-1)) & ~(align-1); ++ size = bpr * h; ++ *stride = bpr / bpp; ++ ++ if (usage & GRALLOC_USAGE_HW_FB) ++ return gralloc_alloc_framebuffer(dev, size, usage, handle); ++ else ++ return gralloc_alloc_buffer(dev, size, usage, handle); ++} ++ ++static int gralloc_free(alloc_device_t *dev, buffer_handle_t handle) ++{ ++ private_module_t *m = ++ reinterpret_cast(dev->common.module); ++ private_handle_t *hnd = ++ const_cast( ++ static_cast(handle)); ++ ++ if (private_handle_t::validate(handle) < 0) ++ return -EINVAL; ++ ++ if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { ++ pthread_mutex_lock(&m->lock); ++ m->buffers[hnd->index].busy = false; ++ pthread_mutex_unlock(&m->lock); ++ } else { ++ gralloc_unmap(&m->base, hnd); ++ } ++ ++ close(hnd->fd); ++ delete hnd; ++ return 0; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Open/close ++ */ ++ ++static int gralloc_close(struct hw_device_t *dev) ++{ ++ gralloc_context_t *ctx = reinterpret_cast(dev); ++ ++ if (ctx) { ++ /* TODO: keep a list of all buffer_handle_t created, and free ++ * them all here. ++ */ ++ delete ctx; ++ } ++ ++ return 0; ++} ++ ++static int gralloc_device_open(const hw_module_t *module, const char *name, ++ hw_device_t **device) ++{ ++ int status = -EINVAL; ++ ++ if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { ++ gralloc_context_t *dev; ++ ++ dev = new(gralloc_context_t); ++ memset(dev, 0, sizeof *dev); ++ ++ /* initialize the procs */ ++ dev->device.common.tag = HARDWARE_DEVICE_TAG; ++ dev->device.common.version = 0; ++ dev->device.common.module = const_cast(module); ++ dev->device.common.close = gralloc_close; ++ ++ dev->device.alloc = gralloc_alloc; ++ dev->device.free = gralloc_free; ++ ++ *device = &dev->device.common; ++ status = 0; ++ } else if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { ++ status = fb_device_open(module, name, device); ++ } ++ ++ return status; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Module ++ */ ++ ++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: "Renesas Electronics Inc.", ++ methods: &gralloc_module_methods ++ }, ++ registerBuffer: gralloc_register_buffer, ++ unregisterBuffer: gralloc_unregister_buffer, ++ lock: gralloc_lock, ++ unlock: gralloc_unlock, ++ }, ++ lock: PTHREAD_MUTEX_INITIALIZER, ++ fd: -1, ++ crtc: 0, ++ mode: 0, ++ kms: 0, ++ num_buffers: 0, ++ buffers: 0, ++ xdpi: 0.0f, ++ ydpi: 0.0f, ++ fps: 0.0f, ++ stride: 0, ++ flags: 0, ++}; +diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h +new file mode 100644 +index 0000000..02854aa +--- /dev/null ++++ b/libgralloc/gralloc_priv.h +@@ -0,0 +1,123 @@ ++/* ++ * 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_PRIV_H_ ++#define GRALLOC_PRIV_H_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++int fb_device_open(const hw_module_t *module, const char *name, ++ hw_device_t **device); ++int fb_map_locked(struct private_module_t *module); ++ ++/* ----------------------------------------------------------------------------- ++ * Module ++ */ ++ ++struct private_buffer_t { ++ struct kms_bo *bo; ++ void *vaddr; ++ bool busy; ++ unsigned int handle; ++ uint32_t fb; ++}; ++ ++struct private_module_t { ++ gralloc_module_t base; ++ pthread_mutex_t lock; ++ ++ int fd; ++ uint32_t crtc; ++ drmModeModeInfo *mode; ++ struct kms_driver *kms; ++ ++ uint32_t num_buffers; ++ struct private_buffer_t *buffers; ++ ++ float xdpi; ++ float ydpi; ++ float fps; ++ unsigned int stride; ++ ++ uint32_t flags; ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Handle ++ */ ++ ++struct private_handle_t : public native_handle { ++ enum { ++ PRIV_FLAGS_FRAMEBUFFER = 0x00000001 ++ }; ++ ++ // File descriptors ++ int fd; ++ ++ // Ints ++ int magic; ++ int flags; ++ int size; ++ int pid; ++ ++ int index; ++ int base; ++ ++ static const int sNumInts = 6; ++ static const int sNumFds = 1; ++ static const int sMagic = 0x3141592; ++ ++ private_handle_t(int fd, int size, int flags) : ++ fd(fd), magic(sMagic), flags(flags), size(size), pid(getpid()), ++ index(0) ++ { ++ version = sizeof(native_handle); ++ numInts = sNumInts; ++ numFds = sNumFds; ++ } ++ ++ ~private_handle_t() { ++ magic = 0; ++ } ++ ++ static int validate(const native_handle *h) { ++ 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) ++ { ++ LOGE("invalid gralloc handle (at %p)", h); ++ return -EINVAL; ++ } ++ ++ return 0; ++ } ++}; ++ ++#endif /* GRALLOC_PRIV_H_ */ +-- +1.7.8.6 + -- cgit v1.2.3