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