| /* |
| * 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; |
| } |