/* * 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 "Overlay" #include <hardware/hardware.h> #include <hardware/overlay.h> #include <fcntl.h> #include <errno.h> #include <cutils/log.h> #include <cutils/atomic.h> /*****************************************************************************/ struct overlay_control_context_t { struct overlay_control_device_t device; /* our private state goes below here */ }; struct overlay_data_context_t { struct overlay_data_device_t device; /* our private state goes below here */ }; static int overlay_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device); static struct hw_module_methods_t overlay_module_methods = { open: overlay_device_open }; struct overlay_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: OVERLAY_HARDWARE_MODULE_ID, name: "Sample Overlay module", author: "The Android Open Source Project", methods: &overlay_module_methods, } }; /*****************************************************************************/ /* * This is the overlay_t object, it is returned to the user and represents * an overlay. * This handles will be passed across processes and possibly given to other * HAL modules (for instance video decode modules). */ class overlay_object : public overlay_t { struct handle_t : public native_handle { /* add the data fields we need here, for instance: */ int width; int height; }; handle_t mHandle; static overlay_handle_t getHandleRef(struct overlay_t* overlay) { /* returns a reference to the handle, caller doesn't take ownership */ return &(static_cast<overlay_object *>(overlay)->mHandle); } public: overlay_object() { this->overlay_t::getHandleRef = getHandleRef; mHandle.version = sizeof(native_handle); mHandle.numFds = 0; mHandle.numInts = 2; // extra ints we have in our handle } }; // **************************************************************************** // Control module // **************************************************************************** static int overlay_get(struct overlay_control_device_t *dev, int name) { int result = -1; switch (name) { case OVERLAY_MINIFICATION_LIMIT: result = 0; // 0 = no limit break; case OVERLAY_MAGNIFICATION_LIMIT: result = 0; // 0 = no limit break; case OVERLAY_SCALING_FRAC_BITS: result = 0; // 0 = infinite break; case OVERLAY_ROTATION_STEP_DEG: result = 90; // 90 rotation steps (for instance) break; case OVERLAY_HORIZONTAL_ALIGNMENT: result = 1; // 1-pixel alignment break; case OVERLAY_VERTICAL_ALIGNMENT: result = 1; // 1-pixel alignment break; case OVERLAY_WIDTH_ALIGNMENT: result = 1; // 1-pixel alignment break; case OVERLAY_HEIGHT_ALIGNMENT: result = 1; // 1-pixel alignment break; } return result; } static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, uint32_t w, uint32_t h, int32_t format) { /* check the input params, reject if not supported or invalid */ switch (format) { case OVERLAY_FORMAT_RGBA_8888: case OVERLAY_FORMAT_RGB_565: case OVERLAY_FORMAT_BGRA_8888: // add supported format here (especially YUV formats) break; default: return NULL; } /* Create overlay object. Talk to the h/w here and adjust to what it can * do. the overlay_t returned can be a C++ object, subclassing overlay_t * if needed. * * we probably want to keep a list of the overlay_t created so they can * all be cleaned up in overlay_close(). */ return new overlay_object( /* pass needed params here*/ ); } static void overlay_destroyOverlay(struct overlay_control_device_t *dev, overlay_t* overlay) { /* free resources associated with this overlay_t */ delete overlay; } static int overlay_setPosition(struct overlay_control_device_t *dev, overlay_t* overlay, int x, int y, uint32_t w, uint32_t h) { /* set this overlay's position (talk to the h/w) */ return -EINVAL; } static int overlay_getPosition(struct overlay_control_device_t *dev, overlay_t* overlay, int* x, int* y, uint32_t* w, uint32_t* h) { /* get this overlay's position */ return -EINVAL; } static int overlay_setParameter(struct overlay_control_device_t *dev, overlay_t* overlay, int param, int value) { int result = 0; /* set this overlay's parameter (talk to the h/w) */ switch (param) { case OVERLAY_ROTATION_DEG: /* if only 90 rotations are supported, the call fails * for other values */ break; case OVERLAY_DITHER: break; case OVERLAY_TRANSFORM: // see OVERLAY_TRANSFORM_* break; default: result = -EINVAL; break; } return result; } static int overlay_control_close(struct hw_device_t *dev) { struct overlay_control_context_t* ctx = (struct overlay_control_context_t*)dev; if (ctx) { /* free all resources associated with this device here * in particular the overlay_handle_t, outstanding overlay_t, etc... */ free(ctx); } return 0; } // **************************************************************************** // Data module // **************************************************************************** int overlay_initialize(struct overlay_data_device_t *dev, overlay_handle_t handle) { /* * overlay_handle_t should contain all the information to "inflate" this * overlay. Typically it'll have a file descriptor, informations about * how many buffers are there, etc... * It is also the place to mmap all buffers associated with this overlay * (see getBufferAddress). * * NOTE: this function doesn't take ownership of overlay_handle_t * */ return -EINVAL; } int overlay_dequeueBuffer(struct overlay_data_device_t *dev, overlay_buffer_t* buf) { /* blocks until a buffer is available and return an opaque structure * representing this buffer. */ return -EINVAL; } int overlay_queueBuffer(struct overlay_data_device_t *dev, overlay_buffer_t buffer) { /* Mark this buffer for posting and recycle or free overlay_buffer_t. */ return -EINVAL; } void *overlay_getBufferAddress(struct overlay_data_device_t *dev, overlay_buffer_t buffer) { /* this may fail (NULL) if this feature is not supported. In that case, * presumably, there is some other HAL module that can fill the buffer, * using a DSP for instance */ return NULL; } static int overlay_data_close(struct hw_device_t *dev) { struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; if (ctx) { /* free all resources associated with this device here * in particular all pending overlay_buffer_t if needed. * * NOTE: overlay_handle_t passed in initialize() is NOT freed and * its file descriptors are not closed (this is the responsibility * of the caller). */ free(ctx); } return 0; } /*****************************************************************************/ static int overlay_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { int status = -EINVAL; if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { struct overlay_control_context_t *dev; dev = (overlay_control_context_t*)malloc(sizeof(*dev)); /* initialize our state here */ 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<hw_module_t*>(module); dev->device.common.close = overlay_control_close; dev->device.get = overlay_get; dev->device.createOverlay = overlay_createOverlay; dev->device.destroyOverlay = overlay_destroyOverlay; dev->device.setPosition = overlay_setPosition; dev->device.getPosition = overlay_getPosition; dev->device.setParameter = overlay_setParameter; *device = &dev->device.common; status = 0; } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) { struct overlay_data_context_t *dev; dev = (overlay_data_context_t*)malloc(sizeof(*dev)); /* initialize our state here */ 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<hw_module_t*>(module); dev->device.common.close = overlay_data_close; dev->device.initialize = overlay_initialize; dev->device.dequeueBuffer = overlay_dequeueBuffer; dev->device.queueBuffer = overlay_queueBuffer; dev->device.getBufferAddress = overlay_getBufferAddress; *device = &dev->device.common; status = 0; } return status; }