From 102e25e36775f09a727eb1b64d377880d69931d6 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 12 Mar 2009 11:02:43 -0700 Subject: [PATCH 008/435] auto import from //branches/cupcake/...@137873 --- libcopybit/Android.mk | 25 +++ libcopybit/copybit.c | 398 ++++++++++++++++++++++++++++++++++++ yuv420sp2rgb/Android.mk | 16 ++ yuv420sp2rgb/cmdline.c | 147 +++++++++++++ yuv420sp2rgb/cmdline.h | 15 ++ yuv420sp2rgb/debug.c | 38 ++++ yuv420sp2rgb/debug.h | 90 ++++++++ yuv420sp2rgb/yuv420sp2rgb.c | 337 ++++++++++++++++++++++++++++++ 8 files changed, 1066 insertions(+) create mode 100644 libcopybit/Android.mk create mode 100644 libcopybit/copybit.c create mode 100644 yuv420sp2rgb/Android.mk create mode 100644 yuv420sp2rgb/cmdline.c create mode 100644 yuv420sp2rgb/cmdline.h create mode 100644 yuv420sp2rgb/debug.c create mode 100644 yuv420sp2rgb/debug.h create mode 100644 yuv420sp2rgb/yuv420sp2rgb.c diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk new file mode 100644 index 0000000..f6a1b4b --- /dev/null +++ b/libcopybit/Android.mk @@ -0,0 +1,25 @@ +# 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/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := copybit.c +LOCAL_MODULE := copybit.msm7k +include $(BUILD_SHARED_LIBRARY) diff --git a/libcopybit/copybit.c b/libcopybit/copybit.c new file mode 100644 index 0000000..168de4c --- /dev/null +++ b/libcopybit/copybit.c @@ -0,0 +1,398 @@ +/* + * 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 + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/******************************************************************************/ + +/** 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 + */ +const 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 (ab) ? 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 COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; + case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; + case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; + case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; + case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_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) { + img->width = rhs->w; + img->height = rhs->h; + img->format = get_format(rhs->format); + img->offset = rhs->offset; + img->memory_id = rhs->fd; +} + +/** 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) { + 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) { + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + } + if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) { + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w); + } +} + +/** setup mdp request */ +static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { + req->alpha = dev->mAlpha; + req->transp_mask = MDP_TRANSP_NOP; + req->flags = dev->mFlags; +} + +/** 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 + 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_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 = 4; + break; + case COPYBIT_MAGNIFICATION_LIMIT: + value = 4; + 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 COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + 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); + set_infos(ctx, &list.req[list.count]); + set_image(&list.req[list.count].dst, dst); + set_image(&list.req[list.count].src, src); + set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip); + 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; + struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t)); + memset(ctx, 0, sizeof(*ctx)); + + ctx->device.common.tag = HARDWARE_DEVICE_TAG; + ctx->device.common.version = 0; + ctx->device.common.module = 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 (strcmp(finfo.id, "msmfb") == 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; +} diff --git a/yuv420sp2rgb/Android.mk b/yuv420sp2rgb/Android.mk new file mode 100644 index 0000000..6e6220d --- /dev/null +++ b/yuv420sp2rgb/Android.mk @@ -0,0 +1,16 @@ +# Copyright 2005 Google Inc. All Rights Reserved. +# +# Android.mk for apriori +# + +LOCAL_PATH:= $(call my-dir) + +ifeq ($(TARGET_ARCH),arm) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := yuv420sp2rgb.c cmdline.c debug.c + +LOCAL_MODULE := yuv420sp2rgb + +include $(BUILD_HOST_EXECUTABLE) +endif diff --git a/yuv420sp2rgb/cmdline.c b/yuv420sp2rgb/cmdline.c new file mode 100644 index 0000000..3bfea99 --- /dev/null +++ b/yuv420sp2rgb/cmdline.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include + +extern char *optarg; +extern int optind, opterr, optopt; + +static struct option long_options[] = { + {"output", required_argument, 0, 'o'}, + {"height", required_argument, 0, 'h'}, + {"width", required_argument, 0, 'w'}, + {"gray", no_argument, 0, 'g'}, + {"type", required_argument, 0, 't'}, + {"rotate", required_argument, 0, 'r'}, + {"verbose", no_argument, 0, 'V'}, + {"help", no_argument, 0, 1}, + {0, 0, 0, 0}, +}; + +/* This array must parallel long_options[] */ +static const char *descriptions[] = { + "output file", + "image height in pixels", + "image width in pixels", + "process the luma plane only", + "encode as one of { 'ppm', 'rgb', or 'argb' }", + "rotate (90, -90, 180 degrees)", + "print verbose output", + "print this help screen", +}; + +void print_help(const char *name) { + fprintf(stdout, + "Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n" + "invokation:\n" + "\t%s infile --height --width --output [ --gray ] [ --rotate ] [ --verbose ]\n" + "\t%s infile --help\n", + name, name); + fprintf(stdout, "options:\n"); + struct option *opt = long_options; + const char **desc = descriptions; + while (opt->name) { + fprintf(stdout, "\t-%c/--%s%s: %s\n", + isprint(opt->val) ? opt->val : ' ', + opt->name, + (opt->has_arg ? " (argument)" : ""), + *desc); + opt++; + desc++; + } +} + +int get_options(int argc, char **argv, + char **outfile, + int *height, + int *width, + int *gray, + char **type, + int *rotate, + int *verbose) { + int c; + + ASSERT(outfile); *outfile = NULL; + ASSERT(height); *height = -1; + ASSERT(width); *width = -1; + ASSERT(gray); *gray = 0; + ASSERT(rotate); *rotate = 0; + ASSERT(verbose); *verbose = 0; + ASSERT(type); *type = NULL; + + while (1) { + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, + "Vgo:h:w:r:t:", + long_options, + &option_index); + /* Detect the end of the options. */ + if (c == -1) break; + + if (isgraph(c)) { + INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); + } + +#define SET_STRING_OPTION(name) do { \ + ASSERT(optarg); \ + (*name) = strdup(optarg); \ +} while(0) + +#define SET_INT_OPTION(val) do { \ + ASSERT(optarg); \ + if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \ + FAILIF(1 != sscanf(optarg+2, "%x", val), \ + "Expecting a hexadecimal argument!\n"); \ + } else { \ + FAILIF(1 != sscanf(optarg, "%d", val), \ + "Expecting a decimal argument!\n"); \ + } \ +} while(0) + + switch (c) { + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) + break; + INFO ("option %s", long_options[option_index].name); + if (optarg) + INFO (" with arg %s", optarg); + INFO ("\n"); + break; + case 1: print_help(argv[0]); exit(1); break; + case 'o': + SET_STRING_OPTION(outfile); + break; + case 't': + SET_STRING_OPTION(type); + break; + case 'h': + SET_INT_OPTION(height); + break; + case 'w': + SET_INT_OPTION(width); + break; + case 'r': + SET_INT_OPTION(rotate); + break; + case 'g': *gray = 1; break; + case 'V': *verbose = 1; break; + case '?': + /* getopt_long already printed an error message. */ + break; + +#undef SET_STRING_OPTION +#undef SET_INT_OPTION + + default: + FAILIF(1, "Unknown option"); + } + } + + return optind; +} diff --git a/yuv420sp2rgb/cmdline.h b/yuv420sp2rgb/cmdline.h new file mode 100644 index 0000000..49760ad --- /dev/null +++ b/yuv420sp2rgb/cmdline.h @@ -0,0 +1,15 @@ +#ifndef CMDLINE_H +#define CMDLINE_H + +void print_help(const char *executable_name); + +extern int get_options(int argc, char **argv, + char **outfile, + int *height, + int *width, + int *gray, + char **type, + int *rotate, + int *verbose); + +#endif/*CMDLINE_H*/ diff --git a/yuv420sp2rgb/debug.c b/yuv420sp2rgb/debug.c new file mode 100644 index 0000000..263e09f --- /dev/null +++ b/yuv420sp2rgb/debug.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#define NUM_COLS (32) + +int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) { + int num_nonprintable = 0; + int i, last; + char *pchr = (char *)b; + fputc('\n', s); + fprintf(s, "%p: ", b); + for (i = last = 0; i < len; i++) { + if (!elsize) { + if (i && !(i % 4)) fprintf(s, " "); + if (i && !(i % 8)) fprintf(s, " "); + } else { + if (i && !(i % elsize)) fprintf(s, " "); + } + + if (i && !(i % NUM_COLS)) { + while (last < i) { + if (isprint(pchr[last])) + fputc(pchr[last], s); + else { + fputc('.', s); + num_nonprintable++; + } + last++; + } + fprintf(s, " (%d)\n%p: ", i, b); + } + fprintf(s, "%02x", (unsigned char)pchr[i]); + } + if (i && (i % NUM_COLS)) fputs("\n", s); + return num_nonprintable; +} + diff --git a/yuv420sp2rgb/debug.h b/yuv420sp2rgb/debug.h new file mode 100644 index 0000000..9bbf47f --- /dev/null +++ b/yuv420sp2rgb/debug.h @@ -0,0 +1,90 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include +#include + +#define unlikely(expr) __builtin_expect (expr, 0) +#define likely(expr) __builtin_expect (expr, 1) + +#ifdef DEBUG + + #define FAILIF(cond, msg...) do { \ + if (unlikely(cond)) { \ + fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \ + fprintf(stderr, ##msg); \ + exit(1); \ + } \ +} while(0) + +/* Debug enabled */ + #define ASSERT(x) do { \ + if (unlikely(!(x))) { \ + fprintf(stderr, \ + "ASSERTION FAILURE %s:%d: [%s]\n", \ + __FILE__, __LINE__, #x); \ + exit(1); \ + } \ +} while(0) + +#else + + #define FAILIF(cond, msg...) do { \ + if (unlikely(cond)) { \ + fprintf(stderr, ##msg); \ + exit(1); \ + } \ +} while(0) + +/* No debug */ + #define ASSERT(x) do { } while(0) + +#endif/* DEBUG */ + +#define FAILIF_LIBELF(cond, function) \ + FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno())); + +static inline void *MALLOC(unsigned int size) { + void *m = malloc(size); + FAILIF(NULL == m, "malloc(%d) failed!\n", size); + return m; +} + +static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) { + void *m = calloc(num_entries, entry_size); + FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size); + return m; +} + +static inline void *REALLOC(void *ptr, unsigned int size) { + void *m = realloc(ptr, size); + FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size); + return m; +} + +static inline void FREE(void *ptr) { + free(ptr); +} + +static inline void FREEIF(void *ptr) { + if (ptr) FREE(ptr); +} + +#define PRINT(x...) do { \ + extern int quiet_flag; \ + if(likely(!quiet_flag)) \ + fprintf(stdout, ##x); \ +} while(0) + +#define ERROR PRINT + +#define INFO(x...) do { \ + extern int verbose_flag; \ + if(unlikely(verbose_flag)) \ + fprintf(stdout, ##x); \ +} while(0) + +/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */ +int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize); + +#endif/*DEBUG_H*/ diff --git a/yuv420sp2rgb/yuv420sp2rgb.c b/yuv420sp2rgb/yuv420sp2rgb.c new file mode 100644 index 0000000..c3fc29b --- /dev/null +++ b/yuv420sp2rgb/yuv420sp2rgb.c @@ -0,0 +1,337 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef max +#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) +#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) +#endif + +#define CONVERT_TYPE_PPM 0 +#define CONVERT_TYPE_RGB 1 +#define CONVERT_TYPE_ARGB 2 + +/* + YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved + U/V plane containing 8 bit 2x2 subsampled chroma samples. + except the interleave order of U and V is reversed. + + H V + Y Sample Period 1 1 + U (Cb) Sample Period 2 2 + V (Cr) Sample Period 2 2 + */ + +typedef struct rgb_context { + unsigned char *buffer; + int width; + int height; + int rotate; + int i; + int j; + int size; /* for debugging */ +} rgb_context; + +typedef void (*rgb_cb)( + unsigned char r, + unsigned char g, + unsigned char b, + rgb_context *ctx); + +const int bytes_per_pixel = 2; + +static void color_convert_common( + unsigned char *pY, unsigned char *pUV, + int width, int height, + unsigned char *buffer, + int size, /* buffer size in bytes */ + int gray, + int rotate, + rgb_cb cb) +{ + int i, j; + int nR, nG, nB; + int nY, nU, nV; + rgb_context ctx; + + ctx.buffer = buffer; + ctx.size = size; /* debug */ + ctx.width = width; + ctx.height = height; + ctx.rotate = rotate; + + if (gray) { + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + nB = *(pY + i * width + j); + ctx.i = i; + ctx.j = j; + cb(nB, nB, nB, &ctx); + } + } + } else { + // YUV 4:2:0 + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + nY = *(pY + i * width + j); + nV = *(pUV + (i/2) * width + bytes_per_pixel * (j/2)); + nU = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1); + + // Yuv Convert + nY -= 16; + nU -= 128; + nV -= 128; + + if (nY < 0) + nY = 0; + + // nR = (int)(1.164 * nY + 2.018 * nU); + // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU); + // nB = (int)(1.164 * nY + 1.596 * nV); + + nB = (int)(1192 * nY + 2066 * nU); + nG = (int)(1192 * nY - 833 * nV - 400 * nU); + nR = (int)(1192 * nY + 1634 * nV); + + nR = min(262143, max(0, nR)); + nG = min(262143, max(0, nG)); + nB = min(262143, max(0, nB)); + + nR >>= 10; nR &= 0xff; + nG >>= 10; nG &= 0xff; + nB >>= 10; nB &= 0xff; + + ctx.i = i; + ctx.j = j; + cb(nR, nG, nB, &ctx); + } + } + } +} + +static void rgb16_cb( + unsigned char r, + unsigned char g, + unsigned char b, + rgb_context *ctx) +{ + unsigned short *rgb16 = (unsigned short *)ctx->buffer; + *(rgb16 + ctx->i * ctx->width + ctx->j) = b | (g << 5) | (r << 11); +} + +static void common_rgb_cb( + unsigned char r, + unsigned char g, + unsigned char b, + rgb_context *ctx, + int alpha) +{ + unsigned char *out = ctx->buffer; + int offset = 0; + int bpp; + int i = 0; + switch(ctx->rotate) { + case 0: /* no rotation */ + offset = ctx->i * ctx->width + ctx->j; + break; + case 1: /* 90 degrees */ + offset = ctx->height * (ctx->j + 1) - ctx->i; + break; + case 2: /* 180 degrees */ + offset = (ctx->height - 1 - ctx->i) * ctx->width + ctx->j; + break; + case 3: /* 270 degrees */ + offset = (ctx->width - 1 - ctx->j) * ctx->height + ctx->i; + break; + default: + FAILIF(1, "Unexpected roation value %d!\n", ctx->rotate); + } + + bpp = 3 + !!alpha; + offset *= bpp; + FAILIF(offset < 0, "point (%d, %d) generates a negative offset.\n", ctx->i, ctx->j); + FAILIF(offset + bpp > ctx->size, "point (%d, %d) at offset %d exceeds the size %d of the buffer.\n", + ctx->i, ctx->j, + offset, + ctx->size); + + out += offset; + + if (alpha) out[i++] = 0xff; + out[i++] = r; + out[i++] = g; + out[i] = b; +} + +static void rgb24_cb( + unsigned char r, + unsigned char g, + unsigned char b, + rgb_context *ctx) +{ + return common_rgb_cb(r,g,b,ctx,0); +} + +static void argb_cb( + unsigned char r, + unsigned char g, + unsigned char b, + rgb_context *ctx) +{ + return common_rgb_cb(r,g,b,ctx,1); +} + +static void convert(const char *infile, + const char *outfile, + int height, + int width, + int gray, + int type, + int rotate) +{ + void *in, *out; + int ifd, ofd, rc; + int psz = getpagesize(); + static char header[1024]; + int header_size; + size_t outsize; + + int bpp = 3; + switch (type) { + case CONVERT_TYPE_PPM: + if (rotate & 1) + header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", height, width); + else + header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", width, height); + case CONVERT_TYPE_RGB: + PRINT("encoding raw RGB24\n"); + header_size = 0; + break; + case CONVERT_TYPE_ARGB: + PRINT("encoding raw ARGB\n"); + header_size = 0; + bpp = 4; + break; + } + + outsize = header_size + width * height * bpp; + outsize = (outsize + psz - 1) & ~(psz - 1); + + INFO("Opening input file %s\n", infile); + ifd = open(infile, O_RDONLY); + FAILIF(ifd < 0, "open(%s) failed: %s (%d)\n", + infile, strerror(errno), errno); + + INFO("Opening output file %s\n", outfile); + ofd = open(outfile, O_RDWR | O_CREAT, 0664); + FAILIF(ofd < 0, "open(%s) failed: %s (%d)\n", + outfile, strerror(errno), errno); + + INFO("Memory-mapping input file %s\n", infile); + in = mmap(0, width * height * 3 / 2, PROT_READ, MAP_PRIVATE, ifd, 0); + FAILIF(in == MAP_FAILED, "could not mmap input file: %s (%d)\n", + strerror(errno), errno); + + INFO("Truncating output file %s to %d bytes\n", outfile, outsize); + FAILIF(ftruncate(ofd, outsize) < 0, + "Could not truncate output file to required size: %s (%d)\n", + strerror(errno), errno); + + INFO("Memory mapping output file %s\n", outfile); + out = mmap(0, outsize, PROT_WRITE, MAP_SHARED, ofd, 0); + FAILIF(out == MAP_FAILED, "could not mmap output file: %s (%d)\n", + strerror(errno), errno); + + INFO("PPM header (%d) bytes:\n%s\n", header_size, header); + FAILIF(write(ofd, header, header_size) != header_size, + "Error wrinting PPM header: %s (%d)\n", + strerror(errno), errno); + + INFO("Converting %dx%d YUV 4:2:0 to RGB24...\n", width, height); + color_convert_common(in, in + width * height, + width, height, + out + header_size, outsize - header_size, + gray, rotate, + type == CONVERT_TYPE_ARGB ? argb_cb : rgb24_cb); +} + +int verbose_flag; +int quiet_flag; + +int main(int argc, char **argv) { + + char *infile, *outfile, *type; + int height, width, gray, rotate; + int cmdline_error = 0; + + /* Parse command-line arguments. */ + + int first = get_options(argc, argv, + &outfile, + &height, + &width, + &gray, + &type, + &rotate, + &verbose_flag); + + if (first == argc) { + ERROR("You must specify an input file!\n"); + cmdline_error++; + } + if (!outfile) { + ERROR("You must specify an output file!\n"); + cmdline_error++; + } + if (height < 0 || width < 0) { + ERROR("You must specify both image height and width!\n"); + cmdline_error++; + } + + FAILIF(rotate % 90, "Rotation angle must be a multiple of 90 degrees!\n"); + + rotate /= 90; + rotate %= 4; + if (rotate < 0) rotate += 4; + + if (cmdline_error) { + print_help(argv[0]); + exit(1); + } + + infile = argv[first]; + + INFO("input file: [%s]\n", infile); + INFO("output file: [%s]\n", outfile); + INFO("height: %d\n", height); + INFO("width: %d\n", width); + INFO("gray only: %d\n", gray); + INFO("encode as: %s\n", type); + INFO("rotation: %d\n", rotate); + + /* Convert the image */ + + int conv_type; + if (!strcmp(type, "ppm")) + conv_type = CONVERT_TYPE_PPM; + else if (!strcmp(type, "rgb")) + conv_type = CONVERT_TYPE_RGB; + else if (!strcmp(type, "argb")) + conv_type = CONVERT_TYPE_ARGB; + else FAILIF(1, "Unknown encoding type %s.\n", type); + + convert(infile, outfile, + height, width, gray, + conv_type, + rotate); + + free(outfile); + return 0; +} From 76c233c0a8202f292f38b9aba6d07e08b66a8b9a Mon Sep 17 00:00:00 2001 From: Mathias Agopian <> Date: Wed, 25 Mar 2009 21:43:45 -0700 Subject: [PATCH 026/435] Automated import from //branches/cupcake/...@142857,142857 --- libcopybit/copybit.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libcopybit/copybit.c b/libcopybit/copybit.c index 168de4c..3565074 100644 --- a/libcopybit/copybit.c +++ b/libcopybit/copybit.c @@ -228,6 +228,13 @@ static int set_parameter_copybit( 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; From 800452873e08d10e1b9885df715901ef8f2aedc8 Mon Sep 17 00:00:00 2001 From: Mathias Agopian <> Date: Fri, 27 Mar 2009 15:40:04 -0700 Subject: [PATCH 028/435] AI 143161: am: CL 142857 Add some bluring to the animation. This requires a new kernel which will be checked-in later, at which point the blur effect will automatically be enabled. Original author: mathias Merged from: //branches/cupcake/... Automated import of CL 143161 --- libcopybit/copybit.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libcopybit/copybit.c b/libcopybit/copybit.c index 168de4c..3565074 100644 --- a/libcopybit/copybit.c +++ b/libcopybit/copybit.c @@ -228,6 +228,13 @@ static int set_parameter_copybit( 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; From a6abcb41dd243329a57b13373cbeb8eea26248d7 Mon Sep 17 00:00:00 2001 From: Mathias Agopian <> Date: Fri, 27 Mar 2009 17:59:34 -0700 Subject: [PATCH 031/435] AI 143310: am: CL 143161 am: CL 142857 Add some bluring to the animation. This requires a new kernel which will be checked-in later, at which point the blur effect will automatically be enabled. Original author: mathias Merged from: //branches/cupcake/... Original author: android-build Merged from: //branches/donutburger/... Automated import of CL 143310 --- libcopybit/copybit.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libcopybit/copybit.c b/libcopybit/copybit.c index 168de4c..3565074 100644 --- a/libcopybit/copybit.c +++ b/libcopybit/copybit.c @@ -228,6 +228,13 @@ static int set_parameter_copybit( 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; From e15b9f94b5b1ef62a36fd9b9cec5bbe7e098997a Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Thu, 23 Apr 2009 13:46:40 -0700 Subject: [PATCH 041/435] remove yuv420sp2rgb from hardware/msm7k Signed-off-by: Iliyan Malchev --- yuv420sp2rgb/Android.mk | 16 -- yuv420sp2rgb/cmdline.c | 147 ---------------- yuv420sp2rgb/cmdline.h | 15 -- yuv420sp2rgb/debug.c | 38 ---- yuv420sp2rgb/debug.h | 90 ---------- yuv420sp2rgb/yuv420sp2rgb.c | 337 ------------------------------------ 6 files changed, 643 deletions(-) delete mode 100644 yuv420sp2rgb/Android.mk delete mode 100644 yuv420sp2rgb/cmdline.c delete mode 100644 yuv420sp2rgb/cmdline.h delete mode 100644 yuv420sp2rgb/debug.c delete mode 100644 yuv420sp2rgb/debug.h delete mode 100644 yuv420sp2rgb/yuv420sp2rgb.c diff --git a/yuv420sp2rgb/Android.mk b/yuv420sp2rgb/Android.mk deleted file mode 100644 index 6e6220d..0000000 --- a/yuv420sp2rgb/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2005 Google Inc. All Rights Reserved. -# -# Android.mk for apriori -# - -LOCAL_PATH:= $(call my-dir) - -ifeq ($(TARGET_ARCH),arm) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := yuv420sp2rgb.c cmdline.c debug.c - -LOCAL_MODULE := yuv420sp2rgb - -include $(BUILD_HOST_EXECUTABLE) -endif diff --git a/yuv420sp2rgb/cmdline.c b/yuv420sp2rgb/cmdline.c deleted file mode 100644 index 3bfea99..0000000 --- a/yuv420sp2rgb/cmdline.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern char *optarg; -extern int optind, opterr, optopt; - -static struct option long_options[] = { - {"output", required_argument, 0, 'o'}, - {"height", required_argument, 0, 'h'}, - {"width", required_argument, 0, 'w'}, - {"gray", no_argument, 0, 'g'}, - {"type", required_argument, 0, 't'}, - {"rotate", required_argument, 0, 'r'}, - {"verbose", no_argument, 0, 'V'}, - {"help", no_argument, 0, 1}, - {0, 0, 0, 0}, -}; - -/* This array must parallel long_options[] */ -static const char *descriptions[] = { - "output file", - "image height in pixels", - "image width in pixels", - "process the luma plane only", - "encode as one of { 'ppm', 'rgb', or 'argb' }", - "rotate (90, -90, 180 degrees)", - "print verbose output", - "print this help screen", -}; - -void print_help(const char *name) { - fprintf(stdout, - "Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n" - "invokation:\n" - "\t%s infile --height --width --output [ --gray ] [ --rotate ] [ --verbose ]\n" - "\t%s infile --help\n", - name, name); - fprintf(stdout, "options:\n"); - struct option *opt = long_options; - const char **desc = descriptions; - while (opt->name) { - fprintf(stdout, "\t-%c/--%s%s: %s\n", - isprint(opt->val) ? opt->val : ' ', - opt->name, - (opt->has_arg ? " (argument)" : ""), - *desc); - opt++; - desc++; - } -} - -int get_options(int argc, char **argv, - char **outfile, - int *height, - int *width, - int *gray, - char **type, - int *rotate, - int *verbose) { - int c; - - ASSERT(outfile); *outfile = NULL; - ASSERT(height); *height = -1; - ASSERT(width); *width = -1; - ASSERT(gray); *gray = 0; - ASSERT(rotate); *rotate = 0; - ASSERT(verbose); *verbose = 0; - ASSERT(type); *type = NULL; - - while (1) { - /* getopt_long stores the option index here. */ - int option_index = 0; - - c = getopt_long (argc, argv, - "Vgo:h:w:r:t:", - long_options, - &option_index); - /* Detect the end of the options. */ - if (c == -1) break; - - if (isgraph(c)) { - INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); - } - -#define SET_STRING_OPTION(name) do { \ - ASSERT(optarg); \ - (*name) = strdup(optarg); \ -} while(0) - -#define SET_INT_OPTION(val) do { \ - ASSERT(optarg); \ - if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \ - FAILIF(1 != sscanf(optarg+2, "%x", val), \ - "Expecting a hexadecimal argument!\n"); \ - } else { \ - FAILIF(1 != sscanf(optarg, "%d", val), \ - "Expecting a decimal argument!\n"); \ - } \ -} while(0) - - switch (c) { - case 0: - /* If this option set a flag, do nothing else now. */ - if (long_options[option_index].flag != 0) - break; - INFO ("option %s", long_options[option_index].name); - if (optarg) - INFO (" with arg %s", optarg); - INFO ("\n"); - break; - case 1: print_help(argv[0]); exit(1); break; - case 'o': - SET_STRING_OPTION(outfile); - break; - case 't': - SET_STRING_OPTION(type); - break; - case 'h': - SET_INT_OPTION(height); - break; - case 'w': - SET_INT_OPTION(width); - break; - case 'r': - SET_INT_OPTION(rotate); - break; - case 'g': *gray = 1; break; - case 'V': *verbose = 1; break; - case '?': - /* getopt_long already printed an error message. */ - break; - -#undef SET_STRING_OPTION -#undef SET_INT_OPTION - - default: - FAILIF(1, "Unknown option"); - } - } - - return optind; -} diff --git a/yuv420sp2rgb/cmdline.h b/yuv420sp2rgb/cmdline.h deleted file mode 100644 index 49760ad..0000000 --- a/yuv420sp2rgb/cmdline.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CMDLINE_H -#define CMDLINE_H - -void print_help(const char *executable_name); - -extern int get_options(int argc, char **argv, - char **outfile, - int *height, - int *width, - int *gray, - char **type, - int *rotate, - int *verbose); - -#endif/*CMDLINE_H*/ diff --git a/yuv420sp2rgb/debug.c b/yuv420sp2rgb/debug.c deleted file mode 100644 index 263e09f..0000000 --- a/yuv420sp2rgb/debug.c +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -#define NUM_COLS (32) - -int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) { - int num_nonprintable = 0; - int i, last; - char *pchr = (char *)b; - fputc('\n', s); - fprintf(s, "%p: ", b); - for (i = last = 0; i < len; i++) { - if (!elsize) { - if (i && !(i % 4)) fprintf(s, " "); - if (i && !(i % 8)) fprintf(s, " "); - } else { - if (i && !(i % elsize)) fprintf(s, " "); - } - - if (i && !(i % NUM_COLS)) { - while (last < i) { - if (isprint(pchr[last])) - fputc(pchr[last], s); - else { - fputc('.', s); - num_nonprintable++; - } - last++; - } - fprintf(s, " (%d)\n%p: ", i, b); - } - fprintf(s, "%02x", (unsigned char)pchr[i]); - } - if (i && (i % NUM_COLS)) fputs("\n", s); - return num_nonprintable; -} - diff --git a/yuv420sp2rgb/debug.h b/yuv420sp2rgb/debug.h deleted file mode 100644 index 9bbf47f..0000000 --- a/yuv420sp2rgb/debug.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -#include -#include - -#define unlikely(expr) __builtin_expect (expr, 0) -#define likely(expr) __builtin_expect (expr, 1) - -#ifdef DEBUG - - #define FAILIF(cond, msg...) do { \ - if (unlikely(cond)) { \ - fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \ - fprintf(stderr, ##msg); \ - exit(1); \ - } \ -} while(0) - -/* Debug enabled */ - #define ASSERT(x) do { \ - if (unlikely(!(x))) { \ - fprintf(stderr, \ - "ASSERTION FAILURE %s:%d: [%s]\n", \ - __FILE__, __LINE__, #x); \ - exit(1); \ - } \ -} while(0) - -#else - - #define FAILIF(cond, msg...) do { \ - if (unlikely(cond)) { \ - fprintf(stderr, ##msg); \ - exit(1); \ - } \ -} while(0) - -/* No debug */ - #define ASSERT(x) do { } while(0) - -#endif/* DEBUG */ - -#define FAILIF_LIBELF(cond, function) \ - FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno())); - -static inline void *MALLOC(unsigned int size) { - void *m = malloc(size); - FAILIF(NULL == m, "malloc(%d) failed!\n", size); - return m; -} - -static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) { - void *m = calloc(num_entries, entry_size); - FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size); - return m; -} - -static inline void *REALLOC(void *ptr, unsigned int size) { - void *m = realloc(ptr, size); - FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size); - return m; -} - -static inline void FREE(void *ptr) { - free(ptr); -} - -static inline void FREEIF(void *ptr) { - if (ptr) FREE(ptr); -} - -#define PRINT(x...) do { \ - extern int quiet_flag; \ - if(likely(!quiet_flag)) \ - fprintf(stdout, ##x); \ -} while(0) - -#define ERROR PRINT - -#define INFO(x...) do { \ - extern int verbose_flag; \ - if(unlikely(verbose_flag)) \ - fprintf(stdout, ##x); \ -} while(0) - -/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */ -int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize); - -#endif/*DEBUG_H*/ diff --git a/yuv420sp2rgb/yuv420sp2rgb.c b/yuv420sp2rgb/yuv420sp2rgb.c deleted file mode 100644 index c3fc29b..0000000 --- a/yuv420sp2rgb/yuv420sp2rgb.c +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef max -#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) -#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) -#endif - -#define CONVERT_TYPE_PPM 0 -#define CONVERT_TYPE_RGB 1 -#define CONVERT_TYPE_ARGB 2 - -/* - YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved - U/V plane containing 8 bit 2x2 subsampled chroma samples. - except the interleave order of U and V is reversed. - - H V - Y Sample Period 1 1 - U (Cb) Sample Period 2 2 - V (Cr) Sample Period 2 2 - */ - -typedef struct rgb_context { - unsigned char *buffer; - int width; - int height; - int rotate; - int i; - int j; - int size; /* for debugging */ -} rgb_context; - -typedef void (*rgb_cb)( - unsigned char r, - unsigned char g, - unsigned char b, - rgb_context *ctx); - -const int bytes_per_pixel = 2; - -static void color_convert_common( - unsigned char *pY, unsigned char *pUV, - int width, int height, - unsigned char *buffer, - int size, /* buffer size in bytes */ - int gray, - int rotate, - rgb_cb cb) -{ - int i, j; - int nR, nG, nB; - int nY, nU, nV; - rgb_context ctx; - - ctx.buffer = buffer; - ctx.size = size; /* debug */ - ctx.width = width; - ctx.height = height; - ctx.rotate = rotate; - - if (gray) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - nB = *(pY + i * width + j); - ctx.i = i; - ctx.j = j; - cb(nB, nB, nB, &ctx); - } - } - } else { - // YUV 4:2:0 - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - nY = *(pY + i * width + j); - nV = *(pUV + (i/2) * width + bytes_per_pixel * (j/2)); - nU = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1); - - // Yuv Convert - nY -= 16; - nU -= 128; - nV -= 128; - - if (nY < 0) - nY = 0; - - // nR = (int)(1.164 * nY + 2.018 * nU); - // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU); - // nB = (int)(1.164 * nY + 1.596 * nV); - - nB = (int)(1192 * nY + 2066 * nU); - nG = (int)(1192 * nY - 833 * nV - 400 * nU); - nR = (int)(1192 * nY + 1634 * nV); - - nR = min(262143, max(0, nR)); - nG = min(262143, max(0, nG)); - nB = min(262143, max(0, nB)); - - nR >>= 10; nR &= 0xff; - nG >>= 10; nG &= 0xff; - nB >>= 10; nB &= 0xff; - - ctx.i = i; - ctx.j = j; - cb(nR, nG, nB, &ctx); - } - } - } -} - -static void rgb16_cb( - unsigned char r, - unsigned char g, - unsigned char b, - rgb_context *ctx) -{ - unsigned short *rgb16 = (unsigned short *)ctx->buffer; - *(rgb16 + ctx->i * ctx->width + ctx->j) = b | (g << 5) | (r << 11); -} - -static void common_rgb_cb( - unsigned char r, - unsigned char g, - unsigned char b, - rgb_context *ctx, - int alpha) -{ - unsigned char *out = ctx->buffer; - int offset = 0; - int bpp; - int i = 0; - switch(ctx->rotate) { - case 0: /* no rotation */ - offset = ctx->i * ctx->width + ctx->j; - break; - case 1: /* 90 degrees */ - offset = ctx->height * (ctx->j + 1) - ctx->i; - break; - case 2: /* 180 degrees */ - offset = (ctx->height - 1 - ctx->i) * ctx->width + ctx->j; - break; - case 3: /* 270 degrees */ - offset = (ctx->width - 1 - ctx->j) * ctx->height + ctx->i; - break; - default: - FAILIF(1, "Unexpected roation value %d!\n", ctx->rotate); - } - - bpp = 3 + !!alpha; - offset *= bpp; - FAILIF(offset < 0, "point (%d, %d) generates a negative offset.\n", ctx->i, ctx->j); - FAILIF(offset + bpp > ctx->size, "point (%d, %d) at offset %d exceeds the size %d of the buffer.\n", - ctx->i, ctx->j, - offset, - ctx->size); - - out += offset; - - if (alpha) out[i++] = 0xff; - out[i++] = r; - out[i++] = g; - out[i] = b; -} - -static void rgb24_cb( - unsigned char r, - unsigned char g, - unsigned char b, - rgb_context *ctx) -{ - return common_rgb_cb(r,g,b,ctx,0); -} - -static void argb_cb( - unsigned char r, - unsigned char g, - unsigned char b, - rgb_context *ctx) -{ - return common_rgb_cb(r,g,b,ctx,1); -} - -static void convert(const char *infile, - const char *outfile, - int height, - int width, - int gray, - int type, - int rotate) -{ - void *in, *out; - int ifd, ofd, rc; - int psz = getpagesize(); - static char header[1024]; - int header_size; - size_t outsize; - - int bpp = 3; - switch (type) { - case CONVERT_TYPE_PPM: - if (rotate & 1) - header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", height, width); - else - header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", width, height); - case CONVERT_TYPE_RGB: - PRINT("encoding raw RGB24\n"); - header_size = 0; - break; - case CONVERT_TYPE_ARGB: - PRINT("encoding raw ARGB\n"); - header_size = 0; - bpp = 4; - break; - } - - outsize = header_size + width * height * bpp; - outsize = (outsize + psz - 1) & ~(psz - 1); - - INFO("Opening input file %s\n", infile); - ifd = open(infile, O_RDONLY); - FAILIF(ifd < 0, "open(%s) failed: %s (%d)\n", - infile, strerror(errno), errno); - - INFO("Opening output file %s\n", outfile); - ofd = open(outfile, O_RDWR | O_CREAT, 0664); - FAILIF(ofd < 0, "open(%s) failed: %s (%d)\n", - outfile, strerror(errno), errno); - - INFO("Memory-mapping input file %s\n", infile); - in = mmap(0, width * height * 3 / 2, PROT_READ, MAP_PRIVATE, ifd, 0); - FAILIF(in == MAP_FAILED, "could not mmap input file: %s (%d)\n", - strerror(errno), errno); - - INFO("Truncating output file %s to %d bytes\n", outfile, outsize); - FAILIF(ftruncate(ofd, outsize) < 0, - "Could not truncate output file to required size: %s (%d)\n", - strerror(errno), errno); - - INFO("Memory mapping output file %s\n", outfile); - out = mmap(0, outsize, PROT_WRITE, MAP_SHARED, ofd, 0); - FAILIF(out == MAP_FAILED, "could not mmap output file: %s (%d)\n", - strerror(errno), errno); - - INFO("PPM header (%d) bytes:\n%s\n", header_size, header); - FAILIF(write(ofd, header, header_size) != header_size, - "Error wrinting PPM header: %s (%d)\n", - strerror(errno), errno); - - INFO("Converting %dx%d YUV 4:2:0 to RGB24...\n", width, height); - color_convert_common(in, in + width * height, - width, height, - out + header_size, outsize - header_size, - gray, rotate, - type == CONVERT_TYPE_ARGB ? argb_cb : rgb24_cb); -} - -int verbose_flag; -int quiet_flag; - -int main(int argc, char **argv) { - - char *infile, *outfile, *type; - int height, width, gray, rotate; - int cmdline_error = 0; - - /* Parse command-line arguments. */ - - int first = get_options(argc, argv, - &outfile, - &height, - &width, - &gray, - &type, - &rotate, - &verbose_flag); - - if (first == argc) { - ERROR("You must specify an input file!\n"); - cmdline_error++; - } - if (!outfile) { - ERROR("You must specify an output file!\n"); - cmdline_error++; - } - if (height < 0 || width < 0) { - ERROR("You must specify both image height and width!\n"); - cmdline_error++; - } - - FAILIF(rotate % 90, "Rotation angle must be a multiple of 90 degrees!\n"); - - rotate /= 90; - rotate %= 4; - if (rotate < 0) rotate += 4; - - if (cmdline_error) { - print_help(argv[0]); - exit(1); - } - - infile = argv[first]; - - INFO("input file: [%s]\n", infile); - INFO("output file: [%s]\n", outfile); - INFO("height: %d\n", height); - INFO("width: %d\n", width); - INFO("gray only: %d\n", gray); - INFO("encode as: %s\n", type); - INFO("rotation: %d\n", rotate); - - /* Convert the image */ - - int conv_type; - if (!strcmp(type, "ppm")) - conv_type = CONVERT_TYPE_PPM; - else if (!strcmp(type, "rgb")) - conv_type = CONVERT_TYPE_RGB; - else if (!strcmp(type, "argb")) - conv_type = CONVERT_TYPE_ARGB; - else FAILIF(1, "Unknown encoding type %s.\n", type); - - convert(infile, outfile, - height, width, gray, - conv_type, - rotate); - - free(outfile); - return 0; -} From 5b08cc9343f6d14b6b5c9a943de38632fb78c805 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Thu, 30 Apr 2009 12:19:03 -0700 Subject: [PATCH 048/435] Add new implementation of libcamera (as libcamera2) (disabled) libcamera2 uses code under vendor/qcom/proprietary/mm-camera, which is the (Qualcomm proprietary) user-space component of the new camera framework. Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 35 + libcamera2/QualcommCameraHardware.cpp | 2136 +++++++++++++++++++++++++ libcamera2/QualcommCameraHardware.h | 286 ++++ 3 files changed, 2457 insertions(+) create mode 100755 libcamera2/Android.mk create mode 100755 libcamera2/QualcommCameraHardware.cpp create mode 100755 libcamera2/QualcommCameraHardware.h diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk new file mode 100755 index 0000000..dab1c17 --- /dev/null +++ b/libcamera2/Android.mk @@ -0,0 +1,35 @@ +BUILD_LIBCAMERA:= +ifeq ($(BUILD_LIBCAMERA),true) + +# When zero we link against libmmcamera; when 1, we dlopen libmmcamera. +DLOPEN_LIBMMCAMERA:=1 + +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= QualcommCameraHardware.cpp + +LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA) + +LOCAL_C_INCLUDES+= \ + vendor/qcom/proprietary/mm-camera/common \ + vendor/qcom/proprietary/mm-camera/apps/appslib \ + vendor/qcom/proprietary/mm-camera/jpeg \ + vendor/qcom/proprietary/mm-camera/jpeg/inc + +LOCAL_SHARED_LIBRARIES:= libutils libui liblog + +ifneq ($(DLOPEN_LIBMMCAMERA),1) +LOCAL_SHARED_LIBRARIES+= libmmcamera +else +LOCAL_SHARED_LIBRARIES+= libdl +endif + +LOCAL_MODULE:= libcamera +include $(BUILD_SHARED_LIBRARY) + +endif # BUILD_TINY_ANDROID +endif # BUILD_LIBCAMERA diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp new file mode 100755 index 0000000..2209c8e --- /dev/null +++ b/libcamera2/QualcommCameraHardware.cpp @@ -0,0 +1,2136 @@ +/* +** Copyright 2008, Google Inc. +** +** 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_NDEBUG 0 +#define LOG_TAG "QualcommCameraHardware" +#include + +#include "QualcommCameraHardware.h" + +#include +#include +#include +#include +#include +#include +#if HAVE_ANDROID_OS +#include +#endif +#include + +#define CAPTURE_RAW 0 +#define LIKELY(exp) __builtin_expect(!!(exp), 1) +#define UNLIKELY(exp) __builtin_expect(!!(exp), 0) + +extern "C" { + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define THUMBNAIL_WIDTH 512 +#define THUMBNAIL_HEIGHT 384 +#define THUMBNAIL_WIDTH_STR "512" +#define THUMBNAIL_HEIGHT_STR "384" +#define DEFAULT_PICTURE_WIDTH 2048 // 1280 +#define DEFAULT_PICTURE_HEIGHT 1536 // 768 +#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) + +#define DEFAULT_PREVIEW_SETTING 2 // HVGA +#define MAX_ZOOM_STEPS 6 +#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) + +#define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values +#define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values + +#if DLOPEN_LIBMMCAMERA +#include + +void* (*LINK_cam_conf)(void *data); +void* (*LINK_cam_frame)(void *data); +bool (*LINK_jpeg_encoder_init)(); +void (*LINK_jpeg_encoder_join)(); +bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, + const uint8_t *thumbnailbuf, int thumbnailfd, + const uint8_t *snapshotbuf, int snapshotfd); +int (*LINK_camframe_terminate)(void); +int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); +// callbacks +void (**LINK_mmcamera_camframe_callback)(struct msm_frame_t *frame); +void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, + uint32_t buff_size); +void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); +#else +#define LINK_cam_conf cam_conf +#define LINK_cam_frame cam_frame +#define LINK_jpeg_encoder_init jpeg_encoder_init +#define LINK_jpeg_encoder_join jpeg_encoder_join +#define LINK_jpeg_encoder_encode jpeg_encoder_encode +#define LINK_camframe_terminate camframe_terminate +#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality +extern void (*mmcamera_camframe_callback)(struct msm_frame_t *frame); +extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, + uint32_t buff_size); +extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); +#endif + +} // extern "C" + +struct preview_size_type { + int width; + int height; +}; + +static preview_size_type preview_sizes[] = { + { 800, 480 }, // WVGA + { 640, 480 }, // VGA + { 480, 320 }, // HVGA + { 352, 288 }, // CIF + { 320, 240 }, // QVGA + { 176, 144 }, // QCIF +}; + +struct str_map { + const char *const desc; + int val; +}; + +static int attr_lookup(const struct str_map *const arr, + const char *name, + int def) +{ + if (name) { + const struct str_map *trav = arr; + while (trav->desc) { + if (!strcmp(trav->desc, name)) + return trav->val; + trav++; + } + } + return def; +} + +#define INIT_VALUES_FOR(parm) do { \ + if (!parm##_values) { \ + parm##_values = (char *)malloc(sizeof(parm)/ \ + sizeof(parm[0])*30); \ + char *ptr = parm##_values; \ + const str_map *trav; \ + for (trav = parm; trav->desc; trav++) { \ + int len = strlen(trav->desc); \ + strcpy(ptr, trav->desc); \ + ptr += len; \ + *ptr++ = ','; \ + } \ + *--ptr = 0; \ + } \ +} while(0) + +// from aeecamera.h +static const str_map whitebalance[] = { + { "auto", CAMERA_WB_AUTO }, + { "custom", CAMERA_WB_CUSTOM }, + { "incandescent", CAMERA_WB_INCANDESCENT }, + { "florescent", CAMERA_WB_FLUORESCENT }, + { "daylight", CAMERA_WB_DAYLIGHT }, + { "cloudy", CAMERA_WB_CLOUDY_DAYLIGHT }, + { "twilight", CAMERA_WB_TWILIGHT }, + { "shade", CAMERA_WB_SHADE }, + { NULL, 0 } +}; +static char *whitebalance_values; + +// from camera_effect_t +static const str_map color_effects[] = { + { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ + { "mono", CAMERA_EFFECT_MONO }, + { "negative", CAMERA_EFFECT_NEGATIVE }, + { "solarize", CAMERA_EFFECT_SOLARIZE }, + { "pastel", CAMERA_EFFECT_PASTEL }, + { "mosaic", CAMERA_EFFECT_MOSAIC }, + { "resize", CAMERA_EFFECT_RESIZE }, + { "sepia", CAMERA_EFFECT_SEPIA }, + { "postersize", CAMERA_EFFECT_POSTERIZE }, + { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, + { "blackboard", CAMERA_EFFECT_BLACKBOARD }, + { "aqua", CAMERA_EFFECT_AQUA }, + { NULL, 0 } +}; +static char *color_effects_values; + +// from qcamera/common/camera.h +static const str_map anti_banding[] = { + { "off", CAMERA_ANTIBANDING_OFF }, + { "60hz", CAMERA_ANTIBANDING_60HZ }, + { "50hz", CAMERA_ANTIBANDING_50HZ }, + { "auto", CAMERA_ANTIBANDING_AUTO }, + { NULL, 0 } +}; +static char *anti_banding_values; + +// round to the next power of two +static inline unsigned clp2(unsigned x) +{ + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + +namespace android { + +static Mutex singleton_lock; + +static void receive_camframe_callback(struct msm_frame_t *frame); +static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); +static void receive_jpeg_callback(jpeg_event_t status); +static uint8_t *hal_mmap (uint32_t size, int *pmemFd); +static int hal_munmap (int pmem_fd, void *addr, size_t size); + +static uint8_t* hal_mmap(uint32_t size, int *pmemFd) +{ + void *ret; /* returned virtual address */ + int pmem_fd = open("/dev/pmem_adsp", O_RDWR); + + if (pmem_fd < 0) { + LOGE("hal_mmap: open /dev/pmem_adsp error %s!", + strerror(errno)); + return NULL; + } + + /* to make it page size aligned */ + // FIXME: use clp2() here + size = (size + 4095) & (~4095); + + LOGV("hal_mmap: pmem_fd %d size: %d", pmem_fd, size); + + ret = mmap(NULL, + size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + pmem_fd, + 0); + + if (ret == MAP_FAILED) { + LOGE("hal_mmap: pmem mmap() error %s", strerror(errno)); + close(pmem_fd); + return NULL; + } + + *pmemFd = pmem_fd; + return (uint8_t *)ret; +} + +static int hal_munmap (int pmem_fd, void *addr, size_t size) +{ + int rc; + + // FIXME: use clp2()? + size = (size + 4095) & (~4095); + + LOGV("hal_munmap pmem_fd %d, size = %d, virt_addr = 0x%x", + pmem_fd, + size, (uint32_t)addr); + + rc = munmap(addr, size); + if (rc < 0) + LOGE("hal_munmap: munmap error %s", strerror(errno)); + + close(pmem_fd); + return rc; +} + +QualcommCameraHardware::QualcommCameraHardware() + : mParameters(), + mPreviewHeight(-1), + mPreviewWidth(-1), + mRawHeight(-1), + mRawWidth(-1), + mBrightness(0), + mZoomValuePrev(0), + mZoomValueCurr(0), + mZoomInitialised(false), + mCameraRunning(false), + mPreviewInitialized(false), + mFrameThreadRunning(false), + mReleasedRecordingFrame(false), + mShutterCallback(0), + mRawPictureCallback(0), + mJpegPictureCallback(0), + mPictureCallbackCookie(0), + mAutoFocusCallback(0), + mAutoFocusCallbackCookie(0), + mPreviewCallback(0), + mPreviewCallbackCookie(0), + mRecordingCallback(0), + mRecordingCallbackCookie(0), + mPreviewFrameSize(0), + mRawSize(0), + mCameraControlFd(-1), + mPmemThumbnailFd(-1), + mPmemSnapshotFd(-1), + mPreviewFrameOffset(0), + mThumbnailBuf(NULL), + mMainImageBuf(NULL), + mAutoFocusThreadRunning(false), + mAutoFocusFd(-1), + mInPreviewCallback(false) +{ + memset(&mZoom, 0, sizeof(mZoom)); + memset(&mFrameThread, 0, sizeof(mFrameThread)); + LOGV("constructor EX"); +} + +void QualcommCameraHardware::initDefaultParameters() +{ + CameraParameters p; + + LOGV("initDefaultParameters E"); + + preview_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING]; + p.setPreviewSize(ps->width, ps->height); + p.setPreviewFrameRate(15); + p.setPreviewFormat("yuv420sp"); // informative + p.setPictureFormat("jpeg"); // informative + + memset(&mDimension, 0, sizeof(mDimension)); + + mDimension.picture_width = DEFAULT_PICTURE_WIDTH; + mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; + mDimension.display_width = ps->width; + mDimension.display_height = ps->height; + mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH; + mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT; + + p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative + p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative + //p.set("jpeg-thumbnail-quality", "90"); // FIXME: hook up through mm-camera + p.setPictureSize(mDimension.picture_width, mDimension.picture_height); + +#if 0 + p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 + p.set("gps-latitude", "37.736071"); // A little house in San Francisco + p.set("gps-longitude", "-122.441983"); + p.set("gps-altitude", "21"); // meters +#endif + + // This will happen only one in the lifetime of the mediaserver process. + // We do not free the _values arrays when we destroy the camera object. + INIT_VALUES_FOR(anti_banding); + INIT_VALUES_FOR(color_effects); + INIT_VALUES_FOR(whitebalance); + + p.set("anti-banding-values", anti_banding_values); + p.set("color-effects-values", color_effects_values); + p.set("whitebalance-values", whitebalance_values); + + // FIXME: we can specify these numeric ranges better + p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); + p.set("zoom-values", "0,1,2,3,4,5,6,7,8,9,10"); + + if (setParameters(p) != NO_ERROR) { + LOGE("Failed to set default parameters?!"); + } + + LOGV("initDefaultParameters X"); +} + +#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff) + +void QualcommCameraHardware::startCamera() +{ + LOGV("startCamera E"); +#if DLOPEN_LIBMMCAMERA + libmmcamera = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("loading libqcamera at %p", libmmcamera); + if (!libmmcamera) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + return; + } + + *(void **)&LINK_cam_frame = + ::dlsym(libmmcamera, "cam_frame"); + *(void **)&LINK_camframe_terminate = + ::dlsym(libmmcamera, "camframe_terminate"); + + *(void **)&LINK_jpeg_encoder_init = + ::dlsym(libmmcamera, "jpeg_encoder_init"); + + *(void **)&LINK_jpeg_encoder_encode = + ::dlsym(libmmcamera, "jpeg_encoder_encode"); + + *(void **)&LINK_jpeg_encoder_join = + ::dlsym(libmmcamera, "jpeg_encoder_join"); + + *(void **)&LINK_mmcamera_camframe_callback = + ::dlsym(libmmcamera, "mmcamera_camframe_callback"); + + *LINK_mmcamera_camframe_callback = receive_camframe_callback; + + *(void **)&LINK_mmcamera_jpegfragment_callback = + ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback"); + + *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; + + *(void **)&LINK_mmcamera_jpeg_callback = + ::dlsym(libmmcamera, "mmcamera_jpeg_callback"); + + *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; + + *(void**)&LINK_jpeg_encoder_setMainImageQuality = + ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); + + *(void **)&LINK_cam_conf = + ::dlsym(libmmcamera, "cam_conf"); +#else + mmcamera_camframe_callback = receive_camframe_callback; + mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; + mmcamera_jpeg_callback = receive_jpeg_callback; +#endif // DLOPEN_LIBMMCAMERA + + /* The control thread is in libcamera itself. */ + mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR); + if (mCameraControlFd < 0) { + LOGE("startCamera X: %s open failed: %s!", + MSM_CAMERA_CONTROL, + strerror(errno)); + return; + } + + pthread_create(&mCamConfigThread, NULL, + LINK_cam_conf, NULL); + + LOGE("startCamera X"); +} + +status_t QualcommCameraHardware::dump(int fd, + const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + + // Dump internal primitives. + result.append("QualcommCameraHardware::dump"); + snprintf(buffer, 255, "preview width(%d) x height (%d)\n", + mPreviewWidth, mPreviewHeight); + result.append(buffer); + snprintf(buffer, 255, "raw width(%d) x height (%d)\n", + mRawWidth, mRawHeight); + result.append(buffer); + snprintf(buffer, 255, + "preview frame size(%d), raw size (%d), jpeg size (%d) " + "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize, + mJpegSize, mJpegMaxSize); + result.append(buffer); + write(fd, result.string(), result.size()); + + // Dump internal objects. + if (mPreviewHeap != 0) { + mPreviewHeap->dump(fd, args); + } + if (mRawHeap != 0) { + mRawHeap->dump(fd, args); + } + if (mJpegHeap != 0) { + mJpegHeap->dump(fd, args); + } + mParameters.dump(fd, args); + return NO_ERROR; +} + +bool QualcommCameraHardware::native_set_dimension(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(cam_ctrl_dimension_t); + ctrlCmd.value = &mDimension; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_set_dimension: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return ctrlCmd.status; +} + +bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) +{ + int rc; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; + ctrlCmd.length = sizeof(af_type); + ctrlCmd.value = &af_type; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) + LOGE("native_set_afmode: ioctl fd %d error %s\n", + camfd, + strerror(errno)); + + LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status); + return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; +} + +bool native_cancel_afmode(int camfd, int af_fd) +{ + int rc; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = af_fd; + + if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0) + LOGE("native_cancel_afmode: ioctl fd %d error %s\n", + camfd, + strerror(errno)); + return rc >= 0; +} + +void QualcommCameraHardware::reg_unreg_buf( + int camfd, + int width, + int height, + int pmempreviewfd, + uint8_t *prev_buf, + int pmem_type, + bool unregister, + bool active) +{ + uint32_t y_size; + struct msm_pmem_info_t pmemBuf; + uint32_t ioctl_cmd; + + if (prev_buf == NULL) + return; + + y_size = width * height; + + pmemBuf.type = pmem_type; + pmemBuf.fd = pmempreviewfd; + pmemBuf.vaddr = prev_buf; + pmemBuf.y_off = 0; + pmemBuf.cbcr_off = PAD_TO_WORD(y_size); + pmemBuf.active = active; + + ioctl_cmd = unregister ? + MSM_CAM_IOCTL_UNREGISTER_PMEM : + MSM_CAM_IOCTL_REGISTER_PMEM; + + LOGV("Entered reg_unreg_buf: camfd = %d, ioctl_cmd = %d, " + "pmemBuf.cbcr_off=%d, active=%d", + camfd, ioctl_cmd, pmemBuf.cbcr_off, active); + if (ioctl(camfd, ioctl_cmd, &pmemBuf) < 0) { + LOGE("reg_unreg_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", + camfd, + strerror(errno)); + } +} + +bool QualcommCameraHardware::native_register_preview_bufs( + int camfd, + struct msm_frame_t *frame, + bool active) +{ + LOGV("mDimension.display_width = %d, display_height = %d", + mDimension.display_width, mDimension.display_height); + + reg_unreg_buf(camfd, + mDimension.display_width, + mDimension.display_height, + frame->fd, + (uint8_t *)frame->buffer, + MSM_PMEM_OUTPUT2, + false, + active); + + return true; +} + +bool QualcommCameraHardware::native_unregister_preview_bufs( + int camfd, + int pmempreviewfd, + uint8_t *prev_buf) +{ + reg_unreg_buf(camfd, + mDimension.display_width, + mDimension.display_height, + pmempreviewfd, + prev_buf, + MSM_PMEM_OUTPUT2, + true, + true); + return true; +} + +bool QualcommCameraHardware::native_start_preview(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_START_PREVIEW; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_register_snapshot_bufs( + int camfd, + int pmemthumbnailfd, + int pmemsnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + reg_unreg_buf(camfd, + mDimension.thumbnail_width, + mDimension.thumbnail_height, + pmemthumbnailfd, + thumbnail_buf, + MSM_PMEM_THUMBAIL, + false, + true); + + /* For original snapshot*/ + reg_unreg_buf(camfd, + mDimension.orig_picture_dx, + mDimension.orig_picture_dy, + pmemsnapshotfd, + main_img_buf, + MSM_PMEM_MAINIMG, + false, + true); + return true; +} + +bool QualcommCameraHardware::native_unregister_snapshot_bufs( + int camfd, + int thumb_fd, + int snap_fd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + reg_unreg_buf(camfd, + mDimension.thumbnail_width, + mDimension.thumbnail_height, + thumb_fd, + thumbnail_buf, + MSM_PMEM_THUMBAIL, + true, + true); + + /* For original snapshot*/ + reg_unreg_buf(camfd, + mDimension.orig_picture_dx, + mDimension.orig_picture_dy, + snap_fd, + main_img_buf, + MSM_PMEM_MAINIMG, + true, + true); + + return true; +} + +bool QualcommCameraHardware::native_get_picture (int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = 0; + + if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { + LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_stop_preview(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_STOP_PREVIEW; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_stop_preview: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_start_snapshot(int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_START_SNAPSHOT; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_start_snapshot: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_stop_snapshot (int camfd) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_STOP_SNAPSHOT; + ctrlCmd.length = 0; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_stop_snapshot: ioctl fd %d error %s", + camfd, + strerror(errno)); + return false; + } + + return true; +} + +bool QualcommCameraHardware::native_jpeg_encode ( + int thumb_fd, + int snap_fd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf) +{ + int jpeg_quality = mParameters.getInt("jpeg-quality"); + if (jpeg_quality >= 0) { + LOGV("native_jpeg_encode, current jpeg main img quality =%d", + jpeg_quality); + if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { + LOGE("native_jpeg_encode set failed"); + return false; + } + } + + if (!LINK_jpeg_encoder_encode(&mDimension, + thumbnail_buf, thumb_fd, + main_img_buf, snap_fd)) { + LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); + return false; + } + return true; +} + +void QualcommCameraHardware::runFrameThread(void *data) +{ + LOGV("runFrameThread E"); + + int cnt; + +#if DLOPEN_LIBMMCAMERA + // We need to maintain a reference to libqcamera.so for the duration of the + // frame thread, because we do not know when it will exit relative to the + // lifetime of this object. We do not want to dlclose() libqcamera while + // LINK_cam_frame is still running. + void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("loading libqcamera at %p", libhandle); + if (!libhandle) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + } + if (libhandle) +#endif + { + LINK_cam_frame(data); + } + + for (cnt = 0; cnt < kPreviewBufferCount; ++cnt) { + LOGV("unregisterPreviewBuf %d", cnt); + native_unregister_preview_bufs(mCameraControlFd, + frames[cnt].fd, + (uint8_t *)frames[cnt].buffer); + LOGV("do_munmap preview buffer %d, fd=%d, prev_buf=0x%lx, size=%d", + cnt, frames[cnt].fd, frames[cnt].buffer,frame_size); + int rc = hal_munmap(frames[cnt].fd, + (uint8_t *)frames[cnt].buffer,frame_size); + LOGV("do_munmap done with return value %d", rc); + } + LOGV("unregisterPreviewBuf %d", cnt); + mPreviewHeap.clear(); + +#if DLOPEN_LIBMMCAMERA + if (libhandle) { + ::dlclose(libhandle); + LOGV("FRAME: dlclose(libqcamera)"); + } +#endif + + mFrameThreadWaitLock.lock(); + mFrameThreadRunning = false; + mFrameThreadWait.signal(); + mFrameThreadWaitLock.unlock(); + + LOGV("runFrameThread X"); +} + +void *frame_thread(void *user) +{ + LOGV("frame_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runFrameThread(user); + } + else LOGW("not starting frame thread: the object went away!"); + LOGV("frame_thread X"); + return NULL; +} + +bool QualcommCameraHardware::initPreview() +{ + // See comments in deinitPreview() for why we have to wait for the frame + // thread here, and why we can't use pthread_join(). + LOGI("initPreview E: preview size=%dx%d", mPreviewWidth, mPreviewHeight); + mFrameThreadWaitLock.lock(); + while (mFrameThreadRunning) { + LOGV("initPreview: waiting for old frame thread to complete."); + mFrameThreadWait.wait(mFrameThreadWaitLock); + LOGV("initPreview: old frame thread completed."); + } + mFrameThreadWaitLock.unlock(); + + int cnt = 0; + mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; + mPreviewHeap = + new PreviewPmemPool(kRawFrameHeaderSize + + mPreviewWidth * mPreviewHeight * 3/2, + kPreviewBufferCount, + mPreviewFrameSize, + kRawFrameHeaderSize, + "preview"); + + if (!mPreviewHeap->initialized()) { + mPreviewHeap.clear(); + LOGE("initPreview X: could not initialize preview heap."); + return false; + } + + bool ret = true; + + mDimension.picture_width = DEFAULT_PICTURE_WIDTH; + mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; + + ret = native_set_dimension(mCameraControlFd); + if(ret) { + frame_size = (clp2(mDimension.display_width * + mDimension.display_height * 3/2)); + for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { + frames[cnt].fd = 0; + frames[cnt].buffer = + (unsigned long)hal_mmap(frame_size, &(frames[cnt].fd)); + frames[cnt].y_off = 0; + frames[cnt].cbcr_off = + mDimension.display_width * mDimension.display_height; + + if (frames[cnt].buffer == 0) { + LOGE("initPreview X: mmap failed!"); + return false; + } + + frames[cnt].path = MSM_FRAME_ENC; + + LOGV("do_mmap pbuf = 0x%lx, pmem_fd = %d", + frames[cnt].buffer, frames[cnt].fd); + native_register_preview_bufs(mCameraControlFd, + &frames[cnt], + cnt != kPreviewBufferCount - 1); + } + + + mFrameThreadWaitLock.lock(); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mFrameThreadRunning = !pthread_create(&mFrameThread, + &attr, + frame_thread, + &frames[kPreviewBufferCount-1]); + ret = mFrameThreadRunning; + mFrameThreadWaitLock.unlock(); + } + + LOGV("initPreview X: %d", ret); + return ret; +} + +void QualcommCameraHardware::deinitPreview(void) +{ + LOGI("deinitPreview E"); + + // When we call deinitPreview(), we signal to the frame thread that it + // needs to exit, but we DO NOT WAIT for it to complete here. The problem + // is that deinitPreview is sometimes called from the frame-thread's + // callback, when the refcount on the Camera client reaches zero. If we + // called pthread_join(), we would deadlock. So, we just call + // LINK_camframe_terminate() in deinitPreview(), which makes sure that + // after the preview callback returns, the camframe thread will exit. We + // could call pthread_join() in initPreview() to join the last frame + // thread. However, we would also have to call pthread_join() in release + // as well, shortly before we destoy the object; this would cause the same + // deadlock, since release(), like deinitPreview(), may also be called from + // the frame-thread's callback. This we have to make the frame thread + // detached, and use a separate mechanism to wait for it to complete. + + if (LINK_camframe_terminate() < 0) + LOGE("failed to stop the camframe thread: %s", + strerror(errno)); + LOGI("deinitPreview X"); +} + +bool QualcommCameraHardware::initRaw(bool initJpegHeap) +{ + LOGV("initRaw E: picture size=%dx%d", + mRawWidth, mRawHeight); + + mDimension.picture_width = mRawWidth; + mDimension.picture_height = mRawHeight; + + if(!native_set_dimension(mCameraControlFd)) { + LOGE("initRaw X: failed to set dimension"); + return false; + } + + mRawSize = mRawWidth * mRawHeight * 1.5; + + mJpegMaxSize = mRawWidth * mRawHeight * 1.5; + + LOGE("initRaw: clearing old mJpegHeap."); + mJpegHeap.clear(); + + // Snapshot + + LOGV("initRaw: initializing mRawHeap."); + mRawHeap = + new RawPmemPool("/dev/pmem_camera", + kRawFrameHeaderSize + mJpegMaxSize, + kRawBufferCount, + mRawSize, + kRawFrameHeaderSize, + "snapshot camera"); + + if (!mRawHeap->initialized()) { + LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); + mRawHeap = + new RawPmemPool("/dev/pmem_adsp", + kRawFrameHeaderSize + mJpegMaxSize, + kRawBufferCount, + mRawSize, + kRawFrameHeaderSize, + "snapshot camera"); + if (!mRawHeap->initialized()) { + LOGE("initRaw X: error initializing mRawHeap"); + mRawHeap.clear(); + return false; + } + } + + mMainImageBuf = (uint8_t *)mRawHeap->mHeap->base(); + mPmemSnapshotFd = mRawHeap->mHeap->getHeapID(); + + LOGV("do_mmap snapshot pbuf = 0x%p, pmem_fd = %d", + mMainImageBuf, mPmemSnapshotFd); + + // Thumbnails + + mThumbnailBuf = hal_mmap(THUMBNAIL_BUFFER_SIZE, &mPmemThumbnailFd); + LOGV("do_mmap thumbnail pbuf = 0x%p, pmem_fd = %d", + mThumbnailBuf, mPmemThumbnailFd); + if (mThumbnailBuf == NULL) { + mRawHeap.clear(); + LOGE("initRaw X: cannot allocate thumbnail memory"); + return false; + } + + native_register_snapshot_bufs(mCameraControlFd, + mPmemThumbnailFd, + mPmemSnapshotFd, + mThumbnailBuf, + mMainImageBuf); + + // Jpeg + + if (initJpegHeap) { + LOGV("initRaw: initializing mJpegHeap."); + mJpegHeap = + new AshmemPool(mJpegMaxSize, + kJpegBufferCount, + 0, // we do not know how big the picture wil be + 0, + "jpeg"); + if (!mJpegHeap->initialized()) { + LOGE("initRaw X failed: error initializing mJpegHeap."); + mJpegHeap.clear(); + mRawHeap.clear(); + return false; + } + } + + LOGV("initRaw X"); + return true; +} + +void QualcommCameraHardware::deinitRaw() +{ + LOGV("deinitRaw E"); + mJpegHeap.clear(); + mRawHeap.clear(); + + native_unregister_snapshot_bufs(mCameraControlFd, + mPmemThumbnailFd, mPmemSnapshotFd, + mThumbnailBuf, mMainImageBuf); + + if (mThumbnailBuf) { + hal_munmap(mPmemThumbnailFd, mThumbnailBuf, THUMBNAIL_BUFFER_SIZE); + mThumbnailBuf = NULL; + } + LOGV("deinitRaw X"); +} + +void QualcommCameraHardware::release() +{ + LOGV("release E"); + Mutex::Autolock l(&mLock); + + if (libmmcamera == NULL) { + LOGE("ERROR: multiple release!"); + return; + } + + int cnt, rc; + struct msm_ctrl_cmd_t ctrlCmd; + + if (mCameraRunning) { + cancelAutoFocus(); + if(mRecordingCallback != NULL) { + mRecordFrameLock.lock(); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + mRecordFrameLock.unlock(); + } + stopPreviewInternal(); + } + + LINK_jpeg_encoder_join(); + deinitRaw(); + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = 0; + ctrlCmd.type = (uint16_t)CAMERA_EXIT; + ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("ioctl CAMERA_EXIT fd %d error %s", + mCameraControlFd, strerror(errno)); + rc = pthread_join(mCamConfigThread, NULL); + if (rc) + LOGE("config_thread exit failure: %s", strerror(errno)); + else + LOGV("pthread_join succeeded on config_thread"); + + close(mCameraControlFd); + mCameraControlFd = -1; + +#if DLOPEN_LIBMMCAMERA + if (libmmcamera) { + ::dlclose(libmmcamera); + LOGV("dlclose(libqcamera)"); + libmmcamera = NULL; + } +#endif + + LOGV("release X"); +} + +QualcommCameraHardware::~QualcommCameraHardware() +{ + LOGV("~QualcommCameraHardware E"); + singleton.clear(); + LOGV("~QualcommCameraHardware X"); +} + +sp QualcommCameraHardware::getRawHeap() const +{ + LOGV("getRawHeap"); + return mRawHeap != NULL ? mRawHeap->mHeap : NULL; +} + +sp QualcommCameraHardware::getPreviewHeap() const +{ + LOGV("getPreviewHeap"); + return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL; +} + +status_t QualcommCameraHardware::startPreviewInternal() +{ + if(mCameraRunning) { + LOGV("startPreview X: preview already running."); + return NO_ERROR; + } + + if (!mPreviewInitialized) { + mPreviewInitialized = initPreview(); + if (!mPreviewInitialized) { + LOGE("startPreview X initPreview failed. Not starting preview."); + return UNKNOWN_ERROR; + } + } + + mCameraRunning = native_start_preview(mCameraControlFd); + if(!mCameraRunning) { + deinitPreview(); + mPreviewInitialized = false; + LOGE("startPreview X: native_start_preview failed!"); + return UNKNOWN_ERROR; + } + + setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); + setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); + setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); + setBrightness(mParameters.getInt("exposure-offset")); + // FIXME: set nightshot, luma adaptatiom, zoom and check ranges + + LOGV("startPreview X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::startPreview(preview_callback cb, void *user) +{ + LOGV("startPreview E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mPreviewCallback = cb; + mPreviewCallbackCookie = user; + } + + return startPreviewInternal(); +} + +void QualcommCameraHardware::stopPreviewInternal() +{ + LOGV("stopPreviewInternal E: %d", mCameraRunning); + if (mCameraRunning) { + mCameraRunning = !native_stop_preview(mCameraControlFd); + if (!mCameraRunning && mPreviewInitialized) { + deinitPreview(); + mPreviewInitialized = false; + } + else LOGE("stopPreviewInternal: failed to stop preview"); + } + LOGV("stopPreviewInternal X: %d", mCameraRunning); +} + +void QualcommCameraHardware::stopPreview() +{ + LOGV("stopPreview: E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mAutoFocusCallback = NULL; + mPreviewCallback = NULL; + mPreviewCallbackCookie = NULL; + if(mRecordingCallback != NULL) + return; + } + + stopPreviewInternal(); + + LOGV("stopPreview: X"); +} + +void QualcommCameraHardware::runAutoFocus() +{ + mAutoFocusThreadLock.lock(); + mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR); + if (mAutoFocusFd < 0) { + LOGE("autofocus: cannot open %s: %s", + MSM_CAMERA_CONTROL, + strerror(errno)); + mAutoFocusThreadRunning = false; + mAutoFocusThreadLock.unlock(); + return; + } + + /* This will block until either AF completes or is cancelled. */ + LOGV("af start (fd %d)", mAutoFocusFd); + bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); + LOGV("af done: %d", (int)status); + mAutoFocusThreadRunning = false; + close(mAutoFocusFd); + mAutoFocusFd = -1; + mAutoFocusThreadLock.unlock(); + + mCallbackLock.lock(); + autofocus_callback cb = mAutoFocusCallback; + void *data = mAutoFocusCallbackCookie; + mCallbackLock.unlock(); + if (cb != NULL) + cb(status, data); +} + +void QualcommCameraHardware::cancelAutoFocus() +{ + LOGV("cancelAutoFocus E"); + native_cancel_afmode(mCameraControlFd, mAutoFocusFd); + LOGV("cancelAutoFocus X"); +} + +void *auto_focus_thread(void *user) +{ + LOGV("auto_focus_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runAutoFocus(); + } + else LOGW("not starting autofocus: the object went away!"); + LOGV("auto_focus_thread X"); + return NULL; +} + +status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, + void *user) +{ + LOGV("autoFocus E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbl(&mCallbackLock); + mAutoFocusCallback = af_cb; + mAutoFocusCallbackCookie = user; + } + + if (mCameraControlFd < 0) { + LOGE("not starting autofocus: main control fd %d", mCameraControlFd); + return UNKNOWN_ERROR; + } + + { + mAutoFocusThreadLock.lock(); + if (!mAutoFocusThreadRunning) { + // Create a detatched thread here so that we don't have to wait + // for it when we cancel AF. + pthread_t thr; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mAutoFocusThreadRunning = + !pthread_create(&thr, &attr, + auto_focus_thread, NULL); + if (!mAutoFocusThreadRunning) { + LOGE("failed to start autofocus thread"); + return UNKNOWN_ERROR; + } + } + mAutoFocusThreadLock.unlock(); + } + + LOGV("autoFocus X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, + raw_callback raw_cb, + jpeg_callback jpeg_cb, + void *user) +{ + LOGV("takePicture: E raw_cb = %p, jpeg_cb = %p", + raw_cb, jpeg_cb); + Mutex::Autolock l(&mLock); + + stopPreviewInternal(); + + if (!initRaw(jpeg_cb != NULL)) { + LOGE("initRaw failed. Not taking picture."); + return UNKNOWN_ERROR; + } + + { + Mutex::Autolock cbLock(&mCallbackLock); + mShutterCallback = shutter_cb; + mRawPictureCallback = raw_cb; + mJpegPictureCallback = jpeg_cb; + mPictureCallbackCookie = user; + } + + if (native_start_snapshot(mCameraControlFd) == false) { + LOGE("main: start_preview failed!"); + return UNKNOWN_ERROR; + } + receiveRawPicture(); + + LOGV("takePicture: X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::cancelPicture( + bool cancel_shutter, bool cancel_raw, bool cancel_jpeg) +{ + LOGV("cancelPicture: E cancel_shutter = %d, " + "cancel_raw = %d, cancel_jpeg = %d", + cancel_shutter, cancel_raw, cancel_jpeg); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + if (cancel_shutter) mShutterCallback = NULL; + if (cancel_raw) mRawPictureCallback = NULL; + if (cancel_jpeg) mJpegPictureCallback = NULL; + } + + LOGV("cancelPicture: X"); + return NO_ERROR; +} + +status_t QualcommCameraHardware::setParameters( + const CameraParameters& params) +{ + LOGV("setParameters: E params = %p", ¶ms); + + Mutex::Autolock l(&mLock); + + mParameters = params; + + int width, height; + params.getPreviewSize(&width, &height); + LOGV("requested size %d x %d", width, height); + preview_size_type *ps = preview_sizes; + size_t i; + for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { + if (width >= ps->width && height >= ps->height) + break; + } + if (i == PREVIEW_SIZE_COUNT) + ps--; + + LOGV("actual size %d x %d", ps->width, ps->height); + mParameters.setPreviewSize(ps->width, ps->height); + + mDimension.display_width = ps->width; + mDimension.display_height = ps->height; + + mParameters.getPreviewSize(&mPreviewWidth, &mPreviewHeight); + mParameters.getPictureSize(&mRawWidth, &mRawHeight); + + mPreviewWidth = (mPreviewWidth + 1) & ~1; + mPreviewHeight = (mPreviewHeight + 1) & ~1; + mRawHeight = (mRawHeight + 1) & ~1; + mRawWidth = (mRawWidth + 1) & ~1; + + if (mCameraRunning) + { + int val = mParameters.getInt("exposure-offset"); + if(val >= 0 && mBrightness != val) + { + if (val > BRIGHTNESS_MAX) + LOGE("invalid brightness value %d", val); + else { + LOGV("new brightness value %d", val); + mBrightness = val; + setBrightness(val); + } + } + + mZoomValueCurr = mParameters.getInt("zoom"); + if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && + mZoomValuePrev != mZoomValueCurr) + { + bool ZoomDirectionIn = true; + if(mZoomValuePrev > mZoomValueCurr) + { + ZoomDirectionIn = false; + } + else + { + ZoomDirectionIn = true; + } + LOGV("new zoom value: %2.2f direction = %s", + mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); + mZoomValuePrev = mZoomValueCurr; + performZoom(ZoomDirectionIn); + } + + setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); + setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); + setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); + setBrightness(mParameters.getInt("exposure-offset")); + // FIXME: set nightshot, luma adaptatiom, zoom and check ranges + } + + LOGV("setParameters: X"); + return NO_ERROR ; +} + +CameraParameters QualcommCameraHardware::getParameters() const +{ + LOGV("getParameters: EX"); + return mParameters; +} + +extern "C" sp openCameraHardware() +{ + LOGV("openCameraHardware: call createInstance"); + return QualcommCameraHardware::createInstance(); +} + +wp QualcommCameraHardware::singleton; + +// If the hardware already exists, return a strong pointer to the current +// object. If not, create a new hardware object, put it in the singleton, +// and return it. +sp QualcommCameraHardware::createInstance() +{ + LOGV("createInstance: E"); + + Mutex::Autolock lock(&singleton_lock); + if (singleton != 0) { + sp hardware = singleton.promote(); + if (hardware != 0) { + LOGV("createInstance: X return existing hardware=%p", &(*hardware)); + return hardware; + } + } + + { + struct stat st; + int rc = stat("/dev/oncrpc", &st); + if (rc < 0) { + LOGV("createInstance: X failed to create hardware: %s", strerror(errno)); + return NULL; + } + } + + QualcommCameraHardware *cam = new QualcommCameraHardware(); + sp hardware(cam); + singleton = hardware; + + cam->startCamera(); + cam->initDefaultParameters(); + LOGV("createInstance: X created hardware=%p", &(*hardware)); + return hardware; +} + +// For internal use only, hence the strong pointer to the derived type. +sp QualcommCameraHardware::getInstance() +{ + sp hardware = singleton.promote(); + if (hardware != 0) { + // LOGV("getInstance: X old instance of hardware"); + return sp(static_cast(hardware.get())); + } else { + LOGV("getInstance: X new instance of hardware"); + return sp(); + } +} + +#if CAPTURE_RAW +static void dump_to_file(const char *fname, + uint8_t *buf, uint32_t size) +{ + int nw, cnt = 0; + uint32_t written = 0; + + LOGD("opening file [%s]", fname); + int fd = open(fname, O_RDWR | O_CREAT); + if (fd < 0) { + LOGE("failed to create file [%s]: %s", fname, strerror(errno)); + return; + } + + LOGD("writing %d uint8_ts to file [%s]", size, fname); + while (written < size) { + nw = ::write(fd, + buf + written, + size - written); + if (nw < 0) { + LOGE("failed to write to file [%s]: %s", + fname, strerror(errno)); + break; + } + written += nw; + cnt++; + } + LOGD("done writing %d uint8_ts to file [%s] in %d passes", + size, fname, cnt); + ::close(fd); +} +#endif // CAMERA_RAW + +void QualcommCameraHardware::receivePreviewFrame(struct msm_frame_t *frame) +{ +// LOGV("receivePreviewFrame E"); + + if (!mCameraRunning) { + LOGE("ignoring preview callback--camera has been stopped"); + return; + } + + mCallbackLock.lock(); + preview_callback pcb = mPreviewCallback; + void *pdata = mPreviewCallbackCookie; + recording_callback rcb = mRecordingCallback; + void *rdata = mRecordingCallbackCookie; + mCallbackLock.unlock(); + + // Find the offset within the heap of the current buffer. + ssize_t offset = + mPreviewWidth * mPreviewHeight * + mPreviewFrameOffset * 3 / 2; + + memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, + (uint8_t *)frame->buffer, + mPreviewWidth * mPreviewHeight * 1.5); + + mInPreviewCallback = true; + if (pcb != NULL) + pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], + pdata); + + mPreviewFrameOffset++; + mPreviewFrameOffset %= kPreviewBufferCount; + + if(rcb != NULL) { + Mutex::Autolock rLock(&mRecordFrameLock); + rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); + while(mReleasedRecordingFrame != true) { + LOGV("block for release frame request/command"); + mRecordWait.wait(mRecordFrameLock); + } + mReleasedRecordingFrame = false; + } + mInPreviewCallback = false; + +// LOGV("receivePreviewFrame X"); +} + +status_t QualcommCameraHardware::startRecording( + recording_callback rcb, void *ruser) +{ + LOGV("startRecording E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mRecordingCallback = rcb; + mRecordingCallbackCookie = ruser; + } + + mReleasedRecordingFrame = false; + + return startPreviewInternal(); +} + +void QualcommCameraHardware::stopRecording() +{ + LOGV("stopRecording: E"); + Mutex::Autolock l(&mLock); + + { + Mutex::Autolock cbLock(&mCallbackLock); + mRecordingCallback = NULL; + mRecordingCallbackCookie = NULL; + + mRecordFrameLock.lock(); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + mRecordFrameLock.unlock(); + + if(mPreviewCallback != NULL) { + LOGV("stopRecording: X, preview still in progress"); + return; + } + } + + stopPreviewInternal(); + LOGV("stopRecording: X"); +} + +void QualcommCameraHardware::releaseRecordingFrame( + const sp& mem __attribute__((unused))) +{ + LOGV("releaseRecordingFrame E"); + Mutex::Autolock l(&mLock); + Mutex::Autolock rLock(&mRecordFrameLock); + mReleasedRecordingFrame = true; + mRecordWait.signal(); + LOGV("releaseRecordingFrame X"); +} + +bool QualcommCameraHardware::recordingEnabled() +{ + Mutex::Autolock l(&mLock); + return mCameraRunning && mRecordingCallback != NULL; +} + +void +QualcommCameraHardware::notifyShutter() +{ + LOGV("notifyShutter: E"); + if (mShutterCallback) + mShutterCallback(mPictureCallbackCookie); + LOGV("notifyShutter: X"); +} + +static ssize_t snapshot_offset = 0; + +void +QualcommCameraHardware::receiveRawPicture() +{ + LOGV("receiveRawPicture: E"); + + int ret,rc,rete; +// Temporary fix for multiple snapshot issue on 8k: disabling shutter callback + Mutex::Autolock cbLock(&mCallbackLock); + notifyShutter(); + if (mRawPictureCallback != NULL) { + if(native_get_picture(mCameraControlFd)== false) { + LOGE("getPicture failed!"); + return; + } + ssize_t offset = (mRawWidth * mRawHeight * 1.5 * snapshot_offset); +#if CAPTURE_RAW + dump_to_file("/sdcard/photo.raw", + (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 1.5 ); +#endif + mRawPictureCallback(mRawHeap->mBuffers[offset], + mPictureCallbackCookie); + } + else LOGV("Raw-picture callback was canceled--skipping."); + + if (mJpegPictureCallback != NULL) { + mJpegSize = 0; + if (LINK_jpeg_encoder_init()) { + if(native_jpeg_encode(mPmemThumbnailFd, + mPmemSnapshotFd, + mThumbnailBuf, + mMainImageBuf)) { + LOGV("receiveRawPicture: X (success)"); + return; + } + LOGE("jpeg encoding failed"); + } + else LOGE("receiveRawPicture X: jpeg_encoder_init failed."); + } + else LOGV("JPEG callback is NULL, not encoding image."); + deinitRaw(); + LOGV("receiveRawPicture: X"); +} + +void QualcommCameraHardware::receiveJpegPictureFragment( + uint8_t *buff_ptr, uint32_t buff_size) +{ + uint32_t remaining = mJpegHeap->mHeap->virtualSize(); + remaining -= mJpegSize; + uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base(); + + LOGV("receiveJpegPictureFragment size %d", buff_size); + if (buff_size > remaining) { + LOGE("receiveJpegPictureFragment: size %d exceeds what " + "remains in JPEG heap (%d), truncating", + buff_size, + remaining); + buff_size = remaining; + } + memcpy(base + mJpegSize, buff_ptr, buff_size); + mJpegSize += buff_size; +} + +void +QualcommCameraHardware::receiveJpegPicture(void) +{ + LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", + mJpegSize, mJpegHeap->mBufferSize); + Mutex::Autolock cbLock(&mCallbackLock); + + int index = 0, rc; + + if (mJpegPictureCallback) { + // The reason we do not allocate into mJpegHeap->mBuffers[offset] is + // that the JPEG image's size will probably change from one snapshot + // to the next, so we cannot reuse the MemoryBase object. + sp buffer = new + MemoryBase(mJpegHeap->mHeap, + index * mJpegHeap->mBufferSize + + mJpegHeap->mFrameOffset, + mJpegSize); + + mJpegPictureCallback(buffer, mPictureCallbackCookie); + buffer = NULL; + } + else LOGV("JPEG callback was cancelled--not delivering image."); + + LINK_jpeg_encoder_join(); + deinitRaw(); + + LOGV("receiveJpegPicture: X callback done."); +} + +bool QualcommCameraHardware::previewEnabled() +{ +// Mutex::Autolock l(&mLock); + return mCameraRunning && mPreviewCallback != NULL; +} + +void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effect) +{ + LOGV("In setSensorPreviewEffect..."); + int effectsValue = 1; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_EFFECT; + ctrlCmd.length = sizeof(uint32_t); + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + effectsValue = attr_lookup(color_effects, effect, CAMERA_EFFECT_OFF); + ctrlCmd.value = (void *)&effectsValue; + LOGV("In setSensorPreviewEffect, color effect match %s %d", + effect, effectsValue); + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setSensorPreviewEffect fd %d error %s", camfd, strerror(errno)); +} + +void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) +{ + int lightingValue = 1; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_WB; + ctrlCmd.length = sizeof(uint32_t); + lightingValue = attr_lookup(whitebalance, lighting, CAMERA_WB_AUTO); + ctrlCmd.value = (void *)&lightingValue; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + LOGV("In setSensorWBLighting: match: %s: %d", + lighting, lightingValue); + if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setSensorWBLighting: ioctl fd %d error %s", + camfd, strerror(errno)); +} + +void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) +{ + int antibandvalue = 0; + struct msm_ctrl_cmd_t ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; + ctrlCmd.length = sizeof(int32_t); + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + antibandvalue = attr_lookup(anti_banding, + antibanding, + CAMERA_ANTIBANDING_OFF); + ctrlCmd.value = (void *)&antibandvalue; + LOGV("In setAntiBanding: match: %s: %d", + antibanding, antibandvalue); + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setAntiBanding: ioctl %d error %s", + camfd, strerror(errno)); +} + +void QualcommCameraHardware::setBrightness(int brightness) +{ + struct msm_ctrl_cmd_t ctrlCmd; + LOGV("In setBrightness: %d", brightness); + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; + ctrlCmd.length = sizeof(int); + ctrlCmd.value = (void *)&brightness; + ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + + if(ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setBrightness: ioctl fd %d error %s", + mCameraControlFd, strerror(errno)); +} + +bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) +{ + struct msm_ctrl_cmd_t ctrlCmd; + cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; + ctrlCmd.type = CAMERA_GET_PARM_ZOOM; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(cam_parm_info_t); + ctrlCmd.value = pZoom; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_get_zoom: ioctl fd %d error %s", + camfd, strerror(errno)); + return false; + } + + LOGV("native_get_zoom::current val=%d max=%d min=%d step val=%d", + pZoom->current_value, + pZoom->maximum_value, + pZoom->minimum_value, + pZoom->step_value); + + memcpy(pZoom, (cam_parm_info_t *)ctrlCmd.value, sizeof(cam_parm_info_t)); + + return ctrlCmd.status; +} + +bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) +{ + struct msm_ctrl_cmd_t ctrlCmd; + + int32_t *pZoom = (int32_t *)pZm; + + ctrlCmd.type = CAMERA_SET_PARM_ZOOM; + ctrlCmd.timeout_ms = 5000; + ctrlCmd.length = sizeof(int32_t); + ctrlCmd.value = pZoom; + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + + if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { + LOGE("native_set_zoom: ioctl fd %d error %s", + camfd, strerror(errno)); + return false; + } + + memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t)); + return ctrlCmd.status; +} + +void QualcommCameraHardware::performZoom(bool ZoomDir) +{ + if(mZoomInitialised == false) { + native_get_zoom(mCameraControlFd, (void *)&mZoom); + if(mZoom.maximum_value != 0) { + mZoomInitialised = true; + mZoom.step_value = (int) (mZoom.maximum_value/MAX_ZOOM_STEPS); + if( mZoom.step_value > 3 ) + mZoom.step_value = 3; + } + } + + if (ZoomDir) { + LOGV("performZoom::got zoom value of %d %d %d zoom in", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + if((mZoom.current_value + mZoom.step_value) < mZoom.maximum_value) { + mZoom.current_value += mZoom.step_value; + LOGV("performZoom::Setting Zoom value of %d ",mZoom.current_value); + native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); + } + else { + LOGV("performZoom::not able to zoom in %d %d %d", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + } + } + else + { + LOGV("performZoom::got zoom value of %d %d %d zoom out", + mZoom.current_value, + mZoom.step_value, + mZoom.minimum_value); + if((mZoom.current_value - mZoom.step_value) >= mZoom.minimum_value) + { + mZoom.current_value -= mZoom.step_value; + LOGV("performZoom::setting zoom value of %d ", + mZoom.current_value); + native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); + } + else + { + LOGV("performZoom::not able to zoom out %d %d %d", + mZoom.current_value, + mZoom.step_value, + mZoom.maximum_value); + } + } +} + +QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + mBufferSize(buffer_size), + mNumBuffers(num_buffers), + mFrameSize(frame_size), + mFrameOffset(frame_offset), + mBuffers(NULL), mName(name) +{ + // empty +} + +void QualcommCameraHardware::MemPool::completeInitialization() +{ + // If we do not know how big the frame will be, we wait to allocate + // the buffers describing the individual frames until we do know their + // size. + + if (mFrameSize > 0) { + mBuffers = new sp[mNumBuffers]; + for (int i = 0; i < mNumBuffers; i++) { + mBuffers[i] = new + MemoryBase(mHeap, + i * mBufferSize + mFrameOffset, + mFrameSize); + } + } +} + +QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::MemPool(buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing MemPool %s backed by ashmem: " + "%d frames @ %d uint8_ts, offset %d, " + "buffer size %d", + mName, + num_buffers, frame_size, frame_offset, buffer_size); + + int page_mask = getpagesize() - 1; + int ashmem_size = buffer_size * num_buffers; + ashmem_size += page_mask; + ashmem_size &= ~page_mask; + + mHeap = new MemoryHeapBase(ashmem_size); + + completeInitialization(); +} + +QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::MemPool(buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing MemPool %s backed by pmem pool %s: " + "%d frames @ %d bytes, offset %d, buffer size %d", + mName, + pmem_pool, num_buffers, frame_size, frame_offset, + buffer_size); + + // Make a new mmap'ed heap that can be shared across processes. + + mAlignedSize = clp2(buffer_size * num_buffers); + + sp masterHeap = + new MemoryHeapBase(pmem_pool, mAlignedSize, 0); + sp pmemHeap = new MemoryHeapPmem(masterHeap, 0); + if (pmemHeap->getHeapID() >= 0) { + pmemHeap->slap(); + masterHeap.clear(); + mHeap = pmemHeap; + pmemHeap.clear(); + + mFd = mHeap->getHeapID(); + if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { + LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", + pmem_pool, + ::strerror(errno), errno); + mHeap.clear(); + return; + } + + LOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", + pmem_pool, + mFd, + mSize.len); + + completeInitialization(); + } + else LOGE("pmem pool %s error: could not create master heap!", + pmem_pool); +} + +QualcommCameraHardware::PreviewPmemPool::PreviewPmemPool( + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::PmemPool("/dev/pmem_adsp", + buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing PreviewPmemPool"); +} + +QualcommCameraHardware::PreviewPmemPool::~PreviewPmemPool() +{ + LOGV("destroying PreviewPmemPool"); + if(initialized()) { + void *base = mHeap->base(); + LOGV("destroying PreviewPmemPool"); + } +} + +QualcommCameraHardware::RawPmemPool::RawPmemPool( + const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name) : + QualcommCameraHardware::PmemPool(pmem_pool, + buffer_size, + num_buffers, + frame_size, + frame_offset, + name) +{ + LOGV("constructing RawPmemPool"); +} + +QualcommCameraHardware::RawPmemPool::~RawPmemPool() +{ + LOGV("destroying RawPmemPool"); + if(initialized()) { + void *base = mHeap->base(); + LOGV("releasing RawPmemPool memory %p", + base); + } +} + +QualcommCameraHardware::MemPool::~MemPool() +{ + LOGV("destroying MemPool %s", mName); + if (mFrameSize > 0) + delete [] mBuffers; + mHeap.clear(); + LOGV("destroying MemPool %s completed", mName); +} + +status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); + result.append(buffer); + if (mName) { + snprintf(buffer, 255, "mem pool name (%s)\n", mName); + result.append(buffer); + } + if (mHeap != 0) { + snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", + mHeap->getBase(), mHeap->getSize(), + mHeap->getFlags(), mHeap->getDevice()); + result.append(buffer); + } + snprintf(buffer, 255, "buffer size (%d), number of buffers (%d)," + " frame size(%d), and frame offset(%d)\n", + mBufferSize, mNumBuffers, mFrameSize, mFrameOffset); + result.append(buffer); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +static void receive_camframe_callback(struct msm_frame_t *frame) +{ + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receivePreviewFrame(frame); + } +} + +static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size) +{ + LOGV("receive_jpeg_fragment_callback E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receiveJpegPictureFragment(buff_ptr, buff_size); + } + LOGV("receive_jpeg_fragment_callback X"); +} + +static void receive_jpeg_callback(jpeg_event_t status) +{ + LOGV("receive_jpeg_callback E (completion status %d)", status); + if (status == JPEG_EVENT_DONE) { + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->receiveJpegPicture(); + } + } + LOGV("receive_jpeg_callback X"); +} + +}; // namespace android diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h new file mode 100755 index 0000000..eec6783 --- /dev/null +++ b/libcamera2/QualcommCameraHardware.h @@ -0,0 +1,286 @@ +/* +** Copyright 2008, Google Inc. +** +** 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 ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H +#define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H + +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +namespace android { + +class QualcommCameraHardware : public CameraHardwareInterface { +public: + + virtual sp getPreviewHeap() const; + virtual sp getRawHeap() const; + + virtual status_t dump(int fd, const Vector& args) const; + virtual status_t startPreview(preview_callback cb, void* user); + virtual void stopPreview(); + virtual status_t startRecording(recording_callback cb, void* user); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp& mem); + virtual status_t autoFocus(autofocus_callback, void *user); + virtual status_t takePicture(shutter_callback, + raw_callback, + jpeg_callback, + void* user); + virtual status_t cancelPicture(bool cancel_shutter, + bool cancel_raw, bool cancel_jpeg); + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; + + virtual void release(); + + static sp createInstance(); + static sp getInstance(); + + + + bool native_set_dimension (int camfd); + void reg_unreg_buf(int camfd, int width, int height, + int pmempreviewfd, uint8_t *prev_buf, + int pmem_type, + bool unregister, + bool active); + bool native_register_preview_bufs(int camfd, + struct msm_frame_t *frame,bool active); + bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, + uint8_t *prev_buf); + + bool native_start_preview(int camfd); + bool native_stop_preview(int camfd); + + bool native_register_snapshot_bufs(int camfd, int pmemthumbnailfd, + int pmemsnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf); + bool native_unregister_snapshot_bufs(int camfd, int pmemThumbnailfd, + int pmemSnapshotfd, + uint8_t *thumbnail_buf, + uint8_t *main_img_buf); + bool native_get_picture(int camfd); + bool native_start_snapshot(int camfd); + bool native_stop_snapshot(int camfd); + bool native_jpeg_encode (int pmemThumbnailfd, int pmemSnapshotfd, + uint8_t *thumbnail_buf, uint8_t *main_img_buf); + + bool native_set_zoom(int camfd, void *pZm); + bool native_get_zoom(int camfd, void *pZm); + + void receivePreviewFrame(struct msm_frame_t *frame); + void receiveJpegPicture(void); + void receiveJpegPictureFragment( + uint8_t * buff_ptr , uint32_t buff_size); + bool previewEnabled(); + + +private: + + QualcommCameraHardware(); + virtual ~QualcommCameraHardware(); + status_t startPreviewInternal(); + void stopPreviewInternal(); + friend void *auto_focus_thread(void *user); + void runAutoFocus(); + void cancelAutoFocus(); + + static wp singleton; + + /* These constants reflect the number of buffers that libmmcamera requires + for preview and raw, and need to be updated when libmmcamera + changes. + */ + static const int kPreviewBufferCount = 4; + static const int kRawBufferCount = 1; + static const int kJpegBufferCount = 1; + static const int kRawFrameHeaderSize = 0; + + //TODO: put the picture dimensions in the CameraParameters object; + CameraParameters mParameters; + int mPreviewHeight; + int mPreviewWidth; + int mRawHeight; + int mRawWidth; + unsigned int frame_size; + int mBrightness; + float mZoomValuePrev; + float mZoomValueCurr; + bool mZoomInitialised; + bool mCameraRunning; + bool mPreviewInitialized; + + // This class represents a heap which maintains several contiguous + // buffers. The heap may be backed by pmem (when pmem_pool contains + // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). + + struct MemPool : public RefBase { + MemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + + virtual ~MemPool() = 0; + + void completeInitialization(); + bool initialized() const { + return mHeap != NULL && mHeap->base() != MAP_FAILED; + } + + virtual status_t dump(int fd, const Vector& args) const; + + int mBufferSize; + int mNumBuffers; + int mFrameSize; + int mFrameOffset; + sp mHeap; + sp *mBuffers; + + const char *mName; + }; + + struct AshmemPool : public MemPool { + AshmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + struct PmemPool : public MemPool { + PmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + virtual ~PmemPool(){ } + int mFd; + uint32_t mAlignedSize; + struct pmem_region mSize; + }; + + struct PreviewPmemPool : public PmemPool { + virtual ~PreviewPmemPool(); + PreviewPmemPool(int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + struct RawPmemPool : public PmemPool { + virtual ~RawPmemPool(); + RawPmemPool(const char *pmem_pool, + int buffer_size, int num_buffers, + int frame_size, + int frame_offset, + const char *name); + }; + + sp mPreviewHeap; + sp mRawHeap; + sp mJpegHeap; + + void startCamera(); + bool initPreview(); + void deinitPreview(); + bool initRaw(bool initJpegHeap); + void deinitRaw(); + + bool mFrameThreadRunning; + Mutex mFrameThreadWaitLock; + Condition mFrameThreadWait; + friend void *frame_thread(void *user); + void runFrameThread(void *data); + + void initDefaultParameters(); + + void setSensorPreviewEffect(int, const char*); + void setSensorWBLighting(int, const char*); + void setAntiBanding(int, const char*); + void setBrightness(int); + void performZoom(bool); + + Mutex mLock; + bool mReleasedRecordingFrame; + + void notifyShutter(); + + void receiveRawPicture(void); + + Mutex mCallbackLock; + Mutex mRecordLock; + Mutex mRecordFrameLock; + Condition mRecordWait; + Condition mStateWait; + + /* mJpegSize keeps track of the size of the accumulated JPEG. We clear it + when we are about to take a picture, so at any time it contains either + zero, or the size of the last JPEG picture taken. + */ + uint32_t mJpegSize; + + + shutter_callback mShutterCallback; + raw_callback mRawPictureCallback; + jpeg_callback mJpegPictureCallback; + void *mPictureCallbackCookie; + + autofocus_callback mAutoFocusCallback; + void *mAutoFocusCallbackCookie; + + preview_callback mPreviewCallback; + void *mPreviewCallbackCookie; + recording_callback mRecordingCallback; + void *mRecordingCallbackCookie; + unsigned int mPreviewFrameSize; + int mRawSize; + int mJpegMaxSize; + +#if DLOPEN_LIBMMCAMERA + void *libmmcamera; +#endif + + int mCameraControlFd; + cam_parm_info_t mZoom; + cam_ctrl_dimension_t mDimension; + int mPmemThumbnailFd; + int mPmemSnapshotFd; + ssize_t mPreviewFrameOffset; + uint8_t *mThumbnailBuf; + uint8_t *mMainImageBuf; + bool mAutoFocusThreadRunning; + Mutex mAutoFocusThreadLock; + int mAutoFocusFd; + + pthread_t mCamConfigThread; + pthread_t mFrameThread; + + struct msm_frame_t frames[kPreviewBufferCount]; + bool mInPreviewCallback; +}; + +}; // namespace android + +#endif From 0a1f5776735aaadc9d5a7923164b71749dded343 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Thu, 4 Jun 2009 13:36:10 -0700 Subject: [PATCH 049/435] Update reflects changes in type names in msm_camera.h. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 44 +++++++++++++-------------- libcamera2/QualcommCameraHardware.h | 6 ++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 2209c8e..c11ea89 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -87,7 +87,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); // callbacks -void (**LINK_mmcamera_camframe_callback)(struct msm_frame_t *frame); +void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); @@ -99,7 +99,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_encode jpeg_encoder_encode #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality -extern void (*mmcamera_camframe_callback)(struct msm_frame_t *frame); +extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); @@ -215,7 +215,7 @@ namespace android { static Mutex singleton_lock; -static void receive_camframe_callback(struct msm_frame_t *frame); +static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); static uint8_t *hal_mmap (uint32_t size, int *pmemFd); @@ -475,7 +475,7 @@ status_t QualcommCameraHardware::dump(int fd, bool QualcommCameraHardware::native_set_dimension(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; ctrlCmd.timeout_ms = 5000; @@ -496,7 +496,7 @@ bool QualcommCameraHardware::native_set_dimension(int camfd) bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; @@ -516,7 +516,7 @@ bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) bool native_cancel_afmode(int camfd, int af_fd) { int rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; @@ -541,7 +541,7 @@ void QualcommCameraHardware::reg_unreg_buf( bool active) { uint32_t y_size; - struct msm_pmem_info_t pmemBuf; + struct msm_pmem_info pmemBuf; uint32_t ioctl_cmd; if (prev_buf == NULL) @@ -572,7 +572,7 @@ void QualcommCameraHardware::reg_unreg_buf( bool QualcommCameraHardware::native_register_preview_bufs( int camfd, - struct msm_frame_t *frame, + struct msm_frame *frame, bool active) { LOGV("mDimension.display_width = %d, display_height = %d", @@ -608,7 +608,7 @@ bool QualcommCameraHardware::native_unregister_preview_bufs( bool QualcommCameraHardware::native_start_preview(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_START_PREVIEW; @@ -684,7 +684,7 @@ bool QualcommCameraHardware::native_unregister_snapshot_bufs( bool QualcommCameraHardware::native_get_picture (int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.length = 0; @@ -701,7 +701,7 @@ bool QualcommCameraHardware::native_get_picture (int camfd) bool QualcommCameraHardware::native_stop_preview(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_STOP_PREVIEW; ctrlCmd.length = 0; @@ -719,7 +719,7 @@ bool QualcommCameraHardware::native_stop_preview(int camfd) bool QualcommCameraHardware::native_start_snapshot(int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_START_SNAPSHOT; @@ -738,7 +738,7 @@ bool QualcommCameraHardware::native_start_snapshot(int camfd) bool QualcommCameraHardware::native_stop_snapshot (int camfd) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_STOP_SNAPSHOT; @@ -1064,7 +1064,7 @@ void QualcommCameraHardware::release() } int cnt, rc; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; if (mCameraRunning) { cancelAutoFocus(); @@ -1523,7 +1523,7 @@ static void dump_to_file(const char *fname, } #endif // CAMERA_RAW -void QualcommCameraHardware::receivePreviewFrame(struct msm_frame_t *frame) +void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) { // LOGV("receivePreviewFrame E"); @@ -1742,7 +1742,7 @@ void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effe { LOGV("In setSensorPreviewEffect..."); int effectsValue = 1; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_EFFECT; @@ -1760,7 +1760,7 @@ void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effe void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) { int lightingValue = 1; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_WB; @@ -1778,7 +1778,7 @@ void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) { int antibandvalue = 0; - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; @@ -1799,7 +1799,7 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) void QualcommCameraHardware::setBrightness(int brightness) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; LOGV("In setBrightness: %d", brightness); ctrlCmd.timeout_ms = 5000; ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; @@ -1814,7 +1814,7 @@ void QualcommCameraHardware::setBrightness(int brightness) bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; ctrlCmd.type = CAMERA_GET_PARM_ZOOM; ctrlCmd.timeout_ms = 5000; @@ -1841,7 +1841,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) { - struct msm_ctrl_cmd_t ctrlCmd; + struct msm_ctrl_cmd ctrlCmd; int32_t *pZoom = (int32_t *)pZm; @@ -2103,7 +2103,7 @@ status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& a return NO_ERROR; } -static void receive_camframe_callback(struct msm_frame_t *frame) +static void receive_camframe_callback(struct msm_frame *frame) { sp obj = QualcommCameraHardware::getInstance(); if (obj != 0) { diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index eec6783..06c38a2 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -67,7 +67,7 @@ public: bool unregister, bool active); bool native_register_preview_bufs(int camfd, - struct msm_frame_t *frame,bool active); + struct msm_frame *frame,bool active); bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, uint8_t *prev_buf); @@ -91,7 +91,7 @@ public: bool native_set_zoom(int camfd, void *pZm); bool native_get_zoom(int camfd, void *pZm); - void receivePreviewFrame(struct msm_frame_t *frame); + void receivePreviewFrame(struct msm_frame *frame); void receiveJpegPicture(void); void receiveJpegPictureFragment( uint8_t * buff_ptr , uint32_t buff_size); @@ -277,7 +277,7 @@ private: pthread_t mCamConfigThread; pthread_t mFrameThread; - struct msm_frame_t frames[kPreviewBufferCount]; + struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; }; From 88dbb2fc3f84ad560c68345aa7e9b8df5f680bda Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 26 May 2009 18:22:13 -0700 Subject: [PATCH 050/435] disable libcamera and enable libcamera2 Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index dab1c17..0a60554 100755 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -1,4 +1,4 @@ -BUILD_LIBCAMERA:= +BUILD_LIBCAMERA:=true ifeq ($(BUILD_LIBCAMERA),true) # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. From 23ef3090e3203ed34b442d9c18c31462249fcab6 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Fri, 5 Jun 2009 00:55:39 -0700 Subject: [PATCH 051/435] temporarily roll back to libcamera --- libcamera2/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index 0a60554..dab1c17 100755 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -1,4 +1,4 @@ -BUILD_LIBCAMERA:=true +BUILD_LIBCAMERA:= ifeq ($(BUILD_LIBCAMERA),true) # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. From 16a33ee8f6f0c7eac96262bf6f8e569ee9d9a6ee Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Fri, 5 Jun 2009 13:53:31 -0700 Subject: [PATCH 052/435] fix libcamera2 for master branch Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 3 ++- libcamera2/QualcommCameraHardware.cpp | 2 +- libcamera2/QualcommCameraHardware.h | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index dab1c17..11e1350 100755 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -1,4 +1,4 @@ -BUILD_LIBCAMERA:= +BUILD_LIBCAMERA:=true ifeq ($(BUILD_LIBCAMERA),true) # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. @@ -22,6 +22,7 @@ LOCAL_C_INCLUDES+= \ LOCAL_SHARED_LIBRARIES:= libutils libui liblog +LOCAL_SHARED_LIBRARIES+= libbinder ifneq ($(DLOPEN_LIBMMCAMERA),1) LOCAL_SHARED_LIBRARIES+= libmmcamera else diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c11ea89..030f914 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -21,7 +21,7 @@ #include "QualcommCameraHardware.h" #include -#include +#include #include #include #include diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 06c38a2..2f75bf3 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -18,8 +18,8 @@ #define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H #include -#include -#include +#include +#include #include extern "C" { From 366cd7e1e3a4f10c190f7afe5bcb45e9cb949893 Mon Sep 17 00:00:00 2001 From: James Dong Date: Fri, 5 Jun 2009 17:59:32 -0700 Subject: [PATCH 053/435] Restore the support for SQVGA (bug 1901755) --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c11ea89..2987ee1 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -118,6 +118,7 @@ static preview_size_type preview_sizes[] = { { 480, 320 }, // HVGA { 352, 288 }, // CIF { 320, 240 }, // QVGA + { 240, 160 }, // SQVGA { 176, 144 }, // QCIF }; From 59b25b06c88aeab1e13e8ca68a24c3906822116c Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 15:32:57 -0700 Subject: [PATCH 054/435] libcamera2: update the frame offset after we call the recording callback Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 2987ee1..c5231ca 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1554,9 +1554,6 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], pdata); - mPreviewFrameOffset++; - mPreviewFrameOffset %= kPreviewBufferCount; - if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); @@ -1568,6 +1565,9 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) } mInPreviewCallback = false; + mPreviewFrameOffset++; + mPreviewFrameOffset %= kPreviewBufferCount; + // LOGV("receivePreviewFrame X"); } From f5e21dce16dd8611b6c0adc577ec44155b0eb164 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 16:46:51 -0700 Subject: [PATCH 055/435] remove floats from libcamera2 Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 12 ++++++------ libcamera2/QualcommCameraHardware.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c5231ca..708a62d 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -958,9 +958,9 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) return false; } - mRawSize = mRawWidth * mRawHeight * 1.5; + mRawSize = mRawWidth * mRawHeight * 3 / 2; - mJpegMaxSize = mRawWidth * mRawHeight * 1.5; + mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; LOGE("initRaw: clearing old mJpegHeap."); mJpegHeap.clear(); @@ -1412,7 +1412,7 @@ status_t QualcommCameraHardware::setParameters( { ZoomDirectionIn = true; } - LOGV("new zoom value: %2.2f direction = %s", + LOGV("new zoom value: %d direction = %s", mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); mZoomValuePrev = mZoomValueCurr; performZoom(ZoomDirectionIn); @@ -1547,7 +1547,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, (uint8_t *)frame->buffer, - mPreviewWidth * mPreviewHeight * 1.5); + mPreviewWidth * mPreviewHeight * 3 / 2); mInPreviewCallback = true; if (pcb != NULL) @@ -1655,10 +1655,10 @@ QualcommCameraHardware::receiveRawPicture() LOGE("getPicture failed!"); return; } - ssize_t offset = (mRawWidth * mRawHeight * 1.5 * snapshot_offset); + ssize_t offset = (mRawWidth * mRawHeight * snapshot_offset * 3 / 2); #if CAPTURE_RAW dump_to_file("/sdcard/photo.raw", - (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 1.5 ); + (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 3 / 2); #endif mRawPictureCallback(mRawHeap->mBuffers[offset], mPictureCallbackCookie); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 06c38a2..b5707b6 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -125,12 +125,12 @@ private: int mPreviewWidth; int mRawHeight; int mRawWidth; - unsigned int frame_size; - int mBrightness; - float mZoomValuePrev; - float mZoomValueCurr; - bool mZoomInitialised; - bool mCameraRunning; + unsigned int frame_size; + int mBrightness; + int mZoomValuePrev; + int mZoomValueCurr; + bool mZoomInitialised; + bool mCameraRunning; bool mPreviewInitialized; // This class represents a heap which maintains several contiguous From ed604c67eedbb7e8ab02df143cf2ef26bfe023f6 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 14:48:33 -0700 Subject: [PATCH 056/435] libcamera: default brightness to 5 when not specified by camera Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 53 ++++++++++++++------------- libcamera2/QualcommCameraHardware.h | 2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 708a62d..80a8696 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -72,6 +72,7 @@ extern "C" { #define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) #define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values +#define BRIGHTNESS_DEF 5 // FIXME: this should correlate with brightness-values #define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values #if DLOPEN_LIBMMCAMERA @@ -281,7 +282,7 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewWidth(-1), mRawHeight(-1), mRawWidth(-1), - mBrightness(0), + mBrightness(BRIGHTNESS_DEF), mZoomValuePrev(0), mZoomValueCurr(0), mZoomInitialised(false), @@ -1153,7 +1154,7 @@ status_t QualcommCameraHardware::startPreviewInternal() setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(mParameters.getInt("exposure-offset")); + setBrightness(); // FIXME: set nightshot, luma adaptatiom, zoom and check ranges LOGV("startPreview X"); @@ -1387,17 +1388,7 @@ status_t QualcommCameraHardware::setParameters( if (mCameraRunning) { - int val = mParameters.getInt("exposure-offset"); - if(val >= 0 && mBrightness != val) - { - if (val > BRIGHTNESS_MAX) - LOGE("invalid brightness value %d", val); - else { - LOGV("new brightness value %d", val); - mBrightness = val; - setBrightness(val); - } - } + setBrightness(); mZoomValueCurr = mParameters.getInt("zoom"); if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && @@ -1421,7 +1412,6 @@ status_t QualcommCameraHardware::setParameters( setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(mParameters.getInt("exposure-offset")); // FIXME: set nightshot, luma adaptatiom, zoom and check ranges } @@ -1798,19 +1788,32 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) camfd, strerror(errno)); } -void QualcommCameraHardware::setBrightness(int brightness) +void QualcommCameraHardware::setBrightness() { - struct msm_ctrl_cmd ctrlCmd; - LOGV("In setBrightness: %d", brightness); - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; - ctrlCmd.length = sizeof(int); - ctrlCmd.value = (void *)&brightness; - ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel + int val = mParameters.getInt("exposure-offset"); + if (val < 0) + val = BRIGHTNESS_DEF; + else if (val > BRIGHTNESS_MAX) + val = BRIGHTNESS_MAX; - if(ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setBrightness: ioctl fd %d error %s", - mCameraControlFd, strerror(errno)); + if (mBrightness != val) { + LOGV("new brightness value %d", val); + mBrightness = val; + + struct msm_ctrl_cmd ctrlCmd; + LOGV("In setBrightness: %d", val); + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; + ctrlCmd.length = sizeof(int); + ctrlCmd.value = (void *)&val; + // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = mCameraControlFd; + + if(ioctl(mCameraControlFd, + MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) + LOGE("setBrightness: ioctl fd %d error %s", + mCameraControlFd, strerror(errno)); + } } bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index b5707b6..02fa598 100755 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -219,7 +219,7 @@ private: void setSensorPreviewEffect(int, const char*); void setSensorWBLighting(int, const char*); void setAntiBanding(int, const char*); - void setBrightness(int); + void setBrightness(void); void performZoom(bool); Mutex mLock; From 32b7f2804eb66a6677826833057ca93bef78b870 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Wed, 10 Jun 2009 14:49:11 -0700 Subject: [PATCH 057/435] libcamera: avoid a race condition on starting and stopping a recording precondition: preview is running -- call startRecording() -- a preview frame arrives, causing the record callback to be called, and then blocks on mRecordWait.wait() -- call stopRecording(), which sets mReleasedRecordingFrame and signals mRecordWait; -- call startRecording(), which clears mReleasedRecordingFrame; -- receivePreviewFrame() wakes up, checks mReleasedRecordingFrame, and blocks again on mRecordWait.wait(), without having notified the client. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 80a8696..718f6bf 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1547,7 +1547,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); - while(mReleasedRecordingFrame != true) { + if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); } From c11ce4c954ddb62f738b868737d01cc9d3b06e8e Mon Sep 17 00:00:00 2001 From: James Dong Date: Wed, 10 Jun 2009 19:59:25 -0700 Subject: [PATCH 058/435] Fix deadlock in camera hal when auto focus failed --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 718f6bf..8952470 100755 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1288,6 +1288,7 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, auto_focus_thread, NULL); if (!mAutoFocusThreadRunning) { LOGE("failed to start autofocus thread"); + mAutoFocusThreadLock.unlock(); return UNKNOWN_ERROR; } } From 2e8a9ddd4ceb49aa66abc0a62882ff641ae37f28 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 10 Jun 2009 14:27:39 +0800 Subject: [PATCH 059/435] Cancel autofocus in stopPreview. --- libcamera2/QualcommCameraHardware.cpp | 32 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) mode change 100755 => 100644 libcamera2/QualcommCameraHardware.cpp diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp old mode 100755 new mode 100644 index 8952470..449a610 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1069,7 +1069,6 @@ void QualcommCameraHardware::release() struct msm_ctrl_cmd ctrlCmd; if (mCameraRunning) { - cancelAutoFocus(); if(mRecordingCallback != NULL) { mRecordFrameLock.lock(); mReleasedRecordingFrame = true; @@ -1179,6 +1178,16 @@ void QualcommCameraHardware::stopPreviewInternal() { LOGV("stopPreviewInternal E: %d", mCameraRunning); if (mCameraRunning) { + // Cancel auto focus. + if (mAutoFocusCallback) { + { + Mutex::Autolock cbLock(&mCallbackLock); + mAutoFocusCallback = NULL; + mAutoFocusCallbackCookie = NULL; + } + cancelAutoFocus(); + } + mCameraRunning = !native_stop_preview(mCameraControlFd); if (!mCameraRunning && mPreviewInitialized) { deinitPreview(); @@ -1196,7 +1205,6 @@ void QualcommCameraHardware::stopPreview() { Mutex::Autolock cbLock(&mCallbackLock); - mAutoFocusCallback = NULL; mPreviewCallback = NULL; mPreviewCallbackCookie = NULL; if(mRecordingCallback != NULL) @@ -1236,6 +1244,11 @@ void QualcommCameraHardware::runAutoFocus() mCallbackLock.unlock(); if (cb != NULL) cb(status, data); + + mCallbackLock.lock(); + mAutoFocusCallback = NULL; + mAutoFocusCallbackCookie = NULL; + mCallbackLock.unlock(); } void QualcommCameraHardware::cancelAutoFocus() @@ -1263,17 +1276,22 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, LOGV("autoFocus E"); Mutex::Autolock l(&mLock); + if (mCameraControlFd < 0) { + LOGE("not starting autofocus: main control fd %d", mCameraControlFd); + return UNKNOWN_ERROR; + } + + if (mAutoFocusCallback != NULL) { + LOGW("Auto focus is already in progress"); + return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; + } + { Mutex::Autolock cbl(&mCallbackLock); mAutoFocusCallback = af_cb; mAutoFocusCallbackCookie = user; } - if (mCameraControlFd < 0) { - LOGE("not starting autofocus: main control fd %d", mCameraControlFd); - return UNKNOWN_ERROR; - } - { mAutoFocusThreadLock.lock(); if (!mAutoFocusThreadRunning) { From 93cde78899419a32da75d01e3de1ddc785b470ee Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 15 Jun 2009 14:20:59 +0800 Subject: [PATCH 060/435] Accept parameter "jpeg-thumbnail-quality" to specify thumbnail quality. --- libcamera2/Android.mk | 0 libcamera2/QualcommCameraHardware.cpp | 17 ++++++++++++++++- libcamera2/QualcommCameraHardware.h | 0 3 files changed, 16 insertions(+), 1 deletion(-) mode change 100755 => 100644 libcamera2/Android.mk mode change 100755 => 100644 libcamera2/QualcommCameraHardware.h diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk old mode 100755 new mode 100644 diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 449a610..886982c 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -87,6 +87,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, const uint8_t *snapshotbuf, int snapshotfd); int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); +int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -100,6 +101,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_encode jpeg_encoder_encode #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality +#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -340,7 +342,7 @@ void QualcommCameraHardware::initDefaultParameters() p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative - //p.set("jpeg-thumbnail-quality", "90"); // FIXME: hook up through mm-camera + p.set("jpeg-thumbnail-quality", "90"); p.setPictureSize(mDimension.picture_width, mDimension.picture_height); #if 0 @@ -416,6 +418,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setMainImageQuality = ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); + *(void**)&LINK_jpeg_encoder_setThumbnailQuality = + ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -773,6 +778,16 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality"); + if (thumbnail_quality >= 0) { + LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", + thumbnail_quality); + if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { + LOGE("native_jpeg_encode set failed"); + return false; + } + } + if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, main_img_buf, snap_fd)) { diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h old mode 100755 new mode 100644 From 4f48dacadaf5cc7fe8fd3c891b147708e005d196 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 15 Jun 2009 17:00:23 +0800 Subject: [PATCH 061/435] Add set rotation function. --- libcamera2/QualcommCameraHardware.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 886982c..646f849 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -88,6 +88,7 @@ bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); +int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -102,6 +103,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_camframe_terminate camframe_terminate #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality #define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality +#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -421,6 +423,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setThumbnailQuality = ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); + *(void**)&LINK_jpeg_encoder_setRotation = + ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -773,7 +778,7 @@ bool QualcommCameraHardware::native_jpeg_encode ( LOGV("native_jpeg_encode, current jpeg main img quality =%d", jpeg_quality); if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { - LOGE("native_jpeg_encode set failed"); + LOGE("native_jpeg_encode set jpeg-quality failed"); return false; } } @@ -783,7 +788,16 @@ bool QualcommCameraHardware::native_jpeg_encode ( LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", thumbnail_quality); if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { - LOGE("native_jpeg_encode set failed"); + LOGE("native_jpeg_encode set thumbnail-quality failed"); + return false; + } + } + + int rotation = mParameters.getInt("rotation"); + if (rotation >= 0) { + LOGV("native_jpeg_encode, rotation = %d", rotation); + if(!LINK_jpeg_encoder_setRotation(rotation)) { + LOGE("native_jpeg_encode set rotation failed"); return false; } } From 9e7909b4391d3661a28411ae7783f8050a81efcf Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Mon, 15 Jun 2009 15:22:17 -0700 Subject: [PATCH 062/435] libcamera2: update to match new libqcamera.so Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 2 +- libcamera2/QualcommCameraHardware.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index 0a60554..26eb4a5 100644 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -23,7 +23,7 @@ LOCAL_C_INCLUDES+= \ LOCAL_SHARED_LIBRARIES:= libutils libui liblog ifneq ($(DLOPEN_LIBMMCAMERA),1) -LOCAL_SHARED_LIBRARIES+= libmmcamera +LOCAL_SHARED_LIBRARIES+= libqcamera else LOCAL_SHARED_LIBRARIES+= libdl endif diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 646f849..ee0ac66 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -84,7 +84,8 @@ bool (*LINK_jpeg_encoder_init)(); void (*LINK_jpeg_encoder_join)(); bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, const uint8_t *thumbnailbuf, int thumbnailfd, - const uint8_t *snapshotbuf, int snapshotfd); + const uint8_t *snapshotbuf, int snapshotfd, + common_crop_t *scaling_parms); int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); @@ -802,9 +803,11 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + static common_crop_t scale; // no scaling if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, - main_img_buf, snap_fd)) { + main_img_buf, snap_fd, + &scale)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; } @@ -1089,10 +1092,14 @@ void QualcommCameraHardware::release() LOGV("release E"); Mutex::Autolock l(&mLock); +#if DLOPEN_LIBMMCAMERA if (libmmcamera == NULL) { LOGE("ERROR: multiple release!"); return; } +#else +#warning "Cannot detect multiple release when not dlopen()ing libqcamera!" +#endif int cnt, rc; struct msm_ctrl_cmd ctrlCmd; From 105a7f6c76583dccf140654e5309905131fdab66 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Tue, 16 Jun 2009 17:15:48 +0800 Subject: [PATCH 063/435] Enable more debug message to debug the Camera startPreview bug. --- libcamera2/QualcommCameraHardware.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index ee0ac66..7778883 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -867,13 +867,13 @@ void QualcommCameraHardware::runFrameThread(void *data) void *frame_thread(void *user) { - LOGV("frame_thread E"); + LOGD("frame_thread E"); sp obj = QualcommCameraHardware::getInstance(); if (obj != 0) { obj->runFrameThread(user); } else LOGW("not starting frame thread: the object went away!"); - LOGV("frame_thread X"); + LOGD("frame_thread X"); return NULL; } @@ -1089,7 +1089,7 @@ void QualcommCameraHardware::deinitRaw() void QualcommCameraHardware::release() { - LOGV("release E"); + LOGD("release E"); Mutex::Autolock l(&mLock); #if DLOPEN_LIBMMCAMERA @@ -1141,14 +1141,14 @@ void QualcommCameraHardware::release() } #endif - LOGV("release X"); + LOGD("release X"); } QualcommCameraHardware::~QualcommCameraHardware() { - LOGV("~QualcommCameraHardware E"); + LOGD("~QualcommCameraHardware E"); singleton.clear(); - LOGV("~QualcommCameraHardware X"); + LOGD("~QualcommCameraHardware X"); } sp QualcommCameraHardware::getRawHeap() const @@ -1493,13 +1493,13 @@ wp QualcommCameraHardware::singleton; // and return it. sp QualcommCameraHardware::createInstance() { - LOGV("createInstance: E"); + LOGD("createInstance: E"); Mutex::Autolock lock(&singleton_lock); if (singleton != 0) { sp hardware = singleton.promote(); if (hardware != 0) { - LOGV("createInstance: X return existing hardware=%p", &(*hardware)); + LOGD("createInstance: X return existing hardware=%p", &(*hardware)); return hardware; } } @@ -1508,7 +1508,7 @@ sp QualcommCameraHardware::createInstance() struct stat st; int rc = stat("/dev/oncrpc", &st); if (rc < 0) { - LOGV("createInstance: X failed to create hardware: %s", strerror(errno)); + LOGD("createInstance: X failed to create hardware: %s", strerror(errno)); return NULL; } } @@ -1519,7 +1519,7 @@ sp QualcommCameraHardware::createInstance() cam->startCamera(); cam->initDefaultParameters(); - LOGV("createInstance: X created hardware=%p", &(*hardware)); + LOGD("createInstance: X created hardware=%p", &(*hardware)); return hardware; } From e610e2518d2982d579f58953267980df68f70a40 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Tue, 16 Jun 2009 01:46:46 +0800 Subject: [PATCH 064/435] Get the values returned from CAMERA_GET_PARM_ZOOM correctly. --- libcamera2/QualcommCameraHardware.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 7778883..152ce56 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1879,7 +1879,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) ctrlCmd.timeout_ms = 5000; ctrlCmd.length = sizeof(cam_parm_info_t); ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { LOGE("native_get_zoom: ioctl fd %d error %s", @@ -1887,14 +1887,14 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) return false; } - LOGV("native_get_zoom::current val=%d max=%d min=%d step val=%d", + memcpy(pZoom, *(cam_parm_info_t **)ctrlCmd.value, sizeof(cam_parm_info_t)); + + LOGD("native_get_zoom::current val=%d max=%d min=%d step val=%d", pZoom->current_value, pZoom->maximum_value, pZoom->minimum_value, pZoom->step_value); - memcpy(pZoom, (cam_parm_info_t *)ctrlCmd.value, sizeof(cam_parm_info_t)); - return ctrlCmd.status; } From 2c2e8580d653632f7945b4d18aa804f9bb7fd237 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 17 Jun 2009 19:03:42 +0800 Subject: [PATCH 065/435] Add picture size values and fix effect values. --- libcamera2/QualcommCameraHardware.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 152ce56..3039181 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -180,7 +180,7 @@ static char *whitebalance_values; // from camera_effect_t static const str_map color_effects[] = { - { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ + { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, @@ -362,8 +362,9 @@ void QualcommCameraHardware::initDefaultParameters() INIT_VALUES_FOR(whitebalance); p.set("anti-banding-values", anti_banding_values); - p.set("color-effects-values", color_effects_values); + p.set("effect-values", color_effects_values); p.set("whitebalance-values", whitebalance_values); + p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); // FIXME: we can specify these numeric ranges better p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); From 321cfafbf54977d45cecdb7d8dc464f3c512d8fe Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Fri, 19 Jun 2009 16:04:38 +0800 Subject: [PATCH 066/435] Add location to exif. --- libcamera2/QualcommCameraHardware.cpp | 51 +++++++++++++++++++++++++++ libcamera2/QualcommCameraHardware.h | 1 + 2 files changed, 52 insertions(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 3039181..cea73f2 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -90,6 +90,7 @@ int (*LINK_camframe_terminate)(void); int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); +int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location); // callbacks void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, @@ -105,6 +106,7 @@ void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality #define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality #define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation +#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); @@ -428,6 +430,9 @@ void QualcommCameraHardware::startCamera() *(void**)&LINK_jpeg_encoder_setRotation = ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); + *(void**)&LINK_jpeg_encoder_setLocation = + ::dlsym(libmmcamera, "jpeg_encoder_setLocation"); + *(void **)&LINK_cam_conf = ::dlsym(libmmcamera, "cam_conf"); #else @@ -804,6 +809,8 @@ bool QualcommCameraHardware::native_jpeg_encode ( } } + jpeg_set_location(); + static common_crop_t scale; // no scaling if (!LINK_jpeg_encoder_encode(&mDimension, thumbnail_buf, thumb_fd, @@ -815,6 +822,50 @@ bool QualcommCameraHardware::native_jpeg_encode ( return true; } +void QualcommCameraHardware::jpeg_set_location() +{ + bool encode_location = true; + camera_position_type pt; + +#define PARSE_LOCATION(what,type,fmt,desc) do { \ + pt.what = 0; \ + const char *what##_str = mParameters.get("gps-"#what); \ + LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \ + if (what##_str) { \ + type what = 0; \ + if (sscanf(what##_str, fmt, &what) == 1) \ + pt.what = what; \ + else { \ + LOGE("GPS " #what " %s could not" \ + " be parsed as a " #desc, what##_str); \ + encode_location = false; \ + } \ + } \ + else { \ + LOGV("GPS " #what " not specified: " \ + "defaulting to zero in EXIF header."); \ + encode_location = false; \ + } \ + } while(0) + + PARSE_LOCATION(timestamp, long, "%ld", "long"); + if (!pt.timestamp) pt.timestamp = time(NULL); + PARSE_LOCATION(altitude, short, "%hd", "short"); + PARSE_LOCATION(latitude, double, "%lf", "double float"); + PARSE_LOCATION(longitude, double, "%lf", "double float"); + +#undef PARSE_LOCATION + + if (encode_location) { + LOGD("setting image location ALT %d LAT %lf LON %lf", + pt.altitude, pt.latitude, pt.longitude); + if (!LINK_jpeg_encoder_setLocation(&pt)) { + LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed."); + } + } + else LOGV("not setting image location"); +} + void QualcommCameraHardware::runFrameThread(void *data) { LOGV("runFrameThread E"); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 02fa598..a4c9dc7 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -97,6 +97,7 @@ public: uint8_t * buff_ptr , uint32_t buff_size); bool previewEnabled(); + void jpeg_set_location(); private: From 3ba00f29ba317790cd3dd3131d2e1fcff00faeb2 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 23 Jun 2009 19:10:08 -0700 Subject: [PATCH 067/435] libcamera fixes -- general cleanup: made a bunch of functions static to QualcommCameraHardware.cpp, not class members; got rid of unnecessary private member variables. The only functions that remain as members are native_set_dimension() and native_jpeg_encode() -- removed kRawFrameHeaderSize; aDSP frame offsets are zero now; -- simplify reg_unreg_buf -- Removed PreviewPmemPool and RawPmemPool, which do not need to be specialized on top of PmemPool. We use PmemPool instead. -- use PmemPool to both create pmem pools and register them with the driver -- takePicture runs in a separate thread -- the destructor keeps a singleton lock -- PmemPool calls dup() on the camera-control file descriptor to guard against release() calling close() on it before PmemPool has a chance to deregister pmem from the camera driver. -- got rid of hal_mmap() and hal_munmap() entirely and created a PmemHeap to manage thumbnails. -- removed support for CAPTURE_RAW. The CameraService can already do this. Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 720 ++++++++++---------------- libcamera2/QualcommCameraHardware.h | 128 ++--- 2 files changed, 309 insertions(+), 539 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index cea73f2..3a10260 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -31,7 +31,6 @@ #endif #include -#define CAPTURE_RAW 0 #define LIKELY(exp) __builtin_expect(!!(exp), 1) #define UNLIKELY(exp) __builtin_expect(!!(exp), 0) @@ -227,61 +226,6 @@ static Mutex singleton_lock; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); -static uint8_t *hal_mmap (uint32_t size, int *pmemFd); -static int hal_munmap (int pmem_fd, void *addr, size_t size); - -static uint8_t* hal_mmap(uint32_t size, int *pmemFd) -{ - void *ret; /* returned virtual address */ - int pmem_fd = open("/dev/pmem_adsp", O_RDWR); - - if (pmem_fd < 0) { - LOGE("hal_mmap: open /dev/pmem_adsp error %s!", - strerror(errno)); - return NULL; - } - - /* to make it page size aligned */ - // FIXME: use clp2() here - size = (size + 4095) & (~4095); - - LOGV("hal_mmap: pmem_fd %d size: %d", pmem_fd, size); - - ret = mmap(NULL, - size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - pmem_fd, - 0); - - if (ret == MAP_FAILED) { - LOGE("hal_mmap: pmem mmap() error %s", strerror(errno)); - close(pmem_fd); - return NULL; - } - - *pmemFd = pmem_fd; - return (uint8_t *)ret; -} - -static int hal_munmap (int pmem_fd, void *addr, size_t size) -{ - int rc; - - // FIXME: use clp2()? - size = (size + 4095) & (~4095); - - LOGV("hal_munmap pmem_fd %d, size = %d, virt_addr = 0x%x", - pmem_fd, - size, (uint32_t)addr); - - rc = munmap(addr, size); - if (rc < 0) - LOGE("hal_munmap: munmap error %s", strerror(errno)); - - close(pmem_fd); - return rc; -} QualcommCameraHardware::QualcommCameraHardware() : mParameters(), @@ -296,6 +240,7 @@ QualcommCameraHardware::QualcommCameraHardware() mCameraRunning(false), mPreviewInitialized(false), mFrameThreadRunning(false), + mSnapshotThreadRunning(false), mReleasedRecordingFrame(false), mShutterCallback(0), mRawPictureCallback(0), @@ -310,17 +255,12 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewFrameSize(0), mRawSize(0), mCameraControlFd(-1), - mPmemThumbnailFd(-1), - mPmemSnapshotFd(-1), - mPreviewFrameOffset(0), - mThumbnailBuf(NULL), - mMainImageBuf(NULL), mAutoFocusThreadRunning(false), mAutoFocusFd(-1), mInPreviewCallback(false) { memset(&mZoom, 0, sizeof(mZoom)); - memset(&mFrameThread, 0, sizeof(mFrameThread)); + memset(&mDimension, 0, sizeof(mDimension)); LOGV("constructor EX"); } @@ -336,19 +276,11 @@ void QualcommCameraHardware::initDefaultParameters() p.setPreviewFormat("yuv420sp"); // informative p.setPictureFormat("jpeg"); // informative - memset(&mDimension, 0, sizeof(mDimension)); - - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; - mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - mDimension.display_width = ps->width; - mDimension.display_height = ps->height; - mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH; - mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT; - p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative p.set("jpeg-thumbnail-quality", "90"); - p.setPictureSize(mDimension.picture_width, mDimension.picture_height); + + p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); #if 0 p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 @@ -453,7 +385,7 @@ void QualcommCameraHardware::startCamera() pthread_create(&mCamConfigThread, NULL, LINK_cam_conf, NULL); - LOGE("startCamera X"); + LOGV("startCamera X"); } status_t QualcommCameraHardware::dump(int fd, @@ -509,10 +441,11 @@ bool QualcommCameraHardware::native_set_dimension(int camfd) return false; } - return ctrlCmd.status; + LOGV("native_set_dimension status %d\n", ctrlCmd.status); + return ctrlCmd.status == CAM_CTRL_SUCCESS; } -bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) +static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; struct msm_ctrl_cmd ctrlCmd; @@ -532,7 +465,7 @@ bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; } -bool native_cancel_afmode(int camfd, int af_fd) +static bool native_cancel_afmode(int camfd, int af_fd) { int rc; struct msm_ctrl_cmd ctrlCmd; @@ -549,83 +482,7 @@ bool native_cancel_afmode(int camfd, int af_fd) return rc >= 0; } -void QualcommCameraHardware::reg_unreg_buf( - int camfd, - int width, - int height, - int pmempreviewfd, - uint8_t *prev_buf, - int pmem_type, - bool unregister, - bool active) -{ - uint32_t y_size; - struct msm_pmem_info pmemBuf; - uint32_t ioctl_cmd; - - if (prev_buf == NULL) - return; - - y_size = width * height; - - pmemBuf.type = pmem_type; - pmemBuf.fd = pmempreviewfd; - pmemBuf.vaddr = prev_buf; - pmemBuf.y_off = 0; - pmemBuf.cbcr_off = PAD_TO_WORD(y_size); - pmemBuf.active = active; - - ioctl_cmd = unregister ? - MSM_CAM_IOCTL_UNREGISTER_PMEM : - MSM_CAM_IOCTL_REGISTER_PMEM; - - LOGV("Entered reg_unreg_buf: camfd = %d, ioctl_cmd = %d, " - "pmemBuf.cbcr_off=%d, active=%d", - camfd, ioctl_cmd, pmemBuf.cbcr_off, active); - if (ioctl(camfd, ioctl_cmd, &pmemBuf) < 0) { - LOGE("reg_unreg_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", - camfd, - strerror(errno)); - } -} - -bool QualcommCameraHardware::native_register_preview_bufs( - int camfd, - struct msm_frame *frame, - bool active) -{ - LOGV("mDimension.display_width = %d, display_height = %d", - mDimension.display_width, mDimension.display_height); - - reg_unreg_buf(camfd, - mDimension.display_width, - mDimension.display_height, - frame->fd, - (uint8_t *)frame->buffer, - MSM_PMEM_OUTPUT2, - false, - active); - - return true; -} - -bool QualcommCameraHardware::native_unregister_preview_bufs( - int camfd, - int pmempreviewfd, - uint8_t *prev_buf) -{ - reg_unreg_buf(camfd, - mDimension.display_width, - mDimension.display_height, - pmempreviewfd, - prev_buf, - MSM_PMEM_OUTPUT2, - true, - true); - return true; -} - -bool QualcommCameraHardware::native_start_preview(int camfd) +static bool native_start_preview(int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -644,64 +501,7 @@ bool QualcommCameraHardware::native_start_preview(int camfd) return true; } -bool QualcommCameraHardware::native_register_snapshot_bufs( - int camfd, - int pmemthumbnailfd, - int pmemsnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) -{ - reg_unreg_buf(camfd, - mDimension.thumbnail_width, - mDimension.thumbnail_height, - pmemthumbnailfd, - thumbnail_buf, - MSM_PMEM_THUMBAIL, - false, - true); - - /* For original snapshot*/ - reg_unreg_buf(camfd, - mDimension.orig_picture_dx, - mDimension.orig_picture_dy, - pmemsnapshotfd, - main_img_buf, - MSM_PMEM_MAINIMG, - false, - true); - return true; -} - -bool QualcommCameraHardware::native_unregister_snapshot_bufs( - int camfd, - int thumb_fd, - int snap_fd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) -{ - reg_unreg_buf(camfd, - mDimension.thumbnail_width, - mDimension.thumbnail_height, - thumb_fd, - thumbnail_buf, - MSM_PMEM_THUMBAIL, - true, - true); - - /* For original snapshot*/ - reg_unreg_buf(camfd, - mDimension.orig_picture_dx, - mDimension.orig_picture_dy, - snap_fd, - main_img_buf, - MSM_PMEM_MAINIMG, - true, - true); - - return true; -} - -bool QualcommCameraHardware::native_get_picture (int camfd) +static bool native_get_picture (int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -718,7 +518,7 @@ bool QualcommCameraHardware::native_get_picture (int camfd) return true; } -bool QualcommCameraHardware::native_stop_preview(int camfd) +static bool native_stop_preview(int camfd) { struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; @@ -736,7 +536,7 @@ bool QualcommCameraHardware::native_stop_preview(int camfd) return true; } -bool QualcommCameraHardware::native_start_snapshot(int camfd) +static bool native_start_snapshot(int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -755,7 +555,7 @@ bool QualcommCameraHardware::native_start_snapshot(int camfd) return true; } -bool QualcommCameraHardware::native_stop_snapshot (int camfd) +static bool native_stop_snapshot (int camfd) { struct msm_ctrl_cmd ctrlCmd; @@ -774,11 +574,7 @@ bool QualcommCameraHardware::native_stop_snapshot (int camfd) return true; } -bool QualcommCameraHardware::native_jpeg_encode ( - int thumb_fd, - int snap_fd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf) +bool QualcommCameraHardware::native_jpeg_encode(void) { int jpeg_quality = mParameters.getInt("jpeg-quality"); if (jpeg_quality >= 0) { @@ -812,9 +608,12 @@ bool QualcommCameraHardware::native_jpeg_encode ( jpeg_set_location(); static common_crop_t scale; // no scaling + if (!LINK_jpeg_encoder_encode(&mDimension, - thumbnail_buf, thumb_fd, - main_img_buf, snap_fd, + (uint8_t *)mThumbnailHeap->mHeap->base(), + mThumbnailHeap->mHeap->getHeapID(), + (uint8_t *)mRawHeap->mHeap->base(), + mRawHeap->mHeap->getHeapID(), &scale)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; @@ -888,18 +687,6 @@ void QualcommCameraHardware::runFrameThread(void *data) LINK_cam_frame(data); } - for (cnt = 0; cnt < kPreviewBufferCount; ++cnt) { - LOGV("unregisterPreviewBuf %d", cnt); - native_unregister_preview_bufs(mCameraControlFd, - frames[cnt].fd, - (uint8_t *)frames[cnt].buffer); - LOGV("do_munmap preview buffer %d, fd=%d, prev_buf=0x%lx, size=%d", - cnt, frames[cnt].fd, frames[cnt].buffer,frame_size); - int rc = hal_munmap(frames[cnt].fd, - (uint8_t *)frames[cnt].buffer,frame_size); - LOGV("do_munmap done with return value %d", rc); - } - LOGV("unregisterPreviewBuf %d", cnt); mPreviewHeap.clear(); #if DLOPEN_LIBMMCAMERA @@ -942,15 +729,24 @@ bool QualcommCameraHardware::initPreview() } mFrameThreadWaitLock.unlock(); + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("initPreview: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("initPreview: old snapshot thread completed."); + } + mSnapshotThreadWaitLock.unlock(); + int cnt = 0; mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; - mPreviewHeap = - new PreviewPmemPool(kRawFrameHeaderSize + - mPreviewWidth * mPreviewHeight * 3/2, - kPreviewBufferCount, - mPreviewFrameSize, - kRawFrameHeaderSize, - "preview"); + mPreviewHeap = new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_OUTPUT2, + mPreviewFrameSize, + kPreviewBufferCount, + mPreviewFrameSize, + 0, + "preview"); if (!mPreviewHeap->initialized()) { mPreviewHeap.clear(); @@ -958,38 +754,21 @@ bool QualcommCameraHardware::initPreview() return false; } - bool ret = true; - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - ret = native_set_dimension(mCameraControlFd); - if(ret) { - frame_size = (clp2(mDimension.display_width * - mDimension.display_height * 3/2)); + bool ret = native_set_dimension(mCameraControlFd); + + if (ret) { for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { - frames[cnt].fd = 0; + frames[cnt].fd = mPreviewHeap->mHeap->getHeapID(); frames[cnt].buffer = - (unsigned long)hal_mmap(frame_size, &(frames[cnt].fd)); + (uint32_t)mPreviewHeap->mHeap->base() + mPreviewFrameSize * cnt; frames[cnt].y_off = 0; - frames[cnt].cbcr_off = - mDimension.display_width * mDimension.display_height; - - if (frames[cnt].buffer == 0) { - LOGE("initPreview X: mmap failed!"); - return false; - } - + frames[cnt].cbcr_off = mPreviewWidth * mPreviewHeight; frames[cnt].path = MSM_FRAME_ENC; - - LOGV("do_mmap pbuf = 0x%lx, pmem_fd = %d", - frames[cnt].buffer, frames[cnt].fd); - native_register_preview_bufs(mCameraControlFd, - &frames[cnt], - cnt != kPreviewBufferCount - 1); } - mFrameThreadWaitLock.lock(); pthread_attr_t attr; pthread_attr_init(&attr); @@ -1037,68 +816,52 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) mDimension.picture_width = mRawWidth; mDimension.picture_height = mRawHeight; + mRawSize = mRawWidth * mRawHeight * 3 / 2; + mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; if(!native_set_dimension(mCameraControlFd)) { LOGE("initRaw X: failed to set dimension"); return false; } - mRawSize = mRawWidth * mRawHeight * 3 / 2; - - mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - - LOGE("initRaw: clearing old mJpegHeap."); - mJpegHeap.clear(); + if (mJpegHeap != NULL) { + LOGV("initRaw: clearing old mJpegHeap."); + mJpegHeap.clear(); + } // Snapshot LOGV("initRaw: initializing mRawHeap."); mRawHeap = - new RawPmemPool("/dev/pmem_camera", - kRawFrameHeaderSize + mJpegMaxSize, - kRawBufferCount, - mRawSize, - kRawFrameHeaderSize, - "snapshot camera"); + new PmemPool("/dev/pmem_camera", + mCameraControlFd, + MSM_PMEM_MAINIMG, + mJpegMaxSize, + kRawBufferCount, + mRawSize, + 0, + "snapshot camera"); if (!mRawHeap->initialized()) { LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); mRawHeap = - new RawPmemPool("/dev/pmem_adsp", - kRawFrameHeaderSize + mJpegMaxSize, - kRawBufferCount, - mRawSize, - kRawFrameHeaderSize, - "snapshot camera"); + new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_MAINIMG, + mJpegMaxSize, + kRawBufferCount, + mRawSize, + 0, + "snapshot camera"); if (!mRawHeap->initialized()) { - LOGE("initRaw X: error initializing mRawHeap"); mRawHeap.clear(); + LOGE("initRaw X: error initializing mRawHeap"); return false; } } - mMainImageBuf = (uint8_t *)mRawHeap->mHeap->base(); - mPmemSnapshotFd = mRawHeap->mHeap->getHeapID(); - - LOGV("do_mmap snapshot pbuf = 0x%p, pmem_fd = %d", - mMainImageBuf, mPmemSnapshotFd); - - // Thumbnails - - mThumbnailBuf = hal_mmap(THUMBNAIL_BUFFER_SIZE, &mPmemThumbnailFd); - LOGV("do_mmap thumbnail pbuf = 0x%p, pmem_fd = %d", - mThumbnailBuf, mPmemThumbnailFd); - if (mThumbnailBuf == NULL) { - mRawHeap.clear(); - LOGE("initRaw X: cannot allocate thumbnail memory"); - return false; - } - - native_register_snapshot_bufs(mCameraControlFd, - mPmemThumbnailFd, - mPmemSnapshotFd, - mThumbnailBuf, - mMainImageBuf); + LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d", + (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID()); // Jpeg @@ -1110,10 +873,31 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) 0, // we do not know how big the picture wil be 0, "jpeg"); + if (!mJpegHeap->initialized()) { - LOGE("initRaw X failed: error initializing mJpegHeap."); mJpegHeap.clear(); mRawHeap.clear(); + LOGE("initRaw X failed: error initializing mJpegHeap."); + return false; + } + + // Thumbnails + + mThumbnailHeap = + new PmemPool("/dev/pmem_adsp", + mCameraControlFd, + MSM_PMEM_THUMBAIL, + THUMBNAIL_BUFFER_SIZE, + 1, + THUMBNAIL_BUFFER_SIZE, + 0, + "thumbnail"); + + if (!mThumbnailHeap->initialized()) { + mThumbnailHeap.clear(); + mJpegHeap.clear(); + mRawHeap.clear(); + LOGE("initRaw X failed: error initializing mThumbnailHeap."); return false; } } @@ -1125,17 +909,11 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) void QualcommCameraHardware::deinitRaw() { LOGV("deinitRaw E"); + + mThumbnailHeap.clear(); mJpegHeap.clear(); mRawHeap.clear(); - native_unregister_snapshot_bufs(mCameraControlFd, - mPmemThumbnailFd, mPmemSnapshotFd, - mThumbnailBuf, mMainImageBuf); - - if (mThumbnailBuf) { - hal_munmap(mPmemThumbnailFd, mThumbnailBuf, THUMBNAIL_BUFFER_SIZE); - mThumbnailBuf = NULL; - } LOGV("deinitRaw X"); } @@ -1199,6 +977,7 @@ void QualcommCameraHardware::release() QualcommCameraHardware::~QualcommCameraHardware() { LOGD("~QualcommCameraHardware E"); + Mutex::Autolock lock(&singleton_lock); singleton.clear(); LOGD("~QualcommCameraHardware X"); } @@ -1405,6 +1184,34 @@ status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, return NO_ERROR; } +void QualcommCameraHardware::runSnapshotThread(void *data) +{ + LOGV("runSnapshotThread E"); + if (native_start_snapshot(mCameraControlFd)) + receiveRawPicture(); + else + LOGE("main: native_start_snapshot failed!"); + + mSnapshotThreadWaitLock.lock(); + mSnapshotThreadRunning = false; + mSnapshotThreadWait.signal(); + mSnapshotThreadWaitLock.unlock(); + + LOGV("runSnapshotThread X"); +} + +void *snapshot_thread(void *user) +{ + LOGD("snapshot_thread E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->runSnapshotThread(user); + } + else LOGW("not starting snapshot thread: the object went away!"); + LOGD("snapshot_thread X"); + return NULL; +} + status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, raw_callback raw_cb, jpeg_callback jpeg_cb, @@ -1429,14 +1236,24 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, mPictureCallbackCookie = user; } - if (native_start_snapshot(mCameraControlFd) == false) { - LOGE("main: start_preview failed!"); - return UNKNOWN_ERROR; + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("takePicture: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("takePicture: old snapshot thread completed."); } - receiveRawPicture(); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + mSnapshotThreadRunning = !pthread_create(&mSnapshotThread, + &attr, + snapshot_thread, + NULL); + mSnapshotThreadWaitLock.unlock(); LOGV("takePicture: X"); - return NO_ERROR; + return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR; } status_t QualcommCameraHardware::cancelPicture( @@ -1465,33 +1282,57 @@ status_t QualcommCameraHardware::setParameters( Mutex::Autolock l(&mLock); - mParameters = params; - - int width, height; - params.getPreviewSize(&width, &height); - LOGV("requested size %d x %d", width, height); preview_size_type *ps = preview_sizes; - size_t i; - for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { - if (width >= ps->width && height >= ps->height) - break; + + { + int width, height; + params.getPreviewSize(&width, &height); + LOGV("requested size %d x %d", width, height); + // Validate the preview size + size_t i; + for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { + if (width == ps->width && height == ps->height) + break; + } + if (i == PREVIEW_SIZE_COUNT) { + LOGE("Invalid preview size requested: %dx%d", + width, height); + return BAD_VALUE; + } } - if (i == PREVIEW_SIZE_COUNT) - ps--; - LOGV("actual size %d x %d", ps->width, ps->height); - mParameters.setPreviewSize(ps->width, ps->height); + mPreviewWidth = mDimension.display_width = ps->width; + mPreviewHeight = mDimension.display_height = ps->height; - mDimension.display_width = ps->width; - mDimension.display_height = ps->height; + // FIXME: validate snapshot sizes, - mParameters.getPreviewSize(&mPreviewWidth, &mPreviewHeight); - mParameters.getPictureSize(&mRawWidth, &mRawHeight); + params.getPictureSize(&mRawWidth, &mRawHeight); + mDimension.picture_width = mRawWidth; + mDimension.picture_height = mRawHeight; - mPreviewWidth = (mPreviewWidth + 1) & ~1; - mPreviewHeight = (mPreviewHeight + 1) & ~1; - mRawHeight = (mRawHeight + 1) & ~1; - mRawWidth = (mRawWidth + 1) & ~1; + // Set up the jpeg-thumbnail-size parameters. + + { + int val; + + val = params.getInt("jpeg-thumbnail-width"); + if (val < 0) { + mDimension.ui_thumbnail_width= THUMBNAIL_WIDTH; + LOGW("jpeg-thumbnail-width is not specified: defaulting to %d", + THUMBNAIL_WIDTH); + } + else mDimension.ui_thumbnail_width = val; + + val = params.getInt("jpeg-thumbnail-height"); + if (val < 0) { + mDimension.ui_thumbnail_height= THUMBNAIL_HEIGHT; + LOGW("jpeg-thumbnail-height is not specified: defaulting to %d", + THUMBNAIL_HEIGHT); + } + else mDimension.ui_thumbnail_height = val; + } + + mParameters = params; if (mCameraRunning) { @@ -1588,39 +1429,6 @@ sp QualcommCameraHardware::getInstance() } } -#if CAPTURE_RAW -static void dump_to_file(const char *fname, - uint8_t *buf, uint32_t size) -{ - int nw, cnt = 0; - uint32_t written = 0; - - LOGD("opening file [%s]", fname); - int fd = open(fname, O_RDWR | O_CREAT); - if (fd < 0) { - LOGE("failed to create file [%s]: %s", fname, strerror(errno)); - return; - } - - LOGD("writing %d uint8_ts to file [%s]", size, fname); - while (written < size) { - nw = ::write(fd, - buf + written, - size - written); - if (nw < 0) { - LOGE("failed to write to file [%s]: %s", - fname, strerror(errno)); - break; - } - written += nw; - cnt++; - } - LOGD("done writing %d uint8_ts to file [%s] in %d passes", - size, fname, cnt); - ::close(fd); -} -#endif // CAMERA_RAW - void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) { // LOGV("receivePreviewFrame E"); @@ -1639,21 +1447,19 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) // Find the offset within the heap of the current buffer. ssize_t offset = - mPreviewWidth * mPreviewHeight * - mPreviewFrameOffset * 3 / 2; + (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); + offset /= mPreviewFrameSize; - memcpy((uint8_t *)mPreviewHeap->mHeap->base() + offset, - (uint8_t *)frame->buffer, - mPreviewWidth * mPreviewHeight * 3 / 2); + //LOGV("%d\n", offset); mInPreviewCallback = true; if (pcb != NULL) - pcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], + pcb(mPreviewHeap->mBuffers[offset], pdata); if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); - rcb(mPreviewHeap->mBuffers[mPreviewFrameOffset], rdata); + rcb(mPreviewHeap->mBuffers[offset], rdata); if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); @@ -1662,9 +1468,6 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) } mInPreviewCallback = false; - mPreviewFrameOffset++; - mPreviewFrameOffset %= kPreviewBufferCount; - // LOGV("receivePreviewFrame X"); } @@ -1727,8 +1530,7 @@ bool QualcommCameraHardware::recordingEnabled() return mCameraRunning && mRecordingCallback != NULL; } -void -QualcommCameraHardware::notifyShutter() +void QualcommCameraHardware::notifyShutter() { LOGV("notifyShutter: E"); if (mShutterCallback) @@ -1736,10 +1538,7 @@ QualcommCameraHardware::notifyShutter() LOGV("notifyShutter: X"); } -static ssize_t snapshot_offset = 0; - -void -QualcommCameraHardware::receiveRawPicture() +void QualcommCameraHardware::receiveRawPicture() { LOGV("receiveRawPicture: E"); @@ -1752,12 +1551,7 @@ QualcommCameraHardware::receiveRawPicture() LOGE("getPicture failed!"); return; } - ssize_t offset = (mRawWidth * mRawHeight * snapshot_offset * 3 / 2); -#if CAPTURE_RAW - dump_to_file("/sdcard/photo.raw", - (uint8_t *)mMainImageBuf, mRawWidth * mRawHeight * 3 / 2); -#endif - mRawPictureCallback(mRawHeap->mBuffers[offset], + mRawPictureCallback(mRawHeap->mBuffers[0], mPictureCallbackCookie); } else LOGV("Raw-picture callback was canceled--skipping."); @@ -1765,10 +1559,7 @@ QualcommCameraHardware::receiveRawPicture() if (mJpegPictureCallback != NULL) { mJpegSize = 0; if (LINK_jpeg_encoder_init()) { - if(native_jpeg_encode(mPmemThumbnailFd, - mPmemSnapshotFd, - mThumbnailBuf, - mMainImageBuf)) { + if(native_jpeg_encode()) { LOGV("receiveRawPicture: X (success)"); return; } @@ -1800,8 +1591,7 @@ void QualcommCameraHardware::receiveJpegPictureFragment( mJpegSize += buff_size; } -void -QualcommCameraHardware::receiveJpegPicture(void) +void QualcommCameraHardware::receiveJpegPicture(void) { LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", mJpegSize, mJpegHeap->mBufferSize); @@ -1923,7 +1713,7 @@ void QualcommCameraHardware::setBrightness() } } -bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) +static bool native_get_zoom(int camfd, void *pZm) { struct msm_ctrl_cmd ctrlCmd; cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; @@ -1950,7 +1740,7 @@ bool QualcommCameraHardware::native_get_zoom(int camfd, void *pZm) return ctrlCmd.status; } -bool QualcommCameraHardware::native_set_zoom(int camfd, void *pZm) +static bool native_set_zoom(int camfd, void *pZm) { struct msm_ctrl_cmd ctrlCmd; @@ -2080,7 +1870,17 @@ QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, completeInitialization(); } +static bool register_buf(int camfd, + int size, + int pmempreviewfd, + uint32_t offset, + uint8_t *buf, + int pmem_type, + bool register_buffer = true); + QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, + int camera_control_fd, + int pmem_type, int buffer_size, int num_buffers, int frame_size, int frame_offset, @@ -2089,7 +1889,9 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, num_buffers, frame_size, frame_offset, - name) + name), + mPmemType(pmem_type), + mCameraControlFd(dup(camera_control_fd)) { LOGV("constructing MemPool %s backed by pmem pool %s: " "%d frames @ %d bytes, offset %d, buffer size %d", @@ -2097,6 +1899,10 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, pmem_pool, num_buffers, frame_size, frame_offset, buffer_size); + LOGV("%s: duplicating control fd %d --> %d", + __FUNCTION__, + camera_control_fd, mCameraControlFd); + // Make a new mmap'ed heap that can be shared across processes. mAlignedSize = clp2(buffer_size * num_buffers); @@ -2119,65 +1925,45 @@ QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, return; } - LOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", + LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", pmem_pool, mFd, mSize.len); + // Unregister preview buffers with the camera drivers. + for (int cnt = 0; cnt < num_buffers; ++cnt) { + register_buf(mCameraControlFd, + buffer_size, + mHeap->getHeapID(), + buffer_size * cnt, + (uint8_t *)mHeap->base() + buffer_size * cnt, + pmem_type); + } + completeInitialization(); } else LOGE("pmem pool %s error: could not create master heap!", pmem_pool); } -QualcommCameraHardware::PreviewPmemPool::PreviewPmemPool( - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::PmemPool("/dev/pmem_adsp", - buffer_size, - num_buffers, - frame_size, - frame_offset, - name) +QualcommCameraHardware::PmemPool::~PmemPool() { - LOGV("constructing PreviewPmemPool"); -} - -QualcommCameraHardware::PreviewPmemPool::~PreviewPmemPool() -{ - LOGV("destroying PreviewPmemPool"); - if(initialized()) { - void *base = mHeap->base(); - LOGV("destroying PreviewPmemPool"); - } -} - -QualcommCameraHardware::RawPmemPool::RawPmemPool( - const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::PmemPool(pmem_pool, - buffer_size, - num_buffers, - frame_size, - frame_offset, - name) -{ - LOGV("constructing RawPmemPool"); -} - -QualcommCameraHardware::RawPmemPool::~RawPmemPool() -{ - LOGV("destroying RawPmemPool"); - if(initialized()) { - void *base = mHeap->base(); - LOGV("releasing RawPmemPool memory %p", - base); + LOGV("%s: %s E", __FUNCTION__, mName); + // Unregister preview buffers with the camera drivers. + for (int cnt = 0; cnt < mNumBuffers; ++cnt) { + register_buf(mCameraControlFd, + mBufferSize, + mHeap->getHeapID(), + mBufferSize * cnt, + (uint8_t *)mHeap->base() + mBufferSize * cnt, + mPmemType, + false /* unregister */); } + LOGV("destroying PmemPool %s: closing control fd %d", + mName, + mCameraControlFd); + close(mCameraControlFd); + LOGV("%s: %s X", __FUNCTION__, mName); } QualcommCameraHardware::MemPool::~MemPool() @@ -2189,6 +1975,40 @@ QualcommCameraHardware::MemPool::~MemPool() LOGV("destroying MemPool %s completed", mName); } +static bool register_buf(int camfd, + int size, + int pmempreviewfd, + uint32_t offset, + uint8_t *buf, + int pmem_type, + bool register_buffer) +{ + struct msm_pmem_info pmemBuf; + + pmemBuf.type = pmem_type; + pmemBuf.fd = pmempreviewfd; + pmemBuf.offset = offset; + pmemBuf.len = size; + pmemBuf.vaddr = buf; + pmemBuf.y_off = 0; + pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3); + pmemBuf.active = true; + + LOGV("register_buf: camfd = %d, reg = %d buffer = %p", + camfd, !register_buffer, buf); + if (ioctl(camfd, + register_buffer ? + MSM_CAM_IOCTL_REGISTER_PMEM : + MSM_CAM_IOCTL_UNREGISTER_PMEM, + &pmemBuf) < 0) { + LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", + camfd, + strerror(errno)); + return false; + } + return true; +} + status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const { const size_t SIZE = 256; diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index a4c9dc7..2ab2384 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -36,68 +36,30 @@ public: virtual sp getPreviewHeap() const; virtual sp getRawHeap() const; - virtual status_t dump(int fd, const Vector& args) const; - virtual status_t startPreview(preview_callback cb, void* user); - virtual void stopPreview(); - virtual status_t startRecording(recording_callback cb, void* user); - virtual void stopRecording(); - virtual bool recordingEnabled(); - virtual void releaseRecordingFrame(const sp& mem); - virtual status_t autoFocus(autofocus_callback, void *user); - virtual status_t takePicture(shutter_callback, - raw_callback, - jpeg_callback, - void* user); - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, bool cancel_jpeg); - virtual status_t setParameters(const CameraParameters& params); - virtual CameraParameters getParameters() const; - + virtual status_t dump(int fd, const Vector& args) const; + virtual status_t startPreview(preview_callback cb, void* user); + virtual void stopPreview(); + virtual bool previewEnabled(); + virtual status_t startRecording(recording_callback cb, void* user); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp& mem); + virtual status_t autoFocus(autofocus_callback, void *user); + virtual status_t takePicture(shutter_callback, raw_callback, + jpeg_callback, void *); + virtual status_t cancelPicture(bool cancel_shutter, + bool cancel_raw, bool cancel_jpeg); + virtual status_t setParameters(const CameraParameters& params); + virtual CameraParameters getParameters() const; virtual void release(); static sp createInstance(); static sp getInstance(); - - - bool native_set_dimension (int camfd); - void reg_unreg_buf(int camfd, int width, int height, - int pmempreviewfd, uint8_t *prev_buf, - int pmem_type, - bool unregister, - bool active); - bool native_register_preview_bufs(int camfd, - struct msm_frame *frame,bool active); - bool native_unregister_preview_bufs(int camfd, int pmempreviewfd, - uint8_t *prev_buf); - - bool native_start_preview(int camfd); - bool native_stop_preview(int camfd); - - bool native_register_snapshot_bufs(int camfd, int pmemthumbnailfd, - int pmemsnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf); - bool native_unregister_snapshot_bufs(int camfd, int pmemThumbnailfd, - int pmemSnapshotfd, - uint8_t *thumbnail_buf, - uint8_t *main_img_buf); - bool native_get_picture(int camfd); - bool native_start_snapshot(int camfd); - bool native_stop_snapshot(int camfd); - bool native_jpeg_encode (int pmemThumbnailfd, int pmemSnapshotfd, - uint8_t *thumbnail_buf, uint8_t *main_img_buf); - - bool native_set_zoom(int camfd, void *pZm); - bool native_get_zoom(int camfd, void *pZm); - void receivePreviewFrame(struct msm_frame *frame); void receiveJpegPicture(void); - void receiveJpegPictureFragment( - uint8_t * buff_ptr , uint32_t buff_size); - bool previewEnabled(); - void jpeg_set_location(); + void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); private: @@ -108,6 +70,8 @@ private: friend void *auto_focus_thread(void *user); void runAutoFocus(); void cancelAutoFocus(); + bool native_set_dimension (int camfd); + bool native_jpeg_encode (void); static wp singleton; @@ -118,7 +82,6 @@ private: static const int kPreviewBufferCount = 4; static const int kRawBufferCount = 1; static const int kJpegBufferCount = 1; - static const int kRawFrameHeaderSize = 0; //TODO: put the picture dimensions in the CameraParameters object; CameraParameters mParameters; @@ -133,7 +96,7 @@ private: bool mZoomInitialised; bool mCameraRunning; bool mPreviewInitialized; - + // This class represents a heap which maintains several contiguous // buffers. The heap may be backed by pmem (when pmem_pool contains // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). @@ -147,7 +110,7 @@ private: virtual ~MemPool() = 0; void completeInitialization(); - bool initialized() const { + bool initialized() const { return mHeap != NULL && mHeap->base() != MAP_FAILED; } @@ -172,37 +135,23 @@ private: struct PmemPool : public MemPool { PmemPool(const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - virtual ~PmemPool(){ } + int control_camera_fd, int pmem_type, + int buffer_size, int num_buffers, + int frame_size, int frame_offset, + const char *name); + virtual ~PmemPool(); int mFd; + int mPmemType; + int mCameraControlFd; uint32_t mAlignedSize; struct pmem_region mSize; }; - struct PreviewPmemPool : public PmemPool { - virtual ~PreviewPmemPool(); - PreviewPmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - struct RawPmemPool : public PmemPool { - virtual ~RawPmemPool(); - RawPmemPool(const char *pmem_pool, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - sp mPreviewHeap; - sp mRawHeap; + sp mPreviewHeap; + sp mThumbnailHeap; + sp mRawHeap; sp mJpegHeap; - + void startCamera(); bool initPreview(); void deinitPreview(); @@ -215,6 +164,12 @@ private: friend void *frame_thread(void *user); void runFrameThread(void *data); + bool mSnapshotThreadRunning; + Mutex mSnapshotThreadWaitLock; + Condition mSnapshotThreadWait; + friend void *snapshot_thread(void *user); + void runSnapshotThread(void *data); + void initDefaultParameters(); void setSensorPreviewEffect(int, const char*); @@ -227,7 +182,7 @@ private: bool mReleasedRecordingFrame; void notifyShutter(); - + void receiveRawPicture(void); Mutex mCallbackLock; @@ -241,7 +196,6 @@ private: zero, or the size of the last JPEG picture taken. */ uint32_t mJpegSize; - shutter_callback mShutterCallback; raw_callback mRawPictureCallback; @@ -266,17 +220,13 @@ private: int mCameraControlFd; cam_parm_info_t mZoom; cam_ctrl_dimension_t mDimension; - int mPmemThumbnailFd; - int mPmemSnapshotFd; - ssize_t mPreviewFrameOffset; - uint8_t *mThumbnailBuf; - uint8_t *mMainImageBuf; bool mAutoFocusThreadRunning; Mutex mAutoFocusThreadLock; int mAutoFocusFd; pthread_t mCamConfigThread; pthread_t mFrameThread; + pthread_t mSnapshotThread; struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; From 00bd746427a41684d7f9ef5ff2aff3caad205094 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 24 Jun 2009 16:52:08 -0700 Subject: [PATCH 068/435] copybit now uses a native_handle_t* instead of a fd/offset --- libcopybit/Android.mk | 3 ++- libcopybit/{copybit.c => copybit.cpp} | 38 +++++++++++++++------------ 2 files changed, 23 insertions(+), 18 deletions(-) rename libcopybit/{copybit.c => copybit.cpp} (93%) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index f6a1b4b..af65671 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -20,6 +20,7 @@ include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := copybit.c +LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k +LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc include $(BUILD_SHARED_LIBRARY) diff --git a/libcopybit/copybit.c b/libcopybit/copybit.cpp similarity index 93% rename from libcopybit/copybit.c rename to libcopybit/copybit.cpp index 3565074..60adc48 100644 --- a/libcopybit/copybit.c +++ b/libcopybit/copybit.cpp @@ -34,6 +34,8 @@ #include +#include "gralloc_priv.h" + /******************************************************************************/ /** State information for each device instance */ @@ -52,21 +54,21 @@ 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 + open: open_copybit }; /* * The COPYBIT Module */ -const 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, +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 } }; @@ -113,13 +115,14 @@ static int get_format(int format) { } /** convert from copybit image to mdp image structure */ -static void set_image(struct mdp_img *img, - const struct copybit_image_t *rhs) { +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 = rhs->offset; - img->memory_id = rhs->fd; + img->offset = hnd->offset; + img->memory_id = hnd->fd; } /** setup rectangles */ @@ -360,12 +363,13 @@ static int open_copybit(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { int status = -EINVAL; - struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t)); + 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 = 0; - ctx->device.common.module = module; + ctx->device.common.version = 1; + ctx->device.common.module = const_cast(module); ctx->device.common.close = close_copybit; ctx->device.set_parameter = set_parameter_copybit; ctx->device.get = get; From 9db8a0fc2669c73018122887b88c523e14f404d7 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Thu, 25 Jun 2009 16:48:11 +0800 Subject: [PATCH 069/435] Add preview size 384x288. --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 3a10260..212b3f0 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -123,6 +123,7 @@ static preview_size_type preview_sizes[] = { { 800, 480 }, // WVGA { 640, 480 }, // VGA { 480, 320 }, // HVGA + { 384, 288 }, { 352, 288 }, // CIF { 320, 240 }, // QVGA { 240, 160 }, // SQVGA From fd3bc52cfec908c230db7a2df887c15f1c792662 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 12 Jun 2009 15:13:14 -0700 Subject: [PATCH 070/435] copybit: also build for qsd8k --- libcopybit/Android.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index f6a1b4b..f326038 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -16,6 +16,8 @@ LOCAL_PATH:= $(call my-dir) # HAL module implemenation, not prelinked and stored in # hw/..so + +ifeq ($(TARGET_BOARD_PLATFORM),msm7k) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw @@ -23,3 +25,14 @@ LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.c LOCAL_MODULE := copybit.msm7k include $(BUILD_SHARED_LIBRARY) +endif + +ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := copybit.c +LOCAL_MODULE := copybit.qsd8k +include $(BUILD_SHARED_LIBRARY) +endif From 3c05a4483c4c5f9eba830fb3b626d97a68c0d4a2 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Mon, 29 Jun 2009 13:09:24 -0700 Subject: [PATCH 071/435] libcamera: dlopen() libqcamera in the AF thread Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 212b3f0..c5ca2cf 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -678,7 +678,7 @@ void QualcommCameraHardware::runFrameThread(void *data) // lifetime of this object. We do not want to dlclose() libqcamera while // LINK_cam_frame is still running. void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("loading libqcamera at %p", libhandle); + LOGV("FRAME: loading libqcamera at %p", libhandle); if (!libhandle) { LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); } @@ -1097,6 +1097,23 @@ void QualcommCameraHardware::runAutoFocus() return; } +#if DLOPEN_LIBMMCAMERA + // We need to maintain a reference to libqcamera.so for the duration of the + // AF thread, because we do not know when it will exit relative to the + // lifetime of this object. We do not want to dlclose() libqcamera while + // LINK_cam_frame is still running. + void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + LOGV("AF: loading libqcamera at %p", libhandle); + if (!libhandle) { + LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + close(mAutoFocusFd); + mAutoFocusFd = -1; + mAutoFocusThreadRunning = false; + mAutoFocusThreadLock.unlock(); + return; + } +#endif + /* This will block until either AF completes or is cancelled. */ LOGV("af start (fd %d)", mAutoFocusFd); bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); @@ -1117,6 +1134,13 @@ void QualcommCameraHardware::runAutoFocus() mAutoFocusCallback = NULL; mAutoFocusCallbackCookie = NULL; mCallbackLock.unlock(); + +#if DLOPEN_LIBMMCAMERA + if (libhandle) { + ::dlclose(libhandle); + LOGV("AF: dlclose(libqcamera)"); + } +#endif } void QualcommCameraHardware::cancelAutoFocus() From ad48d0f0807349dd0f8e8a584411f738d9cd2155 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 30 Jun 2009 16:07:21 -0700 Subject: [PATCH 072/435] libcamera: set antibanding to 60Hz, use cropping information on snapshot -- Set the antibanding to 60Hz for the US (Should be 50Hz for the rest of the world.) -- Save the cropping info returned when taking a picture and then pass it to the JPEG encoder. This enables digital zoom for JPEG images (cropping and upsampling). Signed-off-by: Iliyan Malchev --- libcamera2/QualcommCameraHardware.cpp | 26 +++++++++++++++++++------- libcamera2/QualcommCameraHardware.h | 2 ++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index c5ca2cf..00ef2fa 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -262,6 +262,7 @@ QualcommCameraHardware::QualcommCameraHardware() { memset(&mZoom, 0, sizeof(mZoom)); memset(&mDimension, 0, sizeof(mDimension)); + memset(&mCrop, 0, sizeof(mCrop)); LOGV("constructor EX"); } @@ -502,12 +503,13 @@ static bool native_start_preview(int camfd) return true; } -static bool native_get_picture (int camfd) +static bool native_get_picture (int camfd, common_crop_t *crop) { struct msm_ctrl_cmd ctrlCmd; ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = 0; + ctrlCmd.length = sizeof(common_crop_t); + ctrlCmd.value = crop; if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", @@ -516,6 +518,18 @@ static bool native_get_picture (int camfd) return false; } + LOGV("crop: in1_w %d", crop->in1_w); + LOGV("crop: in1_h %d", crop->in1_h); + LOGV("crop: out1_w %d", crop->out1_w); + LOGV("crop: out1_h %d", crop->out1_h); + + LOGV("crop: in2_w %d", crop->in2_w); + LOGV("crop: in2_h %d", crop->in2_h); + LOGV("crop: out2_w %d", crop->out2_w); + LOGV("crop: out2_h %d", crop->out2_h); + + LOGV("crop: update %d", crop->update_flag); + return true; } @@ -608,14 +622,12 @@ bool QualcommCameraHardware::native_jpeg_encode(void) jpeg_set_location(); - static common_crop_t scale; // no scaling - if (!LINK_jpeg_encoder_encode(&mDimension, (uint8_t *)mThumbnailHeap->mHeap->base(), mThumbnailHeap->mHeap->getHeapID(), (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID(), - &scale)) { + &mCrop)) { LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); return false; } @@ -1572,7 +1584,7 @@ void QualcommCameraHardware::receiveRawPicture() Mutex::Autolock cbLock(&mCallbackLock); notifyShutter(); if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd)== false) { + if(native_get_picture(mCameraControlFd, &mCrop)== false) { LOGE("getPicture failed!"); return; } @@ -1700,7 +1712,7 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) antibandvalue = attr_lookup(anti_banding, antibanding, - CAMERA_ANTIBANDING_OFF); + CAMERA_ANTIBANDING_60HZ); ctrlCmd.value = (void *)&antibandvalue; LOGV("In setAntiBanding: match: %s: %d", antibanding, antibandvalue); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 2ab2384..1a55132 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -228,6 +228,8 @@ private: pthread_t mFrameThread; pthread_t mSnapshotThread; + common_crop_t mCrop; + struct msm_frame frames[kPreviewBufferCount]; bool mInPreviewCallback; }; From 04b2c40f3c18177563dc54175e02ee042ae3ddae Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Mon, 22 Jun 2009 23:23:37 +0800 Subject: [PATCH 073/435] Change the timing of shutter callback. --- libcamera2/QualcommCameraHardware.cpp | 24 ++++++++++++++++++++---- libcamera2/QualcommCameraHardware.h | 3 +-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 00ef2fa..e8c67dd 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -95,6 +95,7 @@ void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); +void (**LINK_mmcamera_shutter_callback)(); #else #define LINK_cam_conf cam_conf #define LINK_cam_frame cam_frame @@ -110,6 +111,7 @@ extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, uint32_t buff_size); extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); +extern void (*mmcamera_shutter_callback)(); #endif } // extern "C" @@ -227,6 +229,7 @@ static Mutex singleton_lock; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); static void receive_jpeg_callback(jpeg_event_t status); +static void receive_shutter_callback(); QualcommCameraHardware::QualcommCameraHardware() : mParameters(), @@ -355,6 +358,11 @@ void QualcommCameraHardware::startCamera() *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; + *(void **)&LINK_mmcamera_shutter_callback = + ::dlsym(libmmcamera, "mmcamera_shutter_callback"); + + *LINK_mmcamera_shutter_callback = receive_shutter_callback; + *(void**)&LINK_jpeg_encoder_setMainImageQuality = ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); @@ -373,6 +381,7 @@ void QualcommCameraHardware::startCamera() mmcamera_camframe_callback = receive_camframe_callback; mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; mmcamera_jpeg_callback = receive_jpeg_callback; + mmcamera_shutter_callback = receive_shutter_callback; #endif // DLOPEN_LIBMMCAMERA /* The control thread is in libcamera itself. */ @@ -1569,10 +1578,18 @@ bool QualcommCameraHardware::recordingEnabled() void QualcommCameraHardware::notifyShutter() { - LOGV("notifyShutter: E"); if (mShutterCallback) mShutterCallback(mPictureCallbackCookie); - LOGV("notifyShutter: X"); +} + +static void receive_shutter_callback() +{ + LOGV("receive_shutter_callback: E"); + sp obj = QualcommCameraHardware::getInstance(); + if (obj != 0) { + obj->notifyShutter(); + } + LOGV("receive_shutter_callback: X"); } void QualcommCameraHardware::receiveRawPicture() @@ -1580,9 +1597,8 @@ void QualcommCameraHardware::receiveRawPicture() LOGV("receiveRawPicture: E"); int ret,rc,rete; -// Temporary fix for multiple snapshot issue on 8k: disabling shutter callback + Mutex::Autolock cbLock(&mCallbackLock); - notifyShutter(); if (mRawPictureCallback != NULL) { if(native_get_picture(mCameraControlFd, &mCrop)== false) { LOGE("getPicture failed!"); diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 1a55132..c647fcd 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -60,6 +60,7 @@ public: void receiveJpegPicture(void); void jpeg_set_location(); void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); + void notifyShutter(); private: @@ -181,8 +182,6 @@ private: Mutex mLock; bool mReleasedRecordingFrame; - void notifyShutter(); - void receiveRawPicture(void); Mutex mCallbackLock; From 9a7afa61af5c513d370b94ee45842ff9601fcd7e Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Tue, 7 Jul 2009 11:13:55 -0700 Subject: [PATCH 074/435] libcopybit: Fix build for qsd8k copybit.c got renamed Signed-off-by: Dima Zavin --- libcopybit/Android.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index 48cfd60..c93e159 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -33,7 +33,8 @@ include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := copybit.c +LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.qsd8k +LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc include $(BUILD_SHARED_LIBRARY) endif From 12b41c417f901fc76d985ff51c2525284635e74e Mon Sep 17 00:00:00 2001 From: Dave Sparks Date: Wed, 8 Jul 2009 15:58:41 -0700 Subject: [PATCH 075/435] Add timestamps to video frames to improve A/V sync. Bug 1927069. --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index e8c67dd..37cf953 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1505,7 +1505,7 @@ void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) if(rcb != NULL) { Mutex::Autolock rLock(&mRecordFrameLock); - rcb(mPreviewHeap->mBuffers[offset], rdata); + rcb(systemTime(), mPreviewHeap->mBuffers[offset], rdata); if (mReleasedRecordingFrame != true) { LOGV("block for release frame request/command"); mRecordWait.wait(mRecordFrameLock); From dbdbc0d26cc9744ae0cc86b85d893e81cc14373e Mon Sep 17 00:00:00 2001 From: James Dong Date: Fri, 10 Jul 2009 17:20:16 -0700 Subject: [PATCH 077/435] The antibanding (60Hz) broke the bar code scanner. bug 1962986 --- libcamera2/QualcommCameraHardware.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 37cf953..9a3555b 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1728,7 +1728,13 @@ void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) antibandvalue = attr_lookup(anti_banding, antibanding, - CAMERA_ANTIBANDING_60HZ); + /* FIXME: + * CAMERA_ANTIBANDING_60HZ broke the barcode scanner + * somehow. turn it off and revert it back to off + * for now until we figure out what is the best + * solution. + */ + CAMERA_ANTIBANDING_OFF /*CAMERA_ANTIBANDING_60HZ */); ctrlCmd.value = (void *)&antibandvalue; LOGV("In setAntiBanding: match: %s: %d", antibanding, antibandvalue); From bb05604b8de9bed83d937148a056eba256dd9e2b Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Mon, 13 Jul 2009 19:29:25 +0800 Subject: [PATCH 078/435] Fix 1956740: startPreview failed The problem is even after release() is done, the singleton variable is not cleared, so a new openCameraHardware() call could return an instance which is already released. The singleton variable is cleared in the destructor, so we wait until that happens in openCameraHardware(). --- libcamera2/QualcommCameraHardware.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 9a3555b..1679133 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -225,6 +225,8 @@ static inline unsigned clp2(unsigned x) namespace android { static Mutex singleton_lock; +static bool singleton_releasing; +static Condition singleton_wait; static void receive_camframe_callback(struct msm_frame *frame); static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); @@ -993,6 +995,9 @@ void QualcommCameraHardware::release() } #endif + Mutex::Autolock lock(&singleton_lock); + singleton_releasing = true; + LOGD("release X"); } @@ -1001,6 +1006,8 @@ QualcommCameraHardware::~QualcommCameraHardware() LOGD("~QualcommCameraHardware E"); Mutex::Autolock lock(&singleton_lock); singleton.clear(); + singleton_releasing = false; + singleton_wait.signal(); LOGD("~QualcommCameraHardware X"); } @@ -1435,6 +1442,13 @@ sp QualcommCameraHardware::createInstance() LOGD("createInstance: E"); Mutex::Autolock lock(&singleton_lock); + + // Wait until the previous release is done. + while (singleton_releasing) { + LOGD("Wait for previous release."); + singleton_wait.wait(singleton_lock); + } + if (singleton != 0) { sp hardware = singleton.promote(); if (hardware != 0) { From c65f33f597c048464650a0fd30edbde132ba8721 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 15 Jul 2009 15:02:32 -0700 Subject: [PATCH 079/435] msm7k now has its own gralloc module -- currently identical to the default gralloc, soon to be different --- libcopybit/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index c93e159..b02b0b9 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -24,7 +24,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k -LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc +LOCAL_C_INCLUDES += hardware/libhardware/msm7k/libgralloc include $(BUILD_SHARED_LIBRARY) endif From 7af3a32e12985fab7088994264a7f9da4f0ea22a Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 15 Jul 2009 16:31:02 -0700 Subject: [PATCH 080/435] fix build --- libcopybit/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index b02b0b9..bc4ffcb 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -24,7 +24,7 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k -LOCAL_C_INCLUDES += hardware/libhardware/msm7k/libgralloc +LOCAL_C_INCLUDES += hardware/msm7k/libgralloc include $(BUILD_SHARED_LIBRARY) endif From 16cddff7d9c920673ed26c3fb51f2cbe2ff57b8a Mon Sep 17 00:00:00 2001 From: Rebecca Schultz Zavin Date: Wed, 15 Jul 2009 18:35:23 -0700 Subject: [PATCH 081/435] Change libcamera to load the vendor camera library by the new name, liboemcamera instead of libqcamera. Signed-off-by: Rebecca Schultz Zavin --- libcamera2/Android.mk | 2 +- libcamera2/QualcommCameraHardware.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index 75df2a1..f00bec6 100644 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -24,7 +24,7 @@ LOCAL_SHARED_LIBRARIES:= libutils libui liblog LOCAL_SHARED_LIBRARIES+= libbinder ifneq ($(DLOPEN_LIBMMCAMERA),1) -LOCAL_SHARED_LIBRARIES+= libqcamera +LOCAL_SHARED_LIBRARIES+= liboemcamera else LOCAL_SHARED_LIBRARIES+= libdl endif diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index d0820f0..95456a4 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -324,10 +324,10 @@ void QualcommCameraHardware::startCamera() { LOGV("startCamera E"); #if DLOPEN_LIBMMCAMERA - libmmcamera = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("loading libqcamera at %p", libmmcamera); + libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW); + LOGV("loading liboemcamera at %p", libmmcamera); if (!libmmcamera) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); return; } @@ -700,10 +700,10 @@ void QualcommCameraHardware::runFrameThread(void *data) // frame thread, because we do not know when it will exit relative to the // lifetime of this object. We do not want to dlclose() libqcamera while // LINK_cam_frame is still running. - void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); LOGV("FRAME: loading libqcamera at %p", libhandle); if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); } if (libhandle) #endif @@ -1130,10 +1130,10 @@ void QualcommCameraHardware::runAutoFocus() // AF thread, because we do not know when it will exit relative to the // lifetime of this object. We do not want to dlclose() libqcamera while // LINK_cam_frame is still running. - void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); + void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); LOGV("AF: loading libqcamera at %p", libhandle); if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); + LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); close(mAutoFocusFd); mAutoFocusFd = -1; mAutoFocusThreadRunning = false; From bcb33e4db815d828f71715bc12fbe33b191045aa Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Wed, 15 Jul 2009 15:58:21 +0800 Subject: [PATCH 084/435] 1. Remove the zoom and brightness. 2. Set default value of antibanding, effect, and white-balance at initialization. 3. Do not set the parameter if it is not found. --- libcamera2/QualcommCameraHardware.cpp | 348 ++++++-------------------- libcamera2/QualcommCameraHardware.h | 22 +- 2 files changed, 88 insertions(+), 282 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 1679133..fe9007a 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -67,12 +67,9 @@ extern "C" { #define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) #define DEFAULT_PREVIEW_SETTING 2 // HVGA -#define MAX_ZOOM_STEPS 6 #define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) -#define BRIGHTNESS_MAX 10 // FIXME: this should correlate with brightness-values -#define BRIGHTNESS_DEF 5 // FIXME: this should correlate with brightness-values -#define ZOOM_MAX 10 // FIXME: this should correlate with zoom-values +#define NOT_FOUND -1 #if DLOPEN_LIBMMCAMERA #include @@ -132,14 +129,7 @@ static preview_size_type preview_sizes[] = { { 176, 144 }, // QCIF }; -struct str_map { - const char *const desc; - int val; -}; - -static int attr_lookup(const struct str_map *const arr, - const char *name, - int def) +static int attr_lookup(const struct str_map *const arr, const char *name) { if (name) { const struct str_map *trav = arr; @@ -149,7 +139,7 @@ static int attr_lookup(const struct str_map *const arr, trav++; } } - return def; + return NOT_FOUND; } #define INIT_VALUES_FOR(parm) do { \ @@ -183,7 +173,7 @@ static const str_map whitebalance[] = { static char *whitebalance_values; // from camera_effect_t -static const str_map color_effects[] = { +static const str_map effect[] = { { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, @@ -198,17 +188,17 @@ static const str_map color_effects[] = { { "aqua", CAMERA_EFFECT_AQUA }, { NULL, 0 } }; -static char *color_effects_values; +static char *effect_values; // from qcamera/common/camera.h -static const str_map anti_banding[] = { +static const str_map antibanding[] = { { "off", CAMERA_ANTIBANDING_OFF }, { "60hz", CAMERA_ANTIBANDING_60HZ }, { "50hz", CAMERA_ANTIBANDING_50HZ }, { "auto", CAMERA_ANTIBANDING_AUTO }, { NULL, 0 } }; -static char *anti_banding_values; +static char *antibanding_values; // round to the next power of two static inline unsigned clp2(unsigned x) @@ -239,10 +229,6 @@ QualcommCameraHardware::QualcommCameraHardware() mPreviewWidth(-1), mRawHeight(-1), mRawWidth(-1), - mBrightness(BRIGHTNESS_DEF), - mZoomValuePrev(0), - mZoomValueCurr(0), - mZoomInitialised(false), mCameraRunning(false), mPreviewInitialized(false), mFrameThreadRunning(false), @@ -265,7 +251,6 @@ QualcommCameraHardware::QualcommCameraHardware() mAutoFocusFd(-1), mInPreviewCallback(false) { - memset(&mZoom, 0, sizeof(mZoom)); memset(&mDimension, 0, sizeof(mDimension)); memset(&mCrop, 0, sizeof(mCrop)); LOGV("constructor EX"); @@ -288,6 +273,15 @@ void QualcommCameraHardware::initDefaultParameters() p.set("jpeg-thumbnail-quality", "90"); p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); + p.set("antibanding", + /* FIXME: + * CAMERA_ANTIBANDING_60HZ broke the barcode scanner somehow. turn it + * off and revert it back to off for now until we figure out what is + * the best solution. + */ + "off" /*"60hz" */); + p.set("effect", "off"); + p.set("whitebalance", "auto"); #if 0 p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 @@ -298,19 +292,15 @@ void QualcommCameraHardware::initDefaultParameters() // This will happen only one in the lifetime of the mediaserver process. // We do not free the _values arrays when we destroy the camera object. - INIT_VALUES_FOR(anti_banding); - INIT_VALUES_FOR(color_effects); + INIT_VALUES_FOR(antibanding); + INIT_VALUES_FOR(effect); INIT_VALUES_FOR(whitebalance); - p.set("anti-banding-values", anti_banding_values); - p.set("effect-values", color_effects_values); + p.set("antibanding-values", antibanding_values); + p.set("effect-values", effect_values); p.set("whitebalance-values", whitebalance_values); p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); - // FIXME: we can specify these numeric ranges better - p.set("exposure-offset-values", "0,1,2,3,4,5,6,7,8,9,10"); - p.set("zoom-values", "0,1,2,3,4,5,6,7,8,9,10"); - if (setParameters(p) != NO_ERROR) { LOGE("Failed to set default parameters?!"); } @@ -437,27 +427,6 @@ status_t QualcommCameraHardware::dump(int fd, return NO_ERROR; } -bool QualcommCameraHardware::native_set_dimension(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.type = CAMERA_SET_PARM_DIMENSION; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(cam_ctrl_dimension_t); - ctrlCmd.value = &mDimension; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_set_dimension: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - LOGV("native_set_dimension status %d\n", ctrlCmd.status); - return ctrlCmd.status == CAM_CTRL_SUCCESS; -} - static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) { int rc; @@ -645,6 +614,36 @@ bool QualcommCameraHardware::native_jpeg_encode(void) return true; } +bool QualcommCameraHardware::native_set_dimension(cam_ctrl_dimension_t *value) +{ + return native_set_parm(CAMERA_SET_PARM_DIMENSION, + sizeof(cam_ctrl_dimension_t), value); +} + +bool QualcommCameraHardware::native_set_parm( + cam_ctrl_type type, uint16_t length, void *value) +{ + int rc = true; + struct msm_ctrl_cmd ctrlCmd; + + ctrlCmd.timeout_ms = 5000; + ctrlCmd.type = (uint16_t)type; + ctrlCmd.length = length; + // FIXME: this will be put in by the kernel + ctrlCmd.resp_fd = mCameraControlFd; + ctrlCmd.value = value; + + LOGV("native_set_parm. camfd=%d, type=%d, length=%d", + mCameraControlFd, type, length); + rc = ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd); + if(rc < 0 || ctrlCmd.status != CAM_CTRL_SUCCESS) { + LOGE("ioctl error. camfd=%d, type=%d, length=%d, rc=%d, ctrlCmd.status=%d, %s", + mCameraControlFd, type, length, rc, ctrlCmd.status, strerror(errno)); + return false; + } + return true; +} + void QualcommCameraHardware::jpeg_set_location() { bool encode_location = true; @@ -781,7 +780,7 @@ bool QualcommCameraHardware::initPreview() mDimension.picture_width = DEFAULT_PICTURE_WIDTH; mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - bool ret = native_set_dimension(mCameraControlFd); + bool ret = native_set_dimension(&mDimension); if (ret) { for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { @@ -843,7 +842,7 @@ bool QualcommCameraHardware::initRaw(bool initJpegHeap) mRawSize = mRawWidth * mRawHeight * 3 / 2; mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - if(!native_set_dimension(mCameraControlFd)) { + if(!native_set_dimension(&mDimension)) { LOGE("initRaw X: failed to set dimension"); return false; } @@ -1046,12 +1045,6 @@ status_t QualcommCameraHardware::startPreviewInternal() return UNKNOWN_ERROR; } - setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); - setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); - setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - setBrightness(); - // FIXME: set nightshot, luma adaptatiom, zoom and check ranges - LOGV("startPreview X"); return NO_ERROR; } @@ -1335,8 +1328,8 @@ status_t QualcommCameraHardware::setParameters( Mutex::Autolock l(&mLock); + // Set preview size. preview_size_type *ps = preview_sizes; - { int width, height; params.getPreviewSize(&width, &height); @@ -1353,18 +1346,15 @@ status_t QualcommCameraHardware::setParameters( return BAD_VALUE; } } - mPreviewWidth = mDimension.display_width = ps->width; mPreviewHeight = mDimension.display_height = ps->height; // FIXME: validate snapshot sizes, - params.getPictureSize(&mRawWidth, &mRawHeight); mDimension.picture_width = mRawWidth; mDimension.picture_height = mRawHeight; // Set up the jpeg-thumbnail-size parameters. - { int val; @@ -1387,34 +1377,10 @@ status_t QualcommCameraHardware::setParameters( mParameters = params; - if (mCameraRunning) - { - setBrightness(); - - mZoomValueCurr = mParameters.getInt("zoom"); - if(mZoomValueCurr >= 0 && mZoomValueCurr <= ZOOM_MAX && - mZoomValuePrev != mZoomValueCurr) - { - bool ZoomDirectionIn = true; - if(mZoomValuePrev > mZoomValueCurr) - { - ZoomDirectionIn = false; - } - else - { - ZoomDirectionIn = true; - } - LOGV("new zoom value: %d direction = %s", - mZoomValueCurr, (ZoomDirectionIn ? "in" : "out")); - mZoomValuePrev = mZoomValueCurr; - performZoom(ZoomDirectionIn); - } - - setSensorPreviewEffect(mCameraControlFd, mParameters.get("effect")); - setSensorWBLighting(mCameraControlFd, mParameters.get("whitebalance")); - setAntiBanding(mCameraControlFd, mParameters.get("antibanding")); - // FIXME: set nightshot, luma adaptatiom, zoom and check ranges - } + setAntibanding(); + setEffect(); + setWhiteBalance(); + // FIXME: set nightshot and luma adaptatiom LOGV("setParameters: X"); return NO_ERROR ; @@ -1693,198 +1659,38 @@ bool QualcommCameraHardware::previewEnabled() return mCameraRunning && mPreviewCallback != NULL; } -void QualcommCameraHardware::setSensorPreviewEffect(int camfd, const char *effect) +int QualcommCameraHardware::getParm( + const char *parm_str, const struct str_map *const parm_map) { - LOGV("In setSensorPreviewEffect..."); - int effectsValue = 1; - struct msm_ctrl_cmd ctrlCmd; + // Check if the parameter exists. + const char *str = mParameters.get(parm_str); + if (str == NULL) return NOT_FOUND; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_EFFECT; - ctrlCmd.length = sizeof(uint32_t); - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - effectsValue = attr_lookup(color_effects, effect, CAMERA_EFFECT_OFF); - ctrlCmd.value = (void *)&effectsValue; - LOGV("In setSensorPreviewEffect, color effect match %s %d", - effect, effectsValue); - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setSensorPreviewEffect fd %d error %s", camfd, strerror(errno)); + // Look up the parameter value. + return attr_lookup(parm_map, str); } -void QualcommCameraHardware::setSensorWBLighting(int camfd, const char *lighting) +void QualcommCameraHardware::setEffect() { - int lightingValue = 1; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_WB; - ctrlCmd.length = sizeof(uint32_t); - lightingValue = attr_lookup(whitebalance, lighting, CAMERA_WB_AUTO); - ctrlCmd.value = (void *)&lightingValue; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - LOGV("In setSensorWBLighting: match: %s: %d", - lighting, lightingValue); - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setSensorWBLighting: ioctl fd %d error %s", - camfd, strerror(errno)); + int32_t value = getParm("effect", effect); + if (value != NOT_FOUND) { + native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value), (void *)&value); + } } -void QualcommCameraHardware::setAntiBanding(int camfd, const char *antibanding) +void QualcommCameraHardware::setWhiteBalance() { - int antibandvalue = 0; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_ANTIBANDING; - ctrlCmd.length = sizeof(int32_t); - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - antibandvalue = attr_lookup(anti_banding, - antibanding, - /* FIXME: - * CAMERA_ANTIBANDING_60HZ broke the barcode scanner - * somehow. turn it off and revert it back to off - * for now until we figure out what is the best - * solution. - */ - CAMERA_ANTIBANDING_OFF /*CAMERA_ANTIBANDING_60HZ */); - ctrlCmd.value = (void *)&antibandvalue; - LOGV("In setAntiBanding: match: %s: %d", - antibanding, antibandvalue); - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setAntiBanding: ioctl %d error %s", - camfd, strerror(errno)); -} - -void QualcommCameraHardware::setBrightness() -{ - int val = mParameters.getInt("exposure-offset"); - if (val < 0) - val = BRIGHTNESS_DEF; - else if (val > BRIGHTNESS_MAX) - val = BRIGHTNESS_MAX; - - if (mBrightness != val) { - LOGV("new brightness value %d", val); - mBrightness = val; - - struct msm_ctrl_cmd ctrlCmd; - LOGV("In setBrightness: %d", val); - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_BRIGHTNESS; - ctrlCmd.length = sizeof(int); - ctrlCmd.value = (void *)&val; - // FIXME: this will be put in by the kernel - ctrlCmd.resp_fd = mCameraControlFd; - - if(ioctl(mCameraControlFd, - MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("setBrightness: ioctl fd %d error %s", - mCameraControlFd, strerror(errno)); + int32_t value = getParm("whitebalance", whitebalance); + if (value != NOT_FOUND) { + native_set_parm(CAMERA_SET_PARM_WB, sizeof(value), (void *)&value); } } -static bool native_get_zoom(int camfd, void *pZm) +void QualcommCameraHardware::setAntibanding() { - struct msm_ctrl_cmd ctrlCmd; - cam_parm_info_t *pZoom = (cam_parm_info_t *)pZm; - ctrlCmd.type = CAMERA_GET_PARM_ZOOM; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(cam_parm_info_t); - ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_get_zoom: ioctl fd %d error %s", - camfd, strerror(errno)); - return false; - } - - memcpy(pZoom, *(cam_parm_info_t **)ctrlCmd.value, sizeof(cam_parm_info_t)); - - LOGD("native_get_zoom::current val=%d max=%d min=%d step val=%d", - pZoom->current_value, - pZoom->maximum_value, - pZoom->minimum_value, - pZoom->step_value); - - return ctrlCmd.status; -} - -static bool native_set_zoom(int camfd, void *pZm) -{ - struct msm_ctrl_cmd ctrlCmd; - - int32_t *pZoom = (int32_t *)pZm; - - ctrlCmd.type = CAMERA_SET_PARM_ZOOM; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(int32_t); - ctrlCmd.value = pZoom; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_set_zoom: ioctl fd %d error %s", - camfd, strerror(errno)); - return false; - } - - memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t)); - return ctrlCmd.status; -} - -void QualcommCameraHardware::performZoom(bool ZoomDir) -{ - if(mZoomInitialised == false) { - native_get_zoom(mCameraControlFd, (void *)&mZoom); - if(mZoom.maximum_value != 0) { - mZoomInitialised = true; - mZoom.step_value = (int) (mZoom.maximum_value/MAX_ZOOM_STEPS); - if( mZoom.step_value > 3 ) - mZoom.step_value = 3; - } - } - - if (ZoomDir) { - LOGV("performZoom::got zoom value of %d %d %d zoom in", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - if((mZoom.current_value + mZoom.step_value) < mZoom.maximum_value) { - mZoom.current_value += mZoom.step_value; - LOGV("performZoom::Setting Zoom value of %d ",mZoom.current_value); - native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); - } - else { - LOGV("performZoom::not able to zoom in %d %d %d", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - } - } - else - { - LOGV("performZoom::got zoom value of %d %d %d zoom out", - mZoom.current_value, - mZoom.step_value, - mZoom.minimum_value); - if((mZoom.current_value - mZoom.step_value) >= mZoom.minimum_value) - { - mZoom.current_value -= mZoom.step_value; - LOGV("performZoom::setting zoom value of %d ", - mZoom.current_value); - native_set_zoom(mCameraControlFd, (void *)&mZoom.current_value); - } - else - { - LOGV("performZoom::not able to zoom out %d %d %d", - mZoom.current_value, - mZoom.step_value, - mZoom.maximum_value); - } - } + camera_antibanding_type value = + (camera_antibanding_type) getParm("antibanding", antibanding); + native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(value), (void *)&value); } QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index c647fcd..5f63abc 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -28,6 +28,11 @@ extern "C" { #include } +struct str_map { + const char *const desc; + int val; +}; + namespace android { class QualcommCameraHardware : public CameraHardwareInterface { @@ -63,7 +68,6 @@ public: void notifyShutter(); private: - QualcommCameraHardware(); virtual ~QualcommCameraHardware(); status_t startPreviewInternal(); @@ -73,6 +77,9 @@ private: void cancelAutoFocus(); bool native_set_dimension (int camfd); bool native_jpeg_encode (void); + bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value); + bool native_set_dimension(cam_ctrl_dimension_t *value); + int getParm(const char *parm_str, const str_map *parm_map); static wp singleton; @@ -91,10 +98,6 @@ private: int mRawHeight; int mRawWidth; unsigned int frame_size; - int mBrightness; - int mZoomValuePrev; - int mZoomValueCurr; - bool mZoomInitialised; bool mCameraRunning; bool mPreviewInitialized; @@ -173,11 +176,9 @@ private: void initDefaultParameters(); - void setSensorPreviewEffect(int, const char*); - void setSensorWBLighting(int, const char*); - void setAntiBanding(int, const char*); - void setBrightness(void); - void performZoom(bool); + void setAntibanding(); + void setEffect(); + void setWhiteBalance(); Mutex mLock; bool mReleasedRecordingFrame; @@ -217,7 +218,6 @@ private: #endif int mCameraControlFd; - cam_parm_info_t mZoom; cam_ctrl_dimension_t mDimension; bool mAutoFocusThreadRunning; Mutex mAutoFocusThreadLock; From 3e4574a18707e412880269bb596c2cbd8d1d6d42 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Mon, 20 Jul 2009 14:37:26 +0800 Subject: [PATCH 085/435] Remove unsupported white balance and effect options. --- libcamera2/QualcommCameraHardware.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index fe9007a..247e24e 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -161,7 +161,6 @@ static int attr_lookup(const struct str_map *const arr, const char *name) // from aeecamera.h static const str_map whitebalance[] = { { "auto", CAMERA_WB_AUTO }, - { "custom", CAMERA_WB_CUSTOM }, { "incandescent", CAMERA_WB_INCANDESCENT }, { "florescent", CAMERA_WB_FLUORESCENT }, { "daylight", CAMERA_WB_DAYLIGHT }, @@ -178,9 +177,6 @@ static const str_map effect[] = { { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, - { "pastel", CAMERA_EFFECT_PASTEL }, - { "mosaic", CAMERA_EFFECT_MOSAIC }, - { "resize", CAMERA_EFFECT_RESIZE }, { "sepia", CAMERA_EFFECT_SEPIA }, { "postersize", CAMERA_EFFECT_POSTERIZE }, { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, From a21ec0f3d3a1300f6ef07ac4c388a4025beaca30 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Tue, 21 Jul 2009 12:28:45 +0800 Subject: [PATCH 087/435] Make sure shutter callback is called before raw callback. --- libcamera2/QualcommCameraHardware.cpp | 32 ++++++++++++++++++--------- libcamera2/QualcommCameraHardware.h | 3 +++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 247e24e..2c820a1 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -1263,6 +1263,14 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, raw_cb, jpeg_cb); Mutex::Autolock l(&mLock); + // Wait for old snapshot thread to complete. + mSnapshotThreadWaitLock.lock(); + while (mSnapshotThreadRunning) { + LOGV("takePicture: waiting for old snapshot thread to complete."); + mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); + LOGV("takePicture: old snapshot thread completed."); + } + stopPreviewInternal(); if (!initRaw(jpeg_cb != NULL)) { @@ -1278,12 +1286,9 @@ status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, mPictureCallbackCookie = user; } - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("takePicture: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("takePicture: old snapshot thread completed."); - } + mShutterLock.lock(); + mShutterPending = true; + mShutterLock.unlock(); pthread_attr_t attr; pthread_attr_init(&attr); @@ -1554,8 +1559,12 @@ bool QualcommCameraHardware::recordingEnabled() void QualcommCameraHardware::notifyShutter() { - if (mShutterCallback) + mShutterLock.lock(); + if (mShutterPending && mShutterCallback) { mShutterCallback(mPictureCallbackCookie); + mShutterPending = false; + } + mShutterLock.unlock(); } static void receive_shutter_callback() @@ -1572,14 +1581,17 @@ void QualcommCameraHardware::receiveRawPicture() { LOGV("receiveRawPicture: E"); - int ret,rc,rete; - Mutex::Autolock cbLock(&mCallbackLock); + if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd, &mCrop)== false) { + if(native_get_picture(mCameraControlFd, &mCrop) == false) { LOGE("getPicture failed!"); return; } + + // By the time native_get_picture returns, picture is taken. Call + // shutter callback if cam config thread has not done that. + notifyShutter(); mRawPictureCallback(mRawHeap->mBuffers[0], mPictureCallbackCookie); } diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h index 5f63abc..a4fe43b 100644 --- a/libcamera2/QualcommCameraHardware.h +++ b/libcamera2/QualcommCameraHardware.h @@ -168,6 +168,9 @@ private: friend void *frame_thread(void *user); void runFrameThread(void *data); + bool mShutterPending; + Mutex mShutterLock; + bool mSnapshotThreadRunning; Mutex mSnapshotThreadWaitLock; Condition mSnapshotThreadWait; From df37da0ff8a3fe52e8ba82f063a947320268c505 Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Thu, 23 Jul 2009 16:51:29 +0800 Subject: [PATCH 088/435] Correct the spelling of posterize. --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 2c820a1..3f808d4 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -178,7 +178,7 @@ static const str_map effect[] = { { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, { "sepia", CAMERA_EFFECT_SEPIA }, - { "postersize", CAMERA_EFFECT_POSTERIZE }, + { "posterize", CAMERA_EFFECT_POSTERIZE }, { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, { "blackboard", CAMERA_EFFECT_BLACKBOARD }, { "aqua", CAMERA_EFFECT_AQUA }, From 086dddb3b5f630829e7b343eb6d688f9495a3e2e Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Thu, 23 Jul 2009 16:51:29 +0800 Subject: [PATCH 090/435] Correct the spelling of posterize. --- libcamera2/QualcommCameraHardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 4d595e8..aa90a45 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -178,7 +178,7 @@ static const str_map effect[] = { { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, { "sepia", CAMERA_EFFECT_SEPIA }, - { "postersize", CAMERA_EFFECT_POSTERIZE }, + { "posterize", CAMERA_EFFECT_POSTERIZE }, { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, { "blackboard", CAMERA_EFFECT_BLACKBOARD }, { "aqua", CAMERA_EFFECT_AQUA }, From 6ffa1f926c62a0ebe4d3541023105dea4e33291c Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Thu, 23 Jul 2009 18:33:39 -0700 Subject: [PATCH 091/435] libcamera2: Add 576x532 as a valid preview size. --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index aa90a45..2e1fc8d 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -121,6 +121,7 @@ struct preview_size_type { static preview_size_type preview_sizes[] = { { 800, 480 }, // WVGA { 640, 480 }, // VGA + { 576, 432 }, { 480, 320 }, // HVGA { 384, 288 }, { 352, 288 }, // CIF From ca745bed48c8ab11c6a79c770e119f5f461df595 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Fri, 31 Jul 2009 11:28:01 +0800 Subject: [PATCH 099/435] Fix 2026448: Missing jpeg-quality parameter in donut. --- libcamera2/QualcommCameraHardware.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 3f808d4..63d739a 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -264,6 +264,7 @@ void QualcommCameraHardware::initDefaultParameters() p.setPreviewFormat("yuv420sp"); // informative p.setPictureFormat("jpeg"); // informative + p.set("jpeg-quality", "100"); // maximum quality p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative p.set("jpeg-thumbnail-quality", "90"); From a4748564979cea756f8f72d43bf9536b10ebe2cc Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Fri, 31 Jul 2009 13:21:39 +0800 Subject: [PATCH 100/435] Remove antibanding because driver does not support them. --- libcamera2/QualcommCameraHardware.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 63d739a..981c46f 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -189,9 +189,6 @@ static char *effect_values; // from qcamera/common/camera.h static const str_map antibanding[] = { { "off", CAMERA_ANTIBANDING_OFF }, - { "60hz", CAMERA_ANTIBANDING_60HZ }, - { "50hz", CAMERA_ANTIBANDING_50HZ }, - { "auto", CAMERA_ANTIBANDING_AUTO }, { NULL, 0 } }; static char *antibanding_values; @@ -270,13 +267,7 @@ void QualcommCameraHardware::initDefaultParameters() p.set("jpeg-thumbnail-quality", "90"); p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); - p.set("antibanding", - /* FIXME: - * CAMERA_ANTIBANDING_60HZ broke the barcode scanner somehow. turn it - * off and revert it back to off for now until we figure out what is - * the best solution. - */ - "off" /*"60hz" */); + p.set("antibanding", "off"); p.set("effect", "off"); p.set("whitebalance", "auto"); From 50b3755b7d26edf2c228d0fbf347783edf168a1c Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 31 Jul 2009 15:09:12 -0700 Subject: [PATCH 101/435] don't send the GPU master fd across to client processes --- libcopybit/copybit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 60adc48..6a4993c 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -122,9 +122,9 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->height = rhs->h; img->format = get_format(rhs->format); img->offset = hnd->offset; - img->memory_id = hnd->fd; + img->memory_id = (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) + ? hnd->gpu_fd : hnd->fd; } - /** setup rectangles */ static void set_rects(struct copybit_context_t *dev, struct mdp_blit_req *e, From 06bd510731211e73725d8957b1933cbe567c87a1 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 31 Jul 2009 16:33:08 -0700 Subject: [PATCH 102/435] should fix qsd8k builds --- libcopybit/Android.mk | 2 ++ libcopybit/copybit.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index bc4ffcb..c2128ee 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -25,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k LOCAL_C_INCLUDES += hardware/msm7k/libgralloc +LOCAL_C_FLAGS := -DCOPYBIT_MSM7K=1 include $(BUILD_SHARED_LIBRARY) endif @@ -36,5 +37,6 @@ LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.qsd8k LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc +LOCAL_C_FLAGS := -DCOPYBIT_QSD8K=1 include $(BUILD_SHARED_LIBRARY) endif diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 6a4993c..f734b73 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -122,8 +122,12 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->height = rhs->h; img->format = get_format(rhs->format); img->offset = hnd->offset; +#if defined(COPYBIT_MSM7K) img->memory_id = (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) ? hnd->gpu_fd : hnd->fd; +#else + img->memory_id = hnd->fd; +#endif } /** setup rectangles */ static void set_rects(struct copybit_context_t *dev, From 641eb403cc33a603e59cc7666129f9f3d7dc16ae Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 31 Jul 2009 16:49:29 -0700 Subject: [PATCH 103/435] really fix the build --- libcopybit/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index c2128ee..36b1416 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -25,7 +25,7 @@ LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k LOCAL_C_INCLUDES += hardware/msm7k/libgralloc -LOCAL_C_FLAGS := -DCOPYBIT_MSM7K=1 +LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 include $(BUILD_SHARED_LIBRARY) endif @@ -37,6 +37,6 @@ LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.qsd8k LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc -LOCAL_C_FLAGS := -DCOPYBIT_QSD8K=1 +LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 include $(BUILD_SHARED_LIBRARY) endif From 3c302caa498b548123b4708f5a65f4d5f4dd55c9 Mon Sep 17 00:00:00 2001 From: Iliyan Malchev Date: Tue, 4 Aug 2009 17:38:08 -0700 Subject: [PATCH 106/435] removing libcamera2 --> moving to vendor/qcom/android Signed-off-by: Iliyan Malchev --- libcamera2/Android.mk | 36 - libcamera2/QualcommCameraHardware.cpp | 1947 ------------------------- libcamera2/QualcommCameraHardware.h | 241 --- 3 files changed, 2224 deletions(-) delete mode 100644 libcamera2/Android.mk delete mode 100644 libcamera2/QualcommCameraHardware.cpp delete mode 100644 libcamera2/QualcommCameraHardware.h diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk deleted file mode 100644 index f00bec6..0000000 --- a/libcamera2/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -BUILD_LIBCAMERA:=true -ifeq ($(BUILD_LIBCAMERA),true) - -# When zero we link against libmmcamera; when 1, we dlopen libmmcamera. -DLOPEN_LIBMMCAMERA:=1 - -ifneq ($(BUILD_TINY_ANDROID),true) - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= QualcommCameraHardware.cpp - -LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA) - -LOCAL_C_INCLUDES+= \ - vendor/qcom/proprietary/mm-camera/common \ - vendor/qcom/proprietary/mm-camera/apps/appslib \ - vendor/qcom/proprietary/mm-camera/jpeg \ - vendor/qcom/proprietary/mm-camera/jpeg/inc - -LOCAL_SHARED_LIBRARIES:= libutils libui liblog - -LOCAL_SHARED_LIBRARIES+= libbinder -ifneq ($(DLOPEN_LIBMMCAMERA),1) -LOCAL_SHARED_LIBRARIES+= liboemcamera -else -LOCAL_SHARED_LIBRARIES+= libdl -endif - -LOCAL_MODULE:= libcamera -include $(BUILD_SHARED_LIBRARY) - -endif # BUILD_TINY_ANDROID -endif # BUILD_LIBCAMERA diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp deleted file mode 100644 index 642d436..0000000 --- a/libcamera2/QualcommCameraHardware.cpp +++ /dev/null @@ -1,1947 +0,0 @@ -/* -** Copyright 2008, Google Inc. -** -** 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_NDEBUG 0 -#define LOG_TAG "QualcommCameraHardware" -#include - -#include "QualcommCameraHardware.h" - -#include -#include -#include -#include -#include -#include -#if HAVE_ANDROID_OS -#include -#endif -#include - -#define LIKELY(exp) __builtin_expect(!!(exp), 1) -#define UNLIKELY(exp) __builtin_expect(!!(exp), 0) - -extern "C" { - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define THUMBNAIL_WIDTH 512 -#define THUMBNAIL_HEIGHT 384 -#define THUMBNAIL_WIDTH_STR "512" -#define THUMBNAIL_HEIGHT_STR "384" -#define DEFAULT_PICTURE_WIDTH 2048 // 1280 -#define DEFAULT_PICTURE_HEIGHT 1536 // 768 -#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) - -#define DEFAULT_PREVIEW_SETTING 2 // HVGA -#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) - -#define NOT_FOUND -1 - -#if DLOPEN_LIBMMCAMERA -#include - -void* (*LINK_cam_conf)(void *data); -void* (*LINK_cam_frame)(void *data); -bool (*LINK_jpeg_encoder_init)(); -void (*LINK_jpeg_encoder_join)(); -bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, - const uint8_t *thumbnailbuf, int thumbnailfd, - const uint8_t *snapshotbuf, int snapshotfd, - common_crop_t *scaling_parms); -int (*LINK_camframe_terminate)(void); -int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); -int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); -int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); -int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location); -// callbacks -void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); -void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, - uint32_t buff_size); -void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); -void (**LINK_mmcamera_shutter_callback)(); -#else -#define LINK_cam_conf cam_conf -#define LINK_cam_frame cam_frame -#define LINK_jpeg_encoder_init jpeg_encoder_init -#define LINK_jpeg_encoder_join jpeg_encoder_join -#define LINK_jpeg_encoder_encode jpeg_encoder_encode -#define LINK_camframe_terminate camframe_terminate -#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality -#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality -#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation -#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation -extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); -extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, - uint32_t buff_size); -extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); -extern void (*mmcamera_shutter_callback)(); -#endif - -} // extern "C" - -struct preview_size_type { - int width; - int height; -}; - -static preview_size_type preview_sizes[] = { - { 800, 480 }, // WVGA - { 640, 480 }, // VGA - { 576, 432 }, - { 480, 320 }, // HVGA - { 384, 288 }, - { 352, 288 }, // CIF - { 320, 240 }, // QVGA - { 240, 160 }, // SQVGA - { 176, 144 }, // QCIF -}; - -static int attr_lookup(const struct str_map *const arr, const char *name) -{ - if (name) { - const struct str_map *trav = arr; - while (trav->desc) { - if (!strcmp(trav->desc, name)) - return trav->val; - trav++; - } - } - return NOT_FOUND; -} - -#define INIT_VALUES_FOR(parm) do { \ - if (!parm##_values) { \ - parm##_values = (char *)malloc(sizeof(parm)/ \ - sizeof(parm[0])*30); \ - char *ptr = parm##_values; \ - const str_map *trav; \ - for (trav = parm; trav->desc; trav++) { \ - int len = strlen(trav->desc); \ - strcpy(ptr, trav->desc); \ - ptr += len; \ - *ptr++ = ','; \ - } \ - *--ptr = 0; \ - } \ -} while(0) - -// from aeecamera.h -static const str_map whitebalance[] = { - { "auto", CAMERA_WB_AUTO }, - { "incandescent", CAMERA_WB_INCANDESCENT }, - { "florescent", CAMERA_WB_FLUORESCENT }, - { "daylight", CAMERA_WB_DAYLIGHT }, - { "cloudy", CAMERA_WB_CLOUDY_DAYLIGHT }, - { "twilight", CAMERA_WB_TWILIGHT }, - { "shade", CAMERA_WB_SHADE }, - { NULL, 0 } -}; -static char *whitebalance_values; - -// from camera_effect_t -static const str_map effect[] = { - { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ - { "mono", CAMERA_EFFECT_MONO }, - { "negative", CAMERA_EFFECT_NEGATIVE }, - { "solarize", CAMERA_EFFECT_SOLARIZE }, - { "sepia", CAMERA_EFFECT_SEPIA }, - { "posterize", CAMERA_EFFECT_POSTERIZE }, - { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, - { "blackboard", CAMERA_EFFECT_BLACKBOARD }, - { "aqua", CAMERA_EFFECT_AQUA }, - { NULL, 0 } -}; -static char *effect_values; - -// from qcamera/common/camera.h -static const str_map antibanding[] = { - { "off", CAMERA_ANTIBANDING_OFF }, - { NULL, 0 } -}; -static char *antibanding_values; - -// round to the next power of two -static inline unsigned clp2(unsigned x) -{ - x = x - 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >>16); - return x + 1; -} - -namespace android { - -static Mutex singleton_lock; -static bool singleton_releasing; -static Condition singleton_wait; - -static void receive_camframe_callback(struct msm_frame *frame); -static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); -static void receive_jpeg_callback(jpeg_event_t status); -static void receive_shutter_callback(); - -QualcommCameraHardware::QualcommCameraHardware() - : mParameters(), - mPreviewHeight(-1), - mPreviewWidth(-1), - mRawHeight(-1), - mRawWidth(-1), - mCameraRunning(false), - mPreviewInitialized(false), - mFrameThreadRunning(false), - mSnapshotThreadRunning(false), - mReleasedRecordingFrame(false), - mShutterCallback(0), - mRawPictureCallback(0), - mJpegPictureCallback(0), - mPictureCallbackCookie(0), - mAutoFocusCallback(0), - mAutoFocusCallbackCookie(0), - mPreviewCallback(0), - mPreviewCallbackCookie(0), - mRecordingCallback(0), - mRecordingCallbackCookie(0), - mPreviewFrameSize(0), - mRawSize(0), - mCameraControlFd(-1), - mAutoFocusThreadRunning(false), - mAutoFocusFd(-1), - mInPreviewCallback(false) -{ - memset(&mDimension, 0, sizeof(mDimension)); - memset(&mCrop, 0, sizeof(mCrop)); - LOGV("constructor EX"); -} - -void QualcommCameraHardware::initDefaultParameters() -{ - CameraParameters p; - - LOGV("initDefaultParameters E"); - - preview_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING]; - p.setPreviewSize(ps->width, ps->height); - p.setPreviewFrameRate(15); - p.setPreviewFormat("yuv420sp"); // informative - p.setPictureFormat("jpeg"); // informative - - p.set("jpeg-quality", "100"); // maximum quality - p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative - p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative - p.set("jpeg-thumbnail-quality", "90"); - - p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); - p.set("antibanding", "off"); - p.set("effect", "off"); - p.set("whitebalance", "auto"); - -#if 0 - p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 - p.set("gps-latitude", "37.736071"); // A little house in San Francisco - p.set("gps-longitude", "-122.441983"); - p.set("gps-altitude", "21"); // meters -#endif - - // This will happen only one in the lifetime of the mediaserver process. - // We do not free the _values arrays when we destroy the camera object. - INIT_VALUES_FOR(antibanding); - INIT_VALUES_FOR(effect); - INIT_VALUES_FOR(whitebalance); - - p.set("antibanding-values", antibanding_values); - p.set("effect-values", effect_values); - p.set("whitebalance-values", whitebalance_values); - p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); - - if (setParameters(p) != NO_ERROR) { - LOGE("Failed to set default parameters?!"); - } - - LOGV("initDefaultParameters X"); -} - -#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff) - -void QualcommCameraHardware::startCamera() -{ - LOGV("startCamera E"); -#if DLOPEN_LIBMMCAMERA - libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW); - LOGV("loading liboemcamera at %p", libmmcamera); - if (!libmmcamera) { - LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); - return; - } - - *(void **)&LINK_cam_frame = - ::dlsym(libmmcamera, "cam_frame"); - *(void **)&LINK_camframe_terminate = - ::dlsym(libmmcamera, "camframe_terminate"); - - *(void **)&LINK_jpeg_encoder_init = - ::dlsym(libmmcamera, "jpeg_encoder_init"); - - *(void **)&LINK_jpeg_encoder_encode = - ::dlsym(libmmcamera, "jpeg_encoder_encode"); - - *(void **)&LINK_jpeg_encoder_join = - ::dlsym(libmmcamera, "jpeg_encoder_join"); - - *(void **)&LINK_mmcamera_camframe_callback = - ::dlsym(libmmcamera, "mmcamera_camframe_callback"); - - *LINK_mmcamera_camframe_callback = receive_camframe_callback; - - *(void **)&LINK_mmcamera_jpegfragment_callback = - ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback"); - - *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; - - *(void **)&LINK_mmcamera_jpeg_callback = - ::dlsym(libmmcamera, "mmcamera_jpeg_callback"); - - *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; - - *(void **)&LINK_mmcamera_shutter_callback = - ::dlsym(libmmcamera, "mmcamera_shutter_callback"); - - *LINK_mmcamera_shutter_callback = receive_shutter_callback; - - *(void**)&LINK_jpeg_encoder_setMainImageQuality = - ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); - - *(void**)&LINK_jpeg_encoder_setThumbnailQuality = - ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); - - *(void**)&LINK_jpeg_encoder_setRotation = - ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); - - *(void**)&LINK_jpeg_encoder_setLocation = - ::dlsym(libmmcamera, "jpeg_encoder_setLocation"); - - *(void **)&LINK_cam_conf = - ::dlsym(libmmcamera, "cam_conf"); -#else - mmcamera_camframe_callback = receive_camframe_callback; - mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; - mmcamera_jpeg_callback = receive_jpeg_callback; - mmcamera_shutter_callback = receive_shutter_callback; -#endif // DLOPEN_LIBMMCAMERA - - /* The control thread is in libcamera itself. */ - mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR); - if (mCameraControlFd < 0) { - LOGE("startCamera X: %s open failed: %s!", - MSM_CAMERA_CONTROL, - strerror(errno)); - return; - } - - pthread_create(&mCamConfigThread, NULL, - LINK_cam_conf, NULL); - - LOGV("startCamera X"); -} - -status_t QualcommCameraHardware::dump(int fd, - const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - // Dump internal primitives. - result.append("QualcommCameraHardware::dump"); - snprintf(buffer, 255, "preview width(%d) x height (%d)\n", - mPreviewWidth, mPreviewHeight); - result.append(buffer); - snprintf(buffer, 255, "raw width(%d) x height (%d)\n", - mRawWidth, mRawHeight); - result.append(buffer); - snprintf(buffer, 255, - "preview frame size(%d), raw size (%d), jpeg size (%d) " - "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize, - mJpegSize, mJpegMaxSize); - result.append(buffer); - write(fd, result.string(), result.size()); - - // Dump internal objects. - if (mPreviewHeap != 0) { - mPreviewHeap->dump(fd, args); - } - if (mRawHeap != 0) { - mRawHeap->dump(fd, args); - } - if (mJpegHeap != 0) { - mJpegHeap->dump(fd, args); - } - mParameters.dump(fd, args); - return NO_ERROR; -} - -static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) -{ - int rc; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; - ctrlCmd.length = sizeof(af_type); - ctrlCmd.value = &af_type; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) - LOGE("native_set_afmode: ioctl fd %d error %s\n", - camfd, - strerror(errno)); - - LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status); - return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; -} - -static bool native_cancel_afmode(int camfd, int af_fd) -{ - int rc; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = af_fd; - - if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0) - LOGE("native_cancel_afmode: ioctl fd %d error %s\n", - camfd, - strerror(errno)); - return rc >= 0; -} - -static bool native_start_preview(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_START_PREVIEW; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_get_picture (int camfd, common_crop_t *crop) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(common_crop_t); - ctrlCmd.value = crop; - - if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { - LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - LOGV("crop: in1_w %d", crop->in1_w); - LOGV("crop: in1_h %d", crop->in1_h); - LOGV("crop: out1_w %d", crop->out1_w); - LOGV("crop: out1_h %d", crop->out1_h); - - LOGV("crop: in2_w %d", crop->in2_w); - LOGV("crop: in2_h %d", crop->in2_h); - LOGV("crop: out2_w %d", crop->out2_w); - LOGV("crop: out2_h %d", crop->out2_h); - - LOGV("crop: update %d", crop->update_flag); - - return true; -} - -static bool native_stop_preview(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_STOP_PREVIEW; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_stop_preview: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_start_snapshot(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_START_SNAPSHOT; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_start_snapshot: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_stop_snapshot (int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_STOP_SNAPSHOT; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_stop_snapshot: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -bool QualcommCameraHardware::native_jpeg_encode(void) -{ - int jpeg_quality = mParameters.getInt("jpeg-quality"); - if (jpeg_quality >= 0) { - LOGV("native_jpeg_encode, current jpeg main img quality =%d", - jpeg_quality); - if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { - LOGE("native_jpeg_encode set jpeg-quality failed"); - return false; - } - } - - int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality"); - if (thumbnail_quality >= 0) { - LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", - thumbnail_quality); - if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { - LOGE("native_jpeg_encode set thumbnail-quality failed"); - return false; - } - } - - int rotation = mParameters.getInt("rotation"); - if (rotation >= 0) { - LOGV("native_jpeg_encode, rotation = %d", rotation); - if(!LINK_jpeg_encoder_setRotation(rotation)) { - LOGE("native_jpeg_encode set rotation failed"); - return false; - } - } - - jpeg_set_location(); - - if (!LINK_jpeg_encoder_encode(&mDimension, - (uint8_t *)mThumbnailHeap->mHeap->base(), - mThumbnailHeap->mHeap->getHeapID(), - (uint8_t *)mRawHeap->mHeap->base(), - mRawHeap->mHeap->getHeapID(), - &mCrop)) { - LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); - return false; - } - return true; -} - -bool QualcommCameraHardware::native_set_dimension(cam_ctrl_dimension_t *value) -{ - return native_set_parm(CAMERA_SET_PARM_DIMENSION, - sizeof(cam_ctrl_dimension_t), value); -} - -bool QualcommCameraHardware::native_set_parm( - cam_ctrl_type type, uint16_t length, void *value) -{ - int rc = true; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = (uint16_t)type; - ctrlCmd.length = length; - // FIXME: this will be put in by the kernel - ctrlCmd.resp_fd = mCameraControlFd; - ctrlCmd.value = value; - - LOGV("native_set_parm. camfd=%d, type=%d, length=%d", - mCameraControlFd, type, length); - rc = ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd); - if(rc < 0 || ctrlCmd.status != CAM_CTRL_SUCCESS) { - LOGE("ioctl error. camfd=%d, type=%d, length=%d, rc=%d, ctrlCmd.status=%d, %s", - mCameraControlFd, type, length, rc, ctrlCmd.status, strerror(errno)); - return false; - } - return true; -} - -void QualcommCameraHardware::jpeg_set_location() -{ - bool encode_location = true; - camera_position_type pt; - -#define PARSE_LOCATION(what,type,fmt,desc) do { \ - pt.what = 0; \ - const char *what##_str = mParameters.get("gps-"#what); \ - LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \ - if (what##_str) { \ - type what = 0; \ - if (sscanf(what##_str, fmt, &what) == 1) \ - pt.what = what; \ - else { \ - LOGE("GPS " #what " %s could not" \ - " be parsed as a " #desc, what##_str); \ - encode_location = false; \ - } \ - } \ - else { \ - LOGV("GPS " #what " not specified: " \ - "defaulting to zero in EXIF header."); \ - encode_location = false; \ - } \ - } while(0) - - PARSE_LOCATION(timestamp, long, "%ld", "long"); - if (!pt.timestamp) pt.timestamp = time(NULL); - PARSE_LOCATION(altitude, short, "%hd", "short"); - PARSE_LOCATION(latitude, double, "%lf", "double float"); - PARSE_LOCATION(longitude, double, "%lf", "double float"); - -#undef PARSE_LOCATION - - if (encode_location) { - LOGD("setting image location ALT %d LAT %lf LON %lf", - pt.altitude, pt.latitude, pt.longitude); - if (!LINK_jpeg_encoder_setLocation(&pt)) { - LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed."); - } - } - else LOGV("not setting image location"); -} - -void QualcommCameraHardware::runFrameThread(void *data) -{ - LOGV("runFrameThread E"); - - int cnt; - -#if DLOPEN_LIBMMCAMERA - // We need to maintain a reference to libqcamera.so for the duration of the - // frame thread, because we do not know when it will exit relative to the - // lifetime of this object. We do not want to dlclose() libqcamera while - // LINK_cam_frame is still running. - void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); - LOGV("FRAME: loading libqcamera at %p", libhandle); - if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); - } - if (libhandle) -#endif - { - LINK_cam_frame(data); - } - - mPreviewHeap.clear(); - -#if DLOPEN_LIBMMCAMERA - if (libhandle) { - ::dlclose(libhandle); - LOGV("FRAME: dlclose(libqcamera)"); - } -#endif - - mFrameThreadWaitLock.lock(); - mFrameThreadRunning = false; - mFrameThreadWait.signal(); - mFrameThreadWaitLock.unlock(); - - LOGV("runFrameThread X"); -} - -void *frame_thread(void *user) -{ - LOGD("frame_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runFrameThread(user); - } - else LOGW("not starting frame thread: the object went away!"); - LOGD("frame_thread X"); - return NULL; -} - -bool QualcommCameraHardware::initPreview() -{ - // See comments in deinitPreview() for why we have to wait for the frame - // thread here, and why we can't use pthread_join(). - LOGI("initPreview E: preview size=%dx%d", mPreviewWidth, mPreviewHeight); - mFrameThreadWaitLock.lock(); - while (mFrameThreadRunning) { - LOGV("initPreview: waiting for old frame thread to complete."); - mFrameThreadWait.wait(mFrameThreadWaitLock); - LOGV("initPreview: old frame thread completed."); - } - mFrameThreadWaitLock.unlock(); - - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("initPreview: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("initPreview: old snapshot thread completed."); - } - mSnapshotThreadWaitLock.unlock(); - - int cnt = 0; - mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; - mPreviewHeap = new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_OUTPUT2, - mPreviewFrameSize, - kPreviewBufferCount, - mPreviewFrameSize, - 0, - "preview"); - - if (!mPreviewHeap->initialized()) { - mPreviewHeap.clear(); - LOGE("initPreview X: could not initialize preview heap."); - return false; - } - - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; - mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - - bool ret = native_set_dimension(&mDimension); - - if (ret) { - for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { - frames[cnt].fd = mPreviewHeap->mHeap->getHeapID(); - frames[cnt].buffer = - (uint32_t)mPreviewHeap->mHeap->base() + mPreviewFrameSize * cnt; - frames[cnt].y_off = 0; - frames[cnt].cbcr_off = mPreviewWidth * mPreviewHeight; - frames[cnt].path = MSM_FRAME_ENC; - } - - mFrameThreadWaitLock.lock(); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mFrameThreadRunning = !pthread_create(&mFrameThread, - &attr, - frame_thread, - &frames[kPreviewBufferCount-1]); - ret = mFrameThreadRunning; - mFrameThreadWaitLock.unlock(); - } - - LOGV("initPreview X: %d", ret); - return ret; -} - -void QualcommCameraHardware::deinitPreview(void) -{ - LOGI("deinitPreview E"); - - // When we call deinitPreview(), we signal to the frame thread that it - // needs to exit, but we DO NOT WAIT for it to complete here. The problem - // is that deinitPreview is sometimes called from the frame-thread's - // callback, when the refcount on the Camera client reaches zero. If we - // called pthread_join(), we would deadlock. So, we just call - // LINK_camframe_terminate() in deinitPreview(), which makes sure that - // after the preview callback returns, the camframe thread will exit. We - // could call pthread_join() in initPreview() to join the last frame - // thread. However, we would also have to call pthread_join() in release - // as well, shortly before we destoy the object; this would cause the same - // deadlock, since release(), like deinitPreview(), may also be called from - // the frame-thread's callback. This we have to make the frame thread - // detached, and use a separate mechanism to wait for it to complete. - - if (LINK_camframe_terminate() < 0) - LOGE("failed to stop the camframe thread: %s", - strerror(errno)); - LOGI("deinitPreview X"); -} - -bool QualcommCameraHardware::initRaw(bool initJpegHeap) -{ - LOGV("initRaw E: picture size=%dx%d", - mRawWidth, mRawHeight); - - mDimension.picture_width = mRawWidth; - mDimension.picture_height = mRawHeight; - mRawSize = mRawWidth * mRawHeight * 3 / 2; - mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - - if(!native_set_dimension(&mDimension)) { - LOGE("initRaw X: failed to set dimension"); - return false; - } - - if (mJpegHeap != NULL) { - LOGV("initRaw: clearing old mJpegHeap."); - mJpegHeap.clear(); - } - - // Snapshot - - LOGV("initRaw: initializing mRawHeap."); - mRawHeap = - new PmemPool("/dev/pmem_camera", - mCameraControlFd, - MSM_PMEM_MAINIMG, - mJpegMaxSize, - kRawBufferCount, - mRawSize, - 0, - "snapshot camera"); - - if (!mRawHeap->initialized()) { - LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); - mRawHeap = - new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_MAINIMG, - mJpegMaxSize, - kRawBufferCount, - mRawSize, - 0, - "snapshot camera"); - if (!mRawHeap->initialized()) { - mRawHeap.clear(); - LOGE("initRaw X: error initializing mRawHeap"); - return false; - } - } - - LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d", - (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID()); - - // Jpeg - - if (initJpegHeap) { - LOGV("initRaw: initializing mJpegHeap."); - mJpegHeap = - new AshmemPool(mJpegMaxSize, - kJpegBufferCount, - 0, // we do not know how big the picture wil be - 0, - "jpeg"); - - if (!mJpegHeap->initialized()) { - mJpegHeap.clear(); - mRawHeap.clear(); - LOGE("initRaw X failed: error initializing mJpegHeap."); - return false; - } - - // Thumbnails - - mThumbnailHeap = - new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_THUMBAIL, - THUMBNAIL_BUFFER_SIZE, - 1, - THUMBNAIL_BUFFER_SIZE, - 0, - "thumbnail"); - - if (!mThumbnailHeap->initialized()) { - mThumbnailHeap.clear(); - mJpegHeap.clear(); - mRawHeap.clear(); - LOGE("initRaw X failed: error initializing mThumbnailHeap."); - return false; - } - } - - LOGV("initRaw X"); - return true; -} - -void QualcommCameraHardware::deinitRaw() -{ - LOGV("deinitRaw E"); - - mThumbnailHeap.clear(); - mJpegHeap.clear(); - mRawHeap.clear(); - - LOGV("deinitRaw X"); -} - -void QualcommCameraHardware::release() -{ - LOGD("release E"); - Mutex::Autolock l(&mLock); - -#if DLOPEN_LIBMMCAMERA - if (libmmcamera == NULL) { - LOGE("ERROR: multiple release!"); - return; - } -#else -#warning "Cannot detect multiple release when not dlopen()ing libqcamera!" -#endif - - int cnt, rc; - struct msm_ctrl_cmd ctrlCmd; - - if (mCameraRunning) { - if(mRecordingCallback != NULL) { - mRecordFrameLock.lock(); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - mRecordFrameLock.unlock(); - } - stopPreviewInternal(); - } - - LINK_jpeg_encoder_join(); - deinitRaw(); - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = 0; - ctrlCmd.type = (uint16_t)CAMERA_EXIT; - ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel - if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("ioctl CAMERA_EXIT fd %d error %s", - mCameraControlFd, strerror(errno)); - rc = pthread_join(mCamConfigThread, NULL); - if (rc) - LOGE("config_thread exit failure: %s", strerror(errno)); - else - LOGV("pthread_join succeeded on config_thread"); - - close(mCameraControlFd); - mCameraControlFd = -1; - -#if DLOPEN_LIBMMCAMERA - if (libmmcamera) { - ::dlclose(libmmcamera); - LOGV("dlclose(libqcamera)"); - libmmcamera = NULL; - } -#endif - - Mutex::Autolock lock(&singleton_lock); - singleton_releasing = true; - - LOGD("release X"); -} - -QualcommCameraHardware::~QualcommCameraHardware() -{ - LOGD("~QualcommCameraHardware E"); - Mutex::Autolock lock(&singleton_lock); - singleton.clear(); - singleton_releasing = false; - singleton_wait.signal(); - LOGD("~QualcommCameraHardware X"); -} - -sp QualcommCameraHardware::getRawHeap() const -{ - LOGV("getRawHeap"); - return mRawHeap != NULL ? mRawHeap->mHeap : NULL; -} - -sp QualcommCameraHardware::getPreviewHeap() const -{ - LOGV("getPreviewHeap"); - return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL; -} - -status_t QualcommCameraHardware::startPreviewInternal() -{ - if(mCameraRunning) { - LOGV("startPreview X: preview already running."); - return NO_ERROR; - } - - if (!mPreviewInitialized) { - mPreviewInitialized = initPreview(); - if (!mPreviewInitialized) { - LOGE("startPreview X initPreview failed. Not starting preview."); - return UNKNOWN_ERROR; - } - } - - mCameraRunning = native_start_preview(mCameraControlFd); - if(!mCameraRunning) { - deinitPreview(); - mPreviewInitialized = false; - LOGE("startPreview X: native_start_preview failed!"); - return UNKNOWN_ERROR; - } - - LOGV("startPreview X"); - return NO_ERROR; -} - -status_t QualcommCameraHardware::startPreview(preview_callback cb, void *user) -{ - LOGV("startPreview E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mPreviewCallback = cb; - mPreviewCallbackCookie = user; - } - - return startPreviewInternal(); -} - -void QualcommCameraHardware::stopPreviewInternal() -{ - LOGV("stopPreviewInternal E: %d", mCameraRunning); - if (mCameraRunning) { - // Cancel auto focus. - if (mAutoFocusCallback) { - { - Mutex::Autolock cbLock(&mCallbackLock); - mAutoFocusCallback = NULL; - mAutoFocusCallbackCookie = NULL; - } - cancelAutoFocus(); - } - - mCameraRunning = !native_stop_preview(mCameraControlFd); - if (!mCameraRunning && mPreviewInitialized) { - deinitPreview(); - mPreviewInitialized = false; - } - else LOGE("stopPreviewInternal: failed to stop preview"); - } - LOGV("stopPreviewInternal X: %d", mCameraRunning); -} - -void QualcommCameraHardware::stopPreview() -{ - LOGV("stopPreview: E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mPreviewCallback = NULL; - mPreviewCallbackCookie = NULL; - if(mRecordingCallback != NULL) - return; - } - - stopPreviewInternal(); - - LOGV("stopPreview: X"); -} - -void QualcommCameraHardware::runAutoFocus() -{ - mAutoFocusThreadLock.lock(); - mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR); - if (mAutoFocusFd < 0) { - LOGE("autofocus: cannot open %s: %s", - MSM_CAMERA_CONTROL, - strerror(errno)); - mAutoFocusThreadRunning = false; - mAutoFocusThreadLock.unlock(); - return; - } - -#if DLOPEN_LIBMMCAMERA - // We need to maintain a reference to libqcamera.so for the duration of the - // AF thread, because we do not know when it will exit relative to the - // lifetime of this object. We do not want to dlclose() libqcamera while - // LINK_cam_frame is still running. - void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); - LOGV("AF: loading libqcamera at %p", libhandle); - if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); - close(mAutoFocusFd); - mAutoFocusFd = -1; - mAutoFocusThreadRunning = false; - mAutoFocusThreadLock.unlock(); - return; - } -#endif - - /* This will block until either AF completes or is cancelled. */ - LOGV("af start (fd %d)", mAutoFocusFd); - bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); - LOGV("af done: %d", (int)status); - mAutoFocusThreadRunning = false; - close(mAutoFocusFd); - mAutoFocusFd = -1; - mAutoFocusThreadLock.unlock(); - - mCallbackLock.lock(); - autofocus_callback cb = mAutoFocusCallback; - void *data = mAutoFocusCallbackCookie; - mCallbackLock.unlock(); - if (cb != NULL) - cb(status, data); - - mCallbackLock.lock(); - mAutoFocusCallback = NULL; - mAutoFocusCallbackCookie = NULL; - mCallbackLock.unlock(); - -#if DLOPEN_LIBMMCAMERA - if (libhandle) { - ::dlclose(libhandle); - LOGV("AF: dlclose(libqcamera)"); - } -#endif -} - -void QualcommCameraHardware::cancelAutoFocus() -{ - LOGV("cancelAutoFocus E"); - native_cancel_afmode(mCameraControlFd, mAutoFocusFd); - LOGV("cancelAutoFocus X"); -} - -void *auto_focus_thread(void *user) -{ - LOGV("auto_focus_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runAutoFocus(); - } - else LOGW("not starting autofocus: the object went away!"); - LOGV("auto_focus_thread X"); - return NULL; -} - -status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, - void *user) -{ - LOGV("autoFocus E"); - Mutex::Autolock l(&mLock); - - if (mCameraControlFd < 0) { - LOGE("not starting autofocus: main control fd %d", mCameraControlFd); - return UNKNOWN_ERROR; - } - - if (mAutoFocusCallback != NULL) { - LOGW("Auto focus is already in progress"); - return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; - } - - { - Mutex::Autolock cbl(&mCallbackLock); - mAutoFocusCallback = af_cb; - mAutoFocusCallbackCookie = user; - } - - { - mAutoFocusThreadLock.lock(); - if (!mAutoFocusThreadRunning) { - // Create a detatched thread here so that we don't have to wait - // for it when we cancel AF. - pthread_t thr; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mAutoFocusThreadRunning = - !pthread_create(&thr, &attr, - auto_focus_thread, NULL); - if (!mAutoFocusThreadRunning) { - LOGE("failed to start autofocus thread"); - mAutoFocusThreadLock.unlock(); - return UNKNOWN_ERROR; - } - } - mAutoFocusThreadLock.unlock(); - } - - LOGV("autoFocus X"); - return NO_ERROR; -} - -void QualcommCameraHardware::runSnapshotThread(void *data) -{ - LOGV("runSnapshotThread E"); - if (native_start_snapshot(mCameraControlFd)) - receiveRawPicture(); - else - LOGE("main: native_start_snapshot failed!"); - - mSnapshotThreadWaitLock.lock(); - mSnapshotThreadRunning = false; - mSnapshotThreadWait.signal(); - mSnapshotThreadWaitLock.unlock(); - - LOGV("runSnapshotThread X"); -} - -void *snapshot_thread(void *user) -{ - LOGD("snapshot_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runSnapshotThread(user); - } - else LOGW("not starting snapshot thread: the object went away!"); - LOGD("snapshot_thread X"); - return NULL; -} - -status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, - raw_callback raw_cb, - jpeg_callback jpeg_cb, - void *user) -{ - LOGV("takePicture: E raw_cb = %p, jpeg_cb = %p", - raw_cb, jpeg_cb); - Mutex::Autolock l(&mLock); - - // Wait for old snapshot thread to complete. - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("takePicture: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("takePicture: old snapshot thread completed."); - } - - stopPreviewInternal(); - - if (!initRaw(jpeg_cb != NULL)) { - LOGE("initRaw failed. Not taking picture."); - return UNKNOWN_ERROR; - } - - { - Mutex::Autolock cbLock(&mCallbackLock); - mShutterCallback = shutter_cb; - mRawPictureCallback = raw_cb; - mJpegPictureCallback = jpeg_cb; - mPictureCallbackCookie = user; - } - - mShutterLock.lock(); - mShutterPending = true; - mShutterLock.unlock(); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mSnapshotThreadRunning = !pthread_create(&mSnapshotThread, - &attr, - snapshot_thread, - NULL); - mSnapshotThreadWaitLock.unlock(); - - LOGV("takePicture: X"); - return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR; -} - -status_t QualcommCameraHardware::cancelPicture( - bool cancel_shutter, bool cancel_raw, bool cancel_jpeg) -{ - LOGV("cancelPicture: E cancel_shutter = %d, " - "cancel_raw = %d, cancel_jpeg = %d", - cancel_shutter, cancel_raw, cancel_jpeg); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - if (cancel_shutter) mShutterCallback = NULL; - if (cancel_raw) mRawPictureCallback = NULL; - if (cancel_jpeg) mJpegPictureCallback = NULL; - } - - LOGV("cancelPicture: X"); - return NO_ERROR; -} - -status_t QualcommCameraHardware::setParameters( - const CameraParameters& params) -{ - LOGV("setParameters: E params = %p", ¶ms); - - Mutex::Autolock l(&mLock); - - // Set preview size. - preview_size_type *ps = preview_sizes; - { - int width, height; - params.getPreviewSize(&width, &height); - LOGV("requested size %d x %d", width, height); - // Validate the preview size - size_t i; - for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { - if (width == ps->width && height == ps->height) - break; - } - if (i == PREVIEW_SIZE_COUNT) { - LOGE("Invalid preview size requested: %dx%d", - width, height); - return BAD_VALUE; - } - } - mPreviewWidth = mDimension.display_width = ps->width; - mPreviewHeight = mDimension.display_height = ps->height; - - // FIXME: validate snapshot sizes, - params.getPictureSize(&mRawWidth, &mRawHeight); - mDimension.picture_width = mRawWidth; - mDimension.picture_height = mRawHeight; - - // Set up the jpeg-thumbnail-size parameters. - { - int val; - - val = params.getInt("jpeg-thumbnail-width"); - if (val < 0) { - mDimension.ui_thumbnail_width= THUMBNAIL_WIDTH; - LOGW("jpeg-thumbnail-width is not specified: defaulting to %d", - THUMBNAIL_WIDTH); - } - else mDimension.ui_thumbnail_width = val; - - val = params.getInt("jpeg-thumbnail-height"); - if (val < 0) { - mDimension.ui_thumbnail_height= THUMBNAIL_HEIGHT; - LOGW("jpeg-thumbnail-height is not specified: defaulting to %d", - THUMBNAIL_HEIGHT); - } - else mDimension.ui_thumbnail_height = val; - } - - mParameters = params; - - setAntibanding(); - setEffect(); - setWhiteBalance(); - // FIXME: set nightshot and luma adaptatiom - - LOGV("setParameters: X"); - return NO_ERROR ; -} - -CameraParameters QualcommCameraHardware::getParameters() const -{ - LOGV("getParameters: EX"); - return mParameters; -} - -extern "C" sp openCameraHardware() -{ - LOGV("openCameraHardware: call createInstance"); - return QualcommCameraHardware::createInstance(); -} - -wp QualcommCameraHardware::singleton; - -// If the hardware already exists, return a strong pointer to the current -// object. If not, create a new hardware object, put it in the singleton, -// and return it. -sp QualcommCameraHardware::createInstance() -{ - LOGD("createInstance: E"); - - Mutex::Autolock lock(&singleton_lock); - - // Wait until the previous release is done. - while (singleton_releasing) { - LOGD("Wait for previous release."); - singleton_wait.wait(singleton_lock); - } - - if (singleton != 0) { - sp hardware = singleton.promote(); - if (hardware != 0) { - LOGD("createInstance: X return existing hardware=%p", &(*hardware)); - return hardware; - } - } - - { - struct stat st; - int rc = stat("/dev/oncrpc", &st); - if (rc < 0) { - LOGD("createInstance: X failed to create hardware: %s", strerror(errno)); - return NULL; - } - } - - QualcommCameraHardware *cam = new QualcommCameraHardware(); - sp hardware(cam); - singleton = hardware; - - cam->startCamera(); - cam->initDefaultParameters(); - LOGD("createInstance: X created hardware=%p", &(*hardware)); - return hardware; -} - -// For internal use only, hence the strong pointer to the derived type. -sp QualcommCameraHardware::getInstance() -{ - sp hardware = singleton.promote(); - if (hardware != 0) { - // LOGV("getInstance: X old instance of hardware"); - return sp(static_cast(hardware.get())); - } else { - LOGV("getInstance: X new instance of hardware"); - return sp(); - } -} - -void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) -{ -// LOGV("receivePreviewFrame E"); - - if (!mCameraRunning) { - LOGE("ignoring preview callback--camera has been stopped"); - return; - } - - mCallbackLock.lock(); - preview_callback pcb = mPreviewCallback; - void *pdata = mPreviewCallbackCookie; - recording_callback rcb = mRecordingCallback; - void *rdata = mRecordingCallbackCookie; - mCallbackLock.unlock(); - - // Find the offset within the heap of the current buffer. - ssize_t offset = - (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); - offset /= mPreviewFrameSize; - - //LOGV("%d\n", offset); - - mInPreviewCallback = true; - if (pcb != NULL) - pcb(mPreviewHeap->mBuffers[offset], - pdata); - - if(rcb != NULL) { - Mutex::Autolock rLock(&mRecordFrameLock); - rcb(systemTime(), mPreviewHeap->mBuffers[offset], rdata); - if (mReleasedRecordingFrame != true) { - LOGV("block for release frame request/command"); - mRecordWait.wait(mRecordFrameLock); - } - mReleasedRecordingFrame = false; - } - mInPreviewCallback = false; - -// LOGV("receivePreviewFrame X"); -} - -status_t QualcommCameraHardware::startRecording( - recording_callback rcb, void *ruser) -{ - LOGV("startRecording E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mRecordingCallback = rcb; - mRecordingCallbackCookie = ruser; - } - - mReleasedRecordingFrame = false; - - return startPreviewInternal(); -} - -void QualcommCameraHardware::stopRecording() -{ - LOGV("stopRecording: E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mRecordingCallback = NULL; - mRecordingCallbackCookie = NULL; - - mRecordFrameLock.lock(); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - mRecordFrameLock.unlock(); - - if(mPreviewCallback != NULL) { - LOGV("stopRecording: X, preview still in progress"); - return; - } - } - - stopPreviewInternal(); - LOGV("stopRecording: X"); -} - -void QualcommCameraHardware::releaseRecordingFrame( - const sp& mem __attribute__((unused))) -{ - LOGV("releaseRecordingFrame E"); - Mutex::Autolock l(&mLock); - Mutex::Autolock rLock(&mRecordFrameLock); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - LOGV("releaseRecordingFrame X"); -} - -bool QualcommCameraHardware::recordingEnabled() -{ - Mutex::Autolock l(&mLock); - return mCameraRunning && mRecordingCallback != NULL; -} - -void QualcommCameraHardware::notifyShutter() -{ - mShutterLock.lock(); - if (mShutterPending && mShutterCallback) { - mShutterCallback(mPictureCallbackCookie); - mShutterPending = false; - } - mShutterLock.unlock(); -} - -static void receive_shutter_callback() -{ - LOGV("receive_shutter_callback: E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->notifyShutter(); - } - LOGV("receive_shutter_callback: X"); -} - -void QualcommCameraHardware::receiveRawPicture() -{ - LOGV("receiveRawPicture: E"); - - Mutex::Autolock cbLock(&mCallbackLock); - - if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd, &mCrop) == false) { - LOGE("getPicture failed!"); - return; - } - - // By the time native_get_picture returns, picture is taken. Call - // shutter callback if cam config thread has not done that. - notifyShutter(); - mRawPictureCallback(mRawHeap->mBuffers[0], - mPictureCallbackCookie); - } - else LOGV("Raw-picture callback was canceled--skipping."); - - if (mJpegPictureCallback != NULL) { - mJpegSize = 0; - if (LINK_jpeg_encoder_init()) { - if(native_jpeg_encode()) { - LOGV("receiveRawPicture: X (success)"); - return; - } - LOGE("jpeg encoding failed"); - } - else LOGE("receiveRawPicture X: jpeg_encoder_init failed."); - } - else LOGV("JPEG callback is NULL, not encoding image."); - deinitRaw(); - LOGV("receiveRawPicture: X"); -} - -void QualcommCameraHardware::receiveJpegPictureFragment( - uint8_t *buff_ptr, uint32_t buff_size) -{ - uint32_t remaining = mJpegHeap->mHeap->virtualSize(); - remaining -= mJpegSize; - uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base(); - - LOGV("receiveJpegPictureFragment size %d", buff_size); - if (buff_size > remaining) { - LOGE("receiveJpegPictureFragment: size %d exceeds what " - "remains in JPEG heap (%d), truncating", - buff_size, - remaining); - buff_size = remaining; - } - memcpy(base + mJpegSize, buff_ptr, buff_size); - mJpegSize += buff_size; -} - -void QualcommCameraHardware::receiveJpegPicture(void) -{ - LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", - mJpegSize, mJpegHeap->mBufferSize); - Mutex::Autolock cbLock(&mCallbackLock); - - int index = 0, rc; - - if (mJpegPictureCallback) { - // The reason we do not allocate into mJpegHeap->mBuffers[offset] is - // that the JPEG image's size will probably change from one snapshot - // to the next, so we cannot reuse the MemoryBase object. - sp buffer = new - MemoryBase(mJpegHeap->mHeap, - index * mJpegHeap->mBufferSize + - mJpegHeap->mFrameOffset, - mJpegSize); - - mJpegPictureCallback(buffer, mPictureCallbackCookie); - buffer = NULL; - } - else LOGV("JPEG callback was cancelled--not delivering image."); - - LINK_jpeg_encoder_join(); - deinitRaw(); - - LOGV("receiveJpegPicture: X callback done."); -} - -bool QualcommCameraHardware::previewEnabled() -{ -// Mutex::Autolock l(&mLock); - return mCameraRunning && mPreviewCallback != NULL; -} - -int QualcommCameraHardware::getParm( - const char *parm_str, const struct str_map *const parm_map) -{ - // Check if the parameter exists. - const char *str = mParameters.get(parm_str); - if (str == NULL) return NOT_FOUND; - - // Look up the parameter value. - return attr_lookup(parm_map, str); -} - -void QualcommCameraHardware::setEffect() -{ - int32_t value = getParm("effect", effect); - if (value != NOT_FOUND) { - native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value), (void *)&value); - } -} - -void QualcommCameraHardware::setWhiteBalance() -{ - int32_t value = getParm("whitebalance", whitebalance); - if (value != NOT_FOUND) { - native_set_parm(CAMERA_SET_PARM_WB, sizeof(value), (void *)&value); - } -} - -void QualcommCameraHardware::setAntibanding() -{ - camera_antibanding_type value = - (camera_antibanding_type) getParm("antibanding", antibanding); - native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(value), (void *)&value); -} - -QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - mBufferSize(buffer_size), - mNumBuffers(num_buffers), - mFrameSize(frame_size), - mFrameOffset(frame_offset), - mBuffers(NULL), mName(name) -{ - // empty -} - -void QualcommCameraHardware::MemPool::completeInitialization() -{ - // If we do not know how big the frame will be, we wait to allocate - // the buffers describing the individual frames until we do know their - // size. - - if (mFrameSize > 0) { - mBuffers = new sp[mNumBuffers]; - for (int i = 0; i < mNumBuffers; i++) { - mBuffers[i] = new - MemoryBase(mHeap, - i * mBufferSize + mFrameOffset, - mFrameSize); - } - } -} - -QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::MemPool(buffer_size, - num_buffers, - frame_size, - frame_offset, - name) -{ - LOGV("constructing MemPool %s backed by ashmem: " - "%d frames @ %d uint8_ts, offset %d, " - "buffer size %d", - mName, - num_buffers, frame_size, frame_offset, buffer_size); - - int page_mask = getpagesize() - 1; - int ashmem_size = buffer_size * num_buffers; - ashmem_size += page_mask; - ashmem_size &= ~page_mask; - - mHeap = new MemoryHeapBase(ashmem_size); - - completeInitialization(); -} - -static bool register_buf(int camfd, - int size, - int pmempreviewfd, - uint32_t offset, - uint8_t *buf, - int pmem_type, - bool register_buffer = true); - -QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, - int camera_control_fd, - int pmem_type, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::MemPool(buffer_size, - num_buffers, - frame_size, - frame_offset, - name), - mPmemType(pmem_type), - mCameraControlFd(dup(camera_control_fd)) -{ - LOGV("constructing MemPool %s backed by pmem pool %s: " - "%d frames @ %d bytes, offset %d, buffer size %d", - mName, - pmem_pool, num_buffers, frame_size, frame_offset, - buffer_size); - - LOGV("%s: duplicating control fd %d --> %d", - __FUNCTION__, - camera_control_fd, mCameraControlFd); - - // Make a new mmap'ed heap that can be shared across processes. - - mAlignedSize = clp2(buffer_size * num_buffers); - - sp masterHeap = - new MemoryHeapBase(pmem_pool, mAlignedSize, 0); - sp pmemHeap = new MemoryHeapPmem(masterHeap, 0); - if (pmemHeap->getHeapID() >= 0) { - pmemHeap->slap(); - masterHeap.clear(); - mHeap = pmemHeap; - pmemHeap.clear(); - - mFd = mHeap->getHeapID(); - if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { - LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", - pmem_pool, - ::strerror(errno), errno); - mHeap.clear(); - return; - } - - LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", - pmem_pool, - mFd, - mSize.len); - - // Unregister preview buffers with the camera drivers. - for (int cnt = 0; cnt < num_buffers; ++cnt) { - register_buf(mCameraControlFd, - buffer_size, - mHeap->getHeapID(), - buffer_size * cnt, - (uint8_t *)mHeap->base() + buffer_size * cnt, - pmem_type); - } - - completeInitialization(); - } - else LOGE("pmem pool %s error: could not create master heap!", - pmem_pool); -} - -QualcommCameraHardware::PmemPool::~PmemPool() -{ - LOGV("%s: %s E", __FUNCTION__, mName); - // Unregister preview buffers with the camera drivers. - for (int cnt = 0; cnt < mNumBuffers; ++cnt) { - register_buf(mCameraControlFd, - mBufferSize, - mHeap->getHeapID(), - mBufferSize * cnt, - (uint8_t *)mHeap->base() + mBufferSize * cnt, - mPmemType, - false /* unregister */); - } - LOGV("destroying PmemPool %s: closing control fd %d", - mName, - mCameraControlFd); - close(mCameraControlFd); - LOGV("%s: %s X", __FUNCTION__, mName); -} - -QualcommCameraHardware::MemPool::~MemPool() -{ - LOGV("destroying MemPool %s", mName); - if (mFrameSize > 0) - delete [] mBuffers; - mHeap.clear(); - LOGV("destroying MemPool %s completed", mName); -} - -static bool register_buf(int camfd, - int size, - int pmempreviewfd, - uint32_t offset, - uint8_t *buf, - int pmem_type, - bool register_buffer) -{ - struct msm_pmem_info pmemBuf; - - pmemBuf.type = pmem_type; - pmemBuf.fd = pmempreviewfd; - pmemBuf.offset = offset; - pmemBuf.len = size; - pmemBuf.vaddr = buf; - pmemBuf.y_off = 0; - pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3); - pmemBuf.active = true; - - LOGV("register_buf: camfd = %d, reg = %d buffer = %p", - camfd, !register_buffer, buf); - if (ioctl(camfd, - register_buffer ? - MSM_CAM_IOCTL_REGISTER_PMEM : - MSM_CAM_IOCTL_UNREGISTER_PMEM, - &pmemBuf) < 0) { - LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", - camfd, - strerror(errno)); - return false; - } - return true; -} - -status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); - result.append(buffer); - if (mName) { - snprintf(buffer, 255, "mem pool name (%s)\n", mName); - result.append(buffer); - } - if (mHeap != 0) { - snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", - mHeap->getBase(), mHeap->getSize(), - mHeap->getFlags(), mHeap->getDevice()); - result.append(buffer); - } - snprintf(buffer, 255, "buffer size (%d), number of buffers (%d)," - " frame size(%d), and frame offset(%d)\n", - mBufferSize, mNumBuffers, mFrameSize, mFrameOffset); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -static void receive_camframe_callback(struct msm_frame *frame) -{ - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receivePreviewFrame(frame); - } -} - -static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size) -{ - LOGV("receive_jpeg_fragment_callback E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receiveJpegPictureFragment(buff_ptr, buff_size); - } - LOGV("receive_jpeg_fragment_callback X"); -} - -static void receive_jpeg_callback(jpeg_event_t status) -{ - LOGV("receive_jpeg_callback E (completion status %d)", status); - if (status == JPEG_EVENT_DONE) { - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receiveJpegPicture(); - } - } - LOGV("receive_jpeg_callback X"); -} - -}; // namespace android diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h deleted file mode 100644 index b4b0cb5..0000000 --- a/libcamera2/QualcommCameraHardware.h +++ /dev/null @@ -1,241 +0,0 @@ -/* -** Copyright 2008, Google Inc. -** -** 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 ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H -#define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H - -#include -#include -#include -#include - -extern "C" { -#include -#include -#include -} - -struct str_map { - const char *const desc; - int val; -}; - -namespace android { - -class QualcommCameraHardware : public CameraHardwareInterface { -public: - - virtual sp getPreviewHeap() const; - virtual sp getRawHeap() const; - - virtual status_t dump(int fd, const Vector& args) const; - virtual status_t startPreview(preview_callback cb, void* user); - virtual void stopPreview(); - virtual bool previewEnabled(); - virtual status_t startRecording(recording_callback cb, void* user); - virtual void stopRecording(); - virtual bool recordingEnabled(); - virtual void releaseRecordingFrame(const sp& mem); - virtual status_t autoFocus(autofocus_callback, void *user); - virtual status_t takePicture(shutter_callback, raw_callback, - jpeg_callback, void *); - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, bool cancel_jpeg); - virtual status_t setParameters(const CameraParameters& params); - virtual CameraParameters getParameters() const; - virtual void release(); - - static sp createInstance(); - static sp getInstance(); - - void receivePreviewFrame(struct msm_frame *frame); - void receiveJpegPicture(void); - void jpeg_set_location(); - void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); - void notifyShutter(); - -private: - QualcommCameraHardware(); - virtual ~QualcommCameraHardware(); - status_t startPreviewInternal(); - void stopPreviewInternal(); - friend void *auto_focus_thread(void *user); - void runAutoFocus(); - void cancelAutoFocus(); - bool native_set_dimension (int camfd); - bool native_jpeg_encode (void); - bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value); - bool native_set_dimension(cam_ctrl_dimension_t *value); - int getParm(const char *parm_str, const str_map *parm_map); - - static wp singleton; - - /* These constants reflect the number of buffers that libmmcamera requires - for preview and raw, and need to be updated when libmmcamera - changes. - */ - static const int kPreviewBufferCount = 4; - static const int kRawBufferCount = 1; - static const int kJpegBufferCount = 1; - - //TODO: put the picture dimensions in the CameraParameters object; - CameraParameters mParameters; - int mPreviewHeight; - int mPreviewWidth; - int mRawHeight; - int mRawWidth; - unsigned int frame_size; - bool mCameraRunning; - bool mPreviewInitialized; - - // This class represents a heap which maintains several contiguous - // buffers. The heap may be backed by pmem (when pmem_pool contains - // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). - - struct MemPool : public RefBase { - MemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - - virtual ~MemPool() = 0; - - void completeInitialization(); - bool initialized() const { - return mHeap != NULL && mHeap->base() != MAP_FAILED; - } - - virtual status_t dump(int fd, const Vector& args) const; - - int mBufferSize; - int mNumBuffers; - int mFrameSize; - int mFrameOffset; - sp mHeap; - sp *mBuffers; - - const char *mName; - }; - - struct AshmemPool : public MemPool { - AshmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - struct PmemPool : public MemPool { - PmemPool(const char *pmem_pool, - int control_camera_fd, int pmem_type, - int buffer_size, int num_buffers, - int frame_size, int frame_offset, - const char *name); - virtual ~PmemPool(); - int mFd; - int mPmemType; - int mCameraControlFd; - uint32_t mAlignedSize; - struct pmem_region mSize; - }; - - sp mPreviewHeap; - sp mThumbnailHeap; - sp mRawHeap; - sp mJpegHeap; - - void startCamera(); - bool initPreview(); - void deinitPreview(); - bool initRaw(bool initJpegHeap); - void deinitRaw(); - - bool mFrameThreadRunning; - Mutex mFrameThreadWaitLock; - Condition mFrameThreadWait; - friend void *frame_thread(void *user); - void runFrameThread(void *data); - - bool mShutterPending; - Mutex mShutterLock; - - bool mSnapshotThreadRunning; - Mutex mSnapshotThreadWaitLock; - Condition mSnapshotThreadWait; - friend void *snapshot_thread(void *user); - void runSnapshotThread(void *data); - - void initDefaultParameters(); - - void setAntibanding(); - void setEffect(); - void setWhiteBalance(); - - Mutex mLock; - bool mReleasedRecordingFrame; - - void receiveRawPicture(void); - - Mutex mCallbackLock; - Mutex mRecordLock; - Mutex mRecordFrameLock; - Condition mRecordWait; - Condition mStateWait; - - /* mJpegSize keeps track of the size of the accumulated JPEG. We clear it - when we are about to take a picture, so at any time it contains either - zero, or the size of the last JPEG picture taken. - */ - uint32_t mJpegSize; - - shutter_callback mShutterCallback; - raw_callback mRawPictureCallback; - jpeg_callback mJpegPictureCallback; - void *mPictureCallbackCookie; - - autofocus_callback mAutoFocusCallback; - void *mAutoFocusCallbackCookie; - - preview_callback mPreviewCallback; - void *mPreviewCallbackCookie; - recording_callback mRecordingCallback; - void *mRecordingCallbackCookie; - unsigned int mPreviewFrameSize; - int mRawSize; - int mJpegMaxSize; - -#if DLOPEN_LIBMMCAMERA - void *libmmcamera; -#endif - - int mCameraControlFd; - cam_ctrl_dimension_t mDimension; - bool mAutoFocusThreadRunning; - Mutex mAutoFocusThreadLock; - int mAutoFocusFd; - - pthread_t mCamConfigThread; - pthread_t mFrameThread; - pthread_t mSnapshotThread; - - common_crop_t mCrop; - - struct msm_frame frames[kPreviewBufferCount]; - bool mInPreviewCallback; -}; - -}; // namespace android - -#endif From 8b4a578e2419531fccfd6b627f0278a6c6f26092 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Thu, 6 Aug 2009 16:36:30 -0700 Subject: [PATCH 112/435] Deactivate libcamera2 It can't be built without proprietary files --- libcamera2/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk index 26eb4a5..80e24fe 100644 --- a/libcamera2/Android.mk +++ b/libcamera2/Android.mk @@ -1,4 +1,4 @@ -BUILD_LIBCAMERA:=true +BUILD_LIBCAMERA:= ifeq ($(BUILD_LIBCAMERA),true) # When zero we link against libmmcamera; when 1, we dlopen libmmcamera. From 32a0f80413b322c7f17d0f921094c22c5304cc3f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 7 Aug 2009 19:09:35 -0700 Subject: [PATCH 116/435] make sure to use the right 32-bit pixelformat on msm7k when using the gpu --- libcopybit/copybit.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index f734b73..8347a0c 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -123,8 +123,15 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->format = get_format(rhs->format); img->offset = hnd->offset; #if defined(COPYBIT_MSM7K) - img->memory_id = (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) - ? hnd->gpu_fd : hnd->fd; + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + img->memory_id = hnd->gpu_fd; + if (img->format == MDP_RGBA_8888) { + // msm7201A GPU only supports BGRA_8888 destinations + img->format = MDP_BGRA_8888; + } + } else { + img->memory_id = hnd->fd; + } #else img->memory_id = hnd->fd; #endif From 5eabeaf821322dd86bfa4f53cd822a9b299659e4 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 7 Aug 2009 20:56:29 -0700 Subject: [PATCH 117/435] add support for RGBX_8888. HOWEVER MDP doesn't support it yet, so we use XRGB which looks wrong for now --- libcopybit/copybit.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 8347a0c..cb17de2 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -105,9 +105,11 @@ static void intersect(struct copybit_rect_t *out, /** convert COPYBIT_FORMAT to MDP format */ static int get_format(int format) { switch (format) { + case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; + case COPYBIT_FORMAT_RGBX_8888: return MDP_XRGB_8888; // currently wrong + case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; } From 9699cda001c700e38678da9076e9c4eeadd709ee Mon Sep 17 00:00:00 2001 From: Wu-cheng Li Date: Mon, 10 Aug 2009 15:07:38 +0800 Subject: [PATCH 119/435] Change the default effect value from "off" to "none". --- libcamera2/QualcommCameraHardware.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp index 981c46f..2a39f20 100644 --- a/libcamera2/QualcommCameraHardware.cpp +++ b/libcamera2/QualcommCameraHardware.cpp @@ -173,7 +173,7 @@ static char *whitebalance_values; // from camera_effect_t static const str_map effect[] = { - { "off", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ + { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ { "mono", CAMERA_EFFECT_MONO }, { "negative", CAMERA_EFFECT_NEGATIVE }, { "solarize", CAMERA_EFFECT_SOLARIZE }, @@ -268,7 +268,7 @@ void QualcommCameraHardware::initDefaultParameters() p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); p.set("antibanding", "off"); - p.set("effect", "off"); + p.set("effect", "none"); p.set("whitebalance", "auto"); #if 0 From c3cf7def5a352b4986fe17bf7027e1c244dcf66d Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 5 Aug 2009 00:26:21 -0700 Subject: [PATCH 121/435] qsd8k: add gralloc for 8k Signed-off-by: Dima Zavin --- libgralloc-qsd8k/Android.mk | 32 ++ libgralloc-qsd8k/allocator.cpp | 154 ++++++++++ libgralloc-qsd8k/allocator.h | 127 ++++++++ libgralloc-qsd8k/framebuffer.cpp | 422 ++++++++++++++++++++++++++ libgralloc-qsd8k/gralloc.cpp | 492 +++++++++++++++++++++++++++++++ libgralloc-qsd8k/gralloc_priv.h | 188 ++++++++++++ libgralloc-qsd8k/mapper.cpp | 239 +++++++++++++++ 7 files changed, 1654 insertions(+) create mode 100644 libgralloc-qsd8k/Android.mk create mode 100644 libgralloc-qsd8k/allocator.cpp create mode 100644 libgralloc-qsd8k/allocator.h create mode 100644 libgralloc-qsd8k/framebuffer.cpp create mode 100644 libgralloc-qsd8k/gralloc.cpp create mode 100644 libgralloc-qsd8k/gralloc_priv.h create mode 100644 libgralloc-qsd8k/mapper.cpp diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk new file mode 100644 index 0000000..9bae065 --- /dev/null +++ b/libgralloc-qsd8k/Android.mk @@ -0,0 +1,32 @@ +# 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/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils + +LOCAL_SRC_FILES := \ + allocator.cpp \ + gralloc.cpp \ + framebuffer.cpp \ + mapper.cpp + +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" +include $(BUILD_SHARED_LIBRARY) diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp new file mode 100644 index 0000000..f901741 --- /dev/null +++ b/libgralloc-qsd8k/allocator.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2009 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 "allocator.h" + + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +{ + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Locker::Autolock _l(mLock); + ssize_t offset = alloc(size, flags); + return offset; +} + +ssize_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Locker::Autolock _l(mLock); + chunk_t const * const freed = dealloc(offset); + if (freed) { + return 0; + } + return -ENOENT; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + return -ENOMEM; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + #ifndef NDEBUG + if (!freed->free) { + dump_l("dealloc (!freed->free)"); + } + #endif + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h new file mode 100644 index 0000000..dfb06f6 --- /dev/null +++ b/libgralloc-qsd8k/allocator.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009 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_ALLOCATOR_H_ +#define GRALLOC_ALLOCATOR_H_ + +#include +#include + +#include "gralloc_priv.h" + +// ---------------------------------------------------------------------------- + +/* + * A simple templatized doubly linked-list implementation + */ + +template +class LinkedList +{ + NODE* mFirst; + NODE* mLast; + +public: + LinkedList() : mFirst(0), mLast(0) { } + bool isEmpty() const { return mFirst == 0; } + NODE const* head() const { return mFirst; } + NODE* head() { return mFirst; } + NODE const* tail() const { return mLast; } + NODE* tail() { return mLast; } + + void insertAfter(NODE* node, NODE* newNode) { + newNode->prev = node; + newNode->next = node->next; + if (node->next == 0) mLast = newNode; + else node->next->prev = newNode; + node->next = newNode; + } + + void insertBefore(NODE* node, NODE* newNode) { + newNode->prev = node->prev; + newNode->next = node; + if (node->prev == 0) mFirst = newNode; + else node->prev->next = newNode; + node->prev = newNode; + } + + void insertHead(NODE* newNode) { + if (mFirst == 0) { + mFirst = mLast = newNode; + newNode->prev = newNode->next = 0; + } else { + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; + } + } + + void insertTail(NODE* newNode) { + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } + } + + NODE* remove(NODE* node) { + if (node->prev == 0) mFirst = node->next; + else node->prev->next = node->next; + if (node->next == 0) mLast = node->prev; + else node->next->prev = node->prev; + return node; + } +}; + +class SimpleBestFitAllocator +{ +public: + + SimpleBestFitAllocator(size_t size); + virtual ~SimpleBestFitAllocator(); + + virtual size_t allocate(size_t size, uint32_t flags = 0); + virtual ssize_t deallocate(size_t offset); + virtual size_t size() const; + +private: + struct chunk_t { + chunk_t(size_t start, size_t size) + : start(start), size(size), free(1), prev(0), next(0) { + } + size_t start; + size_t size : 28; + int free : 4; + mutable chunk_t* prev; + mutable chunk_t* next; + }; + + ssize_t alloc(size_t size, uint32_t flags); + chunk_t* dealloc(size_t start); + + static const int kMemoryAlign; + mutable Locker mLock; + LinkedList mList; + size_t mHeapSize; +}; + + +#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp new file mode 100644 index 0000000..0571c0c --- /dev/null +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -0,0 +1,422 @@ +/* + * 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 + +#if HAVE_ANDROID_OS +#include +#endif + +#include "gralloc_priv.h" +#include +#include +/*****************************************************************************/ + +// should be a build option +#define SUPPORTS_UPDATE_ON_DEMAND 1 + +#define NUM_BUFFERS 2 + + +enum { + PAGE_FLIP = 0x00000001, + LOCKED = 0x00000002 +}; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h); + +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_setUpdateRect(struct framebuffer_device_t* dev, + int l, int t, int w, int h) +{ + if (((w|h) <= 0) || ((l|t)<0)) + return -EINVAL; + + fb_context_t* ctx = (fb_context_t*)dev; + private_module_t* m = reinterpret_cast( + dev->common.module); + m->info.reserved[0] = 0x54445055; // "UPDT"; + m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); + m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); + 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 = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast( + dev->common.module); + + if (m->currentBuffer) { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + + m->base.lock(&m->base, buffer, + private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + + } else { + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + + void* fb_vaddr; + void* buffer_vaddr; + + 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, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + msm_copy_buffer(m->framebuffer, m->framebuffer->fd, + m->info.xres, m->info.yres, + 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); + } + + return 0; +} + +/*****************************************************************************/ + +int mapFrameBufferLocked(struct private_module_t* module) +{ + // already initialized... + if (module->framebuffer) { + return 0; + } + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + + /* + * 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; + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) { + // bleagh, bad info from the driver + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + LOGI( "using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length + ); + + LOGI( "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps + ); + + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + + int err; + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, + private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_FB); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + LOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + module->framebuffer->base = intptr_t(vaddr); + memset(vaddr, 0, fbSize); + return 0; +} + +static int mapFrameBuffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = mapFrameBufferLocked(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; + if (ctx) { + free(ctx); + } + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { + + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) + return status; + + /* 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; +#if SUPPORTS_UPDATE_ON_DEMAND + dev->device.setUpdateRect = fb_setUpdateRect; +#endif + dev->device.post = fb_post; + + private_module_t* m = (private_module_t*)module; + status = mapFrameBuffer(m); + if (status >= 0) { + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast(dev->device.flags) = 0; + const_cast(dev->device.width) = m->info.xres; + const_cast(dev->device.height) = m->info.yres; + const_cast(dev->device.stride) = 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 status; +} + +/* Copy a pmem buffer to the framebuffer */ + +void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h) +{ + struct { + unsigned int count; + mdp_blit_req req; + } blit; + private_handle_t *priv = (private_handle_t*) handle; + + memset(&blit, 0, sizeof(blit)); + blit.count = 1; + + blit.req.flags = 0; + blit.req.alpha = 0xff; + blit.req.transp_mask = 0xffffffff; + + blit.req.src.width = width; + blit.req.src.height = height; + blit.req.src.offset = 0; + blit.req.src.memory_id = priv->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.format = MDP_RGB_565; + + blit.req.src_rect.x = blit.req.dst_rect.x = x; + blit.req.src_rect.y = blit.req.dst_rect.y = y; + blit.req.src_rect.w = blit.req.dst_rect.w = w; + blit.req.src_rect.h = blit.req.dst_rect.h = h; + + if (ioctl(fd, MSMFB_BLIT, &blit)) + LOGE("MSMFB_BLIT failed = %d", -errno); +} diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp new file mode 100644 index 0000000..536d1c4 --- /dev/null +++ b/libgralloc-qsd8k/gralloc.cpp @@ -0,0 +1,492 @@ +/* + * 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 +#include + +#include "gralloc_priv.h" +#include "allocator.h" + +#if HAVE_ANDROID_OS +#include +#endif + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ + int bufferType; +}; + +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); + +/*****************************************************************************/ + +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, + }, + framebuffer: 0, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: 0, + pmem_master: -1, + pmem_master_base: 0, + master_phys: 0, + gpu_master: -1, + gpu_master_base: 0 +}; + +/*****************************************************************************/ + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + + // allocate the framebuffer + if (m->framebuffer == NULL) { + // initialize the framebuffer, the framebuffer is mapped once + // and forever. + int err = 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(dev, bufferSize, newUsage, pHandle); + } + + if (bufferMask >= ((1LU<framebuffer->base); + private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, + private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_FB); + + // find a free slot + for (uint32_t i=0 ; ibufferMask |= (1LU<base = vaddr; + hnd->offset = vaddr - intptr_t(m->framebuffer->base); + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); + pthread_mutex_unlock(&m->lock); + return err; +} + +static SimpleBestFitAllocator sAllocator(10*1024*1024); +static SimpleBestFitAllocator sGPUAllocator(3*1024*1024); + +static int init_pmem_area(private_module_t* m, int type) +{ + int err = 0; + int master_fd = -1; + size_t master_heap_size; + if(type == BUFFER_TYPE_GPU0) + { + master_fd = open("/dev/pmem_gpu0", O_RDWR, 0); + master_heap_size = sGPUAllocator.size(); + } + else if(type == BUFFER_TYPE_GPU1) + { + master_fd = open("/dev/pmem_gpu1", O_RDWR, 0); + master_heap_size = sGPUAllocator.size(); + } + else if (type == BUFFER_TYPE_PMEM) + { + master_fd = open("/dev/pmem", O_RDWR, 0); + master_heap_size = sAllocator.size(); + } + + if (master_fd >= 0) { + void* base = mmap(0, master_heap_size, + PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + if (base == MAP_FAILED) { + LOGE("Enter init_pmem_area error: %d", -errno); + err = -errno; + base = 0; + close(master_fd); + master_fd = -1; + } + if(type == BUFFER_TYPE_PMEM){ + m->pmem_master = master_fd; + m->pmem_master_base = base; + } + else + { + m->gpu_master = master_fd; + m->gpu_master_base = base; + pmem_region region; + err = ioctl(m->gpu_master, PMEM_GET_PHYS, ®ion); + if(err < 0) + { + LOGE("init pmem: master ioctl failed %d", -errno); + } + else + { + m->master_phys = (unsigned long)region.offset; + } + } + } else { + err = -errno; + } + return err; +} + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + int err = 0; + int flags = 0; + + int fd = -1; + void* base = 0; + int offset = 0; + int lockState = 0; + + private_module_t* m = reinterpret_cast( + dev->common.module); + + gralloc_context_t *context = (gralloc_context_t *) dev; + int bufferType; + + size = roundUpToPageSize(size); + + if (usage & (GRALLOC_USAGE_HW_2D | GRALLOC_USAGE_HW_RENDER)) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; + bufferType = context->bufferType; + } + else 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; + bufferType = BUFFER_TYPE_PMEM; + } + + int phys = 0; + if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { +try_ashmem: + fd = ashmem_create_region("Buffer", size); + if (fd < 0) { + LOGE("couldn't create ashmem (%s)", strerror(-errno)); + err = -errno; + } + } else { + + int master_fd = -1; + if(bufferType == BUFFER_TYPE_PMEM) + { + master_fd = m->pmem_master; + } + else + { + master_fd = m->gpu_master; + } + + pthread_mutex_lock(&m->lock); + if (master_fd == -1) { + err = init_pmem_area(m, bufferType); + } + pthread_mutex_unlock(&m->lock); + + if(bufferType == BUFFER_TYPE_PMEM) + { + master_fd = m->pmem_master; + } + else + { + master_fd = m->gpu_master; + } + + if (master_fd >= 0) { + // PMEM buffers are always mmapped + if(bufferType == BUFFER_TYPE_PMEM) + { + base = m->pmem_master_base; + offset = sAllocator.allocate(size); + } + else + { + base = m->gpu_master_base; + offset = sGPUAllocator.allocate(size); + } + + lockState |= private_handle_t::LOCK_STATE_MAPPED; + + if (offset < 0) { + err = -ENOMEM; + } else { + if(bufferType == BUFFER_TYPE_GPU0) + fd = open("/dev/pmem_gpu0", O_RDWR, 0); + else if(bufferType == BUFFER_TYPE_GPU1) + fd = open("/dev/pmem_gpu1", O_RDWR, 0); + else if (bufferType == BUFFER_TYPE_PMEM) + fd = open("/dev/pmem", O_RDWR, 0); + + err = ioctl(fd, PMEM_CONNECT, master_fd); + if (err < 0) { + err = -errno; + } else { + struct pmem_region sub = { offset, size }; + err = ioctl(fd, PMEM_MAP, &sub); + } + + if (err < 0) { + close(fd); + if(bufferType == BUFFER_TYPE_PMEM) + sAllocator.deallocate(offset); + else + sGPUAllocator.deallocate(offset); + fd = -1; + } + //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); + } + } else { + if ((usage & GRALLOC_USAGE_HW_2D) == 0) { + // the caller didn't request PMEM, so we can try something else + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + err = 0; + goto try_ashmem; + } else { + LOGE("couldn't open pmem (%s)", strerror(-errno)); + } + } + } + + if (err == 0) { + private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType); + hnd->offset = offset; + hnd->base = int(base)+offset; + hnd->lockState = lockState; + if(bufferType == BUFFER_TYPE_GPU1) + hnd->phys = m->master_phys + offset; + else + hnd->phys = 0; + *pHandle = hnd; + } + + LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); + + return err; +} + +/*****************************************************************************/ + +static int gralloc_alloc(alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + int align = 4; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + 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_t size = bpr * h; + size_t stride = bpr / bpp; + + int err; + if (usage & GRALLOC_USAGE_HW_FB) { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); + } else { + err = gralloc_alloc_buffer(dev, size, usage, pHandle); + } + if (err < 0) { + return err; + } + + *pStride = stride; + return 0; +} + +static int 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(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + // free this buffer + private_module_t* m = reinterpret_cast( + dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + if (hnd->fd >= 0) { + if(hnd->bufferType == BUFFER_TYPE_PMEM){ + sAllocator.deallocate(hnd->offset); + memset((void *)hnd->base, 0, hnd->size); + } + else { + sGPUAllocator.deallocate(hnd->offset); + memset((void *)hnd->base, 0, hnd->size); + } + } + } + + gralloc_module_t* m = reinterpret_cast( + dev->common.module); + gralloc_unregister_buffer(m, handle); + + close(hnd->fd); + delete hnd; + return 0; +} + +/*****************************************************************************/ + +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. + */ + free(ctx); + } + return 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)) { + gralloc_context_t *dev; + dev = (gralloc_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(module); + dev->device.common.close = gralloc_close; + + dev->device.alloc = gralloc_alloc; + dev->device.free = gralloc_free; + dev->bufferType = BUFFER_TYPE_GPU1; + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h new file mode 100644 index 0000000..e92db19 --- /dev/null +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -0,0 +1,188 @@ +/* + * 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 + +#include + +#if HAVE_ANDROID_OS +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + BUFFER_TYPE_GPU0 = 0, + BUFFER_TYPE_GPU1 = 1, + BUFFER_TYPE_FB = 2, + BUFFER_TYPE_PMEM = 3 +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGESIZE-1)) & ~(PAGESIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +#endif //__cplusplus + +/*****************************************************************************/ + +#ifdef __cplusplus +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; +#endif //__cplusplus +/*****************************************************************************/ + +struct private_handle_t; + +struct private_module_t { + struct gralloc_module_t base; + + struct private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int pmem_master; + void* pmem_master_base; + unsigned long master_phys; + int gpu_master; + void* gpu_master_base; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + + enum { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; +}; + +/*****************************************************************************/ +#ifdef __cplusplus +struct private_handle_t : public native_handle +#else +struct private_handle_t +#endif +{ + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_PMEM = 0x00000002, + }; + + enum { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; + +#ifndef __cplusplus + native_handle nativeHandle; +#endif + + int fd; + int magic; + int flags; + int size; + int offset; + // FIXME: the attributes below should be out-of-line + int base; + int lockState; + int writeOwner; + int bufferType; + int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care + int pid; + +#ifdef __cplusplus + static const int sNumInts = 10; + static const int sNumFds = 1; + static const int sMagic = 0x3141592; + + private_handle_t(int fd, int size, int flags, int type) : + fd(fd), magic(sMagic), flags(flags), size(size), offset(0), + base(0), lockState(0), writeOwner(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts; + numFds = sNumFds; + bufferType = type; + } + ~private_handle_t() { + magic = 0; + } + + bool usesPhysicallyContiguousMemory() { + return (flags & PRIV_FLAGS_USES_PMEM) != 0; + } + + static int validate(const native_handle* h) { + if (!h || h->version != sizeof(native_handle) || + h->numInts!=sNumInts || h->numFds!=sNumFds) { + return -EINVAL; + } + const private_handle_t* hnd = (const private_handle_t*)h; + if (hnd->magic != sMagic) + return -EINVAL; + return 0; + } + + static private_handle_t* dynamicCast(const native_handle* in) { + if (validate(in) == 0) { + return (private_handle_t*) in; + } + return NULL; + } +#endif //__cplusplus + +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp new file mode 100644 index 0000000..1ab70ec --- /dev/null +++ b/libgralloc-qsd8k/mapper.cpp @@ -0,0 +1,239 @@ +/* + * 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 "gralloc_priv.h" + + +// we need this for now because pmem cannot mmap at an offset +#define PMEM_HACK 1 + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* module, + buffer_handle_t handle, + void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + size_t size = hnd->size; +#if PMEM_HACK + size += hnd->offset; +#endif + void* mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + LOGE("Could not mmap %s", strerror(errno)); + return -errno; + } + hnd->base = intptr_t(mappedAddress) + hnd->offset; + //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + // hnd->fd, hnd->offset, hnd->size, mappedAddress); + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + 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; +} + +/*****************************************************************************/ + +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + // In this implementation, we don't need to do anything here + + /* 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 + * 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; + if (hnd->pid != getpid()) { + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + /* + * If the buffer has been mapped during a lock operation, it's time + * to un-map it. It's an error to be here with a locked buffer. + * NOTE: the framebuffer is handled differently and is never unmapped. + */ + + private_handle_t* hnd = (private_handle_t*)handle; + + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "handle %p still locked (state=%08x)", + hnd, hnd->lockState); + + // never unmap buffers that were created in this process + if (hnd->pid != getpid()) { + if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { + gralloc_unmap(module, handle); + } + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + int err = 0; + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + int retry; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_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) { + // already locked for read + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + LOGE("handle %p already locked for read", handle); + return -EBUSY; + } else { + // this is not an error + //LOGD("%p already locked for read... count = %d", + // handle, (current_value & ~(1<<31))); + } + } + + // not currently locked + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + // locking for write + new_value |= private_handle_t::LOCK_STATE_WRITE; + } + new_value++; + + retry = android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState); + } while (retry); + + if (new_value & private_handle_t::LOCK_STATE_WRITE) { + // locking for write, store the tid + hnd->writeOwner = gettid(); + } + + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { + if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { + // we need to map for real + pthread_mutex_t* const lock = &sMapLock; + pthread_mutex_lock(lock); + if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { + err = gralloc_map(module, handle, vaddr); + if (err == 0) { + android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, + (volatile int32_t*)&(hnd->lockState)); + } + } + pthread_mutex_unlock(lock); + } + *vaddr = (void*)hnd->base; + } + + return err; +} + +int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_WRITE) { + // locked for write + if (hnd->writeOwner == gettid()) { + hnd->writeOwner = 0; + new_value &= ~private_handle_t::LOCK_STATE_WRITE; + } + } + + if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { + LOGE("handle %p not locked", handle); + return -EINVAL; + } + + new_value--; + + } while (android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState)); + + return 0; +} From 3ad1a951ac531a1e5764529e0ba01a7a34392ce3 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 12 Aug 2009 22:55:02 -0700 Subject: [PATCH 122/435] gralloc8k: fix partial updates, some cleanups Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 55 +++++++++++++++----------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 0571c0c..d01cdae 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -14,29 +14,21 @@ * limitations under the License. */ -#include - #include - +#include +#include +#include +#include +#include +#include +#include #include #include - #include #include -#include -#include - -#include -#include - -#if HAVE_ANDROID_OS -#include -#endif - #include "gralloc_priv.h" -#include -#include + /*****************************************************************************/ // should be a build option @@ -44,7 +36,6 @@ #define NUM_BUFFERS 2 - enum { PAGE_FLIP = 0x00000001, LOCKED = 0x00000002 @@ -56,7 +47,7 @@ struct fb_context_t { /*****************************************************************************/ -void +static void msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, int x, int y, int w, int h); @@ -95,14 +86,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_handle_t const* hnd = reinterpret_cast(buffer); private_module_t* m = reinterpret_cast( dev->common.module); - + if (m->currentBuffer) { m->base.unlock(&m->base, m->currentBuffer); m->currentBuffer = 0; } if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { - m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 0, 0, m->info.xres, m->info.yres, NULL); @@ -116,14 +106,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) return -errno; } m->currentBuffer = buffer; - } else { // If we can't do the page_flip, just copy the buffer to the front // FIXME: use copybit HAL instead of memcpy - + void* fb_vaddr; void* buffer_vaddr; - + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, 0, 0, m->info.xres, m->info.yres, @@ -135,7 +124,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) &buffer_vaddr); //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); - + msm_copy_buffer(m->framebuffer, m->framebuffer->fd, m->info.xres, m->info.yres, m->info.xoffset, m->info.yoffset, @@ -144,7 +133,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->base.unlock(&m->base, buffer); m->base.unlock(&m->base, m->framebuffer); } - + return 0; } @@ -356,10 +345,8 @@ int fb_device_open(hw_module_t const* module, const char* name, dev->device.common.module = const_cast(module); dev->device.common.close = fb_close; dev->device.setSwapInterval = fb_setSwapInterval; -#if SUPPORTS_UPDATE_ON_DEMAND - dev->device.setUpdateRect = fb_setUpdateRect; -#endif dev->device.post = fb_post; + dev->device.setUpdateRect = 0; private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); @@ -376,6 +363,14 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.minSwapInterval) = 1; const_cast(dev->device.maxSwapInterval) = 1; +#if SUPPORTS_UPDATE_ON_DEMAND + if (m->finfo.reserved[0] == 0x5444 && + m->finfo.reserved[1] == 0x5055) { + dev->device.setUpdateRect = fb_setUpdateRect; + LOGD("UPDATE_ON_DEMAND supported"); + } +#endif + *device = &dev->device.common; } } @@ -384,7 +379,7 @@ int fb_device_open(hw_module_t const* module, const char* name, /* Copy a pmem buffer to the framebuffer */ -void +static void msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, int x, int y, int w, int h) { @@ -405,7 +400,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, blit.req.src.height = height; blit.req.src.offset = 0; blit.req.src.memory_id = priv->fd; - + blit.req.dst.width = width; blit.req.dst.height = height; blit.req.dst.offset = 0; From cbece3c82984b3328fa0c5dee39540307908f5c3 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 7 Aug 2009 15:58:07 -0700 Subject: [PATCH 123/435] gralloc8k: make sure to set the physical address of the framebuffer Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 1 + libgralloc-qsd8k/gralloc.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index d01cdae..af8f1fb 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -301,6 +301,7 @@ int mapFrameBufferLocked(struct private_module_t* module) return -errno; } module->framebuffer->base = intptr_t(vaddr); + module->framebuffer->phys = intptr_t(finfo.smem_start); memset(vaddr, 0, fbSize); return 0; } diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 536d1c4..89d1fe3 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -155,9 +155,10 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, } vaddr += bufferSize; } - + hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); + hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; From 47996717227925e1cac23666abc00e9474269803 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 5 Aug 2009 00:26:21 -0700 Subject: [PATCH 126/435] qsd8k: add gralloc for 8k Signed-off-by: Dima Zavin --- libgralloc-qsd8k/Android.mk | 32 ++ libgralloc-qsd8k/allocator.cpp | 154 ++++++++++ libgralloc-qsd8k/allocator.h | 127 ++++++++ libgralloc-qsd8k/framebuffer.cpp | 422 ++++++++++++++++++++++++++ libgralloc-qsd8k/gralloc.cpp | 492 +++++++++++++++++++++++++++++++ libgralloc-qsd8k/gralloc_priv.h | 188 ++++++++++++ libgralloc-qsd8k/mapper.cpp | 239 +++++++++++++++ 7 files changed, 1654 insertions(+) create mode 100644 libgralloc-qsd8k/Android.mk create mode 100644 libgralloc-qsd8k/allocator.cpp create mode 100644 libgralloc-qsd8k/allocator.h create mode 100644 libgralloc-qsd8k/framebuffer.cpp create mode 100644 libgralloc-qsd8k/gralloc.cpp create mode 100644 libgralloc-qsd8k/gralloc_priv.h create mode 100644 libgralloc-qsd8k/mapper.cpp diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk new file mode 100644 index 0000000..9bae065 --- /dev/null +++ b/libgralloc-qsd8k/Android.mk @@ -0,0 +1,32 @@ +# 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/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils + +LOCAL_SRC_FILES := \ + allocator.cpp \ + gralloc.cpp \ + framebuffer.cpp \ + mapper.cpp + +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" +include $(BUILD_SHARED_LIBRARY) diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp new file mode 100644 index 0000000..f901741 --- /dev/null +++ b/libgralloc-qsd8k/allocator.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2009 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 "allocator.h" + + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +{ + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Locker::Autolock _l(mLock); + ssize_t offset = alloc(size, flags); + return offset; +} + +ssize_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Locker::Autolock _l(mLock); + chunk_t const * const freed = dealloc(offset); + if (freed) { + return 0; + } + return -ENOENT; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + return -ENOMEM; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + #ifndef NDEBUG + if (!freed->free) { + dump_l("dealloc (!freed->free)"); + } + #endif + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h new file mode 100644 index 0000000..dfb06f6 --- /dev/null +++ b/libgralloc-qsd8k/allocator.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009 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_ALLOCATOR_H_ +#define GRALLOC_ALLOCATOR_H_ + +#include +#include + +#include "gralloc_priv.h" + +// ---------------------------------------------------------------------------- + +/* + * A simple templatized doubly linked-list implementation + */ + +template +class LinkedList +{ + NODE* mFirst; + NODE* mLast; + +public: + LinkedList() : mFirst(0), mLast(0) { } + bool isEmpty() const { return mFirst == 0; } + NODE const* head() const { return mFirst; } + NODE* head() { return mFirst; } + NODE const* tail() const { return mLast; } + NODE* tail() { return mLast; } + + void insertAfter(NODE* node, NODE* newNode) { + newNode->prev = node; + newNode->next = node->next; + if (node->next == 0) mLast = newNode; + else node->next->prev = newNode; + node->next = newNode; + } + + void insertBefore(NODE* node, NODE* newNode) { + newNode->prev = node->prev; + newNode->next = node; + if (node->prev == 0) mFirst = newNode; + else node->prev->next = newNode; + node->prev = newNode; + } + + void insertHead(NODE* newNode) { + if (mFirst == 0) { + mFirst = mLast = newNode; + newNode->prev = newNode->next = 0; + } else { + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; + } + } + + void insertTail(NODE* newNode) { + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } + } + + NODE* remove(NODE* node) { + if (node->prev == 0) mFirst = node->next; + else node->prev->next = node->next; + if (node->next == 0) mLast = node->prev; + else node->next->prev = node->prev; + return node; + } +}; + +class SimpleBestFitAllocator +{ +public: + + SimpleBestFitAllocator(size_t size); + virtual ~SimpleBestFitAllocator(); + + virtual size_t allocate(size_t size, uint32_t flags = 0); + virtual ssize_t deallocate(size_t offset); + virtual size_t size() const; + +private: + struct chunk_t { + chunk_t(size_t start, size_t size) + : start(start), size(size), free(1), prev(0), next(0) { + } + size_t start; + size_t size : 28; + int free : 4; + mutable chunk_t* prev; + mutable chunk_t* next; + }; + + ssize_t alloc(size_t size, uint32_t flags); + chunk_t* dealloc(size_t start); + + static const int kMemoryAlign; + mutable Locker mLock; + LinkedList mList; + size_t mHeapSize; +}; + + +#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp new file mode 100644 index 0000000..0571c0c --- /dev/null +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -0,0 +1,422 @@ +/* + * 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 + +#if HAVE_ANDROID_OS +#include +#endif + +#include "gralloc_priv.h" +#include +#include +/*****************************************************************************/ + +// should be a build option +#define SUPPORTS_UPDATE_ON_DEMAND 1 + +#define NUM_BUFFERS 2 + + +enum { + PAGE_FLIP = 0x00000001, + LOCKED = 0x00000002 +}; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h); + +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_setUpdateRect(struct framebuffer_device_t* dev, + int l, int t, int w, int h) +{ + if (((w|h) <= 0) || ((l|t)<0)) + return -EINVAL; + + fb_context_t* ctx = (fb_context_t*)dev; + private_module_t* m = reinterpret_cast( + dev->common.module); + m->info.reserved[0] = 0x54445055; // "UPDT"; + m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); + m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); + 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 = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast( + dev->common.module); + + if (m->currentBuffer) { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + + m->base.lock(&m->base, buffer, + private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + + } else { + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + + void* fb_vaddr; + void* buffer_vaddr; + + 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, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + msm_copy_buffer(m->framebuffer, m->framebuffer->fd, + m->info.xres, m->info.yres, + 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); + } + + return 0; +} + +/*****************************************************************************/ + +int mapFrameBufferLocked(struct private_module_t* module) +{ + // already initialized... + if (module->framebuffer) { + return 0; + } + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + + /* + * 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; + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) { + // bleagh, bad info from the driver + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + LOGI( "using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length + ); + + LOGI( "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps + ); + + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + + int err; + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, + private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_FB); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + LOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + module->framebuffer->base = intptr_t(vaddr); + memset(vaddr, 0, fbSize); + return 0; +} + +static int mapFrameBuffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = mapFrameBufferLocked(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; + if (ctx) { + free(ctx); + } + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { + + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) + return status; + + /* 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; +#if SUPPORTS_UPDATE_ON_DEMAND + dev->device.setUpdateRect = fb_setUpdateRect; +#endif + dev->device.post = fb_post; + + private_module_t* m = (private_module_t*)module; + status = mapFrameBuffer(m); + if (status >= 0) { + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast(dev->device.flags) = 0; + const_cast(dev->device.width) = m->info.xres; + const_cast(dev->device.height) = m->info.yres; + const_cast(dev->device.stride) = 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 status; +} + +/* Copy a pmem buffer to the framebuffer */ + +void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h) +{ + struct { + unsigned int count; + mdp_blit_req req; + } blit; + private_handle_t *priv = (private_handle_t*) handle; + + memset(&blit, 0, sizeof(blit)); + blit.count = 1; + + blit.req.flags = 0; + blit.req.alpha = 0xff; + blit.req.transp_mask = 0xffffffff; + + blit.req.src.width = width; + blit.req.src.height = height; + blit.req.src.offset = 0; + blit.req.src.memory_id = priv->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.format = MDP_RGB_565; + + blit.req.src_rect.x = blit.req.dst_rect.x = x; + blit.req.src_rect.y = blit.req.dst_rect.y = y; + blit.req.src_rect.w = blit.req.dst_rect.w = w; + blit.req.src_rect.h = blit.req.dst_rect.h = h; + + if (ioctl(fd, MSMFB_BLIT, &blit)) + LOGE("MSMFB_BLIT failed = %d", -errno); +} diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp new file mode 100644 index 0000000..536d1c4 --- /dev/null +++ b/libgralloc-qsd8k/gralloc.cpp @@ -0,0 +1,492 @@ +/* + * 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 +#include + +#include "gralloc_priv.h" +#include "allocator.h" + +#if HAVE_ANDROID_OS +#include +#endif + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ + int bufferType; +}; + +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); + +/*****************************************************************************/ + +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, + }, + framebuffer: 0, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: 0, + pmem_master: -1, + pmem_master_base: 0, + master_phys: 0, + gpu_master: -1, + gpu_master_base: 0 +}; + +/*****************************************************************************/ + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + + // allocate the framebuffer + if (m->framebuffer == NULL) { + // initialize the framebuffer, the framebuffer is mapped once + // and forever. + int err = 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(dev, bufferSize, newUsage, pHandle); + } + + if (bufferMask >= ((1LU<framebuffer->base); + private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, + private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_FB); + + // find a free slot + for (uint32_t i=0 ; ibufferMask |= (1LU<base = vaddr; + hnd->offset = vaddr - intptr_t(m->framebuffer->base); + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); + pthread_mutex_unlock(&m->lock); + return err; +} + +static SimpleBestFitAllocator sAllocator(10*1024*1024); +static SimpleBestFitAllocator sGPUAllocator(3*1024*1024); + +static int init_pmem_area(private_module_t* m, int type) +{ + int err = 0; + int master_fd = -1; + size_t master_heap_size; + if(type == BUFFER_TYPE_GPU0) + { + master_fd = open("/dev/pmem_gpu0", O_RDWR, 0); + master_heap_size = sGPUAllocator.size(); + } + else if(type == BUFFER_TYPE_GPU1) + { + master_fd = open("/dev/pmem_gpu1", O_RDWR, 0); + master_heap_size = sGPUAllocator.size(); + } + else if (type == BUFFER_TYPE_PMEM) + { + master_fd = open("/dev/pmem", O_RDWR, 0); + master_heap_size = sAllocator.size(); + } + + if (master_fd >= 0) { + void* base = mmap(0, master_heap_size, + PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + if (base == MAP_FAILED) { + LOGE("Enter init_pmem_area error: %d", -errno); + err = -errno; + base = 0; + close(master_fd); + master_fd = -1; + } + if(type == BUFFER_TYPE_PMEM){ + m->pmem_master = master_fd; + m->pmem_master_base = base; + } + else + { + m->gpu_master = master_fd; + m->gpu_master_base = base; + pmem_region region; + err = ioctl(m->gpu_master, PMEM_GET_PHYS, ®ion); + if(err < 0) + { + LOGE("init pmem: master ioctl failed %d", -errno); + } + else + { + m->master_phys = (unsigned long)region.offset; + } + } + } else { + err = -errno; + } + return err; +} + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + int err = 0; + int flags = 0; + + int fd = -1; + void* base = 0; + int offset = 0; + int lockState = 0; + + private_module_t* m = reinterpret_cast( + dev->common.module); + + gralloc_context_t *context = (gralloc_context_t *) dev; + int bufferType; + + size = roundUpToPageSize(size); + + if (usage & (GRALLOC_USAGE_HW_2D | GRALLOC_USAGE_HW_RENDER)) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; + bufferType = context->bufferType; + } + else 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; + bufferType = BUFFER_TYPE_PMEM; + } + + int phys = 0; + if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { +try_ashmem: + fd = ashmem_create_region("Buffer", size); + if (fd < 0) { + LOGE("couldn't create ashmem (%s)", strerror(-errno)); + err = -errno; + } + } else { + + int master_fd = -1; + if(bufferType == BUFFER_TYPE_PMEM) + { + master_fd = m->pmem_master; + } + else + { + master_fd = m->gpu_master; + } + + pthread_mutex_lock(&m->lock); + if (master_fd == -1) { + err = init_pmem_area(m, bufferType); + } + pthread_mutex_unlock(&m->lock); + + if(bufferType == BUFFER_TYPE_PMEM) + { + master_fd = m->pmem_master; + } + else + { + master_fd = m->gpu_master; + } + + if (master_fd >= 0) { + // PMEM buffers are always mmapped + if(bufferType == BUFFER_TYPE_PMEM) + { + base = m->pmem_master_base; + offset = sAllocator.allocate(size); + } + else + { + base = m->gpu_master_base; + offset = sGPUAllocator.allocate(size); + } + + lockState |= private_handle_t::LOCK_STATE_MAPPED; + + if (offset < 0) { + err = -ENOMEM; + } else { + if(bufferType == BUFFER_TYPE_GPU0) + fd = open("/dev/pmem_gpu0", O_RDWR, 0); + else if(bufferType == BUFFER_TYPE_GPU1) + fd = open("/dev/pmem_gpu1", O_RDWR, 0); + else if (bufferType == BUFFER_TYPE_PMEM) + fd = open("/dev/pmem", O_RDWR, 0); + + err = ioctl(fd, PMEM_CONNECT, master_fd); + if (err < 0) { + err = -errno; + } else { + struct pmem_region sub = { offset, size }; + err = ioctl(fd, PMEM_MAP, &sub); + } + + if (err < 0) { + close(fd); + if(bufferType == BUFFER_TYPE_PMEM) + sAllocator.deallocate(offset); + else + sGPUAllocator.deallocate(offset); + fd = -1; + } + //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); + } + } else { + if ((usage & GRALLOC_USAGE_HW_2D) == 0) { + // the caller didn't request PMEM, so we can try something else + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + err = 0; + goto try_ashmem; + } else { + LOGE("couldn't open pmem (%s)", strerror(-errno)); + } + } + } + + if (err == 0) { + private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType); + hnd->offset = offset; + hnd->base = int(base)+offset; + hnd->lockState = lockState; + if(bufferType == BUFFER_TYPE_GPU1) + hnd->phys = m->master_phys + offset; + else + hnd->phys = 0; + *pHandle = hnd; + } + + LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); + + return err; +} + +/*****************************************************************************/ + +static int gralloc_alloc(alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + int align = 4; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + 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_t size = bpr * h; + size_t stride = bpr / bpp; + + int err; + if (usage & GRALLOC_USAGE_HW_FB) { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); + } else { + err = gralloc_alloc_buffer(dev, size, usage, pHandle); + } + if (err < 0) { + return err; + } + + *pStride = stride; + return 0; +} + +static int 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(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + // free this buffer + private_module_t* m = reinterpret_cast( + dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + if (hnd->fd >= 0) { + if(hnd->bufferType == BUFFER_TYPE_PMEM){ + sAllocator.deallocate(hnd->offset); + memset((void *)hnd->base, 0, hnd->size); + } + else { + sGPUAllocator.deallocate(hnd->offset); + memset((void *)hnd->base, 0, hnd->size); + } + } + } + + gralloc_module_t* m = reinterpret_cast( + dev->common.module); + gralloc_unregister_buffer(m, handle); + + close(hnd->fd); + delete hnd; + return 0; +} + +/*****************************************************************************/ + +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. + */ + free(ctx); + } + return 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)) { + gralloc_context_t *dev; + dev = (gralloc_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(module); + dev->device.common.close = gralloc_close; + + dev->device.alloc = gralloc_alloc; + dev->device.free = gralloc_free; + dev->bufferType = BUFFER_TYPE_GPU1; + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h new file mode 100644 index 0000000..e92db19 --- /dev/null +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -0,0 +1,188 @@ +/* + * 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 + +#include + +#if HAVE_ANDROID_OS +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + BUFFER_TYPE_GPU0 = 0, + BUFFER_TYPE_GPU1 = 1, + BUFFER_TYPE_FB = 2, + BUFFER_TYPE_PMEM = 3 +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGESIZE-1)) & ~(PAGESIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +#endif //__cplusplus + +/*****************************************************************************/ + +#ifdef __cplusplus +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; +#endif //__cplusplus +/*****************************************************************************/ + +struct private_handle_t; + +struct private_module_t { + struct gralloc_module_t base; + + struct private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int pmem_master; + void* pmem_master_base; + unsigned long master_phys; + int gpu_master; + void* gpu_master_base; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + + enum { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; +}; + +/*****************************************************************************/ +#ifdef __cplusplus +struct private_handle_t : public native_handle +#else +struct private_handle_t +#endif +{ + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_PMEM = 0x00000002, + }; + + enum { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; + +#ifndef __cplusplus + native_handle nativeHandle; +#endif + + int fd; + int magic; + int flags; + int size; + int offset; + // FIXME: the attributes below should be out-of-line + int base; + int lockState; + int writeOwner; + int bufferType; + int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care + int pid; + +#ifdef __cplusplus + static const int sNumInts = 10; + static const int sNumFds = 1; + static const int sMagic = 0x3141592; + + private_handle_t(int fd, int size, int flags, int type) : + fd(fd), magic(sMagic), flags(flags), size(size), offset(0), + base(0), lockState(0), writeOwner(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts; + numFds = sNumFds; + bufferType = type; + } + ~private_handle_t() { + magic = 0; + } + + bool usesPhysicallyContiguousMemory() { + return (flags & PRIV_FLAGS_USES_PMEM) != 0; + } + + static int validate(const native_handle* h) { + if (!h || h->version != sizeof(native_handle) || + h->numInts!=sNumInts || h->numFds!=sNumFds) { + return -EINVAL; + } + const private_handle_t* hnd = (const private_handle_t*)h; + if (hnd->magic != sMagic) + return -EINVAL; + return 0; + } + + static private_handle_t* dynamicCast(const native_handle* in) { + if (validate(in) == 0) { + return (private_handle_t*) in; + } + return NULL; + } +#endif //__cplusplus + +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp new file mode 100644 index 0000000..1ab70ec --- /dev/null +++ b/libgralloc-qsd8k/mapper.cpp @@ -0,0 +1,239 @@ +/* + * 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 "gralloc_priv.h" + + +// we need this for now because pmem cannot mmap at an offset +#define PMEM_HACK 1 + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* module, + buffer_handle_t handle, + void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + size_t size = hnd->size; +#if PMEM_HACK + size += hnd->offset; +#endif + void* mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + LOGE("Could not mmap %s", strerror(errno)); + return -errno; + } + hnd->base = intptr_t(mappedAddress) + hnd->offset; + //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + // hnd->fd, hnd->offset, hnd->size, mappedAddress); + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + 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; +} + +/*****************************************************************************/ + +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + // In this implementation, we don't need to do anything here + + /* 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 + * 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; + if (hnd->pid != getpid()) { + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + /* + * If the buffer has been mapped during a lock operation, it's time + * to un-map it. It's an error to be here with a locked buffer. + * NOTE: the framebuffer is handled differently and is never unmapped. + */ + + private_handle_t* hnd = (private_handle_t*)handle; + + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "handle %p still locked (state=%08x)", + hnd, hnd->lockState); + + // never unmap buffers that were created in this process + if (hnd->pid != getpid()) { + if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { + gralloc_unmap(module, handle); + } + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + int err = 0; + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + int retry; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_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) { + // already locked for read + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + LOGE("handle %p already locked for read", handle); + return -EBUSY; + } else { + // this is not an error + //LOGD("%p already locked for read... count = %d", + // handle, (current_value & ~(1<<31))); + } + } + + // not currently locked + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + // locking for write + new_value |= private_handle_t::LOCK_STATE_WRITE; + } + new_value++; + + retry = android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState); + } while (retry); + + if (new_value & private_handle_t::LOCK_STATE_WRITE) { + // locking for write, store the tid + hnd->writeOwner = gettid(); + } + + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { + if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { + // we need to map for real + pthread_mutex_t* const lock = &sMapLock; + pthread_mutex_lock(lock); + if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { + err = gralloc_map(module, handle, vaddr); + if (err == 0) { + android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, + (volatile int32_t*)&(hnd->lockState)); + } + } + pthread_mutex_unlock(lock); + } + *vaddr = (void*)hnd->base; + } + + return err; +} + +int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_WRITE) { + // locked for write + if (hnd->writeOwner == gettid()) { + hnd->writeOwner = 0; + new_value &= ~private_handle_t::LOCK_STATE_WRITE; + } + } + + if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { + LOGE("handle %p not locked", handle); + return -EINVAL; + } + + new_value--; + + } while (android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState)); + + return 0; +} From 0f1f4c1ac8992a525cbfa2d0d59cfe0a440a7127 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 12 Aug 2009 22:55:02 -0700 Subject: [PATCH 127/435] gralloc8k: fix partial updates, some cleanups Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 55 +++++++++++++++----------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 0571c0c..d01cdae 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -14,29 +14,21 @@ * limitations under the License. */ -#include - #include - +#include +#include +#include +#include +#include +#include +#include #include #include - #include #include -#include -#include - -#include -#include - -#if HAVE_ANDROID_OS -#include -#endif - #include "gralloc_priv.h" -#include -#include + /*****************************************************************************/ // should be a build option @@ -44,7 +36,6 @@ #define NUM_BUFFERS 2 - enum { PAGE_FLIP = 0x00000001, LOCKED = 0x00000002 @@ -56,7 +47,7 @@ struct fb_context_t { /*****************************************************************************/ -void +static void msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, int x, int y, int w, int h); @@ -95,14 +86,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_handle_t const* hnd = reinterpret_cast(buffer); private_module_t* m = reinterpret_cast( dev->common.module); - + if (m->currentBuffer) { m->base.unlock(&m->base, m->currentBuffer); m->currentBuffer = 0; } if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { - m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 0, 0, m->info.xres, m->info.yres, NULL); @@ -116,14 +106,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) return -errno; } m->currentBuffer = buffer; - } else { // If we can't do the page_flip, just copy the buffer to the front // FIXME: use copybit HAL instead of memcpy - + void* fb_vaddr; void* buffer_vaddr; - + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, 0, 0, m->info.xres, m->info.yres, @@ -135,7 +124,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) &buffer_vaddr); //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); - + msm_copy_buffer(m->framebuffer, m->framebuffer->fd, m->info.xres, m->info.yres, m->info.xoffset, m->info.yoffset, @@ -144,7 +133,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->base.unlock(&m->base, buffer); m->base.unlock(&m->base, m->framebuffer); } - + return 0; } @@ -356,10 +345,8 @@ int fb_device_open(hw_module_t const* module, const char* name, dev->device.common.module = const_cast(module); dev->device.common.close = fb_close; dev->device.setSwapInterval = fb_setSwapInterval; -#if SUPPORTS_UPDATE_ON_DEMAND - dev->device.setUpdateRect = fb_setUpdateRect; -#endif dev->device.post = fb_post; + dev->device.setUpdateRect = 0; private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); @@ -376,6 +363,14 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.minSwapInterval) = 1; const_cast(dev->device.maxSwapInterval) = 1; +#if SUPPORTS_UPDATE_ON_DEMAND + if (m->finfo.reserved[0] == 0x5444 && + m->finfo.reserved[1] == 0x5055) { + dev->device.setUpdateRect = fb_setUpdateRect; + LOGD("UPDATE_ON_DEMAND supported"); + } +#endif + *device = &dev->device.common; } } @@ -384,7 +379,7 @@ int fb_device_open(hw_module_t const* module, const char* name, /* Copy a pmem buffer to the framebuffer */ -void +static void msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, int x, int y, int w, int h) { @@ -405,7 +400,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, blit.req.src.height = height; blit.req.src.offset = 0; blit.req.src.memory_id = priv->fd; - + blit.req.dst.width = width; blit.req.dst.height = height; blit.req.dst.offset = 0; From 0c7b6963a6ee2b9d89fc84603ecb9cf67d2c23cb Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 7 Aug 2009 15:58:07 -0700 Subject: [PATCH 128/435] gralloc8k: make sure to set the physical address of the framebuffer Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 1 + libgralloc-qsd8k/gralloc.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index d01cdae..af8f1fb 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -301,6 +301,7 @@ int mapFrameBufferLocked(struct private_module_t* module) return -errno; } module->framebuffer->base = intptr_t(vaddr); + module->framebuffer->phys = intptr_t(finfo.smem_start); memset(vaddr, 0, fbSize); return 0; } diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 536d1c4..89d1fe3 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -155,9 +155,10 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, } vaddr += bufferSize; } - + hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); + hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; From 78087b26642bc3a55330de42732e5792f9ad3500 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 18 Aug 2009 18:39:57 -0700 Subject: [PATCH 131/435] make gralloc-qsd8k closer to the generic gralloc so it's easier to maintain --- libgralloc-qsd8k/allocator.cpp | 28 ++- libgralloc-qsd8k/allocator.h | 16 +- libgralloc-qsd8k/framebuffer.cpp | 39 ++- libgralloc-qsd8k/gr.h | 63 +++++ libgralloc-qsd8k/gralloc.cpp | 398 +++++++++++++++++++------------ libgralloc-qsd8k/gralloc_priv.h | 94 ++------ libgralloc-qsd8k/mapper.cpp | 55 ++++- 7 files changed, 437 insertions(+), 256 deletions(-) create mode 100644 libgralloc-qsd8k/gr.h diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp index f901741..4dad6a1 100644 --- a/libgralloc-qsd8k/allocator.cpp +++ b/libgralloc-qsd8k/allocator.cpp @@ -22,13 +22,15 @@ // align all the memory blocks on a cache-line boundary const int SimpleBestFitAllocator::kMemoryAlign = 32; -SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +SimpleBestFitAllocator::SimpleBestFitAllocator() + : mHeapSize(0) { - size_t pagesize = getpagesize(); - mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); +} - chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); - mList.insertHead(node); +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) + : mHeapSize(0) +{ + setSize(size); } SimpleBestFitAllocator::~SimpleBestFitAllocator() @@ -38,14 +40,27 @@ SimpleBestFitAllocator::~SimpleBestFitAllocator() } } +ssize_t SimpleBestFitAllocator::setSize(size_t size) +{ + Locker::Autolock _l(mLock); + if (mHeapSize != 0) return -EINVAL; + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); + return size; +} + + size_t SimpleBestFitAllocator::size() const { return mHeapSize; } -size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) { Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; ssize_t offset = alloc(size, flags); return offset; } @@ -53,6 +68,7 @@ size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) ssize_t SimpleBestFitAllocator::deallocate(size_t offset) { Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; chunk_t const * const freed = dealloc(offset); if (freed) { return 0; diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h index dfb06f6..b0d89e9 100644 --- a/libgralloc-qsd8k/allocator.h +++ b/libgralloc-qsd8k/allocator.h @@ -21,7 +21,7 @@ #include #include -#include "gralloc_priv.h" +#include "gr.h" // ---------------------------------------------------------------------------- @@ -95,12 +95,15 @@ class SimpleBestFitAllocator { public: - SimpleBestFitAllocator(size_t size); - virtual ~SimpleBestFitAllocator(); + SimpleBestFitAllocator(); + SimpleBestFitAllocator(size_t size); + ~SimpleBestFitAllocator(); - virtual size_t allocate(size_t size, uint32_t flags = 0); - virtual ssize_t deallocate(size_t offset); - virtual size_t size() const; + ssize_t setSize(size_t size); + + ssize_t allocate(size_t size, uint32_t flags = 0); + ssize_t deallocate(size_t offset); + size_t size() const; private: struct chunk_t { @@ -123,5 +126,4 @@ private: size_t mHeapSize; }; - #endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index af8f1fb..5d3fc7d 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -14,28 +14,40 @@ * limitations under the License. */ -#include -#include -#include -#include -#include #include -#include -#include + +#include + #include #include + #include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + #include "gralloc_priv.h" +#include "gr.h" /*****************************************************************************/ // should be a build option -#define SUPPORTS_UPDATE_ON_DEMAND 1 +#define SUPPORTS_UPDATE_ON_DEMAND 0 +// numbers of buffers for page flipping #define NUM_BUFFERS 2 + enum { PAGE_FLIP = 0x00000001, LOCKED = 0x00000002 @@ -86,13 +98,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_handle_t const* hnd = reinterpret_cast(buffer); private_module_t* m = reinterpret_cast( dev->common.module); - + if (m->currentBuffer) { m->base.unlock(&m->base, m->currentBuffer); m->currentBuffer = 0; } if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 0, 0, m->info.xres, m->info.yres, NULL); @@ -106,13 +119,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) return -errno; } m->currentBuffer = buffer; + } else { // If we can't do the page_flip, just copy the buffer to the front // FIXME: use copybit HAL instead of memcpy - + void* fb_vaddr; void* buffer_vaddr; - + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, 0, 0, m->info.xres, m->info.yres, @@ -290,7 +304,7 @@ 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(dup(fd), fbSize, - private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_FB); + private_handle_t::PRIV_FLAGS_USES_PMEM); module->numBuffers = info.yres_virtual / info.yres; module->bufferMask = 0; @@ -330,7 +344,6 @@ int fb_device_open(hw_module_t const* module, const char* name, { int status = -EINVAL; if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { - alloc_device_t* gralloc_device; status = gralloc_open(module, &gralloc_device); if (status < 0) diff --git a/libgralloc-qsd8k/gr.h b/libgralloc-qsd8k/gr.h new file mode 100644 index 0000000..1775bfa --- /dev/null +++ b/libgralloc-qsd8k/gr.h @@ -0,0 +1,63 @@ +/* + * 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 GR_H_ +#define GR_H_ + +#include +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include +#else +# include +#endif +#include +#include +#include +#include +#include + +#include + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); + +/*****************************************************************************/ + +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; + +#endif /* GR_H_ */ diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 89d1fe3..d9f2c7b 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -41,10 +43,16 @@ /*****************************************************************************/ +#define ALLOCATORREGION_RESERVED_SIZE (3<<20) + +static SimpleBestFitAllocator sAllocator; +static SimpleBestFitAllocator sAllocatorGPU(ALLOCATORREGION_RESERVED_SIZE); + +/*****************************************************************************/ + struct gralloc_context_t { alloc_device_t device; /* our private data here */ - int bufferType; }; static int gralloc_alloc_buffer(alloc_device_t* dev, @@ -103,8 +111,8 @@ struct private_module_t HAL_MODULE_INFO_SYM = { pmem_master: -1, pmem_master_base: 0, master_phys: 0, - gpu_master: -1, - gpu_master_base: 0 + gpu: -1, + gpu_base: 0 }; /*****************************************************************************/ @@ -145,7 +153,7 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, intptr_t vaddr = intptr_t(m->framebuffer->base); private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, private_handle_t::PRIV_FLAGS_USES_PMEM | - private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_FB); + private_handle_t::PRIV_FLAGS_FRAMEBUFFER); // find a free slot for (uint32_t i=0 ; ibase = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); - hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; @@ -175,65 +182,116 @@ static int gralloc_alloc_framebuffer(alloc_device_t* dev, return err; } -static SimpleBestFitAllocator sAllocator(10*1024*1024); -static SimpleBestFitAllocator sGPUAllocator(3*1024*1024); -static int init_pmem_area(private_module_t* m, int type) +static int init_pmem_area_locked(private_module_t* m) { int err = 0; - int master_fd = -1; - size_t master_heap_size; - if(type == BUFFER_TYPE_GPU0) - { - master_fd = open("/dev/pmem_gpu0", O_RDWR, 0); - master_heap_size = sGPUAllocator.size(); - } - else if(type == BUFFER_TYPE_GPU1) - { - master_fd = open("/dev/pmem_gpu1", O_RDWR, 0); - master_heap_size = sGPUAllocator.size(); - } - else if (type == BUFFER_TYPE_PMEM) - { - master_fd = open("/dev/pmem", O_RDWR, 0); - master_heap_size = sAllocator.size(); - } - + int master_fd = open("/dev/pmem", O_RDWR, 0); if (master_fd >= 0) { - void* base = mmap(0, master_heap_size, + + size_t size; + pmem_region region; + if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { + LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode"); + size = 8<<20; // 8 MiB + } else { + size = region.len; + } + sAllocator.setSize(size); + + void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); if (base == MAP_FAILED) { - LOGE("Enter init_pmem_area error: %d", -errno); err = -errno; base = 0; close(master_fd); master_fd = -1; } - if(type == BUFFER_TYPE_PMEM){ - m->pmem_master = master_fd; - m->pmem_master_base = base; - } - else - { - m->gpu_master = master_fd; - m->gpu_master_base = base; - pmem_region region; - err = ioctl(m->gpu_master, PMEM_GET_PHYS, ®ion); - if(err < 0) - { - LOGE("init pmem: master ioctl failed %d", -errno); - } - else - { - m->master_phys = (unsigned long)region.offset; - } - } + m->pmem_master = master_fd; + m->pmem_master_base = base; } else { err = -errno; } return err; } +static int init_pmem_area(private_module_t* m) +{ + pthread_mutex_lock(&m->lock); + int err = m->pmem_master; + if (err == -1) { + // first time, try to initialize pmem + err = init_pmem_area_locked(m); + if (err) { + m->pmem_master = err; + } + } else if (err < 0) { + // pmem couldn't be initialized, never use it + } else { + // pmem OK + err = 0; + } + pthread_mutex_unlock(&m->lock); + return err; +} + +static int init_gpu_area_locked(private_module_t* m) +{ + int err = 0; + int gpu = open("/dev/pmem_gpu1", O_RDWR, 0); + LOGE_IF(gpu<0, "could not open /dev/pmem_gpu1 (%s)", strerror(errno)); + if (gpu >= 0) { + size_t size = sAllocatorGPU.size(); + void* base = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, gpu, 0); + + if (base == MAP_FAILED) { + LOGE("mmap /dev/pmem_gpu1 (%s)", strerror(errno)); + err = -errno; + base = 0; + close(gpu); + gpu = -1; + } else { + pmem_region region; + err = ioctl(gpu, PMEM_GET_PHYS, ®ion); + if(err < 0) { + LOGE("init pmem: master ioctl failed %d", -errno); + } else { + m->master_phys = (unsigned long)region.offset; + } + } + + m->gpu = gpu; + m->gpu_base = base; + + } else { + err = -errno; + m->gpu = 0; + m->gpu_base = 0; + } + return err; +} + +static int init_gpu_area(private_module_t* m) +{ + pthread_mutex_lock(&m->lock); + int err = m->gpu; + if (err == -1) { + // first time, try to initialize gpu + err = init_gpu_area_locked(m); + if (err) { + m->gpu = err; + } + } else if (err < 0) { + // gpu couldn't be initialized, never use it + } else { + // gpu OK + err = 0; + } + pthread_mutex_unlock(&m->lock); + return err; +} + static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { @@ -241,105 +299,66 @@ static int gralloc_alloc_buffer(alloc_device_t* dev, int flags = 0; int fd = -1; + int gpu_fd = -1; void* base = 0; int offset = 0; int lockState = 0; - - private_module_t* m = reinterpret_cast( - dev->common.module); - - gralloc_context_t *context = (gralloc_context_t *) dev; - int bufferType; size = roundUpToPageSize(size); - if (usage & (GRALLOC_USAGE_HW_2D | GRALLOC_USAGE_HW_RENDER)) { - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - bufferType = context->bufferType; - } - else if (usage & GRALLOC_USAGE_HW_TEXTURE) { + 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; - bufferType = BUFFER_TYPE_PMEM; + } + + if (usage & GRALLOC_USAGE_HW_2D) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } - int phys = 0; if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { try_ashmem: - fd = ashmem_create_region("Buffer", size); + fd = ashmem_create_region("gralloc-buffer", size); if (fd < 0) { - LOGE("couldn't create ashmem (%s)", strerror(-errno)); + LOGE("couldn't create ashmem (%s)", strerror(errno)); err = -errno; } - } else { - - int master_fd = -1; - if(bufferType == BUFFER_TYPE_PMEM) - { - master_fd = m->pmem_master; - } - else - { - master_fd = m->gpu_master; - } + } else if ((usage & GRALLOC_USAGE_HW_RENDER) == 0) { + private_module_t* m = reinterpret_cast( + dev->common.module); - pthread_mutex_lock(&m->lock); - if (master_fd == -1) { - err = init_pmem_area(m, bufferType); - } - pthread_mutex_unlock(&m->lock); - - if(bufferType == BUFFER_TYPE_PMEM) - { - master_fd = m->pmem_master; - } - else - { - master_fd = m->gpu_master; - } - - if (master_fd >= 0) { + err = init_pmem_area(m); + if (err == 0) { // PMEM buffers are always mmapped - if(bufferType == BUFFER_TYPE_PMEM) - { - base = m->pmem_master_base; - offset = sAllocator.allocate(size); - } - else - { - base = m->gpu_master_base; - offset = sGPUAllocator.allocate(size); - } - + base = m->pmem_master_base; lockState |= private_handle_t::LOCK_STATE_MAPPED; + offset = sAllocator.allocate(size); if (offset < 0) { + // no more pmem memory err = -ENOMEM; } else { - if(bufferType == BUFFER_TYPE_GPU0) - fd = open("/dev/pmem_gpu0", O_RDWR, 0); - else if(bufferType == BUFFER_TYPE_GPU1) - fd = open("/dev/pmem_gpu1", O_RDWR, 0); - else if (bufferType == BUFFER_TYPE_PMEM) - fd = open("/dev/pmem", O_RDWR, 0); + struct pmem_region sub = { offset, size }; + + // now create the "sub-heap" + fd = open("/dev/pmem", O_RDWR, 0); + err = fd < 0 ? fd : 0; + + // and connect to it + if (err == 0) + err = ioctl(fd, PMEM_CONNECT, m->pmem_master); + + // and make it available to the client process + if (err == 0) + err = ioctl(fd, PMEM_MAP, &sub); - err = ioctl(fd, PMEM_CONNECT, master_fd); if (err < 0) { err = -errno; - } else { - struct pmem_region sub = { offset, size }; - err = ioctl(fd, PMEM_MAP, &sub); - } - - if (err < 0) { close(fd); - if(bufferType == BUFFER_TYPE_PMEM) - sAllocator.deallocate(offset); - else - sGPUAllocator.deallocate(offset); + sAllocator.deallocate(offset); fd = -1; } + memset((char*)base + offset, 0, size); //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); } } else { @@ -349,20 +368,51 @@ try_ashmem: err = 0; goto try_ashmem; } else { - LOGE("couldn't open pmem (%s)", strerror(-errno)); + LOGE("couldn't open pmem (%s)", strerror(errno)); } - } + } + } else { + // looks like we want 3D... + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + flags |= private_handle_t::PRIV_FLAGS_USES_GPU; + + private_module_t* m = reinterpret_cast( + dev->common.module); + + err = init_gpu_area(m); + if (err == 0) { + // GPU buffers are always mmapped + base = m->gpu_base; + lockState |= private_handle_t::LOCK_STATE_MAPPED; + offset = sAllocatorGPU.allocate(size); + if (offset < 0) { + // no more pmem memory + err = -ENOMEM; + } else { + LOGD("allocating GPU size=%d, offset=%d", size, offset); + fd = open("/dev/null", O_RDONLY); // just so marshalling doesn't fail + gpu_fd = m->gpu; + memset((char*)base + offset, 0, size); + } + } else { + // not enough memory, try ashmem + flags &= ~private_handle_t::PRIV_FLAGS_USES_GPU; + err = 0; + goto try_ashmem; + } } if (err == 0) { - private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType); + private_handle_t* hnd = new private_handle_t(fd, size, flags); hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; - if(bufferType == BUFFER_TYPE_GPU1) - hnd->phys = m->master_phys + offset; - else - hnd->phys = 0; + hnd->gpu_fd = gpu_fd; + if (flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + private_module_t* m = reinterpret_cast( + dev->common.module); + hnd->phys = m->master_phys + offset; + } *pHandle = hnd; } @@ -380,32 +430,56 @@ static int gralloc_alloc(alloc_device_t* dev, if (!pHandle || !pStride) return -EINVAL; - int align = 4; - int bpp = 0; - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_BGRA_8888: - bpp = 4; - 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 size, stride; + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || + format == HAL_PIXEL_FORMAT_YCbCr_422_SP) + { + // FIXME: there is no way to return the vstride + int vstride; + stride = (w + 1) & ~1; + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + size = stride * h * 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + vstride = (h+1) & ~1; + size = (stride * vstride) + (w/2 * h/2) * 2; + break; + default: + return -EINVAL; + } + } else { + int align = 4; + int bpp = 0; + 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; } - size_t bpr = (w*bpp + (align-1)) & ~(align-1); - size_t size = bpr * h; - size_t stride = bpr / bpp; - int err; if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); } else { err = gralloc_alloc_buffer(dev, size, usage, pHandle); } + if (err < 0) { return err; } @@ -428,23 +502,31 @@ static int gralloc_free(alloc_device_t* dev, const size_t bufferSize = m->finfo.line_length * m->info.yres; int index = (hnd->base - m->framebuffer->base) / bufferSize; m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - if (hnd->fd >= 0) { - if(hnd->bufferType == BUFFER_TYPE_PMEM){ - sAllocator.deallocate(hnd->offset); - memset((void *)hnd->base, 0, hnd->size); + } else { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + if (hnd->fd >= 0) { + struct pmem_region sub = { hnd->offset, hnd->size }; + int err = ioctl(hnd->fd, PMEM_UNMAP, &sub); + LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " + "fd=%d, sub.offset=%lu, sub.size=%lu", + strerror(errno), hnd->fd, hnd->offset, hnd->size); + if (err == 0) { + // we can't deallocate the memory in case of UNMAP failure + // because it would give that process access to someone else's + // surfaces, which would be a security breach. + sAllocator.deallocate(hnd->offset); + } } - else { - sGPUAllocator.deallocate(hnd->offset); - memset((void *)hnd->base, 0, hnd->size); - } - } + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + LOGD("freeing GPU buffer at %d", hnd->offset); + sAllocatorGPU.deallocate(hnd->offset); + } + + gralloc_module_t* module = reinterpret_cast( + dev->common.module); + terminateBuffer(module, const_cast(hnd)); } - gralloc_module_t* m = reinterpret_cast( - dev->common.module); - gralloc_unregister_buffer(m, handle); - close(hnd->fd); delete hnd; return 0; @@ -483,7 +565,7 @@ int gralloc_device_open(const hw_module_t* module, const char* name, dev->device.alloc = gralloc_alloc; dev->device.free = gralloc_free; - dev->bufferType = BUFFER_TYPE_GPU1; + *device = &dev->device.common; status = 0; } else { diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index e92db19..f2a77c2 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -18,8 +18,6 @@ #define GRALLOC_PRIV_H_ #include -#include -#include #include #include #include @@ -29,57 +27,17 @@ #include -#if HAVE_ANDROID_OS #include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - BUFFER_TYPE_GPU0 = 0, - BUFFER_TYPE_GPU1 = 1, - BUFFER_TYPE_FB = 2, - BUFFER_TYPE_PMEM = 3 -}; /*****************************************************************************/ -#ifdef __cplusplus -inline size_t roundUpToPageSize(size_t x) { - return (x + (PAGESIZE-1)) & ~(PAGESIZE-1); -} - -int mapFrameBufferLocked(struct private_module_t* module); -#endif //__cplusplus - -/*****************************************************************************/ - -#ifdef __cplusplus -class Locker { - pthread_mutex_t mutex; -public: - class Autolock { - Locker& locker; - public: - inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } - inline ~Autolock() { locker.unlock(); } - }; - inline Locker() { pthread_mutex_init(&mutex, 0); } - inline ~Locker() { pthread_mutex_destroy(&mutex); } - inline void lock() { pthread_mutex_lock(&mutex); } - inline void unlock() { pthread_mutex_unlock(&mutex); } -}; -#endif //__cplusplus -/*****************************************************************************/ - +struct private_module_t; struct private_handle_t; struct private_module_t { - struct gralloc_module_t base; + gralloc_module_t base; - struct private_handle_t* framebuffer; + private_handle_t* framebuffer; uint32_t flags; uint32_t numBuffers; uint32_t bufferMask; @@ -88,8 +46,8 @@ struct private_module_t { int pmem_master; void* pmem_master_base; unsigned long master_phys; - int gpu_master; - void* gpu_master_base; + int gpu; + void* gpu_base; struct fb_var_screeninfo info; struct fb_fix_screeninfo finfo; @@ -104,15 +62,18 @@ struct private_module_t { }; /*****************************************************************************/ + #ifdef __cplusplus -struct private_handle_t : public native_handle +struct private_handle_t : public native_handle { #else -struct private_handle_t +struct private_handle_t { + struct native_handle nativeHandle; #endif -{ + enum { PRIV_FLAGS_FRAMEBUFFER = 0x00000001, PRIV_FLAGS_USES_PMEM = 0x00000002, + PRIV_FLAGS_USES_GPU = 0x00000004, }; enum { @@ -121,15 +82,15 @@ struct private_handle_t LOCK_STATE_READ_MASK = 0x3FFFFFFF }; -#ifndef __cplusplus - native_handle nativeHandle; -#endif - + // file-descriptors int fd; + // ints int magic; int flags; int size; int offset; + int gpu_fd; + // FIXME: the attributes below should be out-of-line int base; int lockState; @@ -139,35 +100,35 @@ struct private_handle_t int pid; #ifdef __cplusplus - static const int sNumInts = 10; + static const int sNumInts = 11; static const int sNumFds = 1; - static const int sMagic = 0x3141592; + static const int sMagic = 0x3141592; // FIXME: should be 'msm8' - private_handle_t(int fd, int size, int flags, int type) : + private_handle_t(int fd, int size, int flags) : fd(fd), magic(sMagic), flags(flags), size(size), offset(0), base(0), lockState(0), writeOwner(0), pid(getpid()) { version = sizeof(native_handle); numInts = sNumInts; numFds = sNumFds; - bufferType = type; } ~private_handle_t() { magic = 0; } bool usesPhysicallyContiguousMemory() { - return (flags & PRIV_FLAGS_USES_PMEM) != 0; + return (flags & (PRIV_FLAGS_USES_PMEM|PRIV_FLAGS_USES_GPU)) != 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) { + h->numInts != sNumInts || h->numFds != sNumFds || + hnd->magic != sMagic) + { + LOGE("invalid gralloc handle (at %p)", h); return -EINVAL; } - const private_handle_t* hnd = (const private_handle_t*)h; - if (hnd->magic != sMagic) - return -EINVAL; return 0; } @@ -177,12 +138,7 @@ struct private_handle_t } return NULL; } -#endif //__cplusplus - +#endif }; -#ifdef __cplusplus -} -#endif - #endif /* GRALLOC_PRIV_H_ */ diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 1ab70ec..2254f96 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,14 @@ // 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 +pid_t gettid() { return syscall(__NR_gettid);} +#undef __KERNEL__ +#endif + /*****************************************************************************/ static int gralloc_map(gralloc_module_t const* module, @@ -50,7 +59,9 @@ static int gralloc_map(gralloc_module_t const* module, void* mappedAddress = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); if (mappedAddress == MAP_FAILED) { - LOGE("Could not mmap %s", strerror(errno)); + LOGE("Could not mmap handle %p, fd=%d (%s)", + handle, hnd->fd, strerror(errno)); + hnd->base = 0; return -errno; } hnd->base = intptr_t(mappedAddress) + hnd->offset; @@ -66,7 +77,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)) { - if (munmap((void*)hnd->base, hnd->size) < 0) { + 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)); } } @@ -120,7 +138,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, - "handle %p still locked (state=%08x)", + "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); // never unmap buffers that were created in this process @@ -135,6 +153,37 @@ int gralloc_unregister_buffer(gralloc_module_t const* module, return 0; } +int terminateBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + /* + * If the buffer has been mapped during a lock operation, it's time + * to un-map it. It's an error to be here with a locked buffer. + */ + + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "[terminate] handle %p still locked (state=%08x)", + hnd, hnd->lockState); + + 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) { + if (hnd->pid != getpid()) { + // ... unless it's a "master" pmem buffer, that is a buffer + // mapped in the process it's been allocated. + // (see gralloc_alloc_buffer()) + gralloc_unmap(module, hnd); + } + } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + // XXX: for now do nothing here + } else { + gralloc_unmap(module, hnd); + } + } + + return 0; +} + int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, From 6e83a3025103d43493457b4d240f11c377a1b7fb Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 19 Aug 2009 13:45:02 -0700 Subject: [PATCH 133/435] reenabled partial updates in msm7k/qsd8k --- libgralloc-qsd8k/framebuffer.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 5d3fc7d..6a7ce52 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -41,9 +41,6 @@ /*****************************************************************************/ -// should be a build option -#define SUPPORTS_UPDATE_ON_DEMAND 0 - // numbers of buffers for page flipping #define NUM_BUFFERS 2 @@ -377,13 +374,11 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.minSwapInterval) = 1; const_cast(dev->device.maxSwapInterval) = 1; -#if SUPPORTS_UPDATE_ON_DEMAND if (m->finfo.reserved[0] == 0x5444 && m->finfo.reserved[1] == 0x5055) { dev->device.setUpdateRect = fb_setUpdateRect; LOGD("UPDATE_ON_DEMAND supported"); } -#endif *device = &dev->device.common; } From c779b2b67dee186bddb324bbee63de9d859d5b22 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 19 Aug 2009 14:17:17 -0700 Subject: [PATCH 134/435] make gralloc_priv.h for msm7k and qsd8k identical and C friendly --- libgralloc-qsd8k/gralloc_priv.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index f2a77c2..baa315a 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -37,7 +37,7 @@ struct private_handle_t; struct private_module_t { gralloc_module_t base; - private_handle_t* framebuffer; + struct private_handle_t* framebuffer; uint32_t flags; uint32_t numBuffers; uint32_t bufferMask; @@ -67,7 +67,7 @@ struct private_module_t { struct private_handle_t : public native_handle { #else struct private_handle_t { - struct native_handle nativeHandle; + native_handle_t nativeHandle; #endif enum { @@ -89,20 +89,19 @@ struct private_handle_t { int flags; int size; int offset; - int gpu_fd; + int gpu_fd; // stored as an int, b/c we don't want it marshalled // FIXME: the attributes below should be out-of-line int base; int lockState; int writeOwner; - int bufferType; int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care int pid; #ifdef __cplusplus - static const int sNumInts = 11; + static const int sNumInts = 10; static const int sNumFds = 1; - static const int sMagic = 0x3141592; // FIXME: should be 'msm8' + static const int sMagic = 'msm8'; private_handle_t(int fd, int size, int flags) : fd(fd), magic(sMagic), flags(flags), size(size), offset(0), From 854a1e77bbf7b05d6511835d70224893110026c9 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 19 Aug 2009 15:16:48 -0700 Subject: [PATCH 136/435] use the same magic value for native_handle in 7k and 8k, since the handles are actually identical --- libgralloc-qsd8k/gralloc_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index baa315a..70e7d30 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -101,7 +101,7 @@ struct private_handle_t { #ifdef __cplusplus static const int sNumInts = 10; static const int sNumFds = 1; - static const int sMagic = 'msm8'; + static const int sMagic = 'gmsm'; private_handle_t(int fd, int size, int flags) : fd(fd), magic(sMagic), flags(flags), size(size), offset(0), From 717cf60b7a3c79c5c4401c2079100fde6c145b31 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 20 Aug 2009 15:41:34 -0700 Subject: [PATCH 138/435] fix gralloc qsd8k. we actually don't need to use /pmem/gpu1, since the gpu is now able to use regular PMEM. this module is now closer to the generic gralloc module, although it will have to evolve in the near future. --- libgralloc-qsd8k/gralloc.cpp | 113 ++++---------------------------- libgralloc-qsd8k/gralloc_priv.h | 9 +-- libgralloc-qsd8k/mapper.cpp | 2 - 3 files changed, 16 insertions(+), 108 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index d9f2c7b..1cbc817 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -43,10 +43,7 @@ /*****************************************************************************/ -#define ALLOCATORREGION_RESERVED_SIZE (3<<20) - static SimpleBestFitAllocator sAllocator; -static SimpleBestFitAllocator sAllocatorGPU(ALLOCATORREGION_RESERVED_SIZE); /*****************************************************************************/ @@ -110,9 +107,7 @@ struct private_module_t HAL_MODULE_INFO_SYM = { currentBuffer: 0, pmem_master: -1, pmem_master_base: 0, - master_phys: 0, - gpu: -1, - gpu_base: 0 + master_phys: 0 }; /*****************************************************************************/ @@ -166,6 +161,7 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); + hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; @@ -188,7 +184,6 @@ static int init_pmem_area_locked(private_module_t* m) int err = 0; int master_fd = open("/dev/pmem", O_RDWR, 0); if (master_fd >= 0) { - size_t size; pmem_region region; if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { @@ -206,6 +201,15 @@ static int init_pmem_area_locked(private_module_t* m) base = 0; close(master_fd); master_fd = -1; + } else { + // FIXME: get physical address, eventually this will have to go away + pmem_region region; + err = ioctl(master_fd, PMEM_GET_PHYS, ®ion); + if (err < 0) { + LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno)); + } else { + m->master_phys = (unsigned long)region.offset; + } } m->pmem_master = master_fd; m->pmem_master_base = base; @@ -235,63 +239,6 @@ static int init_pmem_area(private_module_t* m) return err; } -static int init_gpu_area_locked(private_module_t* m) -{ - int err = 0; - int gpu = open("/dev/pmem_gpu1", O_RDWR, 0); - LOGE_IF(gpu<0, "could not open /dev/pmem_gpu1 (%s)", strerror(errno)); - if (gpu >= 0) { - size_t size = sAllocatorGPU.size(); - void* base = mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, gpu, 0); - - if (base == MAP_FAILED) { - LOGE("mmap /dev/pmem_gpu1 (%s)", strerror(errno)); - err = -errno; - base = 0; - close(gpu); - gpu = -1; - } else { - pmem_region region; - err = ioctl(gpu, PMEM_GET_PHYS, ®ion); - if(err < 0) { - LOGE("init pmem: master ioctl failed %d", -errno); - } else { - m->master_phys = (unsigned long)region.offset; - } - } - - m->gpu = gpu; - m->gpu_base = base; - - } else { - err = -errno; - m->gpu = 0; - m->gpu_base = 0; - } - return err; -} - -static int init_gpu_area(private_module_t* m) -{ - pthread_mutex_lock(&m->lock); - int err = m->gpu; - if (err == -1) { - // first time, try to initialize gpu - err = init_gpu_area_locked(m); - if (err) { - m->gpu = err; - } - } else if (err < 0) { - // gpu couldn't be initialized, never use it - } else { - // gpu OK - err = 0; - } - pthread_mutex_unlock(&m->lock); - return err; -} - static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { @@ -299,7 +246,6 @@ static int gralloc_alloc_buffer(alloc_device_t* dev, int flags = 0; int fd = -1; - int gpu_fd = -1; void* base = 0; int offset = 0; int lockState = 0; @@ -323,7 +269,7 @@ try_ashmem: LOGE("couldn't create ashmem (%s)", strerror(errno)); err = -errno; } - } else if ((usage & GRALLOC_USAGE_HW_RENDER) == 0) { + } else { private_module_t* m = reinterpret_cast( dev->common.module); @@ -371,35 +317,6 @@ try_ashmem: LOGE("couldn't open pmem (%s)", strerror(errno)); } } - } else { - // looks like we want 3D... - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; - flags |= private_handle_t::PRIV_FLAGS_USES_GPU; - - private_module_t* m = reinterpret_cast( - dev->common.module); - - err = init_gpu_area(m); - if (err == 0) { - // GPU buffers are always mmapped - base = m->gpu_base; - lockState |= private_handle_t::LOCK_STATE_MAPPED; - offset = sAllocatorGPU.allocate(size); - if (offset < 0) { - // no more pmem memory - err = -ENOMEM; - } else { - LOGD("allocating GPU size=%d, offset=%d", size, offset); - fd = open("/dev/null", O_RDONLY); // just so marshalling doesn't fail - gpu_fd = m->gpu; - memset((char*)base + offset, 0, size); - } - } else { - // not enough memory, try ashmem - flags &= ~private_handle_t::PRIV_FLAGS_USES_GPU; - err = 0; - goto try_ashmem; - } } if (err == 0) { @@ -407,8 +324,7 @@ try_ashmem: hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; - hnd->gpu_fd = gpu_fd; - if (flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { private_module_t* m = reinterpret_cast( dev->common.module); hnd->phys = m->master_phys + offset; @@ -517,9 +433,6 @@ static int gralloc_free(alloc_device_t* dev, sAllocator.deallocate(hnd->offset); } } - } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { - LOGD("freeing GPU buffer at %d", hnd->offset); - sAllocatorGPU.deallocate(hnd->offset); } gralloc_module_t* module = reinterpret_cast( diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 70e7d30..534b4c0 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -46,8 +46,6 @@ struct private_module_t { int pmem_master; void* pmem_master_base; unsigned long master_phys; - int gpu; - void* gpu_base; struct fb_var_screeninfo info; struct fb_fix_screeninfo finfo; @@ -73,7 +71,6 @@ struct private_handle_t { enum { PRIV_FLAGS_FRAMEBUFFER = 0x00000001, PRIV_FLAGS_USES_PMEM = 0x00000002, - PRIV_FLAGS_USES_GPU = 0x00000004, }; enum { @@ -104,8 +101,8 @@ struct private_handle_t { static const int sMagic = 'gmsm'; private_handle_t(int fd, int size, int flags) : - fd(fd), magic(sMagic), flags(flags), size(size), offset(0), - base(0), lockState(0), writeOwner(0), pid(getpid()) + fd(fd), magic(sMagic), flags(flags), size(size), offset(0), gpu_fd(-1), + base(0), lockState(0), writeOwner(0), phys(0), pid(getpid()) { version = sizeof(native_handle); numInts = sNumInts; @@ -116,7 +113,7 @@ struct private_handle_t { } bool usesPhysicallyContiguousMemory() { - return (flags & (PRIV_FLAGS_USES_PMEM|PRIV_FLAGS_USES_GPU)) != 0; + return (flags & PRIV_FLAGS_USES_PMEM) != 0; } static int validate(const native_handle* h) { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 2254f96..93264a6 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -174,8 +174,6 @@ int terminateBuffer(gralloc_module_t const* module, // (see gralloc_alloc_buffer()) gralloc_unmap(module, hnd); } - } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { - // XXX: for now do nothing here } else { gralloc_unmap(module, hnd); } From 1e118264336cb7a29426aeca134386ebc177ac2f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 21 Aug 2009 18:19:16 -0700 Subject: [PATCH 139/435] fix a bug with RGBX_8888 surfaces would be rendered incorrectly by the MDP. --- libcopybit/copybit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index cb17de2..bd548a1 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -106,7 +106,7 @@ static void intersect(struct copybit_rect_t *out, static int get_format(int format) { switch (format) { case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; - case COPYBIT_FORMAT_RGBX_8888: return MDP_XRGB_8888; // currently wrong + case COPYBIT_FORMAT_RGBX_8888: return MDP_RGBX_8888; case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; From fde8e11201a47c3b70f419540094314af4133fe3 Mon Sep 17 00:00:00 2001 From: Simon Wilson Date: Fri, 21 Aug 2009 19:19:39 -0700 Subject: [PATCH 140/435] Enforce 32 pixel alignment for Adreno 200 --- libgralloc-qsd8k/gralloc.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 1cbc817..479ed0c 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -346,26 +346,26 @@ static int gralloc_alloc(alloc_device_t* dev, if (!pHandle || !pStride) return -EINVAL; - size_t size, stride; + size_t size, alignedw, alignedh; if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCbCr_422_SP) { - // FIXME: there is no way to return the vstride - int vstride; - stride = (w + 1) & ~1; + // FIXME: there is no way to return the alignedh + alignedw = (w + 1) & ~1; switch (format) { case HAL_PIXEL_FORMAT_YCbCr_420_SP: - size = stride * h * 2; + size = alignedw * h * 2; break; case HAL_PIXEL_FORMAT_YCbCr_422_SP: - vstride = (h+1) & ~1; - size = (stride * vstride) + (w/2 * h/2) * 2; + alignedh = (h+1) & ~1; + size = (alignedw * alignedh) + (w/2 * h/2) * 2; break; default: return -EINVAL; } } else { - int align = 4; + alignedw = (w + 31) & ~31; + alignedh = (h + 31) & ~31; int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: @@ -384,9 +384,7 @@ static int gralloc_alloc(alloc_device_t* dev, default: return -EINVAL; } - size_t bpr = (w*bpp + (align-1)) & ~(align-1); - size = bpr * h; - stride = bpr / bpp; + size = alignedw * alignedh * bpp; } int err; @@ -400,7 +398,7 @@ static int gralloc_alloc(alloc_device_t* dev, return err; } - *pStride = stride; + *pStride = alignedw; return 0; } From f2d52d61f92c8af46ddbdd3e540dfeafc1f29ae9 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 8 Sep 2009 16:18:51 -0700 Subject: [PATCH 151/435] QSD8K supports 8x scaling --- libcopybit/copybit.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index bd548a1..24b5199 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -38,6 +38,16 @@ /******************************************************************************/ +#if defined(COPYBIT_MSM7K) +#define MAX_SCALE_FACTOR (4) +#else if defined(COPYBIT_QSD8K) +#define MAX_SCALE_FACTOR (8) +#else +#error "Unsupported MDP version" +#endif + +/******************************************************************************/ + /** State information for each device instance */ struct copybit_context_t { struct copybit_device_t device; @@ -273,10 +283,10 @@ static int get(struct copybit_device_t *dev, int name) if (ctx) { switch(name) { case COPYBIT_MINIFICATION_LIMIT: - value = 4; + value = MAX_SCALE_FACTOR; break; case COPYBIT_MAGNIFICATION_LIMIT: - value = 4; + value = MAX_SCALE_FACTOR; break; case COPYBIT_SCALING_FRAC_BITS: value = 32; From 03f9cb24ddf15ef7adebcb7ad36431e0f9345764 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Tue, 8 Sep 2009 18:49:41 -0700 Subject: [PATCH 152/435] libcopybit: Fix typo, and the build Change-Id: I4f75e7ee4eff4f6159099de92ae3b4501ad7474a Signed-off-by: Dima Zavin --- libcopybit/copybit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 24b5199..5ce89e8 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -40,7 +40,7 @@ #if defined(COPYBIT_MSM7K) #define MAX_SCALE_FACTOR (4) -#else if defined(COPYBIT_QSD8K) +#elif defined(COPYBIT_QSD8K) #define MAX_SCALE_FACTOR (8) #else #error "Unsupported MDP version" From d24467414b60768e8d0d0e82b6fce787d464744a Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Thu, 24 Sep 2009 01:07:33 -0700 Subject: [PATCH 154/435] copybit: hack to always request premultiplied alpha blend. The kernel will only do it for images with an alpha plane. Change-Id: Idcba41945ed7d17daae0a5bcc48c64a82a49dded Signed-off-by: Dima Zavin --- libcopybit/copybit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 5ce89e8..b3d44f6 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -192,7 +192,7 @@ static void set_rects(struct copybit_context_t *dev, static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { req->alpha = dev->mAlpha; req->transp_mask = MDP_TRANSP_NOP; - req->flags = dev->mFlags; + req->flags = dev->mFlags | MDP_BLEND_FG_PREMULT; } /** copy the bits */ From ef7776257a1890b7eef9f9b882f30705f1498f13 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 2 Oct 2009 19:18:55 -0700 Subject: [PATCH 159/435] gralloc-qsd8k: Call glFinish on composition complete. Change-Id: I09c8287bcaf89f3f8bcaa4108631641a0fcc397b Signed-off-by: Dima Zavin --- libgralloc-qsd8k/Android.mk | 2 +- libgralloc-qsd8k/framebuffer.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index 9bae065..d5ffa42 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -19,7 +19,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM LOCAL_SRC_FILES := \ allocator.cpp \ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 6a7ce52..797982f 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -36,6 +36,8 @@ #include #include +#include + #include "gralloc_priv.h" #include "gr.h" @@ -148,6 +150,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) return 0; } +static int fb_compositionComplete(struct framebuffer_device_t* dev) +{ + // STOPSHIP: Properly implement composition complete callback + glFinish(); + + return 0; +} + /*****************************************************************************/ int mapFrameBufferLocked(struct private_module_t* module) @@ -358,6 +368,7 @@ int fb_device_open(hw_module_t const* module, const char* name, dev->device.setSwapInterval = fb_setSwapInterval; dev->device.post = fb_post; dev->device.setUpdateRect = 0; + dev->device.compositionComplete = fb_compositionComplete; private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); From 4705b7db85c4c452608ab6d6d66c3e8df97e01bd Mon Sep 17 00:00:00 2001 From: Patrick Scott Date: Thu, 29 Oct 2009 08:35:22 -0400 Subject: [PATCH 168/435] Remove calls to dump_l. This fails to compile without NDEBUG and the log statement is accomplishing the same thing. --- libgralloc-qsd8k/allocator.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp index 4dad6a1..e7645b1 100644 --- a/libgralloc-qsd8k/allocator.cpp +++ b/libgralloc-qsd8k/allocator.cpp @@ -153,11 +153,6 @@ SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) cur = n; } while (cur && cur->free); - #ifndef NDEBUG - if (!freed->free) { - dump_l("dealloc (!freed->free)"); - } - #endif LOG_FATAL_IF(!freed->free, "freed block at offset 0x%08lX of size 0x%08lX is not free!", freed->start * kMemoryAlign, freed->size * kMemoryAlign); From b73f40535ff94b332eb27d0052a518d4824bc38e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 29 Oct 2009 19:50:47 -0700 Subject: [PATCH 169/435] fix[2222341] Soft reset while going back from camcorder settings add a way to convert a mapped "pushbuffer" buffer to a gralloc handle which then can be safely used by surfaceflinger also make sure to not send empty rectangles to the MDP. --- libcopybit/copybit.cpp | 49 +++++++++++++++++++++++++++++++----- libgralloc-qsd8k/gralloc.cpp | 4 +++ libgralloc-qsd8k/mapper.cpp | 36 ++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index b3d44f6..367941b 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -36,6 +36,8 @@ #include "gralloc_priv.h" +#define DEBUG_MDP_ERRORS 0 + /******************************************************************************/ #if defined(COPYBIT_MSM7K) @@ -201,10 +203,37 @@ 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) + if (err == 0) { return 0; - else + } else { +#if DEBUG_MDP_ERRORS + struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list; + for (int i=0 ; icount ; 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; + } } /*****************************************************************************/ @@ -338,10 +367,18 @@ static int stretch_copybit( status = 0; while ((status == 0) && region->next(region, &clip)) { intersect(&clip, &bounds, &clip); - set_infos(ctx, &list.req[list.count]); - set_image(&list.req[list.count].dst, dst); - set_image(&list.req[list.count].src, src); - set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip); + mdp_blit_req* req = &list.req[list.count]; + set_infos(ctx, req); + set_image(&req->dst, dst); + set_image(&req->src, src); + set_rects(ctx, req, dst_rect, src_rect, &clip); + + 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; diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 479ed0c..45746ef 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -77,6 +77,9 @@ extern int gralloc_register_buffer(gralloc_module_t const* module, 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, ... ); + /*****************************************************************************/ static struct hw_module_methods_t gralloc_module_methods = { @@ -98,6 +101,7 @@ struct private_module_t HAL_MODULE_INFO_SYM = { unregisterBuffer: gralloc_unregister_buffer, lock: gralloc_lock, unlock: gralloc_unlock, + perform: gralloc_perform, }, framebuffer: 0, flags: 0, diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 93264a6..8c199b3 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -284,3 +285,38 @@ int gralloc_unlock(gralloc_module_t const* module, return 0; } + +/*****************************************************************************/ + +int gralloc_perform(struct gralloc_module_t const* module, + int operation, ... ) +{ + int res = -EINVAL; + va_list args; + 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*); + native_handle_t** handle = va_arg(args, native_handle_t**); + 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 = private_handle_t::PRIV_FLAGS_USES_PMEM; + hnd->size = size; + hnd->offset = offset; + hnd->base = intptr_t(base) + offset; + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + *handle = (native_handle_t *)hnd; + res = 0; + break; + } + } + + va_end(args); + return res; +} From 9e8b8a119d449b721845d81ffe9b3eb40c9bbebf Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 9 Nov 2009 20:15:50 -0800 Subject: [PATCH 184/435] enable mdp debugging on error, also check for invalid inputs --- libcopybit/copybit.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 367941b..ba8531b 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -36,7 +36,7 @@ #include "gralloc_priv.h" -#define DEBUG_MDP_ERRORS 0 +#define DEBUG_MDP_ERRORS 1 /******************************************************************************/ @@ -359,7 +359,13 @@ static int stretch_copybit( 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; + } + 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; From ef686c51fdc87570b2a186fe0321b7c42e1947f1 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 9 Nov 2009 20:14:02 -0800 Subject: [PATCH 186/435] should help [2223746] qsd8k MDP locks up, logs show copyBits failed (Connection timed out) in Passion camera zoom level 1 make sure to return an error when mdp limits are exceeded --- libcopybit/copybit.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index ba8531b..fb605fe 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -42,8 +42,10 @@ #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 @@ -366,6 +368,12 @@ static int stretch_copybit( 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; From 81cd37b750a71dd0fb5d9e67dff39f2bfede765b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Thu, 12 Nov 2009 18:46:07 -0800 Subject: [PATCH 188/435] eclair snapshot --- libcamera2/Android.mk | 35 - libcamera2/QualcommCameraHardware.cpp | 1946 ------------------------- libcamera2/QualcommCameraHardware.h | 241 --- libcopybit/Android.mk | 19 +- libcopybit/{copybit.c => copybit.cpp} | 128 +- libgralloc-qsd8k/Android.mk | 32 + libgralloc-qsd8k/allocator.cpp | 170 +++ libgralloc-qsd8k/allocator.h | 129 ++ libgralloc-qsd8k/framebuffer.cpp | 437 ++++++ libgralloc-qsd8k/gr.h | 63 + libgralloc-qsd8k/gralloc.cpp | 490 +++++++ libgralloc-qsd8k/gralloc_priv.h | 140 ++ libgralloc-qsd8k/mapper.cpp | 322 ++++ 13 files changed, 1900 insertions(+), 2252 deletions(-) delete mode 100644 libcamera2/Android.mk delete mode 100644 libcamera2/QualcommCameraHardware.cpp delete mode 100644 libcamera2/QualcommCameraHardware.h rename libcopybit/{copybit.c => copybit.cpp} (77%) create mode 100644 libgralloc-qsd8k/Android.mk create mode 100644 libgralloc-qsd8k/allocator.cpp create mode 100644 libgralloc-qsd8k/allocator.h create mode 100644 libgralloc-qsd8k/framebuffer.cpp create mode 100644 libgralloc-qsd8k/gr.h create mode 100644 libgralloc-qsd8k/gralloc.cpp create mode 100644 libgralloc-qsd8k/gralloc_priv.h create mode 100644 libgralloc-qsd8k/mapper.cpp diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk deleted file mode 100644 index 80e24fe..0000000 --- a/libcamera2/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -BUILD_LIBCAMERA:= -ifeq ($(BUILD_LIBCAMERA),true) - -# When zero we link against libmmcamera; when 1, we dlopen libmmcamera. -DLOPEN_LIBMMCAMERA:=1 - -ifneq ($(BUILD_TINY_ANDROID),true) - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= QualcommCameraHardware.cpp - -LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA) - -LOCAL_C_INCLUDES+= \ - vendor/qcom/proprietary/mm-camera/common \ - vendor/qcom/proprietary/mm-camera/apps/appslib \ - vendor/qcom/proprietary/mm-camera/jpeg \ - vendor/qcom/proprietary/mm-camera/jpeg/inc - -LOCAL_SHARED_LIBRARIES:= libutils libui liblog - -ifneq ($(DLOPEN_LIBMMCAMERA),1) -LOCAL_SHARED_LIBRARIES+= libqcamera -else -LOCAL_SHARED_LIBRARIES+= libdl -endif - -LOCAL_MODULE:= libcamera -include $(BUILD_SHARED_LIBRARY) - -endif # BUILD_TINY_ANDROID -endif # BUILD_LIBCAMERA diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp deleted file mode 100644 index 2a39f20..0000000 --- a/libcamera2/QualcommCameraHardware.cpp +++ /dev/null @@ -1,1946 +0,0 @@ -/* -** Copyright 2008, Google Inc. -** -** 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_NDEBUG 0 -#define LOG_TAG "QualcommCameraHardware" -#include - -#include "QualcommCameraHardware.h" - -#include -#include -#include -#include -#include -#include -#if HAVE_ANDROID_OS -#include -#endif -#include - -#define LIKELY(exp) __builtin_expect(!!(exp), 1) -#define UNLIKELY(exp) __builtin_expect(!!(exp), 0) - -extern "C" { - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define THUMBNAIL_WIDTH 512 -#define THUMBNAIL_HEIGHT 384 -#define THUMBNAIL_WIDTH_STR "512" -#define THUMBNAIL_HEIGHT_STR "384" -#define DEFAULT_PICTURE_WIDTH 2048 // 1280 -#define DEFAULT_PICTURE_HEIGHT 1536 // 768 -#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) - -#define DEFAULT_PREVIEW_SETTING 2 // HVGA -#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type)) - -#define NOT_FOUND -1 - -#if DLOPEN_LIBMMCAMERA -#include - -void* (*LINK_cam_conf)(void *data); -void* (*LINK_cam_frame)(void *data); -bool (*LINK_jpeg_encoder_init)(); -void (*LINK_jpeg_encoder_join)(); -bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, - const uint8_t *thumbnailbuf, int thumbnailfd, - const uint8_t *snapshotbuf, int snapshotfd, - common_crop_t *scaling_parms); -int (*LINK_camframe_terminate)(void); -int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); -int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); -int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); -int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location); -// callbacks -void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame); -void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, - uint32_t buff_size); -void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status); -void (**LINK_mmcamera_shutter_callback)(); -#else -#define LINK_cam_conf cam_conf -#define LINK_cam_frame cam_frame -#define LINK_jpeg_encoder_init jpeg_encoder_init -#define LINK_jpeg_encoder_join jpeg_encoder_join -#define LINK_jpeg_encoder_encode jpeg_encoder_encode -#define LINK_camframe_terminate camframe_terminate -#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality -#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality -#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation -#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation -extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); -extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, - uint32_t buff_size); -extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); -extern void (*mmcamera_shutter_callback)(); -#endif - -} // extern "C" - -struct preview_size_type { - int width; - int height; -}; - -static preview_size_type preview_sizes[] = { - { 800, 480 }, // WVGA - { 640, 480 }, // VGA - { 480, 320 }, // HVGA - { 384, 288 }, - { 352, 288 }, // CIF - { 320, 240 }, // QVGA - { 240, 160 }, // SQVGA - { 176, 144 }, // QCIF -}; - -static int attr_lookup(const struct str_map *const arr, const char *name) -{ - if (name) { - const struct str_map *trav = arr; - while (trav->desc) { - if (!strcmp(trav->desc, name)) - return trav->val; - trav++; - } - } - return NOT_FOUND; -} - -#define INIT_VALUES_FOR(parm) do { \ - if (!parm##_values) { \ - parm##_values = (char *)malloc(sizeof(parm)/ \ - sizeof(parm[0])*30); \ - char *ptr = parm##_values; \ - const str_map *trav; \ - for (trav = parm; trav->desc; trav++) { \ - int len = strlen(trav->desc); \ - strcpy(ptr, trav->desc); \ - ptr += len; \ - *ptr++ = ','; \ - } \ - *--ptr = 0; \ - } \ -} while(0) - -// from aeecamera.h -static const str_map whitebalance[] = { - { "auto", CAMERA_WB_AUTO }, - { "incandescent", CAMERA_WB_INCANDESCENT }, - { "florescent", CAMERA_WB_FLUORESCENT }, - { "daylight", CAMERA_WB_DAYLIGHT }, - { "cloudy", CAMERA_WB_CLOUDY_DAYLIGHT }, - { "twilight", CAMERA_WB_TWILIGHT }, - { "shade", CAMERA_WB_SHADE }, - { NULL, 0 } -}; -static char *whitebalance_values; - -// from camera_effect_t -static const str_map effect[] = { - { "none", CAMERA_EFFECT_OFF }, /* This list must match aeecamera.h */ - { "mono", CAMERA_EFFECT_MONO }, - { "negative", CAMERA_EFFECT_NEGATIVE }, - { "solarize", CAMERA_EFFECT_SOLARIZE }, - { "sepia", CAMERA_EFFECT_SEPIA }, - { "posterize", CAMERA_EFFECT_POSTERIZE }, - { "whiteboard", CAMERA_EFFECT_WHITEBOARD }, - { "blackboard", CAMERA_EFFECT_BLACKBOARD }, - { "aqua", CAMERA_EFFECT_AQUA }, - { NULL, 0 } -}; -static char *effect_values; - -// from qcamera/common/camera.h -static const str_map antibanding[] = { - { "off", CAMERA_ANTIBANDING_OFF }, - { NULL, 0 } -}; -static char *antibanding_values; - -// round to the next power of two -static inline unsigned clp2(unsigned x) -{ - x = x - 1; - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >>16); - return x + 1; -} - -namespace android { - -static Mutex singleton_lock; -static bool singleton_releasing; -static Condition singleton_wait; - -static void receive_camframe_callback(struct msm_frame *frame); -static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size); -static void receive_jpeg_callback(jpeg_event_t status); -static void receive_shutter_callback(); - -QualcommCameraHardware::QualcommCameraHardware() - : mParameters(), - mPreviewHeight(-1), - mPreviewWidth(-1), - mRawHeight(-1), - mRawWidth(-1), - mCameraRunning(false), - mPreviewInitialized(false), - mFrameThreadRunning(false), - mSnapshotThreadRunning(false), - mReleasedRecordingFrame(false), - mShutterCallback(0), - mRawPictureCallback(0), - mJpegPictureCallback(0), - mPictureCallbackCookie(0), - mAutoFocusCallback(0), - mAutoFocusCallbackCookie(0), - mPreviewCallback(0), - mPreviewCallbackCookie(0), - mRecordingCallback(0), - mRecordingCallbackCookie(0), - mPreviewFrameSize(0), - mRawSize(0), - mCameraControlFd(-1), - mAutoFocusThreadRunning(false), - mAutoFocusFd(-1), - mInPreviewCallback(false) -{ - memset(&mDimension, 0, sizeof(mDimension)); - memset(&mCrop, 0, sizeof(mCrop)); - LOGV("constructor EX"); -} - -void QualcommCameraHardware::initDefaultParameters() -{ - CameraParameters p; - - LOGV("initDefaultParameters E"); - - preview_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING]; - p.setPreviewSize(ps->width, ps->height); - p.setPreviewFrameRate(15); - p.setPreviewFormat("yuv420sp"); // informative - p.setPictureFormat("jpeg"); // informative - - p.set("jpeg-quality", "100"); // maximum quality - p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative - p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative - p.set("jpeg-thumbnail-quality", "90"); - - p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); - p.set("antibanding", "off"); - p.set("effect", "none"); - p.set("whitebalance", "auto"); - -#if 0 - p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00 - p.set("gps-latitude", "37.736071"); // A little house in San Francisco - p.set("gps-longitude", "-122.441983"); - p.set("gps-altitude", "21"); // meters -#endif - - // This will happen only one in the lifetime of the mediaserver process. - // We do not free the _values arrays when we destroy the camera object. - INIT_VALUES_FOR(antibanding); - INIT_VALUES_FOR(effect); - INIT_VALUES_FOR(whitebalance); - - p.set("antibanding-values", antibanding_values); - p.set("effect-values", effect_values); - p.set("whitebalance-values", whitebalance_values); - p.set("picture-size-values", "2048x1536,1600x1200,1024x768"); - - if (setParameters(p) != NO_ERROR) { - LOGE("Failed to set default parameters?!"); - } - - LOGV("initDefaultParameters X"); -} - -#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff) - -void QualcommCameraHardware::startCamera() -{ - LOGV("startCamera E"); -#if DLOPEN_LIBMMCAMERA - libmmcamera = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("loading libqcamera at %p", libmmcamera); - if (!libmmcamera) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); - return; - } - - *(void **)&LINK_cam_frame = - ::dlsym(libmmcamera, "cam_frame"); - *(void **)&LINK_camframe_terminate = - ::dlsym(libmmcamera, "camframe_terminate"); - - *(void **)&LINK_jpeg_encoder_init = - ::dlsym(libmmcamera, "jpeg_encoder_init"); - - *(void **)&LINK_jpeg_encoder_encode = - ::dlsym(libmmcamera, "jpeg_encoder_encode"); - - *(void **)&LINK_jpeg_encoder_join = - ::dlsym(libmmcamera, "jpeg_encoder_join"); - - *(void **)&LINK_mmcamera_camframe_callback = - ::dlsym(libmmcamera, "mmcamera_camframe_callback"); - - *LINK_mmcamera_camframe_callback = receive_camframe_callback; - - *(void **)&LINK_mmcamera_jpegfragment_callback = - ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback"); - - *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; - - *(void **)&LINK_mmcamera_jpeg_callback = - ::dlsym(libmmcamera, "mmcamera_jpeg_callback"); - - *LINK_mmcamera_jpeg_callback = receive_jpeg_callback; - - *(void **)&LINK_mmcamera_shutter_callback = - ::dlsym(libmmcamera, "mmcamera_shutter_callback"); - - *LINK_mmcamera_shutter_callback = receive_shutter_callback; - - *(void**)&LINK_jpeg_encoder_setMainImageQuality = - ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); - - *(void**)&LINK_jpeg_encoder_setThumbnailQuality = - ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); - - *(void**)&LINK_jpeg_encoder_setRotation = - ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); - - *(void**)&LINK_jpeg_encoder_setLocation = - ::dlsym(libmmcamera, "jpeg_encoder_setLocation"); - - *(void **)&LINK_cam_conf = - ::dlsym(libmmcamera, "cam_conf"); -#else - mmcamera_camframe_callback = receive_camframe_callback; - mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback; - mmcamera_jpeg_callback = receive_jpeg_callback; - mmcamera_shutter_callback = receive_shutter_callback; -#endif // DLOPEN_LIBMMCAMERA - - /* The control thread is in libcamera itself. */ - mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR); - if (mCameraControlFd < 0) { - LOGE("startCamera X: %s open failed: %s!", - MSM_CAMERA_CONTROL, - strerror(errno)); - return; - } - - pthread_create(&mCamConfigThread, NULL, - LINK_cam_conf, NULL); - - LOGV("startCamera X"); -} - -status_t QualcommCameraHardware::dump(int fd, - const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - - // Dump internal primitives. - result.append("QualcommCameraHardware::dump"); - snprintf(buffer, 255, "preview width(%d) x height (%d)\n", - mPreviewWidth, mPreviewHeight); - result.append(buffer); - snprintf(buffer, 255, "raw width(%d) x height (%d)\n", - mRawWidth, mRawHeight); - result.append(buffer); - snprintf(buffer, 255, - "preview frame size(%d), raw size (%d), jpeg size (%d) " - "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize, - mJpegSize, mJpegMaxSize); - result.append(buffer); - write(fd, result.string(), result.size()); - - // Dump internal objects. - if (mPreviewHeap != 0) { - mPreviewHeap->dump(fd, args); - } - if (mRawHeap != 0) { - mRawHeap->dump(fd, args); - } - if (mJpegHeap != 0) { - mJpegHeap->dump(fd, args); - } - mParameters.dump(fd, args); - return NO_ERROR; -} - -static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type) -{ - int rc; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS; - ctrlCmd.length = sizeof(af_type); - ctrlCmd.value = &af_type; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) - LOGE("native_set_afmode: ioctl fd %d error %s\n", - camfd, - strerror(errno)); - - LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status); - return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE; -} - -static bool native_cancel_afmode(int camfd, int af_fd) -{ - int rc; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = af_fd; - - if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0) - LOGE("native_cancel_afmode: ioctl fd %d error %s\n", - camfd, - strerror(errno)); - return rc >= 0; -} - -static bool native_start_preview(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_START_PREVIEW; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_get_picture (int camfd, common_crop_t *crop) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = sizeof(common_crop_t); - ctrlCmd.value = crop; - - if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) { - LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - LOGV("crop: in1_w %d", crop->in1_w); - LOGV("crop: in1_h %d", crop->in1_h); - LOGV("crop: out1_w %d", crop->out1_w); - LOGV("crop: out1_h %d", crop->out1_h); - - LOGV("crop: in2_w %d", crop->in2_w); - LOGV("crop: in2_h %d", crop->in2_h); - LOGV("crop: out2_w %d", crop->out2_w); - LOGV("crop: out2_h %d", crop->out2_h); - - LOGV("crop: update %d", crop->update_flag); - - return true; -} - -static bool native_stop_preview(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_STOP_PREVIEW; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_stop_preview: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_start_snapshot(int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_START_SNAPSHOT; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_start_snapshot: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -static bool native_stop_snapshot (int camfd) -{ - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = CAMERA_STOP_SNAPSHOT; - ctrlCmd.length = 0; - ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel - - if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) { - LOGE("native_stop_snapshot: ioctl fd %d error %s", - camfd, - strerror(errno)); - return false; - } - - return true; -} - -bool QualcommCameraHardware::native_jpeg_encode(void) -{ - int jpeg_quality = mParameters.getInt("jpeg-quality"); - if (jpeg_quality >= 0) { - LOGV("native_jpeg_encode, current jpeg main img quality =%d", - jpeg_quality); - if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) { - LOGE("native_jpeg_encode set jpeg-quality failed"); - return false; - } - } - - int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality"); - if (thumbnail_quality >= 0) { - LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d", - thumbnail_quality); - if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) { - LOGE("native_jpeg_encode set thumbnail-quality failed"); - return false; - } - } - - int rotation = mParameters.getInt("rotation"); - if (rotation >= 0) { - LOGV("native_jpeg_encode, rotation = %d", rotation); - if(!LINK_jpeg_encoder_setRotation(rotation)) { - LOGE("native_jpeg_encode set rotation failed"); - return false; - } - } - - jpeg_set_location(); - - if (!LINK_jpeg_encoder_encode(&mDimension, - (uint8_t *)mThumbnailHeap->mHeap->base(), - mThumbnailHeap->mHeap->getHeapID(), - (uint8_t *)mRawHeap->mHeap->base(), - mRawHeap->mHeap->getHeapID(), - &mCrop)) { - LOGE("native_jpeg_encode: jpeg_encoder_encode failed."); - return false; - } - return true; -} - -bool QualcommCameraHardware::native_set_dimension(cam_ctrl_dimension_t *value) -{ - return native_set_parm(CAMERA_SET_PARM_DIMENSION, - sizeof(cam_ctrl_dimension_t), value); -} - -bool QualcommCameraHardware::native_set_parm( - cam_ctrl_type type, uint16_t length, void *value) -{ - int rc = true; - struct msm_ctrl_cmd ctrlCmd; - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.type = (uint16_t)type; - ctrlCmd.length = length; - // FIXME: this will be put in by the kernel - ctrlCmd.resp_fd = mCameraControlFd; - ctrlCmd.value = value; - - LOGV("native_set_parm. camfd=%d, type=%d, length=%d", - mCameraControlFd, type, length); - rc = ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd); - if(rc < 0 || ctrlCmd.status != CAM_CTRL_SUCCESS) { - LOGE("ioctl error. camfd=%d, type=%d, length=%d, rc=%d, ctrlCmd.status=%d, %s", - mCameraControlFd, type, length, rc, ctrlCmd.status, strerror(errno)); - return false; - } - return true; -} - -void QualcommCameraHardware::jpeg_set_location() -{ - bool encode_location = true; - camera_position_type pt; - -#define PARSE_LOCATION(what,type,fmt,desc) do { \ - pt.what = 0; \ - const char *what##_str = mParameters.get("gps-"#what); \ - LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \ - if (what##_str) { \ - type what = 0; \ - if (sscanf(what##_str, fmt, &what) == 1) \ - pt.what = what; \ - else { \ - LOGE("GPS " #what " %s could not" \ - " be parsed as a " #desc, what##_str); \ - encode_location = false; \ - } \ - } \ - else { \ - LOGV("GPS " #what " not specified: " \ - "defaulting to zero in EXIF header."); \ - encode_location = false; \ - } \ - } while(0) - - PARSE_LOCATION(timestamp, long, "%ld", "long"); - if (!pt.timestamp) pt.timestamp = time(NULL); - PARSE_LOCATION(altitude, short, "%hd", "short"); - PARSE_LOCATION(latitude, double, "%lf", "double float"); - PARSE_LOCATION(longitude, double, "%lf", "double float"); - -#undef PARSE_LOCATION - - if (encode_location) { - LOGD("setting image location ALT %d LAT %lf LON %lf", - pt.altitude, pt.latitude, pt.longitude); - if (!LINK_jpeg_encoder_setLocation(&pt)) { - LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed."); - } - } - else LOGV("not setting image location"); -} - -void QualcommCameraHardware::runFrameThread(void *data) -{ - LOGV("runFrameThread E"); - - int cnt; - -#if DLOPEN_LIBMMCAMERA - // We need to maintain a reference to libqcamera.so for the duration of the - // frame thread, because we do not know when it will exit relative to the - // lifetime of this object. We do not want to dlclose() libqcamera while - // LINK_cam_frame is still running. - void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("FRAME: loading libqcamera at %p", libhandle); - if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); - } - if (libhandle) -#endif - { - LINK_cam_frame(data); - } - - mPreviewHeap.clear(); - -#if DLOPEN_LIBMMCAMERA - if (libhandle) { - ::dlclose(libhandle); - LOGV("FRAME: dlclose(libqcamera)"); - } -#endif - - mFrameThreadWaitLock.lock(); - mFrameThreadRunning = false; - mFrameThreadWait.signal(); - mFrameThreadWaitLock.unlock(); - - LOGV("runFrameThread X"); -} - -void *frame_thread(void *user) -{ - LOGD("frame_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runFrameThread(user); - } - else LOGW("not starting frame thread: the object went away!"); - LOGD("frame_thread X"); - return NULL; -} - -bool QualcommCameraHardware::initPreview() -{ - // See comments in deinitPreview() for why we have to wait for the frame - // thread here, and why we can't use pthread_join(). - LOGI("initPreview E: preview size=%dx%d", mPreviewWidth, mPreviewHeight); - mFrameThreadWaitLock.lock(); - while (mFrameThreadRunning) { - LOGV("initPreview: waiting for old frame thread to complete."); - mFrameThreadWait.wait(mFrameThreadWaitLock); - LOGV("initPreview: old frame thread completed."); - } - mFrameThreadWaitLock.unlock(); - - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("initPreview: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("initPreview: old snapshot thread completed."); - } - mSnapshotThreadWaitLock.unlock(); - - int cnt = 0; - mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2; - mPreviewHeap = new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_OUTPUT2, - mPreviewFrameSize, - kPreviewBufferCount, - mPreviewFrameSize, - 0, - "preview"); - - if (!mPreviewHeap->initialized()) { - mPreviewHeap.clear(); - LOGE("initPreview X: could not initialize preview heap."); - return false; - } - - mDimension.picture_width = DEFAULT_PICTURE_WIDTH; - mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; - - bool ret = native_set_dimension(&mDimension); - - if (ret) { - for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { - frames[cnt].fd = mPreviewHeap->mHeap->getHeapID(); - frames[cnt].buffer = - (uint32_t)mPreviewHeap->mHeap->base() + mPreviewFrameSize * cnt; - frames[cnt].y_off = 0; - frames[cnt].cbcr_off = mPreviewWidth * mPreviewHeight; - frames[cnt].path = MSM_FRAME_ENC; - } - - mFrameThreadWaitLock.lock(); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mFrameThreadRunning = !pthread_create(&mFrameThread, - &attr, - frame_thread, - &frames[kPreviewBufferCount-1]); - ret = mFrameThreadRunning; - mFrameThreadWaitLock.unlock(); - } - - LOGV("initPreview X: %d", ret); - return ret; -} - -void QualcommCameraHardware::deinitPreview(void) -{ - LOGI("deinitPreview E"); - - // When we call deinitPreview(), we signal to the frame thread that it - // needs to exit, but we DO NOT WAIT for it to complete here. The problem - // is that deinitPreview is sometimes called from the frame-thread's - // callback, when the refcount on the Camera client reaches zero. If we - // called pthread_join(), we would deadlock. So, we just call - // LINK_camframe_terminate() in deinitPreview(), which makes sure that - // after the preview callback returns, the camframe thread will exit. We - // could call pthread_join() in initPreview() to join the last frame - // thread. However, we would also have to call pthread_join() in release - // as well, shortly before we destoy the object; this would cause the same - // deadlock, since release(), like deinitPreview(), may also be called from - // the frame-thread's callback. This we have to make the frame thread - // detached, and use a separate mechanism to wait for it to complete. - - if (LINK_camframe_terminate() < 0) - LOGE("failed to stop the camframe thread: %s", - strerror(errno)); - LOGI("deinitPreview X"); -} - -bool QualcommCameraHardware::initRaw(bool initJpegHeap) -{ - LOGV("initRaw E: picture size=%dx%d", - mRawWidth, mRawHeight); - - mDimension.picture_width = mRawWidth; - mDimension.picture_height = mRawHeight; - mRawSize = mRawWidth * mRawHeight * 3 / 2; - mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2; - - if(!native_set_dimension(&mDimension)) { - LOGE("initRaw X: failed to set dimension"); - return false; - } - - if (mJpegHeap != NULL) { - LOGV("initRaw: clearing old mJpegHeap."); - mJpegHeap.clear(); - } - - // Snapshot - - LOGV("initRaw: initializing mRawHeap."); - mRawHeap = - new PmemPool("/dev/pmem_camera", - mCameraControlFd, - MSM_PMEM_MAINIMG, - mJpegMaxSize, - kRawBufferCount, - mRawSize, - 0, - "snapshot camera"); - - if (!mRawHeap->initialized()) { - LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp"); - mRawHeap = - new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_MAINIMG, - mJpegMaxSize, - kRawBufferCount, - mRawSize, - 0, - "snapshot camera"); - if (!mRawHeap->initialized()) { - mRawHeap.clear(); - LOGE("initRaw X: error initializing mRawHeap"); - return false; - } - } - - LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d", - (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID()); - - // Jpeg - - if (initJpegHeap) { - LOGV("initRaw: initializing mJpegHeap."); - mJpegHeap = - new AshmemPool(mJpegMaxSize, - kJpegBufferCount, - 0, // we do not know how big the picture wil be - 0, - "jpeg"); - - if (!mJpegHeap->initialized()) { - mJpegHeap.clear(); - mRawHeap.clear(); - LOGE("initRaw X failed: error initializing mJpegHeap."); - return false; - } - - // Thumbnails - - mThumbnailHeap = - new PmemPool("/dev/pmem_adsp", - mCameraControlFd, - MSM_PMEM_THUMBAIL, - THUMBNAIL_BUFFER_SIZE, - 1, - THUMBNAIL_BUFFER_SIZE, - 0, - "thumbnail"); - - if (!mThumbnailHeap->initialized()) { - mThumbnailHeap.clear(); - mJpegHeap.clear(); - mRawHeap.clear(); - LOGE("initRaw X failed: error initializing mThumbnailHeap."); - return false; - } - } - - LOGV("initRaw X"); - return true; -} - -void QualcommCameraHardware::deinitRaw() -{ - LOGV("deinitRaw E"); - - mThumbnailHeap.clear(); - mJpegHeap.clear(); - mRawHeap.clear(); - - LOGV("deinitRaw X"); -} - -void QualcommCameraHardware::release() -{ - LOGD("release E"); - Mutex::Autolock l(&mLock); - -#if DLOPEN_LIBMMCAMERA - if (libmmcamera == NULL) { - LOGE("ERROR: multiple release!"); - return; - } -#else -#warning "Cannot detect multiple release when not dlopen()ing libqcamera!" -#endif - - int cnt, rc; - struct msm_ctrl_cmd ctrlCmd; - - if (mCameraRunning) { - if(mRecordingCallback != NULL) { - mRecordFrameLock.lock(); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - mRecordFrameLock.unlock(); - } - stopPreviewInternal(); - } - - LINK_jpeg_encoder_join(); - deinitRaw(); - - ctrlCmd.timeout_ms = 5000; - ctrlCmd.length = 0; - ctrlCmd.type = (uint16_t)CAMERA_EXIT; - ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel - if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) - LOGE("ioctl CAMERA_EXIT fd %d error %s", - mCameraControlFd, strerror(errno)); - rc = pthread_join(mCamConfigThread, NULL); - if (rc) - LOGE("config_thread exit failure: %s", strerror(errno)); - else - LOGV("pthread_join succeeded on config_thread"); - - close(mCameraControlFd); - mCameraControlFd = -1; - -#if DLOPEN_LIBMMCAMERA - if (libmmcamera) { - ::dlclose(libmmcamera); - LOGV("dlclose(libqcamera)"); - libmmcamera = NULL; - } -#endif - - Mutex::Autolock lock(&singleton_lock); - singleton_releasing = true; - - LOGD("release X"); -} - -QualcommCameraHardware::~QualcommCameraHardware() -{ - LOGD("~QualcommCameraHardware E"); - Mutex::Autolock lock(&singleton_lock); - singleton.clear(); - singleton_releasing = false; - singleton_wait.signal(); - LOGD("~QualcommCameraHardware X"); -} - -sp QualcommCameraHardware::getRawHeap() const -{ - LOGV("getRawHeap"); - return mRawHeap != NULL ? mRawHeap->mHeap : NULL; -} - -sp QualcommCameraHardware::getPreviewHeap() const -{ - LOGV("getPreviewHeap"); - return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL; -} - -status_t QualcommCameraHardware::startPreviewInternal() -{ - if(mCameraRunning) { - LOGV("startPreview X: preview already running."); - return NO_ERROR; - } - - if (!mPreviewInitialized) { - mPreviewInitialized = initPreview(); - if (!mPreviewInitialized) { - LOGE("startPreview X initPreview failed. Not starting preview."); - return UNKNOWN_ERROR; - } - } - - mCameraRunning = native_start_preview(mCameraControlFd); - if(!mCameraRunning) { - deinitPreview(); - mPreviewInitialized = false; - LOGE("startPreview X: native_start_preview failed!"); - return UNKNOWN_ERROR; - } - - LOGV("startPreview X"); - return NO_ERROR; -} - -status_t QualcommCameraHardware::startPreview(preview_callback cb, void *user) -{ - LOGV("startPreview E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mPreviewCallback = cb; - mPreviewCallbackCookie = user; - } - - return startPreviewInternal(); -} - -void QualcommCameraHardware::stopPreviewInternal() -{ - LOGV("stopPreviewInternal E: %d", mCameraRunning); - if (mCameraRunning) { - // Cancel auto focus. - if (mAutoFocusCallback) { - { - Mutex::Autolock cbLock(&mCallbackLock); - mAutoFocusCallback = NULL; - mAutoFocusCallbackCookie = NULL; - } - cancelAutoFocus(); - } - - mCameraRunning = !native_stop_preview(mCameraControlFd); - if (!mCameraRunning && mPreviewInitialized) { - deinitPreview(); - mPreviewInitialized = false; - } - else LOGE("stopPreviewInternal: failed to stop preview"); - } - LOGV("stopPreviewInternal X: %d", mCameraRunning); -} - -void QualcommCameraHardware::stopPreview() -{ - LOGV("stopPreview: E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mPreviewCallback = NULL; - mPreviewCallbackCookie = NULL; - if(mRecordingCallback != NULL) - return; - } - - stopPreviewInternal(); - - LOGV("stopPreview: X"); -} - -void QualcommCameraHardware::runAutoFocus() -{ - mAutoFocusThreadLock.lock(); - mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR); - if (mAutoFocusFd < 0) { - LOGE("autofocus: cannot open %s: %s", - MSM_CAMERA_CONTROL, - strerror(errno)); - mAutoFocusThreadRunning = false; - mAutoFocusThreadLock.unlock(); - return; - } - -#if DLOPEN_LIBMMCAMERA - // We need to maintain a reference to libqcamera.so for the duration of the - // AF thread, because we do not know when it will exit relative to the - // lifetime of this object. We do not want to dlclose() libqcamera while - // LINK_cam_frame is still running. - void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW); - LOGV("AF: loading libqcamera at %p", libhandle); - if (!libhandle) { - LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror()); - close(mAutoFocusFd); - mAutoFocusFd = -1; - mAutoFocusThreadRunning = false; - mAutoFocusThreadLock.unlock(); - return; - } -#endif - - /* This will block until either AF completes or is cancelled. */ - LOGV("af start (fd %d)", mAutoFocusFd); - bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO); - LOGV("af done: %d", (int)status); - mAutoFocusThreadRunning = false; - close(mAutoFocusFd); - mAutoFocusFd = -1; - mAutoFocusThreadLock.unlock(); - - mCallbackLock.lock(); - autofocus_callback cb = mAutoFocusCallback; - void *data = mAutoFocusCallbackCookie; - mCallbackLock.unlock(); - if (cb != NULL) - cb(status, data); - - mCallbackLock.lock(); - mAutoFocusCallback = NULL; - mAutoFocusCallbackCookie = NULL; - mCallbackLock.unlock(); - -#if DLOPEN_LIBMMCAMERA - if (libhandle) { - ::dlclose(libhandle); - LOGV("AF: dlclose(libqcamera)"); - } -#endif -} - -void QualcommCameraHardware::cancelAutoFocus() -{ - LOGV("cancelAutoFocus E"); - native_cancel_afmode(mCameraControlFd, mAutoFocusFd); - LOGV("cancelAutoFocus X"); -} - -void *auto_focus_thread(void *user) -{ - LOGV("auto_focus_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runAutoFocus(); - } - else LOGW("not starting autofocus: the object went away!"); - LOGV("auto_focus_thread X"); - return NULL; -} - -status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb, - void *user) -{ - LOGV("autoFocus E"); - Mutex::Autolock l(&mLock); - - if (mCameraControlFd < 0) { - LOGE("not starting autofocus: main control fd %d", mCameraControlFd); - return UNKNOWN_ERROR; - } - - if (mAutoFocusCallback != NULL) { - LOGW("Auto focus is already in progress"); - return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION; - } - - { - Mutex::Autolock cbl(&mCallbackLock); - mAutoFocusCallback = af_cb; - mAutoFocusCallbackCookie = user; - } - - { - mAutoFocusThreadLock.lock(); - if (!mAutoFocusThreadRunning) { - // Create a detatched thread here so that we don't have to wait - // for it when we cancel AF. - pthread_t thr; - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mAutoFocusThreadRunning = - !pthread_create(&thr, &attr, - auto_focus_thread, NULL); - if (!mAutoFocusThreadRunning) { - LOGE("failed to start autofocus thread"); - mAutoFocusThreadLock.unlock(); - return UNKNOWN_ERROR; - } - } - mAutoFocusThreadLock.unlock(); - } - - LOGV("autoFocus X"); - return NO_ERROR; -} - -void QualcommCameraHardware::runSnapshotThread(void *data) -{ - LOGV("runSnapshotThread E"); - if (native_start_snapshot(mCameraControlFd)) - receiveRawPicture(); - else - LOGE("main: native_start_snapshot failed!"); - - mSnapshotThreadWaitLock.lock(); - mSnapshotThreadRunning = false; - mSnapshotThreadWait.signal(); - mSnapshotThreadWaitLock.unlock(); - - LOGV("runSnapshotThread X"); -} - -void *snapshot_thread(void *user) -{ - LOGD("snapshot_thread E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->runSnapshotThread(user); - } - else LOGW("not starting snapshot thread: the object went away!"); - LOGD("snapshot_thread X"); - return NULL; -} - -status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb, - raw_callback raw_cb, - jpeg_callback jpeg_cb, - void *user) -{ - LOGV("takePicture: E raw_cb = %p, jpeg_cb = %p", - raw_cb, jpeg_cb); - Mutex::Autolock l(&mLock); - - // Wait for old snapshot thread to complete. - mSnapshotThreadWaitLock.lock(); - while (mSnapshotThreadRunning) { - LOGV("takePicture: waiting for old snapshot thread to complete."); - mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); - LOGV("takePicture: old snapshot thread completed."); - } - - stopPreviewInternal(); - - if (!initRaw(jpeg_cb != NULL)) { - LOGE("initRaw failed. Not taking picture."); - return UNKNOWN_ERROR; - } - - { - Mutex::Autolock cbLock(&mCallbackLock); - mShutterCallback = shutter_cb; - mRawPictureCallback = raw_cb; - mJpegPictureCallback = jpeg_cb; - mPictureCallbackCookie = user; - } - - mShutterLock.lock(); - mShutterPending = true; - mShutterLock.unlock(); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - mSnapshotThreadRunning = !pthread_create(&mSnapshotThread, - &attr, - snapshot_thread, - NULL); - mSnapshotThreadWaitLock.unlock(); - - LOGV("takePicture: X"); - return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR; -} - -status_t QualcommCameraHardware::cancelPicture( - bool cancel_shutter, bool cancel_raw, bool cancel_jpeg) -{ - LOGV("cancelPicture: E cancel_shutter = %d, " - "cancel_raw = %d, cancel_jpeg = %d", - cancel_shutter, cancel_raw, cancel_jpeg); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - if (cancel_shutter) mShutterCallback = NULL; - if (cancel_raw) mRawPictureCallback = NULL; - if (cancel_jpeg) mJpegPictureCallback = NULL; - } - - LOGV("cancelPicture: X"); - return NO_ERROR; -} - -status_t QualcommCameraHardware::setParameters( - const CameraParameters& params) -{ - LOGV("setParameters: E params = %p", ¶ms); - - Mutex::Autolock l(&mLock); - - // Set preview size. - preview_size_type *ps = preview_sizes; - { - int width, height; - params.getPreviewSize(&width, &height); - LOGV("requested size %d x %d", width, height); - // Validate the preview size - size_t i; - for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) { - if (width == ps->width && height == ps->height) - break; - } - if (i == PREVIEW_SIZE_COUNT) { - LOGE("Invalid preview size requested: %dx%d", - width, height); - return BAD_VALUE; - } - } - mPreviewWidth = mDimension.display_width = ps->width; - mPreviewHeight = mDimension.display_height = ps->height; - - // FIXME: validate snapshot sizes, - params.getPictureSize(&mRawWidth, &mRawHeight); - mDimension.picture_width = mRawWidth; - mDimension.picture_height = mRawHeight; - - // Set up the jpeg-thumbnail-size parameters. - { - int val; - - val = params.getInt("jpeg-thumbnail-width"); - if (val < 0) { - mDimension.ui_thumbnail_width= THUMBNAIL_WIDTH; - LOGW("jpeg-thumbnail-width is not specified: defaulting to %d", - THUMBNAIL_WIDTH); - } - else mDimension.ui_thumbnail_width = val; - - val = params.getInt("jpeg-thumbnail-height"); - if (val < 0) { - mDimension.ui_thumbnail_height= THUMBNAIL_HEIGHT; - LOGW("jpeg-thumbnail-height is not specified: defaulting to %d", - THUMBNAIL_HEIGHT); - } - else mDimension.ui_thumbnail_height = val; - } - - mParameters = params; - - setAntibanding(); - setEffect(); - setWhiteBalance(); - // FIXME: set nightshot and luma adaptatiom - - LOGV("setParameters: X"); - return NO_ERROR ; -} - -CameraParameters QualcommCameraHardware::getParameters() const -{ - LOGV("getParameters: EX"); - return mParameters; -} - -extern "C" sp openCameraHardware() -{ - LOGV("openCameraHardware: call createInstance"); - return QualcommCameraHardware::createInstance(); -} - -wp QualcommCameraHardware::singleton; - -// If the hardware already exists, return a strong pointer to the current -// object. If not, create a new hardware object, put it in the singleton, -// and return it. -sp QualcommCameraHardware::createInstance() -{ - LOGD("createInstance: E"); - - Mutex::Autolock lock(&singleton_lock); - - // Wait until the previous release is done. - while (singleton_releasing) { - LOGD("Wait for previous release."); - singleton_wait.wait(singleton_lock); - } - - if (singleton != 0) { - sp hardware = singleton.promote(); - if (hardware != 0) { - LOGD("createInstance: X return existing hardware=%p", &(*hardware)); - return hardware; - } - } - - { - struct stat st; - int rc = stat("/dev/oncrpc", &st); - if (rc < 0) { - LOGD("createInstance: X failed to create hardware: %s", strerror(errno)); - return NULL; - } - } - - QualcommCameraHardware *cam = new QualcommCameraHardware(); - sp hardware(cam); - singleton = hardware; - - cam->startCamera(); - cam->initDefaultParameters(); - LOGD("createInstance: X created hardware=%p", &(*hardware)); - return hardware; -} - -// For internal use only, hence the strong pointer to the derived type. -sp QualcommCameraHardware::getInstance() -{ - sp hardware = singleton.promote(); - if (hardware != 0) { - // LOGV("getInstance: X old instance of hardware"); - return sp(static_cast(hardware.get())); - } else { - LOGV("getInstance: X new instance of hardware"); - return sp(); - } -} - -void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) -{ -// LOGV("receivePreviewFrame E"); - - if (!mCameraRunning) { - LOGE("ignoring preview callback--camera has been stopped"); - return; - } - - mCallbackLock.lock(); - preview_callback pcb = mPreviewCallback; - void *pdata = mPreviewCallbackCookie; - recording_callback rcb = mRecordingCallback; - void *rdata = mRecordingCallbackCookie; - mCallbackLock.unlock(); - - // Find the offset within the heap of the current buffer. - ssize_t offset = - (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); - offset /= mPreviewFrameSize; - - //LOGV("%d\n", offset); - - mInPreviewCallback = true; - if (pcb != NULL) - pcb(mPreviewHeap->mBuffers[offset], - pdata); - - if(rcb != NULL) { - Mutex::Autolock rLock(&mRecordFrameLock); - rcb(systemTime(), mPreviewHeap->mBuffers[offset], rdata); - if (mReleasedRecordingFrame != true) { - LOGV("block for release frame request/command"); - mRecordWait.wait(mRecordFrameLock); - } - mReleasedRecordingFrame = false; - } - mInPreviewCallback = false; - -// LOGV("receivePreviewFrame X"); -} - -status_t QualcommCameraHardware::startRecording( - recording_callback rcb, void *ruser) -{ - LOGV("startRecording E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mRecordingCallback = rcb; - mRecordingCallbackCookie = ruser; - } - - mReleasedRecordingFrame = false; - - return startPreviewInternal(); -} - -void QualcommCameraHardware::stopRecording() -{ - LOGV("stopRecording: E"); - Mutex::Autolock l(&mLock); - - { - Mutex::Autolock cbLock(&mCallbackLock); - mRecordingCallback = NULL; - mRecordingCallbackCookie = NULL; - - mRecordFrameLock.lock(); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - mRecordFrameLock.unlock(); - - if(mPreviewCallback != NULL) { - LOGV("stopRecording: X, preview still in progress"); - return; - } - } - - stopPreviewInternal(); - LOGV("stopRecording: X"); -} - -void QualcommCameraHardware::releaseRecordingFrame( - const sp& mem __attribute__((unused))) -{ - LOGV("releaseRecordingFrame E"); - Mutex::Autolock l(&mLock); - Mutex::Autolock rLock(&mRecordFrameLock); - mReleasedRecordingFrame = true; - mRecordWait.signal(); - LOGV("releaseRecordingFrame X"); -} - -bool QualcommCameraHardware::recordingEnabled() -{ - Mutex::Autolock l(&mLock); - return mCameraRunning && mRecordingCallback != NULL; -} - -void QualcommCameraHardware::notifyShutter() -{ - mShutterLock.lock(); - if (mShutterPending && mShutterCallback) { - mShutterCallback(mPictureCallbackCookie); - mShutterPending = false; - } - mShutterLock.unlock(); -} - -static void receive_shutter_callback() -{ - LOGV("receive_shutter_callback: E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->notifyShutter(); - } - LOGV("receive_shutter_callback: X"); -} - -void QualcommCameraHardware::receiveRawPicture() -{ - LOGV("receiveRawPicture: E"); - - Mutex::Autolock cbLock(&mCallbackLock); - - if (mRawPictureCallback != NULL) { - if(native_get_picture(mCameraControlFd, &mCrop) == false) { - LOGE("getPicture failed!"); - return; - } - - // By the time native_get_picture returns, picture is taken. Call - // shutter callback if cam config thread has not done that. - notifyShutter(); - mRawPictureCallback(mRawHeap->mBuffers[0], - mPictureCallbackCookie); - } - else LOGV("Raw-picture callback was canceled--skipping."); - - if (mJpegPictureCallback != NULL) { - mJpegSize = 0; - if (LINK_jpeg_encoder_init()) { - if(native_jpeg_encode()) { - LOGV("receiveRawPicture: X (success)"); - return; - } - LOGE("jpeg encoding failed"); - } - else LOGE("receiveRawPicture X: jpeg_encoder_init failed."); - } - else LOGV("JPEG callback is NULL, not encoding image."); - deinitRaw(); - LOGV("receiveRawPicture: X"); -} - -void QualcommCameraHardware::receiveJpegPictureFragment( - uint8_t *buff_ptr, uint32_t buff_size) -{ - uint32_t remaining = mJpegHeap->mHeap->virtualSize(); - remaining -= mJpegSize; - uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base(); - - LOGV("receiveJpegPictureFragment size %d", buff_size); - if (buff_size > remaining) { - LOGE("receiveJpegPictureFragment: size %d exceeds what " - "remains in JPEG heap (%d), truncating", - buff_size, - remaining); - buff_size = remaining; - } - memcpy(base + mJpegSize, buff_ptr, buff_size); - mJpegSize += buff_size; -} - -void QualcommCameraHardware::receiveJpegPicture(void) -{ - LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)", - mJpegSize, mJpegHeap->mBufferSize); - Mutex::Autolock cbLock(&mCallbackLock); - - int index = 0, rc; - - if (mJpegPictureCallback) { - // The reason we do not allocate into mJpegHeap->mBuffers[offset] is - // that the JPEG image's size will probably change from one snapshot - // to the next, so we cannot reuse the MemoryBase object. - sp buffer = new - MemoryBase(mJpegHeap->mHeap, - index * mJpegHeap->mBufferSize + - mJpegHeap->mFrameOffset, - mJpegSize); - - mJpegPictureCallback(buffer, mPictureCallbackCookie); - buffer = NULL; - } - else LOGV("JPEG callback was cancelled--not delivering image."); - - LINK_jpeg_encoder_join(); - deinitRaw(); - - LOGV("receiveJpegPicture: X callback done."); -} - -bool QualcommCameraHardware::previewEnabled() -{ -// Mutex::Autolock l(&mLock); - return mCameraRunning && mPreviewCallback != NULL; -} - -int QualcommCameraHardware::getParm( - const char *parm_str, const struct str_map *const parm_map) -{ - // Check if the parameter exists. - const char *str = mParameters.get(parm_str); - if (str == NULL) return NOT_FOUND; - - // Look up the parameter value. - return attr_lookup(parm_map, str); -} - -void QualcommCameraHardware::setEffect() -{ - int32_t value = getParm("effect", effect); - if (value != NOT_FOUND) { - native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value), (void *)&value); - } -} - -void QualcommCameraHardware::setWhiteBalance() -{ - int32_t value = getParm("whitebalance", whitebalance); - if (value != NOT_FOUND) { - native_set_parm(CAMERA_SET_PARM_WB, sizeof(value), (void *)&value); - } -} - -void QualcommCameraHardware::setAntibanding() -{ - camera_antibanding_type value = - (camera_antibanding_type) getParm("antibanding", antibanding); - native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(value), (void *)&value); -} - -QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - mBufferSize(buffer_size), - mNumBuffers(num_buffers), - mFrameSize(frame_size), - mFrameOffset(frame_offset), - mBuffers(NULL), mName(name) -{ - // empty -} - -void QualcommCameraHardware::MemPool::completeInitialization() -{ - // If we do not know how big the frame will be, we wait to allocate - // the buffers describing the individual frames until we do know their - // size. - - if (mFrameSize > 0) { - mBuffers = new sp[mNumBuffers]; - for (int i = 0; i < mNumBuffers; i++) { - mBuffers[i] = new - MemoryBase(mHeap, - i * mBufferSize + mFrameOffset, - mFrameSize); - } - } -} - -QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::MemPool(buffer_size, - num_buffers, - frame_size, - frame_offset, - name) -{ - LOGV("constructing MemPool %s backed by ashmem: " - "%d frames @ %d uint8_ts, offset %d, " - "buffer size %d", - mName, - num_buffers, frame_size, frame_offset, buffer_size); - - int page_mask = getpagesize() - 1; - int ashmem_size = buffer_size * num_buffers; - ashmem_size += page_mask; - ashmem_size &= ~page_mask; - - mHeap = new MemoryHeapBase(ashmem_size); - - completeInitialization(); -} - -static bool register_buf(int camfd, - int size, - int pmempreviewfd, - uint32_t offset, - uint8_t *buf, - int pmem_type, - bool register_buffer = true); - -QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, - int camera_control_fd, - int pmem_type, - int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name) : - QualcommCameraHardware::MemPool(buffer_size, - num_buffers, - frame_size, - frame_offset, - name), - mPmemType(pmem_type), - mCameraControlFd(dup(camera_control_fd)) -{ - LOGV("constructing MemPool %s backed by pmem pool %s: " - "%d frames @ %d bytes, offset %d, buffer size %d", - mName, - pmem_pool, num_buffers, frame_size, frame_offset, - buffer_size); - - LOGV("%s: duplicating control fd %d --> %d", - __FUNCTION__, - camera_control_fd, mCameraControlFd); - - // Make a new mmap'ed heap that can be shared across processes. - - mAlignedSize = clp2(buffer_size * num_buffers); - - sp masterHeap = - new MemoryHeapBase(pmem_pool, mAlignedSize, 0); - sp pmemHeap = new MemoryHeapPmem(masterHeap, 0); - if (pmemHeap->getHeapID() >= 0) { - pmemHeap->slap(); - masterHeap.clear(); - mHeap = pmemHeap; - pmemHeap.clear(); - - mFd = mHeap->getHeapID(); - if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { - LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", - pmem_pool, - ::strerror(errno), errno); - mHeap.clear(); - return; - } - - LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", - pmem_pool, - mFd, - mSize.len); - - // Unregister preview buffers with the camera drivers. - for (int cnt = 0; cnt < num_buffers; ++cnt) { - register_buf(mCameraControlFd, - buffer_size, - mHeap->getHeapID(), - buffer_size * cnt, - (uint8_t *)mHeap->base() + buffer_size * cnt, - pmem_type); - } - - completeInitialization(); - } - else LOGE("pmem pool %s error: could not create master heap!", - pmem_pool); -} - -QualcommCameraHardware::PmemPool::~PmemPool() -{ - LOGV("%s: %s E", __FUNCTION__, mName); - // Unregister preview buffers with the camera drivers. - for (int cnt = 0; cnt < mNumBuffers; ++cnt) { - register_buf(mCameraControlFd, - mBufferSize, - mHeap->getHeapID(), - mBufferSize * cnt, - (uint8_t *)mHeap->base() + mBufferSize * cnt, - mPmemType, - false /* unregister */); - } - LOGV("destroying PmemPool %s: closing control fd %d", - mName, - mCameraControlFd); - close(mCameraControlFd); - LOGV("%s: %s X", __FUNCTION__, mName); -} - -QualcommCameraHardware::MemPool::~MemPool() -{ - LOGV("destroying MemPool %s", mName); - if (mFrameSize > 0) - delete [] mBuffers; - mHeap.clear(); - LOGV("destroying MemPool %s completed", mName); -} - -static bool register_buf(int camfd, - int size, - int pmempreviewfd, - uint32_t offset, - uint8_t *buf, - int pmem_type, - bool register_buffer) -{ - struct msm_pmem_info pmemBuf; - - pmemBuf.type = pmem_type; - pmemBuf.fd = pmempreviewfd; - pmemBuf.offset = offset; - pmemBuf.len = size; - pmemBuf.vaddr = buf; - pmemBuf.y_off = 0; - pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3); - pmemBuf.active = true; - - LOGV("register_buf: camfd = %d, reg = %d buffer = %p", - camfd, !register_buffer, buf); - if (ioctl(camfd, - register_buffer ? - MSM_CAM_IOCTL_REGISTER_PMEM : - MSM_CAM_IOCTL_UNREGISTER_PMEM, - &pmemBuf) < 0) { - LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s", - camfd, - strerror(errno)); - return false; - } - return true; -} - -status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector& args) const -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); - result.append(buffer); - if (mName) { - snprintf(buffer, 255, "mem pool name (%s)\n", mName); - result.append(buffer); - } - if (mHeap != 0) { - snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", - mHeap->getBase(), mHeap->getSize(), - mHeap->getFlags(), mHeap->getDevice()); - result.append(buffer); - } - snprintf(buffer, 255, "buffer size (%d), number of buffers (%d)," - " frame size(%d), and frame offset(%d)\n", - mBufferSize, mNumBuffers, mFrameSize, mFrameOffset); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -static void receive_camframe_callback(struct msm_frame *frame) -{ - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receivePreviewFrame(frame); - } -} - -static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size) -{ - LOGV("receive_jpeg_fragment_callback E"); - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receiveJpegPictureFragment(buff_ptr, buff_size); - } - LOGV("receive_jpeg_fragment_callback X"); -} - -static void receive_jpeg_callback(jpeg_event_t status) -{ - LOGV("receive_jpeg_callback E (completion status %d)", status); - if (status == JPEG_EVENT_DONE) { - sp obj = QualcommCameraHardware::getInstance(); - if (obj != 0) { - obj->receiveJpegPicture(); - } - } - LOGV("receive_jpeg_callback X"); -} - -}; // namespace android diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h deleted file mode 100644 index a4fe43b..0000000 --- a/libcamera2/QualcommCameraHardware.h +++ /dev/null @@ -1,241 +0,0 @@ -/* -** Copyright 2008, Google Inc. -** -** 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 ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H -#define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H - -#include -#include -#include -#include - -extern "C" { -#include -#include -#include -} - -struct str_map { - const char *const desc; - int val; -}; - -namespace android { - -class QualcommCameraHardware : public CameraHardwareInterface { -public: - - virtual sp getPreviewHeap() const; - virtual sp getRawHeap() const; - - virtual status_t dump(int fd, const Vector& args) const; - virtual status_t startPreview(preview_callback cb, void* user); - virtual void stopPreview(); - virtual bool previewEnabled(); - virtual status_t startRecording(recording_callback cb, void* user); - virtual void stopRecording(); - virtual bool recordingEnabled(); - virtual void releaseRecordingFrame(const sp& mem); - virtual status_t autoFocus(autofocus_callback, void *user); - virtual status_t takePicture(shutter_callback, raw_callback, - jpeg_callback, void *); - virtual status_t cancelPicture(bool cancel_shutter, - bool cancel_raw, bool cancel_jpeg); - virtual status_t setParameters(const CameraParameters& params); - virtual CameraParameters getParameters() const; - virtual void release(); - - static sp createInstance(); - static sp getInstance(); - - void receivePreviewFrame(struct msm_frame *frame); - void receiveJpegPicture(void); - void jpeg_set_location(); - void receiveJpegPictureFragment(uint8_t *buf, uint32_t size); - void notifyShutter(); - -private: - QualcommCameraHardware(); - virtual ~QualcommCameraHardware(); - status_t startPreviewInternal(); - void stopPreviewInternal(); - friend void *auto_focus_thread(void *user); - void runAutoFocus(); - void cancelAutoFocus(); - bool native_set_dimension (int camfd); - bool native_jpeg_encode (void); - bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value); - bool native_set_dimension(cam_ctrl_dimension_t *value); - int getParm(const char *parm_str, const str_map *parm_map); - - static wp singleton; - - /* These constants reflect the number of buffers that libmmcamera requires - for preview and raw, and need to be updated when libmmcamera - changes. - */ - static const int kPreviewBufferCount = 4; - static const int kRawBufferCount = 1; - static const int kJpegBufferCount = 1; - - //TODO: put the picture dimensions in the CameraParameters object; - CameraParameters mParameters; - int mPreviewHeight; - int mPreviewWidth; - int mRawHeight; - int mRawWidth; - unsigned int frame_size; - bool mCameraRunning; - bool mPreviewInitialized; - - // This class represents a heap which maintains several contiguous - // buffers. The heap may be backed by pmem (when pmem_pool contains - // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL). - - struct MemPool : public RefBase { - MemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - - virtual ~MemPool() = 0; - - void completeInitialization(); - bool initialized() const { - return mHeap != NULL && mHeap->base() != MAP_FAILED; - } - - virtual status_t dump(int fd, const Vector& args) const; - - int mBufferSize; - int mNumBuffers; - int mFrameSize; - int mFrameOffset; - sp mHeap; - sp *mBuffers; - - const char *mName; - }; - - struct AshmemPool : public MemPool { - AshmemPool(int buffer_size, int num_buffers, - int frame_size, - int frame_offset, - const char *name); - }; - - struct PmemPool : public MemPool { - PmemPool(const char *pmem_pool, - int control_camera_fd, int pmem_type, - int buffer_size, int num_buffers, - int frame_size, int frame_offset, - const char *name); - virtual ~PmemPool(); - int mFd; - int mPmemType; - int mCameraControlFd; - uint32_t mAlignedSize; - struct pmem_region mSize; - }; - - sp mPreviewHeap; - sp mThumbnailHeap; - sp mRawHeap; - sp mJpegHeap; - - void startCamera(); - bool initPreview(); - void deinitPreview(); - bool initRaw(bool initJpegHeap); - void deinitRaw(); - - bool mFrameThreadRunning; - Mutex mFrameThreadWaitLock; - Condition mFrameThreadWait; - friend void *frame_thread(void *user); - void runFrameThread(void *data); - - bool mShutterPending; - Mutex mShutterLock; - - bool mSnapshotThreadRunning; - Mutex mSnapshotThreadWaitLock; - Condition mSnapshotThreadWait; - friend void *snapshot_thread(void *user); - void runSnapshotThread(void *data); - - void initDefaultParameters(); - - void setAntibanding(); - void setEffect(); - void setWhiteBalance(); - - Mutex mLock; - bool mReleasedRecordingFrame; - - void receiveRawPicture(void); - - Mutex mCallbackLock; - Mutex mRecordLock; - Mutex mRecordFrameLock; - Condition mRecordWait; - Condition mStateWait; - - /* mJpegSize keeps track of the size of the accumulated JPEG. We clear it - when we are about to take a picture, so at any time it contains either - zero, or the size of the last JPEG picture taken. - */ - uint32_t mJpegSize; - - shutter_callback mShutterCallback; - raw_callback mRawPictureCallback; - jpeg_callback mJpegPictureCallback; - void *mPictureCallbackCookie; - - autofocus_callback mAutoFocusCallback; - void *mAutoFocusCallbackCookie; - - preview_callback mPreviewCallback; - void *mPreviewCallbackCookie; - recording_callback mRecordingCallback; - void *mRecordingCallbackCookie; - unsigned int mPreviewFrameSize; - int mRawSize; - int mJpegMaxSize; - -#if DLOPEN_LIBMMCAMERA - void *libmmcamera; -#endif - - int mCameraControlFd; - cam_ctrl_dimension_t mDimension; - bool mAutoFocusThreadRunning; - Mutex mAutoFocusThreadLock; - int mAutoFocusFd; - - pthread_t mCamConfigThread; - pthread_t mFrameThread; - pthread_t mSnapshotThread; - - common_crop_t mCrop; - - struct msm_frame frames[kPreviewBufferCount]; - bool mInPreviewCallback; -}; - -}; // namespace android - -#endif diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index f6a1b4b..36b1416 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -16,10 +16,27 @@ LOCAL_PATH:= $(call my-dir) # HAL module implemenation, not prelinked and stored in # hw/..so + +ifeq ($(TARGET_BOARD_PLATFORM),msm7k) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SRC_FILES := copybit.c +LOCAL_SRC_FILES := copybit.cpp LOCAL_MODULE := copybit.msm7k +LOCAL_C_INCLUDES += hardware/msm7k/libgralloc +LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 include $(BUILD_SHARED_LIBRARY) +endif + +ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) +include $(CLEAR_VARS) +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 += hardware/libhardware/modules/gralloc +LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 +include $(BUILD_SHARED_LIBRARY) +endif diff --git a/libcopybit/copybit.c b/libcopybit/copybit.cpp similarity index 77% rename from libcopybit/copybit.c rename to libcopybit/copybit.cpp index 3565074..ba8531b 100644 --- a/libcopybit/copybit.c +++ b/libcopybit/copybit.cpp @@ -34,6 +34,20 @@ #include +#include "gralloc_priv.h" + +#define DEBUG_MDP_ERRORS 1 + +/******************************************************************************/ + +#if defined(COPYBIT_MSM7K) +#define MAX_SCALE_FACTOR (4) +#elif defined(COPYBIT_QSD8K) +#define MAX_SCALE_FACTOR (8) +#else +#error "Unsupported MDP version" +#endif + /******************************************************************************/ /** State information for each device instance */ @@ -52,21 +66,21 @@ 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 + open: open_copybit }; /* * The COPYBIT Module */ -const 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, +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 } }; @@ -103,9 +117,11 @@ static void intersect(struct copybit_rect_t *out, /** convert COPYBIT_FORMAT to MDP format */ static int get_format(int format) { switch (format) { + case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; + case COPYBIT_FORMAT_RGBX_8888: return MDP_RGBX_8888; + case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; } @@ -113,15 +129,27 @@ static int get_format(int format) { } /** convert from copybit image to mdp image structure */ -static void set_image(struct mdp_img *img, - const struct copybit_image_t *rhs) { +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 = rhs->offset; - img->memory_id = rhs->fd; + img->offset = hnd->offset; +#if defined(COPYBIT_MSM7K) + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + img->memory_id = hnd->gpu_fd; + if (img->format == MDP_RGBA_8888) { + // msm7201A GPU only supports BGRA_8888 destinations + img->format = MDP_BGRA_8888; + } + } else { + img->memory_id = hnd->fd; + } +#else + img->memory_id = hnd->fd; +#endif } - /** setup rectangles */ static void set_rects(struct copybit_context_t *dev, struct mdp_blit_req *e, @@ -166,7 +194,7 @@ static void set_rects(struct copybit_context_t *dev, static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { req->alpha = dev->mAlpha; req->transp_mask = MDP_TRANSP_NOP; - req->flags = dev->mFlags; + req->flags = dev->mFlags | MDP_BLEND_FG_PREMULT; } /** copy the bits */ @@ -175,10 +203,37 @@ 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) + if (err == 0) { return 0; - else + } else { +#if DEBUG_MDP_ERRORS + struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list; + for (int i=0 ; icount ; 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; + } } /*****************************************************************************/ @@ -257,10 +312,10 @@ static int get(struct copybit_device_t *dev, int name) if (ctx) { switch(name) { case COPYBIT_MINIFICATION_LIMIT: - value = 4; + value = MAX_SCALE_FACTOR; break; case COPYBIT_MAGNIFICATION_LIMIT: - value = 4; + value = MAX_SCALE_FACTOR; break; case COPYBIT_SCALING_FRAC_BITS: value = 32; @@ -304,7 +359,13 @@ static int stretch_copybit( 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; + } + 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; @@ -312,10 +373,18 @@ static int stretch_copybit( status = 0; while ((status == 0) && region->next(region, &clip)) { intersect(&clip, &bounds, &clip); - set_infos(ctx, &list.req[list.count]); - set_image(&list.req[list.count].dst, dst); - set_image(&list.req[list.count].src, src); - set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip); + mdp_blit_req* req = &list.req[list.count]; + set_infos(ctx, req); + set_image(&req->dst, dst); + set_image(&req->src, src); + set_rects(ctx, req, dst_rect, src_rect, &clip); + + 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; @@ -360,12 +429,13 @@ static int open_copybit(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { int status = -EINVAL; - struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t)); + 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 = 0; - ctx->device.common.module = module; + ctx->device.common.version = 1; + ctx->device.common.module = const_cast(module); ctx->device.common.close = close_copybit; ctx->device.set_parameter = set_parameter_copybit; ctx->device.get = get; diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk new file mode 100644 index 0000000..d5ffa42 --- /dev/null +++ b/libgralloc-qsd8k/Android.mk @@ -0,0 +1,32 @@ +# 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/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM + +LOCAL_SRC_FILES := \ + allocator.cpp \ + gralloc.cpp \ + framebuffer.cpp \ + mapper.cpp + +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" +include $(BUILD_SHARED_LIBRARY) diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp new file mode 100644 index 0000000..4dad6a1 --- /dev/null +++ b/libgralloc-qsd8k/allocator.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2009 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 "allocator.h" + + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator() + : mHeapSize(0) +{ +} + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) + : mHeapSize(0) +{ + setSize(size); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +ssize_t SimpleBestFitAllocator::setSize(size_t size) +{ + Locker::Autolock _l(mLock); + if (mHeapSize != 0) return -EINVAL; + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); + return size; +} + + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; + ssize_t offset = alloc(size, flags); + return offset; +} + +ssize_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; + chunk_t const * const freed = dealloc(offset); + if (freed) { + return 0; + } + return -ENOENT; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + return -ENOMEM; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + #ifndef NDEBUG + if (!freed->free) { + dump_l("dealloc (!freed->free)"); + } + #endif + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h new file mode 100644 index 0000000..b0d89e9 --- /dev/null +++ b/libgralloc-qsd8k/allocator.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2009 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_ALLOCATOR_H_ +#define GRALLOC_ALLOCATOR_H_ + +#include +#include + +#include "gr.h" + +// ---------------------------------------------------------------------------- + +/* + * A simple templatized doubly linked-list implementation + */ + +template +class LinkedList +{ + NODE* mFirst; + NODE* mLast; + +public: + LinkedList() : mFirst(0), mLast(0) { } + bool isEmpty() const { return mFirst == 0; } + NODE const* head() const { return mFirst; } + NODE* head() { return mFirst; } + NODE const* tail() const { return mLast; } + NODE* tail() { return mLast; } + + void insertAfter(NODE* node, NODE* newNode) { + newNode->prev = node; + newNode->next = node->next; + if (node->next == 0) mLast = newNode; + else node->next->prev = newNode; + node->next = newNode; + } + + void insertBefore(NODE* node, NODE* newNode) { + newNode->prev = node->prev; + newNode->next = node; + if (node->prev == 0) mFirst = newNode; + else node->prev->next = newNode; + node->prev = newNode; + } + + void insertHead(NODE* newNode) { + if (mFirst == 0) { + mFirst = mLast = newNode; + newNode->prev = newNode->next = 0; + } else { + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; + } + } + + void insertTail(NODE* newNode) { + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } + } + + NODE* remove(NODE* node) { + if (node->prev == 0) mFirst = node->next; + else node->prev->next = node->next; + if (node->next == 0) mLast = node->prev; + else node->next->prev = node->prev; + return node; + } +}; + +class SimpleBestFitAllocator +{ +public: + + SimpleBestFitAllocator(); + SimpleBestFitAllocator(size_t size); + ~SimpleBestFitAllocator(); + + ssize_t setSize(size_t size); + + ssize_t allocate(size_t size, uint32_t flags = 0); + ssize_t deallocate(size_t offset); + size_t size() const; + +private: + struct chunk_t { + chunk_t(size_t start, size_t size) + : start(start), size(size), free(1), prev(0), next(0) { + } + size_t start; + size_t size : 28; + int free : 4; + mutable chunk_t* prev; + mutable chunk_t* next; + }; + + ssize_t alloc(size_t size, uint32_t flags); + chunk_t* dealloc(size_t start); + + static const int kMemoryAlign; + mutable Locker mLock; + LinkedList mList; + size_t mHeapSize; +}; + +#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp new file mode 100644 index 0000000..797982f --- /dev/null +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -0,0 +1,437 @@ +/* + * 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 + +#include +#include + +#include + +#include "gralloc_priv.h" +#include "gr.h" + +/*****************************************************************************/ + +// numbers of buffers for page flipping +#define NUM_BUFFERS 2 + + +enum { + PAGE_FLIP = 0x00000001, + LOCKED = 0x00000002 +}; + +struct fb_context_t { + framebuffer_device_t device; +}; + +/*****************************************************************************/ + +static void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h); + +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_setUpdateRect(struct framebuffer_device_t* dev, + int l, int t, int w, int h) +{ + if (((w|h) <= 0) || ((l|t)<0)) + return -EINVAL; + + fb_context_t* ctx = (fb_context_t*)dev; + private_module_t* m = reinterpret_cast( + dev->common.module); + m->info.reserved[0] = 0x54445055; // "UPDT"; + m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); + m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); + 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 = reinterpret_cast(buffer); + private_module_t* m = reinterpret_cast( + dev->common.module); + + if (m->currentBuffer) { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + + m->base.lock(&m->base, buffer, + private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("FBIOPUT_VSCREENINFO failed"); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + + } else { + // If we can't do the page_flip, just copy the buffer to the front + // FIXME: use copybit HAL instead of memcpy + + void* fb_vaddr; + void* buffer_vaddr; + + 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, + 0, 0, m->info.xres, m->info.yres, + &buffer_vaddr); + + //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + msm_copy_buffer(m->framebuffer, m->framebuffer->fd, + m->info.xres, m->info.yres, + 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); + } + + return 0; +} + +static int fb_compositionComplete(struct framebuffer_device_t* dev) +{ + // STOPSHIP: Properly implement composition complete callback + glFinish(); + + return 0; +} + +/*****************************************************************************/ + +int mapFrameBufferLocked(struct private_module_t* module) +{ + // already initialized... + if (module->framebuffer) { + return 0; + } + + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char name[64]; + + while ((fd==-1) && device_template[i]) { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + if (fd < 0) + return -errno; + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + + /* + * 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; + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); + } + + if (info.yres_virtual < info.yres * 2) { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", + info.yres_virtual, info.yres*2); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + return -errno; + + int refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres ) + * ( info.left_margin + info.right_margin + info.xres ) + * info.pixclock + ); + + if (refreshRate == 0) { + // bleagh, bad info from the driver + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + LOGI( "using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length + ); + + LOGI( "width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps + ); + + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + return -errno; + + if (finfo.smem_len <= 0) + return -errno; + + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + + /* + * map the framebuffer + */ + + int err; + size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); + module->framebuffer = new private_handle_t(dup(fd), fbSize, + private_handle_t::PRIV_FLAGS_USES_PMEM); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) { + LOGE("Error mapping the framebuffer (%s)", strerror(errno)); + return -errno; + } + module->framebuffer->base = intptr_t(vaddr); + module->framebuffer->phys = intptr_t(finfo.smem_start); + memset(vaddr, 0, fbSize); + return 0; +} + +static int mapFrameBuffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = mapFrameBufferLocked(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; + if (ctx) { + free(ctx); + } + return 0; +} + +int fb_device_open(hw_module_t const* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_FB0)) { + alloc_device_t* gralloc_device; + status = gralloc_open(module, &gralloc_device); + if (status < 0) + return status; + + /* 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; + dev->device.compositionComplete = fb_compositionComplete; + + private_module_t* m = (private_module_t*)module; + status = mapFrameBuffer(m); + if (status >= 0) { + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast(dev->device.flags) = 0; + const_cast(dev->device.width) = m->info.xres; + const_cast(dev->device.height) = m->info.yres; + const_cast(dev->device.stride) = 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; + + if (m->finfo.reserved[0] == 0x5444 && + m->finfo.reserved[1] == 0x5055) { + dev->device.setUpdateRect = fb_setUpdateRect; + LOGD("UPDATE_ON_DEMAND supported"); + } + + *device = &dev->device.common; + } + } + return status; +} + +/* Copy a pmem buffer to the framebuffer */ + +static void +msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, + int x, int y, int w, int h) +{ + struct { + unsigned int count; + mdp_blit_req req; + } blit; + private_handle_t *priv = (private_handle_t*) handle; + + memset(&blit, 0, sizeof(blit)); + blit.count = 1; + + blit.req.flags = 0; + blit.req.alpha = 0xff; + blit.req.transp_mask = 0xffffffff; + + blit.req.src.width = width; + blit.req.src.height = height; + blit.req.src.offset = 0; + blit.req.src.memory_id = priv->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.format = MDP_RGB_565; + + blit.req.src_rect.x = blit.req.dst_rect.x = x; + blit.req.src_rect.y = blit.req.dst_rect.y = y; + blit.req.src_rect.w = blit.req.dst_rect.w = w; + blit.req.src_rect.h = blit.req.dst_rect.h = h; + + if (ioctl(fd, MSMFB_BLIT, &blit)) + LOGE("MSMFB_BLIT failed = %d", -errno); +} diff --git a/libgralloc-qsd8k/gr.h b/libgralloc-qsd8k/gr.h new file mode 100644 index 0000000..1775bfa --- /dev/null +++ b/libgralloc-qsd8k/gr.h @@ -0,0 +1,63 @@ +/* + * 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 GR_H_ +#define GR_H_ + +#include +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include +#else +# include +#endif +#include +#include +#include +#include +#include + +#include + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +inline size_t roundUpToPageSize(size_t x) { + return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); +} + +int mapFrameBufferLocked(struct private_module_t* module); +int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); + +/*****************************************************************************/ + +class Locker { + pthread_mutex_t mutex; +public: + class Autolock { + Locker& locker; + public: + inline Autolock(Locker& locker) : locker(locker) { locker.lock(); } + inline ~Autolock() { locker.unlock(); } + }; + inline Locker() { pthread_mutex_init(&mutex, 0); } + inline ~Locker() { pthread_mutex_destroy(&mutex); } + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } +}; + +#endif /* GR_H_ */ diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp new file mode 100644 index 0000000..45746ef --- /dev/null +++ b/libgralloc-qsd8k/gralloc.cpp @@ -0,0 +1,490 @@ +/* + * 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 +#include + +#include +#include + +#include "gralloc_priv.h" +#include "allocator.h" + +#if HAVE_ANDROID_OS +#include +#endif + +/*****************************************************************************/ + +static SimpleBestFitAllocator sAllocator; + +/*****************************************************************************/ + +struct gralloc_context_t { + alloc_device_t device; + /* our private data here */ +}; + +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, ... ); + +/*****************************************************************************/ + +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, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: 0, + pmem_master: -1, + pmem_master_base: 0, + master_phys: 0 +}; + +/*****************************************************************************/ + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + + // allocate the framebuffer + if (m->framebuffer == NULL) { + // initialize the framebuffer, the framebuffer is mapped once + // and forever. + int err = 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(dev, bufferSize, newUsage, pHandle); + } + + if (bufferMask >= ((1LU<framebuffer->base); + private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, + private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_FRAMEBUFFER); + + // find a free slot + for (uint32_t i=0 ; ibufferMask |= (1LU<base = vaddr; + hnd->offset = vaddr - intptr_t(m->framebuffer->base); + hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); + pthread_mutex_unlock(&m->lock); + return err; +} + + +static int init_pmem_area_locked(private_module_t* m) +{ + int err = 0; + int master_fd = open("/dev/pmem", O_RDWR, 0); + if (master_fd >= 0) { + size_t size; + pmem_region region; + if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { + LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode"); + size = 8<<20; // 8 MiB + } else { + size = region.len; + } + sAllocator.setSize(size); + + void* base = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + if (base == MAP_FAILED) { + err = -errno; + base = 0; + close(master_fd); + master_fd = -1; + } else { + // FIXME: get physical address, eventually this will have to go away + pmem_region region; + err = ioctl(master_fd, PMEM_GET_PHYS, ®ion); + if (err < 0) { + LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno)); + } else { + m->master_phys = (unsigned long)region.offset; + } + } + m->pmem_master = master_fd; + m->pmem_master_base = base; + } else { + err = -errno; + } + return err; +} + +static int init_pmem_area(private_module_t* m) +{ + pthread_mutex_lock(&m->lock); + int err = m->pmem_master; + if (err == -1) { + // first time, try to initialize pmem + err = init_pmem_area_locked(m); + if (err) { + m->pmem_master = err; + } + } else if (err < 0) { + // pmem couldn't be initialized, never use it + } else { + // pmem OK + err = 0; + } + pthread_mutex_unlock(&m->lock); + return err; +} + +static int gralloc_alloc_buffer(alloc_device_t* dev, + size_t size, int usage, buffer_handle_t* pHandle) +{ + int err = 0; + int flags = 0; + + int fd = -1; + void* base = 0; + int offset = 0; + int lockState = 0; + + size = roundUpToPageSize(size); + + 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; + } + + if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { +try_ashmem: + fd = ashmem_create_region("gralloc-buffer", size); + if (fd < 0) { + LOGE("couldn't create ashmem (%s)", strerror(errno)); + err = -errno; + } + } else { + private_module_t* m = reinterpret_cast( + dev->common.module); + + err = init_pmem_area(m); + if (err == 0) { + // PMEM buffers are always mmapped + base = m->pmem_master_base; + lockState |= private_handle_t::LOCK_STATE_MAPPED; + + offset = sAllocator.allocate(size); + if (offset < 0) { + // no more pmem memory + err = -ENOMEM; + } else { + struct pmem_region sub = { offset, size }; + + // now create the "sub-heap" + fd = open("/dev/pmem", O_RDWR, 0); + err = fd < 0 ? fd : 0; + + // and connect to it + if (err == 0) + err = ioctl(fd, PMEM_CONNECT, m->pmem_master); + + // and make it available to the client process + if (err == 0) + err = ioctl(fd, PMEM_MAP, &sub); + + if (err < 0) { + err = -errno; + close(fd); + sAllocator.deallocate(offset); + fd = -1; + } + memset((char*)base + offset, 0, size); + //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); + } + } else { + if ((usage & GRALLOC_USAGE_HW_2D) == 0) { + // the caller didn't request PMEM, so we can try something else + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + err = 0; + goto try_ashmem; + } else { + LOGE("couldn't open pmem (%s)", strerror(errno)); + } + } + } + + 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; + if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + private_module_t* m = reinterpret_cast( + dev->common.module); + hnd->phys = m->master_phys + offset; + } + *pHandle = hnd; + } + + LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); + + return err; +} + +/*****************************************************************************/ + +static int gralloc_alloc(alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* pHandle, int* pStride) +{ + if (!pHandle || !pStride) + return -EINVAL; + + size_t size, alignedw, alignedh; + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || + format == HAL_PIXEL_FORMAT_YCbCr_422_SP) + { + // FIXME: there is no way to return the alignedh + alignedw = (w + 1) & ~1; + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + size = alignedw * h * 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + alignedh = (h+1) & ~1; + size = (alignedw * alignedh) + (w/2 * h/2) * 2; + break; + default: + return -EINVAL; + } + } else { + alignedw = (w + 31) & ~31; + alignedh = (h + 31) & ~31; + int bpp = 0; + 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 = alignedw * alignedh * bpp; + } + + int err; + if (usage & GRALLOC_USAGE_HW_FB) { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); + } else { + err = gralloc_alloc_buffer(dev, size, usage, pHandle); + } + + if (err < 0) { + return err; + } + + *pStride = alignedw; + return 0; +} + +static int 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(handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { + // free this buffer + private_module_t* m = reinterpret_cast( + dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = (hnd->base - m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + if (hnd->fd >= 0) { + struct pmem_region sub = { hnd->offset, hnd->size }; + int err = ioctl(hnd->fd, PMEM_UNMAP, &sub); + LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " + "fd=%d, sub.offset=%lu, sub.size=%lu", + strerror(errno), hnd->fd, hnd->offset, hnd->size); + if (err == 0) { + // we can't deallocate the memory in case of UNMAP failure + // because it would give that process access to someone else's + // surfaces, which would be a security breach. + sAllocator.deallocate(hnd->offset); + } + } + } + + gralloc_module_t* module = reinterpret_cast( + dev->common.module); + terminateBuffer(module, const_cast(hnd)); + } + + close(hnd->fd); + delete hnd; + return 0; +} + +/*****************************************************************************/ + +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. + */ + free(ctx); + } + return 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)) { + gralloc_context_t *dev; + dev = (gralloc_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(module); + dev->device.common.close = gralloc_close; + + dev->device.alloc = gralloc_alloc; + dev->device.free = gralloc_free; + + *device = &dev->device.common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h new file mode 100644 index 0000000..534b4c0 --- /dev/null +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -0,0 +1,140 @@ +/* + * 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 + +/*****************************************************************************/ + +struct private_module_t; +struct private_handle_t; + +struct private_module_t { + gralloc_module_t base; + + struct private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int pmem_master; + void* pmem_master_base; + unsigned long master_phys; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + + enum { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +struct private_handle_t : public native_handle { +#else +struct private_handle_t { + native_handle_t nativeHandle; +#endif + + enum { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_PMEM = 0x00000002, + }; + + enum { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; + + // file-descriptors + int fd; + // ints + int magic; + int flags; + int size; + int offset; + int gpu_fd; // stored as an int, b/c we don't want it marshalled + + // FIXME: the attributes below should be out-of-line + int base; + int lockState; + int writeOwner; + int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care + int pid; + +#ifdef __cplusplus + static const int sNumInts = 10; + 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), phys(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts; + numFds = sNumFds; + } + ~private_handle_t() { + magic = 0; + } + + bool usesPhysicallyContiguousMemory() { + return (flags & PRIV_FLAGS_USES_PMEM) != 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; + } + + static private_handle_t* dynamicCast(const native_handle* in) { + if (validate(in) == 0) { + return (private_handle_t*) in; + } + return NULL; + } +#endif +}; + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp new file mode 100644 index 0000000..8c199b3 --- /dev/null +++ b/libgralloc-qsd8k/mapper.cpp @@ -0,0 +1,322 @@ +/* + * 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 + +#include "gralloc_priv.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 +pid_t gettid() { return syscall(__NR_gettid);} +#undef __KERNEL__ +#endif + +/*****************************************************************************/ + +static int gralloc_map(gralloc_module_t const* module, + buffer_handle_t handle, + void** vaddr) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + size_t size = hnd->size; +#if PMEM_HACK + size += hnd->offset; +#endif + void* mappedAddress = mmap(0, size, + PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + if (mappedAddress == MAP_FAILED) { + LOGE("Could not mmap handle %p, fd=%d (%s)", + handle, hnd->fd, strerror(errno)); + hnd->base = 0; + return -errno; + } + hnd->base = intptr_t(mappedAddress) + hnd->offset; + //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + // hnd->fd, hnd->offset, hnd->size, mappedAddress); + } + *vaddr = (void*)hnd->base; + return 0; +} + +static int gralloc_unmap(gralloc_module_t const* module, + buffer_handle_t handle) +{ + private_handle_t* hnd = (private_handle_t*)handle; + if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + 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)); + } + } + hnd->base = 0; + return 0; +} + +/*****************************************************************************/ + +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; + +/*****************************************************************************/ + +int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + // In this implementation, we don't need to do anything here + + /* 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 + * 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; + if (hnd->pid != getpid()) { + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + /* + * If the buffer has been mapped during a lock operation, it's time + * to un-map it. It's an error to be here with a locked buffer. + * NOTE: the framebuffer is handled differently and is never unmapped. + */ + + 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); + + // never unmap buffers that were created in this process + if (hnd->pid != getpid()) { + if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { + gralloc_unmap(module, handle); + } + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + } + return 0; +} + +int terminateBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + /* + * If the buffer has been mapped during a lock operation, it's time + * to un-map it. It's an error to be here with a locked buffer. + */ + + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, + "[terminate] handle %p still locked (state=%08x)", + hnd, hnd->lockState); + + 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) { + if (hnd->pid != getpid()) { + // ... unless it's a "master" pmem buffer, that is a buffer + // mapped in the process it's been allocated. + // (see gralloc_alloc_buffer()) + gralloc_unmap(module, hnd); + } + } else { + gralloc_unmap(module, hnd); + } + } + + return 0; +} + +int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + int err = 0; + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + int retry; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_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) { + // already locked for read + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + LOGE("handle %p already locked for read", handle); + return -EBUSY; + } else { + // this is not an error + //LOGD("%p already locked for read... count = %d", + // handle, (current_value & ~(1<<31))); + } + } + + // not currently locked + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { + // locking for write + new_value |= private_handle_t::LOCK_STATE_WRITE; + } + new_value++; + + retry = android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState); + } while (retry); + + if (new_value & private_handle_t::LOCK_STATE_WRITE) { + // locking for write, store the tid + hnd->writeOwner = gettid(); + } + + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { + if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { + // we need to map for real + pthread_mutex_t* const lock = &sMapLock; + pthread_mutex_lock(lock); + if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { + err = gralloc_map(module, handle, vaddr); + if (err == 0) { + android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, + (volatile int32_t*)&(hnd->lockState)); + } + } + pthread_mutex_unlock(lock); + } + *vaddr = (void*)hnd->base; + } + + return err; +} + +int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + return -EINVAL; + + private_handle_t* hnd = (private_handle_t*)handle; + int32_t current_value, new_value; + + do { + current_value = hnd->lockState; + new_value = current_value; + + if (current_value & private_handle_t::LOCK_STATE_WRITE) { + // locked for write + if (hnd->writeOwner == gettid()) { + hnd->writeOwner = 0; + new_value &= ~private_handle_t::LOCK_STATE_WRITE; + } + } + + if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { + LOGE("handle %p not locked", handle); + return -EINVAL; + } + + new_value--; + + } while (android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState)); + + return 0; +} + +/*****************************************************************************/ + +int gralloc_perform(struct gralloc_module_t const* module, + int operation, ... ) +{ + int res = -EINVAL; + va_list args; + 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*); + native_handle_t** handle = va_arg(args, native_handle_t**); + 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 = private_handle_t::PRIV_FLAGS_USES_PMEM; + hnd->size = size; + hnd->offset = offset; + hnd->base = intptr_t(base) + offset; + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + *handle = (native_handle_t *)hnd; + res = 0; + break; + } + } + + va_end(args); + return res; +} From 1e1a87f0a59831bf8c267393b5829f2cc6955d4f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 3 Nov 2009 18:42:05 -0800 Subject: [PATCH 194/435] part of fix [2186418] switch qsd8k devices to 24-bits framebuffer Add support for 32 bits framebuffers --- libgralloc-qsd8k/framebuffer.cpp | 42 +++++++++++++++++++------------- libgralloc-qsd8k/gralloc.cpp | 1 + libgralloc-qsd8k/gralloc_priv.h | 1 + 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 797982f..d9cc89e 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -59,7 +59,8 @@ struct fb_context_t { /*****************************************************************************/ static void -msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, +msm_copy_buffer(buffer_handle_t handle, int fd, + int width, int height, int format, int x, int y, int w, int h); static int fb_setSwapInterval(struct framebuffer_device_t* dev, @@ -120,9 +121,6 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->currentBuffer = buffer; } else { - // If we can't do the page_flip, just copy the buffer to the front - // FIXME: use copybit HAL instead of memcpy - void* fb_vaddr; void* buffer_vaddr; @@ -138,8 +136,9 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); - msm_copy_buffer(m->framebuffer, m->framebuffer->fd, - m->info.xres, m->info.yres, + msm_copy_buffer( + m->framebuffer, m->framebuffer->fd, + m->info.xres, m->info.yres, m->fbFormat, m->info.xoffset, m->info.yoffset, m->info.width, m->info.height); @@ -199,18 +198,26 @@ int mapFrameBufferLocked(struct private_module_t* module) info.yoffset = 0; info.activate = FB_ACTIVATE_NOW; + /* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. This implies + * big-endian byte order if bits_per_pixel is greater than 8. + */ + /* - * Explicitly request 5/6/5 + * Explicitly request RGBA_8888 */ - 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.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 = 0; + module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) @@ -378,7 +385,7 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.width) = m->info.xres; const_cast(dev->device.height) = m->info.yres; const_cast(dev->device.stride) = stride; - const_cast(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565; + const_cast(dev->device.format) = m->fbFormat; const_cast(dev->device.xdpi) = m->xdpi; const_cast(dev->device.ydpi) = m->ydpi; const_cast(dev->device.fps) = m->fps; @@ -400,7 +407,8 @@ int fb_device_open(hw_module_t const* module, const char* name, /* Copy a pmem buffer to the framebuffer */ static void -msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, +msm_copy_buffer(buffer_handle_t handle, int fd, + int width, int height, int format, int x, int y, int w, int h) { struct { @@ -425,7 +433,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, blit.req.dst.height = height; blit.req.dst.offset = 0; blit.req.dst.memory_id = fd; - blit.req.dst.format = MDP_RGB_565; + blit.req.dst.format = format; blit.req.src_rect.x = blit.req.dst_rect.x = x; blit.req.src_rect.y = blit.req.dst_rect.y = y; diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 45746ef..32bd24a 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -104,6 +104,7 @@ struct private_module_t HAL_MODULE_INFO_SYM = { perform: gralloc_perform, }, framebuffer: 0, + fbFormat: 0, flags: 0, numBuffers: 0, bufferMask: 0, diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 534b4c0..1432c25 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -38,6 +38,7 @@ struct private_module_t { gralloc_module_t base; struct private_handle_t* framebuffer; + uint32_t fbFormat; uint32_t flags; uint32_t numBuffers; uint32_t bufferMask; From be6f97aad3028ff5f8db59b219dc292ac511f590 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Tue, 1 Dec 2009 23:50:54 -0800 Subject: [PATCH 197/435] libgralloc-qsd8k: Do not use the physical address of surfaces/framebuffer The GPU now correctly maps everything throug hthe MMU so physical addresses are no longer needed. Change-Id: Id16a690f63d7141c8ee6694b246b1955f450b8ed Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 1 - libgralloc-qsd8k/gralloc.cpp | 16 ---------------- libgralloc-qsd8k/gralloc_priv.h | 5 ++--- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index d9cc89e..20a00ab 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -329,7 +329,6 @@ int mapFrameBufferLocked(struct private_module_t* module) return -errno; } module->framebuffer->base = intptr_t(vaddr); - module->framebuffer->phys = intptr_t(finfo.smem_start); memset(vaddr, 0, fbSize); return 0; } diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 32bd24a..38f3885 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -112,7 +112,6 @@ struct private_module_t HAL_MODULE_INFO_SYM = { currentBuffer: 0, pmem_master: -1, pmem_master_base: 0, - master_phys: 0 }; /*****************************************************************************/ @@ -166,7 +165,6 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); - hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; @@ -206,15 +204,6 @@ static int init_pmem_area_locked(private_module_t* m) base = 0; close(master_fd); master_fd = -1; - } else { - // FIXME: get physical address, eventually this will have to go away - pmem_region region; - err = ioctl(master_fd, PMEM_GET_PHYS, ®ion); - if (err < 0) { - LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno)); - } else { - m->master_phys = (unsigned long)region.offset; - } } m->pmem_master = master_fd; m->pmem_master_base = base; @@ -329,11 +318,6 @@ try_ashmem: hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; - if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - private_module_t* m = reinterpret_cast( - dev->common.module); - hnd->phys = m->master_phys + offset; - } *pHandle = hnd; } diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 1432c25..d74c1f2 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -46,7 +46,6 @@ struct private_module_t { buffer_handle_t currentBuffer; int pmem_master; void* pmem_master_base; - unsigned long master_phys; struct fb_var_screeninfo info; struct fb_fix_screeninfo finfo; @@ -93,7 +92,7 @@ struct private_handle_t { int base; int lockState; int writeOwner; - int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care + int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care int pid; #ifdef __cplusplus @@ -103,7 +102,7 @@ struct private_handle_t { 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), phys(0), pid(getpid()) + base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()) { version = sizeof(native_handle); numInts = sNumInts; From 62447949f2fe9c6cf52a54354d36cd997144cb76 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 4 Dec 2009 15:41:06 -0800 Subject: [PATCH 199/435] gralloc-qsd8k: Change composition_complete being a glfinish from stopship to a TODO We really need to fix this eventually, but it's not a ship blocker. Change-Id: I35f66988e7adba13e47c2a86e13a7425cc5aada3 Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 20a00ab..67001c3 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -151,7 +151,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) static int fb_compositionComplete(struct framebuffer_device_t* dev) { - // STOPSHIP: Properly implement composition complete callback + // TODO: Properly implement composition complete callback glFinish(); return 0; From 6d4fd653ce81fa26e68c6cea679f062ed882c520 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Fri, 4 Dec 2009 19:22:39 -0800 Subject: [PATCH 200/435] gralloc-qsd8k: If using gpu composition, request rgba8888 instead of rgbx8888 Change-Id: Ic41d4854d6acbc21c85a03e82bd63af234273886 Signed-off-by: Dima Zavin --- libgralloc-qsd8k/framebuffer.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 67001c3..11b303a 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -217,7 +218,15 @@ int mapFrameBufferLocked(struct private_module_t* module) info.blue.length = 8; info.transp.offset = 0; info.transp.length = 0; - module->fbFormat = HAL_PIXEL_FORMAT_RGBX_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. */ + char property[PROPERTY_VALUE_MAX]; + if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) + module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; + else + module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) From e17d093d0ccb4f2d69f435d4a739e265f562ba55 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 8 Dec 2009 19:34:43 -0800 Subject: [PATCH 202/435] improve cache behavior of gralloc allocations on qsd8k make sure to use cached buffers only when frequent cpu access is needed. also, always flush buffers after they are allocated and cleared. --- libgralloc-qsd8k/gralloc.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 38f3885..f1d8f55 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -279,9 +279,16 @@ try_ashmem: err = -ENOMEM; } else { struct pmem_region sub = { offset, size }; - + int openFlags = O_RDWR | O_SYNC; + uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK; + uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK; + if (uread == GRALLOC_USAGE_SW_READ_OFTEN || + uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) { + openFlags &= ~O_SYNC; + } + // now create the "sub-heap" - fd = open("/dev/pmem", O_RDWR, 0); + fd = open("/dev/pmem", openFlags, 0); err = fd < 0 ? fd : 0; // and connect to it @@ -297,8 +304,11 @@ try_ashmem: close(fd); sAllocator.deallocate(offset); fd = -1; + } else { + memset((char*)base + offset, 0, size); + // clean and invalidate the new allocation + cacheflush(intptr_t(base) + offset, size, 0); } - memset((char*)base + offset, 0, size); //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); } } else { From 7e8932dad3ccb017785b1c0ad2097b09fd886cfb Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Wed, 9 Dec 2009 21:13:44 -0800 Subject: [PATCH 204/435] gralloc-qsd8k: make sure that we never try to allocatio 0 bytes Change-Id: Ic05b895c09a55d746c737aa0c3356edc511d7c96 Signed-off-by: Dima Zavin --- libgralloc-qsd8k/gralloc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index f1d8f55..9887057 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -386,6 +386,9 @@ static int gralloc_alloc(alloc_device_t* dev, size = alignedw * alignedh * bpp; } + if ((ssize_t)size <= 0) + return -EINVAL; + int err; if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); From 44311757be4494ad601b6249d3722c71ffb17777 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 12 Jan 2010 15:19:05 -0800 Subject: [PATCH 211/435] android-2.1_r1 snapshot --- libcopybit/copybit.cpp | 8 +++++ libgralloc-qsd8k/framebuffer.cpp | 54 +++++++++++++++++++++----------- libgralloc-qsd8k/gralloc.cpp | 36 ++++++++++----------- libgralloc-qsd8k/gralloc_priv.h | 6 ++-- 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index ba8531b..fb605fe 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -42,8 +42,10 @@ #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 @@ -366,6 +368,12 @@ static int stretch_copybit( 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; diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 797982f..11b303a 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -59,7 +60,8 @@ struct fb_context_t { /*****************************************************************************/ static void -msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, +msm_copy_buffer(buffer_handle_t handle, int fd, + int width, int height, int format, int x, int y, int w, int h); static int fb_setSwapInterval(struct framebuffer_device_t* dev, @@ -120,9 +122,6 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->currentBuffer = buffer; } else { - // If we can't do the page_flip, just copy the buffer to the front - // FIXME: use copybit HAL instead of memcpy - void* fb_vaddr; void* buffer_vaddr; @@ -138,8 +137,9 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); - msm_copy_buffer(m->framebuffer, m->framebuffer->fd, - m->info.xres, m->info.yres, + msm_copy_buffer( + m->framebuffer, m->framebuffer->fd, + m->info.xres, m->info.yres, m->fbFormat, m->info.xoffset, m->info.yoffset, m->info.width, m->info.height); @@ -152,7 +152,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) static int fb_compositionComplete(struct framebuffer_device_t* dev) { - // STOPSHIP: Properly implement composition complete callback + // TODO: Properly implement composition complete callback glFinish(); return 0; @@ -199,19 +199,35 @@ int mapFrameBufferLocked(struct private_module_t* module) info.yoffset = 0; info.activate = FB_ACTIVATE_NOW; + /* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. This implies + * big-endian byte order if bits_per_pixel is greater than 8. + */ + /* - * Explicitly request 5/6/5 + * Explicitly request RGBA_8888 */ - 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.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 = 0; + /* 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. */ + char property[PROPERTY_VALUE_MAX]; + if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) + module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; + else + module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; + /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) */ @@ -322,7 +338,6 @@ int mapFrameBufferLocked(struct private_module_t* module) return -errno; } module->framebuffer->base = intptr_t(vaddr); - module->framebuffer->phys = intptr_t(finfo.smem_start); memset(vaddr, 0, fbSize); return 0; } @@ -378,7 +393,7 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.width) = m->info.xres; const_cast(dev->device.height) = m->info.yres; const_cast(dev->device.stride) = stride; - const_cast(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565; + const_cast(dev->device.format) = m->fbFormat; const_cast(dev->device.xdpi) = m->xdpi; const_cast(dev->device.ydpi) = m->ydpi; const_cast(dev->device.fps) = m->fps; @@ -400,7 +415,8 @@ int fb_device_open(hw_module_t const* module, const char* name, /* Copy a pmem buffer to the framebuffer */ static void -msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, +msm_copy_buffer(buffer_handle_t handle, int fd, + int width, int height, int format, int x, int y, int w, int h) { struct { @@ -425,7 +441,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height, blit.req.dst.height = height; blit.req.dst.offset = 0; blit.req.dst.memory_id = fd; - blit.req.dst.format = MDP_RGB_565; + blit.req.dst.format = format; blit.req.src_rect.x = blit.req.dst_rect.x = x; blit.req.src_rect.y = blit.req.dst_rect.y = y; diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 45746ef..9887057 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -104,6 +104,7 @@ struct private_module_t HAL_MODULE_INFO_SYM = { perform: gralloc_perform, }, framebuffer: 0, + fbFormat: 0, flags: 0, numBuffers: 0, bufferMask: 0, @@ -111,7 +112,6 @@ struct private_module_t HAL_MODULE_INFO_SYM = { currentBuffer: 0, pmem_master: -1, pmem_master_base: 0, - master_phys: 0 }; /*****************************************************************************/ @@ -165,7 +165,6 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, hnd->base = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); - hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset; *pHandle = hnd; return 0; @@ -205,15 +204,6 @@ static int init_pmem_area_locked(private_module_t* m) base = 0; close(master_fd); master_fd = -1; - } else { - // FIXME: get physical address, eventually this will have to go away - pmem_region region; - err = ioctl(master_fd, PMEM_GET_PHYS, ®ion); - if (err < 0) { - LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno)); - } else { - m->master_phys = (unsigned long)region.offset; - } } m->pmem_master = master_fd; m->pmem_master_base = base; @@ -289,9 +279,16 @@ try_ashmem: err = -ENOMEM; } else { struct pmem_region sub = { offset, size }; - + int openFlags = O_RDWR | O_SYNC; + uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK; + uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK; + if (uread == GRALLOC_USAGE_SW_READ_OFTEN || + uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) { + openFlags &= ~O_SYNC; + } + // now create the "sub-heap" - fd = open("/dev/pmem", O_RDWR, 0); + fd = open("/dev/pmem", openFlags, 0); err = fd < 0 ? fd : 0; // and connect to it @@ -307,8 +304,11 @@ try_ashmem: close(fd); sAllocator.deallocate(offset); fd = -1; + } else { + memset((char*)base + offset, 0, size); + // clean and invalidate the new allocation + cacheflush(intptr_t(base) + offset, size, 0); } - memset((char*)base + offset, 0, size); //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); } } else { @@ -328,11 +328,6 @@ try_ashmem: hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; - if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - private_module_t* m = reinterpret_cast( - dev->common.module); - hnd->phys = m->master_phys + offset; - } *pHandle = hnd; } @@ -391,6 +386,9 @@ static int gralloc_alloc(alloc_device_t* dev, size = alignedw * alignedh * bpp; } + if ((ssize_t)size <= 0) + return -EINVAL; + int err; if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 534b4c0..d74c1f2 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -38,6 +38,7 @@ struct private_module_t { gralloc_module_t base; struct private_handle_t* framebuffer; + uint32_t fbFormat; uint32_t flags; uint32_t numBuffers; uint32_t bufferMask; @@ -45,7 +46,6 @@ struct private_module_t { buffer_handle_t currentBuffer; int pmem_master; void* pmem_master_base; - unsigned long master_phys; struct fb_var_screeninfo info; struct fb_fix_screeninfo finfo; @@ -92,7 +92,7 @@ struct private_handle_t { int base; int lockState; int writeOwner; - int phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care + int gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care int pid; #ifdef __cplusplus @@ -102,7 +102,7 @@ struct private_handle_t { 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), phys(0), pid(getpid()) + base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()) { version = sizeof(native_handle); numInts = sNumInts; From fd92f42c3912f21dbd359696639cc5e75cbd51c0 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 20 Jan 2010 13:13:08 -0800 Subject: [PATCH 216/435] part of fix for [2363506] [Sapphire] Video playback broken make sure to reject incompatible buffers in special function GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER we use ioctl(PMEM_GET_SIZE) to validate that the given buffer is indeed a pmem buffer. --- libgralloc-qsd8k/mapper.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 8c199b3..d79d9fa 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,8 @@ #include #include +#include + #include "gralloc_priv.h" @@ -301,6 +304,13 @@ int gralloc_perform(struct gralloc_module_t const* module, size_t size = va_arg(args, size_t); size_t offset = va_arg(args, size_t); void* base = va_arg(args, void*); + + // 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**); private_handle_t* hnd = (private_handle_t*)native_handle_create( private_handle_t::sNumFds, private_handle_t::sNumInts); From 48000e415aab0bd9fa5f4d98cb12bcd74ca2083b Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 16 Feb 2010 14:04:36 -0800 Subject: [PATCH 234/435] fix [2444483] gralloc size for YUV formats --- libgralloc-qsd8k/gralloc.cpp | 59 +++++++++++++----------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 9887057..5f1aa2f 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -346,45 +346,28 @@ static int gralloc_alloc(alloc_device_t* dev, return -EINVAL; size_t size, alignedw, alignedh; - if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || - format == HAL_PIXEL_FORMAT_YCbCr_422_SP) - { - // FIXME: there is no way to return the alignedh - alignedw = (w + 1) & ~1; - switch (format) { - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - size = alignedw * h * 2; - break; - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - alignedh = (h+1) & ~1; - size = (alignedw * alignedh) + (w/2 * h/2) * 2; - break; - default: - return -EINVAL; - } - } else { - alignedw = (w + 31) & ~31; - alignedh = (h + 31) & ~31; - int bpp = 0; - 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 = alignedw * alignedh * bpp; + + alignedw = (w + 31) & ~31; + alignedh = (h + 31) & ~31; + int bpp = 0; + 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 = alignedw * alignedh * bpp; if ((ssize_t)size <= 0) return -EINVAL; From f238b9e88c44b97e11e04d70f53d4b6bce79c94e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 16 Feb 2010 19:44:06 -0800 Subject: [PATCH 235/435] temporary hack to map the correct yuv format to the current (broken) mdp constants --- libcopybit/copybit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index fb605fe..8bf65aa 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -124,8 +124,8 @@ static int get_format(int format) { case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; - case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; + case COPYBIT_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1; + case COPYBIT_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; } return -1; } From a5ffced80a46900ed2cb356e735331b49c11a257 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 17 Feb 2010 18:02:17 -0800 Subject: [PATCH 236/435] add support for YCbCr (as opposed to YCrCb) to copybit --- libcopybit/copybit.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 8bf65aa..08a650b 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -126,6 +126,8 @@ static int get_format(int format) { case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; case COPYBIT_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1; case COPYBIT_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; + case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1; + case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2; } return -1; } From c0f1d7592013f52544f5dde393b39ad751b56272 Mon Sep 17 00:00:00 2001 From: Dima Zavin Date: Tue, 2 Mar 2010 15:09:54 -0800 Subject: [PATCH 240/435] libgralloc-qsd8k: flush SW_WRITE cached pmem regions in unlock Change-Id: I31d1257f031c6b9b8dae604c2c1a8aa246ce3b84 Signed-off-by: Dima Zavin --- libgralloc-qsd8k/gralloc_priv.h | 1 + libgralloc-qsd8k/mapper.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index d74c1f2..28ea79b 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -71,6 +71,7 @@ struct private_handle_t { enum { PRIV_FLAGS_FRAMEBUFFER = 0x00000001, PRIV_FLAGS_USES_PMEM = 0x00000002, + PRIV_FLAGS_NEEDS_FLUSH = 0x00000004, }; enum { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index d79d9fa..9e9fad0 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -235,6 +235,13 @@ int gralloc_lock(gralloc_module_t const* module, hnd->writeOwner = gettid(); } + // if requesting sw write for non-framebuffer handles, flag for + // flushing at unlock + if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) && + !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; + } + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { // we need to map for real @@ -264,6 +271,18 @@ int gralloc_unlock(gralloc_module_t const* module, private_handle_t* hnd = (private_handle_t*)handle; int32_t current_value, new_value; + if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { + struct pmem_region region; + int err; + + region.offset = hnd->offset; + region.len = hnd->size; + err = ioctl(hnd->fd, PMEM_CACHE_FLUSH, ®ion); + LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n", + hnd, hnd->offset, hnd->size); + hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; + } + do { current_value = hnd->lockState; new_value = current_value; From e55ffb9bb8074bae4e3a21eee6610508c7396666 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 18 Mar 2010 18:16:45 -0700 Subject: [PATCH 254/435] gralloc and copybit now can properly handle EBI or SMI GPU surfaces up until now we relied on the EBI region map_offset being zero, which prevented us to use SMI for surfaces, as their map_offset is different. the copybit hal needs the map_offset to figure out which region to use. Change-Id: I920b31ecb77a7b0943dfcd8e3362e2c38ac83297 --- libcopybit/copybit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 08a650b..ea013ee 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -142,6 +142,7 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->offset = hnd->offset; #if defined(COPYBIT_MSM7K) if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { + img->offset += hnd->map_offset; img->memory_id = hnd->gpu_fd; if (img->format == MDP_RGBA_8888) { // msm7201A GPU only supports BGRA_8888 destinations From ec040bb3a1af9adcb78908dd62b3345ca9aee89f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Fri, 19 Mar 2010 15:49:35 -0700 Subject: [PATCH 256/435] Add tags and notices where appropriate. Also tweak copyright notices as appropriate. Bug: 2084753 Change-Id: Ifbf795b8b16dbc45cf5ac9a72b97f2b74cbf3550 --- libcopybit/MODULE_LICENSE_APACHE2 | 0 libcopybit/NOTICE | 190 ++++++++++++++++++++++++ libgralloc-qsd8k/MODULE_LICENSE_APACHE2 | 0 libgralloc-qsd8k/NOTICE | 190 ++++++++++++++++++++++++ 4 files changed, 380 insertions(+) create mode 100644 libcopybit/MODULE_LICENSE_APACHE2 create mode 100644 libcopybit/NOTICE create mode 100644 libgralloc-qsd8k/MODULE_LICENSE_APACHE2 create mode 100644 libgralloc-qsd8k/NOTICE diff --git a/libcopybit/MODULE_LICENSE_APACHE2 b/libcopybit/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 diff --git a/libcopybit/NOTICE b/libcopybit/NOTICE new file mode 100644 index 0000000..7340b9e --- /dev/null +++ b/libcopybit/NOTICE @@ -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 + diff --git a/libgralloc-qsd8k/MODULE_LICENSE_APACHE2 b/libgralloc-qsd8k/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 diff --git a/libgralloc-qsd8k/NOTICE b/libgralloc-qsd8k/NOTICE new file mode 100644 index 0000000..3237da6 --- /dev/null +++ b/libgralloc-qsd8k/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2008-2009, 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 + From b43cd9549f7b1af0c4f804209645dafb6692b1a6 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 16 Jun 2010 14:27:27 -0700 Subject: [PATCH 270/435] Add support for allocating YUV formats Currently they're all allocated in pmem, instead of pmem_adsp. Change-Id: Ief367a64667dc0b67fdeabeabbf9f201082d6ad2 --- libgralloc-qsd8k/gralloc.cpp | 38 +++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 5f1aa2f..e551120 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -338,6 +338,10 @@ try_ashmem: /*****************************************************************************/ +static inline size_t ALIGN(size_t x, size_t align) { + return (x + align-1) & (align-1); +} + static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) @@ -347,27 +351,47 @@ static int gralloc_alloc(alloc_device_t* dev, size_t size, alignedw, alignedh; - alignedw = (w + 31) & ~31; - alignedh = (h + 31) & ~31; - int bpp = 0; + 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: - bpp = 4; + size = alignedw * alignedh * 4; break; case HAL_PIXEL_FORMAT_RGB_888: - bpp = 3; + size = alignedw * alignedh * 3; break; case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_RGBA_5551: case HAL_PIXEL_FORMAT_RGBA_4444: - bpp = 2; + size = alignedw * alignedh * 2; break; + + // adreno formats + case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 + size = ALIGN(alignedw*alignedh, 4096); + size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096); + break; + case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUYV + case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY + size = ALIGN(alignedw*alignedh*2, 4096); + break; + case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 + size = ALIGN(alignedw*alignedh, 4096); + size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 + case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 + // The chroma plane is subsampled, + // but the pitch in bytes is unchanged + size = ALIGN( ALIGN(w, 128) * alignedh, 4096); + size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); + break; + default: return -EINVAL; } - size = alignedw * alignedh * bpp; if ((ssize_t)size <= 0) return -EINVAL; From ce599f6e8dbb2a1414b11ccacaf24eef0ee10c65 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 21 Jun 2010 17:46:33 -0700 Subject: [PATCH 271/435] remove unused YUV formats Change-Id: I47769af34112856e6a2ef177a966f6e8e6242031 --- libgralloc-qsd8k/gralloc.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index e551120..4291705 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -377,12 +377,7 @@ static int gralloc_alloc(alloc_device_t* dev, case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY size = ALIGN(alignedw*alignedh*2, 4096); break; - case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 - size = ALIGN(alignedw*alignedh, 4096); - size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; - break; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 - case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 // The chroma plane is subsampled, // but the pitch in bytes is unchanged size = ALIGN( ALIGN(w, 128) * alignedh, 4096); From 5d471952a5e3742980d8886a983ae36bc5bccde2 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Tue, 22 Jun 2010 13:32:36 -0400 Subject: [PATCH 272/435] Revert "remove unused YUV formats" This reverts commit 05ea9ede5600fef7a8fdf416b44ec98e58fb224b. --- libgralloc-qsd8k/gralloc.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 4291705..e551120 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -377,7 +377,12 @@ static int gralloc_alloc(alloc_device_t* dev, case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY size = ALIGN(alignedw*alignedh*2, 4096); break; + case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 + size = ALIGN(alignedw*alignedh, 4096); + size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; + break; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 + case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 // The chroma plane is subsampled, // but the pitch in bytes is unchanged size = ALIGN( ALIGN(w, 128) * alignedh, 4096); From 151d2b884bf652f7c90d3a303093bf987a8e04b5 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Tue, 22 Jun 2010 13:32:55 -0400 Subject: [PATCH 273/435] Revert "Add support for allocating YUV formats" This reverts commit 7b1f00a95490552131d06a13b78c279f6c779a1a. --- libgralloc-qsd8k/gralloc.cpp | 38 +++++++----------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index e551120..5f1aa2f 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -338,10 +338,6 @@ try_ashmem: /*****************************************************************************/ -static inline size_t ALIGN(size_t x, size_t align) { - return (x + align-1) & (align-1); -} - static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) @@ -351,47 +347,27 @@ static int gralloc_alloc(alloc_device_t* dev, size_t size, alignedw, alignedh; - alignedw = ALIGN(w, 32); - alignedh = ALIGN(h, 32); + alignedw = (w + 31) & ~31; + alignedh = (h + 31) & ~31; + int bpp = 0; switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: - size = alignedw * alignedh * 4; + bpp = 4; break; case HAL_PIXEL_FORMAT_RGB_888: - size = alignedw * alignedh * 3; + bpp = 3; break; case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_RGBA_5551: case HAL_PIXEL_FORMAT_RGBA_4444: - size = alignedw * alignedh * 2; + bpp = 2; break; - - // adreno formats - case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 - size = ALIGN(alignedw*alignedh, 4096); - size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096); - break; - case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUYV - case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY - size = ALIGN(alignedw*alignedh*2, 4096); - break; - case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 - size = ALIGN(alignedw*alignedh, 4096); - size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; - break; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 - case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 - // The chroma plane is subsampled, - // but the pitch in bytes is unchanged - size = ALIGN( ALIGN(w, 128) * alignedh, 4096); - size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); - break; - default: return -EINVAL; } + size = alignedw * alignedh * bpp; if ((ssize_t)size <= 0) return -EINVAL; From 0f6dc7ea55750c2f8f97cb2332a1d84e7cccbeb0 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 16 Jun 2010 14:27:27 -0700 Subject: [PATCH 274/435] Add support for allocating YUV formats Currently they're all allocated in pmem, instead of pmem_adsp. Change-Id: Ibc3edf2da4155d2f086d81dee8940270f9cb9f6b --- libgralloc-qsd8k/gralloc.cpp | 38 +++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 5f1aa2f..e551120 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -338,6 +338,10 @@ try_ashmem: /*****************************************************************************/ +static inline size_t ALIGN(size_t x, size_t align) { + return (x + align-1) & (align-1); +} + static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) @@ -347,27 +351,47 @@ static int gralloc_alloc(alloc_device_t* dev, size_t size, alignedw, alignedh; - alignedw = (w + 31) & ~31; - alignedh = (h + 31) & ~31; - int bpp = 0; + 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: - bpp = 4; + size = alignedw * alignedh * 4; break; case HAL_PIXEL_FORMAT_RGB_888: - bpp = 3; + size = alignedw * alignedh * 3; break; case HAL_PIXEL_FORMAT_RGB_565: case HAL_PIXEL_FORMAT_RGBA_5551: case HAL_PIXEL_FORMAT_RGBA_4444: - bpp = 2; + size = alignedw * alignedh * 2; break; + + // adreno formats + case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 + size = ALIGN(alignedw*alignedh, 4096); + size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096); + break; + case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUYV + case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY + size = ALIGN(alignedw*alignedh*2, 4096); + break; + case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 + size = ALIGN(alignedw*alignedh, 4096); + size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; + break; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 + case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 + // The chroma plane is subsampled, + // but the pitch in bytes is unchanged + size = ALIGN( ALIGN(w, 128) * alignedh, 4096); + size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); + break; + default: return -EINVAL; } - size = alignedw * alignedh * bpp; if ((ssize_t)size <= 0) return -EINVAL; From a82aad454a684bb7d5ac8a7479e7c0d437f77c54 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 22 Jun 2010 16:15:10 -0700 Subject: [PATCH 275/435] fix typo in ALIGN macro Change-Id: Idaddf65f0b726a158f47639223f4281fd07447a7 --- libgralloc-qsd8k/gralloc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index e551120..9b3d95f 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -339,7 +339,7 @@ try_ashmem: /*****************************************************************************/ static inline size_t ALIGN(size_t x, size_t align) { - return (x + align-1) & (align-1); + return (x + align-1) & ~(align-1); } static int gralloc_alloc(alloc_device_t* dev, From 0adc045aa2b4292968aa154f78c67da49efc3a6f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 21 Jun 2010 17:46:33 -0700 Subject: [PATCH 276/435] remove unused YUV formats Change-Id: I41c18551a61bec9f928399544a12024c81947ed0 --- libgralloc-qsd8k/gralloc.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 9b3d95f..ee477ca 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -377,12 +377,7 @@ static int gralloc_alloc(alloc_device_t* dev, case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY size = ALIGN(alignedw*alignedh*2, 4096); break; - case HAL_PIXEL_FORMAT_YCrCb_422_P: // YV12 - size = ALIGN(alignedw*alignedh, 4096); - size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h, 32), 4096) * 2; - break; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 - case HAL_PIXEL_FORMAT_YCrCb_420_SP_TILED: // NV21 // The chroma plane is subsampled, // but the pitch in bytes is unchanged size = ALIGN( ALIGN(w, 128) * alignedh, 4096); From d3c18d49384879162c21e12157290aacd28c4548 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 22 Jun 2010 22:06:12 -0700 Subject: [PATCH 277/435] NV12 tiled needs 8K plane alignment Change-Id: I8f2ca6f058ff9d7dd666871a696428c55dbe6cf1 --- libgralloc-qsd8k/gralloc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index ee477ca..5a0f622 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -380,7 +380,8 @@ static int gralloc_alloc(alloc_device_t* dev, case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: // NV12 // The chroma plane is subsampled, // but the pitch in bytes is unchanged - size = ALIGN( ALIGN(w, 128) * alignedh, 4096); + // The GPU needs 4K alignment, but the video decoder needs 8K + size = ALIGN( ALIGN(w, 128) * alignedh, 8192); size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); break; From 6c2bc88a035cf5cecf39cd5a6e20da7f7e63abcf Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 1 Jul 2010 21:19:31 -0700 Subject: [PATCH 278/435] remove unused YUV formats Change-Id: Ia590a9cb9a02bf62f35da344f29775d1256e3da7 --- libcopybit/copybit.cpp | 2 -- libgralloc-qsd8k/gralloc.cpp | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index ea013ee..7130ca7 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -124,10 +124,8 @@ static int get_format(int format) { case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1; case COPYBIT_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1; - case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2; } return -1; } diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 5a0f622..3d08cfd 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -373,18 +373,27 @@ static int gralloc_alloc(alloc_device_t* dev, size = ALIGN(alignedw*alignedh, 4096); size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096); break; - case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUYV - case HAL_PIXEL_FORMAT_CbYCrY_422_I: // UYVY - size = ALIGN(alignedw*alignedh*2, 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( ALIGN(w, 128) * alignedh, 8192); size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); break; + case HAL_PIXEL_FORMAT_YV12: + alignedw = ALIGN(w, 16); + alignedh = ALIGN(h, 16); + size = alignedw * alignedh; + size += size / 2; + break; + + case HAL_PIXEL_FORMAT_YV16: + alignedh = ALIGN(h, 16); + size = alignedw * alignedh * 2; + break; + default: return -EINVAL; } From 5bc176b1a6fa7710845b23e38bc1c93c8345a3fc Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Wed, 21 Apr 2010 17:33:32 -0700 Subject: [PATCH 279/435] Refactor the qsd8k gralloc implementation. The purpose of this change is to add support for allocating gralloc buffers from either /dev/pmem or /dev/pmem_adsp depending on the usage flags. It does this by factoring out and abstracting the interactions with the pmem device. For /dev/pmem allocations, the kernel allocator is not used, so a single master fd is opened, and all the allocations are sub-allocated from that by gralloc. For /dev/pmem_adsp the kernel allocator is used, so it simply opens a new fd for each allocation. A very basic unit test that can be run on the host is included. It requires gtest, so to run it on a host system gtest must (currently) be compiled with BUILD_WITH_ASTL=true. Change-Id: If2ae0151698fad8107e18e808a3fa012a846263f --- libgralloc-qsd8k/Android.mk | 16 +- libgralloc-qsd8k/allocator.h | 13 +- libgralloc-qsd8k/gpu.cpp | 340 ++++++++++++ libgralloc-qsd8k/gpu.h | 76 +++ libgralloc-qsd8k/gralloc.cpp | 496 ++++-------------- libgralloc-qsd8k/gralloc_priv.h | 15 +- libgralloc-qsd8k/mapper.cpp | 3 +- libgralloc-qsd8k/pmemalloc.cpp | 324 ++++++++++++ libgralloc-qsd8k/pmemalloc.h | 161 ++++++ libgralloc-qsd8k/tests/Android.mk | 55 ++ libgralloc-qsd8k/tests/pmemalloc_test.cpp | 601 ++++++++++++++++++++++ 11 files changed, 1686 insertions(+), 414 deletions(-) create mode 100644 libgralloc-qsd8k/gpu.cpp create mode 100644 libgralloc-qsd8k/gpu.h create mode 100644 libgralloc-qsd8k/pmemalloc.cpp create mode 100644 libgralloc-qsd8k/pmemalloc.h create mode 100644 libgralloc-qsd8k/tests/Android.mk create mode 100644 libgralloc-qsd8k/tests/pmemalloc_test.cpp diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index d5ffa42..cc92d04 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -23,10 +23,22 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM LOCAL_SRC_FILES := \ allocator.cpp \ - gralloc.cpp \ framebuffer.cpp \ - mapper.cpp + gpu.cpp \ + gralloc.cpp \ + mapper.cpp \ + pmemalloc.cpp LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" include $(BUILD_SHARED_LIBRARY) + +# Build a host library for testing +include $(CLEAR_VARS) +LOCAL_SRC_FILES := \ + gpu.cpp \ + pmemalloc.cpp + +LOCAL_MODULE := libgralloc_qsd8k_host +LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\" +include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h index b0d89e9..dc81f51 100644 --- a/libgralloc-qsd8k/allocator.h +++ b/libgralloc-qsd8k/allocator.h @@ -22,6 +22,7 @@ #include #include "gr.h" +#include "pmemalloc.h" // ---------------------------------------------------------------------------- @@ -91,19 +92,19 @@ public: } }; -class SimpleBestFitAllocator +class SimpleBestFitAllocator : public PmemUserspaceAllocator::Deps::Allocator { public: SimpleBestFitAllocator(); SimpleBestFitAllocator(size_t size); - ~SimpleBestFitAllocator(); + virtual ~SimpleBestFitAllocator(); - ssize_t setSize(size_t size); + virtual ssize_t setSize(size_t size); - ssize_t allocate(size_t size, uint32_t flags = 0); - ssize_t deallocate(size_t offset); - size_t size() const; + virtual ssize_t allocate(size_t size, uint32_t flags = 0); + virtual ssize_t deallocate(size_t offset); + virtual size_t size() const; private: struct chunk_t { diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp new file mode 100644 index 0000000..2a2d6d5 --- /dev/null +++ b/libgralloc-qsd8k/gpu.cpp @@ -0,0 +1,340 @@ +/* + * 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 +#include +#include + +#include + +#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) +{ + // Zero out the alloc_device_t + memset(static_cast(this), 0, sizeof(alloc_device_t)); + + // Initialize the procs + common.tag = HARDWARE_DEVICE_TAG; + common.version = 0; + common.module = const_cast(&module->base.common); + common.close = gralloc_close; + alloc = gralloc_alloc; + 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(common.module); + + // we don't support allocations with both the FB and PMEM_ADSP flags + if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { + 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<framebuffer->base); + private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, + private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_FRAMEBUFFER); + + // find a free slot + for (uint32_t i=0 ; ibufferMask |= (1LU<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(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 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); + + 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; + } + + if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + } + + private_module_t* m = reinterpret_cast(common.module); + + 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_HW_2D) == 0) && + ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { + // the caller didn't request PMEM, so we can try something else + flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; + err = 0; + goto try_ashmem; + } else { + LOGE("couldn't open pmem (%s)", strerror(errno)); + } + } + } else { +try_ashmem: + fd = deps.ashmem_create_region("gralloc-buffer", size); + if (fd < 0) { + LOGE("couldn't create ashmem (%s)", strerror(errno)); + err = -errno; + } + } + + 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: // 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: + alignedw = ALIGN(w, 16); + alignedh = ALIGN(h, 16); + size = alignedw * alignedh; + size += size / 2; + break; + + case HAL_PIXEL_FORMAT_YV16: + alignedh = ALIGN(h, 16); + size = alignedw * alignedh * 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(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<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; + } + pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base, + hnd->offset, hnd->fd); + deps.terminateBuffer(&m->base, const_cast(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(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(handle); + gpu_context_t* gpu = reinterpret_cast(dev); + return gpu->free_impl(hnd); +} + +/*****************************************************************************/ + +int gpu_context_t::gralloc_close(struct hw_device_t *dev) +{ + gpu_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; +} + + +gpu_context_t::Deps::~Deps() {} diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h new file mode 100644 index 0000000..5da7b6a --- /dev/null +++ b/libgralloc-qsd8k/gpu.h @@ -0,0 +1,76 @@ +/* + * 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 +#include +#include +#include + +#include +#include + +#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; +}; + +#endif // GRALLOC_QSD8K_GPU_H diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 3d08cfd..bf60324 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -14,44 +14,22 @@ * limitations under the License. */ -#include #include #include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include - -#include -#include - -#include "gralloc_priv.h" -#include "allocator.h" - -#if HAVE_ANDROID_OS #include -#endif + +#include "allocator.h" +#include "gr.h" +#include "gpu.h" /*****************************************************************************/ -static SimpleBestFitAllocator sAllocator; - -/*****************************************************************************/ - -struct gralloc_context_t { - alloc_device_t device; - /* our private data here */ -}; - static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle); @@ -82,8 +60,93 @@ extern int gralloc_perform(struct gralloc_module_t const* module, /*****************************************************************************/ +/* On-device dependency implementation */ +class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, + public PmemKernelAllocator::Deps { + + virtual size_t getPmemTotalSize(int fd, size_t* size) { + pmem_region region; + int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion); + if (err == 0) { + *size = region.len; + } + 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 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); + } +}; + +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 + open: gralloc_device_open }; struct private_module_t HAL_MODULE_INFO_SYM = { @@ -110,388 +173,21 @@ struct private_module_t HAL_MODULE_INFO_SYM = { bufferMask: 0, lock: PTHREAD_MUTEX_INITIALIZER, currentBuffer: 0, - pmem_master: -1, - pmem_master_base: 0, }; /*****************************************************************************/ -static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, - size_t size, int usage, buffer_handle_t* pHandle) -{ - private_module_t* m = reinterpret_cast( - dev->common.module); - - // allocate the framebuffer - if (m->framebuffer == NULL) { - // initialize the framebuffer, the framebuffer is mapped once - // and forever. - int err = 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(dev, bufferSize, newUsage, pHandle); - } - - if (bufferMask >= ((1LU<framebuffer->base); - private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, - private_handle_t::PRIV_FLAGS_USES_PMEM | - private_handle_t::PRIV_FLAGS_FRAMEBUFFER); - - // find a free slot - for (uint32_t i=0 ; ibufferMask |= (1LU<base = vaddr; - hnd->offset = vaddr - intptr_t(m->framebuffer->base); - *pHandle = hnd; - - return 0; -} - -static int gralloc_alloc_framebuffer(alloc_device_t* dev, - size_t size, int usage, buffer_handle_t* pHandle) -{ - private_module_t* m = reinterpret_cast( - dev->common.module); - pthread_mutex_lock(&m->lock); - int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); - pthread_mutex_unlock(&m->lock); - return err; -} - - -static int init_pmem_area_locked(private_module_t* m) -{ - int err = 0; - int master_fd = open("/dev/pmem", O_RDWR, 0); - if (master_fd >= 0) { - size_t size; - pmem_region region; - if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { - LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode"); - size = 8<<20; // 8 MiB - } else { - size = region.len; - } - sAllocator.setSize(size); - - void* base = mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); - if (base == MAP_FAILED) { - err = -errno; - base = 0; - close(master_fd); - master_fd = -1; - } - m->pmem_master = master_fd; - m->pmem_master_base = base; - } else { - err = -errno; - } - return err; -} - -static int init_pmem_area(private_module_t* m) -{ - pthread_mutex_lock(&m->lock); - int err = m->pmem_master; - if (err == -1) { - // first time, try to initialize pmem - err = init_pmem_area_locked(m); - if (err) { - m->pmem_master = err; - } - } else if (err < 0) { - // pmem couldn't be initialized, never use it - } else { - // pmem OK - err = 0; - } - pthread_mutex_unlock(&m->lock); - return err; -} - -static int gralloc_alloc_buffer(alloc_device_t* dev, - size_t size, int usage, buffer_handle_t* pHandle) -{ - int err = 0; - int flags = 0; - - int fd = -1; - void* base = 0; - int offset = 0; - int lockState = 0; - - size = roundUpToPageSize(size); - - 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; - } - - if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { -try_ashmem: - fd = ashmem_create_region("gralloc-buffer", size); - if (fd < 0) { - LOGE("couldn't create ashmem (%s)", strerror(errno)); - err = -errno; - } - } else { - private_module_t* m = reinterpret_cast( - dev->common.module); - - err = init_pmem_area(m); - if (err == 0) { - // PMEM buffers are always mmapped - base = m->pmem_master_base; - lockState |= private_handle_t::LOCK_STATE_MAPPED; - - offset = sAllocator.allocate(size); - if (offset < 0) { - // no more pmem memory - err = -ENOMEM; - } else { - struct pmem_region sub = { offset, size }; - int openFlags = O_RDWR | O_SYNC; - uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK; - uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK; - if (uread == GRALLOC_USAGE_SW_READ_OFTEN || - uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) { - openFlags &= ~O_SYNC; - } - - // now create the "sub-heap" - fd = open("/dev/pmem", openFlags, 0); - err = fd < 0 ? fd : 0; - - // and connect to it - if (err == 0) - err = ioctl(fd, PMEM_CONNECT, m->pmem_master); - - // and make it available to the client process - if (err == 0) - err = ioctl(fd, PMEM_MAP, &sub); - - if (err < 0) { - err = -errno; - close(fd); - sAllocator.deallocate(offset); - fd = -1; - } else { - memset((char*)base + offset, 0, size); - // clean and invalidate the new allocation - cacheflush(intptr_t(base) + offset, size, 0); - } - //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); - } - } else { - if ((usage & GRALLOC_USAGE_HW_2D) == 0) { - // the caller didn't request PMEM, so we can try something else - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; - err = 0; - goto try_ashmem; - } else { - LOGE("couldn't open pmem (%s)", strerror(errno)); - } - } - } - - 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); -} - -static int gralloc_alloc(alloc_device_t* dev, - 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: // 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( ALIGN(w, 128) * alignedh, 8192); - size += ALIGN( ALIGN(w, 128) * ALIGN(h/2, 32), 4096); - break; - - case HAL_PIXEL_FORMAT_YV12: - alignedw = ALIGN(w, 16); - alignedh = ALIGN(h, 16); - size = alignedw * alignedh; - size += size / 2; - break; - - case HAL_PIXEL_FORMAT_YV16: - alignedh = ALIGN(h, 16); - size = alignedw * alignedh * 2; - break; - - default: - return -EINVAL; - } - - if ((ssize_t)size <= 0) - return -EINVAL; - - int err; - if (usage & GRALLOC_USAGE_HW_FB) { - err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); - } else { - err = gralloc_alloc_buffer(dev, size, usage, pHandle); - } - - if (err < 0) { - return err; - } - - *pStride = alignedw; - return 0; -} - -static int 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(handle); - if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { - // free this buffer - private_module_t* m = reinterpret_cast( - dev->common.module); - const size_t bufferSize = m->finfo.line_length * m->info.yres; - int index = (hnd->base - m->framebuffer->base) / bufferSize; - m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - if (hnd->fd >= 0) { - struct pmem_region sub = { hnd->offset, hnd->size }; - int err = ioctl(hnd->fd, PMEM_UNMAP, &sub); - LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " - "fd=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), hnd->fd, hnd->offset, hnd->size); - if (err == 0) { - // we can't deallocate the memory in case of UNMAP failure - // because it would give that process access to someone else's - // surfaces, which would be a security breach. - sAllocator.deallocate(hnd->offset); - } - } - } - - gralloc_module_t* module = reinterpret_cast( - dev->common.module); - terminateBuffer(module, const_cast(hnd)); - } - - close(hnd->fd); - delete hnd; - return 0; -} - -/*****************************************************************************/ - -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. - */ - free(ctx); - } - return 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)) { - gralloc_context_t *dev; - dev = (gralloc_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(module); - dev->device.common.close = gralloc_close; - - dev->device.alloc = gralloc_alloc; - dev->device.free = gralloc_free; - - *device = &dev->device.common; + const private_module_t* m = reinterpret_cast( + module); + 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); diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 28ea79b..36e6796 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -29,10 +29,16 @@ #include +enum { + /* gralloc usage bit indicating a pmem_adsp allocation should be used */ + GRALLOC_USAGE_PRIVATE_PMEM_ADSP = GRALLOC_USAGE_PRIVATE_0, +}; + /*****************************************************************************/ struct private_module_t; struct private_handle_t; +struct PmemAllocator; struct private_module_t { gralloc_module_t base; @@ -44,8 +50,6 @@ struct private_module_t { uint32_t bufferMask; pthread_mutex_t lock; buffer_handle_t currentBuffer; - int pmem_master; - void* pmem_master_base; struct fb_var_screeninfo info; struct fb_fix_screeninfo finfo; @@ -69,9 +73,10 @@ struct private_handle_t { #endif enum { - PRIV_FLAGS_FRAMEBUFFER = 0x00000001, - PRIV_FLAGS_USES_PMEM = 0x00000002, - PRIV_FLAGS_NEEDS_FLUSH = 0x00000004, + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_PMEM = 0x00000002, + PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004, + PRIV_FLAGS_NEEDS_FLUSH = 0x00000008, }; enum { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 9e9fad0..e8be6f6 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -171,7 +171,8 @@ 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) { + if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) || + (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) { if (hnd->pid != getpid()) { // ... unless it's a "master" pmem buffer, that is a buffer // mapped in the process it's been allocated. diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp new file mode 100644 index 0000000..e42e898 --- /dev/null +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -0,0 +1,324 @@ +/* + * 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. + */ + +//#define LOG_NDEBUG 0 + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "gralloc_priv.h" +#include "pmemalloc.h" + + +#define BEGIN_FUNC LOGV("%s begin", __PRETTY_FUNCTION__) +#define END_FUNC LOGV("%s end", __PRETTY_FUNCTION__) + + +static int get_open_flags(int usage) { + int openFlags = O_RDWR | O_SYNC; + uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK; + uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK; + if (uread == GRALLOC_USAGE_SW_READ_OFTEN || + uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) { + openFlags &= ~O_SYNC; + } + return openFlags; +} + +PmemAllocator::~PmemAllocator() +{ + BEGIN_FUNC; + END_FUNC; +} + + +PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev): + deps(deps), + allocator(allocator), + pmemdev(pmemdev), + master_fd(MASTER_FD_INIT) +{ + BEGIN_FUNC; + pthread_mutex_init(&lock, NULL); + END_FUNC; +} + + +PmemUserspaceAllocator::~PmemUserspaceAllocator() +{ + BEGIN_FUNC; + END_FUNC; +} + + +void* PmemUserspaceAllocator::get_base_address() { + BEGIN_FUNC; + END_FUNC; + return master_base; +} + + +int PmemUserspaceAllocator::init_pmem_area_locked() +{ + BEGIN_FUNC; + int err = 0; + int fd = deps.open(pmemdev, O_RDWR, 0); + if (fd >= 0) { + size_t size = 0; + err = deps.getPmemTotalSize(fd, &size); + if (err < 0) { + LOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", pmemdev, + err); + size = 8<<20; // 8 MiB + } + allocator.setSize(size); + + void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, + 0); + if (base == MAP_FAILED) { + LOGE("%s: failed to map pmem master fd: %s", pmemdev, + strerror(deps.getErrno())); + err = -deps.getErrno(); + base = 0; + deps.close(fd); + fd = -1; + } else { + master_fd = fd; + master_base = base; + } + } else { + LOGE("%s: failed to open pmem device: %s", pmemdev, + strerror(deps.getErrno())); + err = -deps.getErrno(); + } + END_FUNC; + return err; +} + + +int PmemUserspaceAllocator::init_pmem_area() +{ + BEGIN_FUNC; + pthread_mutex_lock(&lock); + int err = master_fd; + if (err == MASTER_FD_INIT) { + // first time, try to initialize pmem + err = init_pmem_area_locked(); + if (err) { + LOGE("%s: failed to initialize pmem area", pmemdev); + master_fd = err; + } + } else if (err < 0) { + // pmem couldn't be initialized, never use it + } else { + // pmem OK + err = 0; + } + pthread_mutex_unlock(&lock); + END_FUNC; + return err; +} + + +int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, + void** pBase, int* pOffset, int* pFd) +{ + BEGIN_FUNC; + int err = init_pmem_area(); + if (err == 0) { + void* base = master_base; + int offset = allocator.allocate(size); + if (offset < 0) { + // no more pmem memory + LOGE("%s: no more pmem available", pmemdev); + err = -ENOMEM; + } else { + int openFlags = get_open_flags(usage); + + //LOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset); + + // now create the "sub-heap" + int fd = deps.open(pmemdev, openFlags, 0); + err = fd < 0 ? fd : 0; + + // and connect to it + if (err == 0) + err = deps.connectPmem(fd, master_fd); + + // and make it available to the client process + if (err == 0) + err = deps.mapPmem(fd, offset, size); + + if (err < 0) { + LOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev, + err); + err = -deps.getErrno(); + deps.close(fd); + allocator.deallocate(offset); + fd = -1; + } else { + LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); + memset((char*)base + offset, 0, size); + *pBase = base; + *pOffset = offset; + *pFd = fd; + } + //LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset); + } + } + END_FUNC; + return err; +} + + +int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd) +{ + BEGIN_FUNC; + int err = 0; + if (fd >= 0) { + int err = deps.unmapPmem(fd, offset, size); + LOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, " + "sub.size=%u", strerror(deps.getErrno()), fd, offset, size); + if (err == 0) { + // we can't deallocate the memory in case of UNMAP failure + // because it would give that process access to someone else's + // surfaces, which would be a security breach. + allocator.deallocate(offset); + } + } + END_FUNC; + return err; +} + +PmemUserspaceAllocator::Deps::Allocator::~Allocator() +{ + BEGIN_FUNC; + END_FUNC; +} + +PmemUserspaceAllocator::Deps::~Deps() +{ + BEGIN_FUNC; + END_FUNC; +} + +PmemKernelAllocator::PmemKernelAllocator(Deps& deps, const char* pmemdev): + deps(deps), + pmemdev(pmemdev) +{ + BEGIN_FUNC; + END_FUNC; +} + + +PmemKernelAllocator::~PmemKernelAllocator() +{ + BEGIN_FUNC; + END_FUNC; +} + + +void* PmemKernelAllocator::get_base_address() { + BEGIN_FUNC; + END_FUNC; + return 0; +} + + +static unsigned clp2(unsigned x) { + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return x + 1; +} + + +int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, + void** pBase,int* pOffset, int* pFd) +{ + BEGIN_FUNC; + + *pBase = 0; + *pOffset = 0; + *pFd = -1; + + int err; + int openFlags = get_open_flags(usage); + int fd = deps.open(pmemdev, openFlags, 0); + if (fd < 0) { + err = -deps.getErrno(); + END_FUNC; + return err; + } + + // The size should already be page aligned, now round it up to a power of 2. + size = clp2(size); + + 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, + strerror(deps.getErrno())); + err = -deps.getErrno(); + deps.close(fd); + END_FUNC; + return err; + } + + memset(base, 0, size); + + *pBase = base; + *pOffset = 0; + *pFd = fd; + + END_FUNC; + return 0; +} + + +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 + // like we did when allocating. + 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)); + return -err; + } + END_FUNC; + return 0; +} + +PmemKernelAllocator::Deps::~Deps() +{ + BEGIN_FUNC; + END_FUNC; +} diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h new file mode 100644 index 0000000..b0f45c7 --- /dev/null +++ b/libgralloc-qsd8k/pmemalloc.h @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#ifndef GRALLOC_QSD8K_PMEMALLOC_H +#define GRALLOC_QSD8K_PMEMALLOC_H + +#include +#include +#include +#include + + +/** + * An interface to the PMEM allocators. + */ +class PmemAllocator { + + public: + + virtual ~PmemAllocator(); + + // Only valid after init_pmem_area() has completed successfully. + virtual void* get_base_address() = 0; + + virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase, + int* pOffset, int* pFd) = 0; + virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0; +}; + + +/** + * A PMEM allocator that allocates the entire pmem memory from the kernel and + * then uses a user-space allocator to suballocate from that. This requires + * that the PMEM device driver have kernel allocation disabled. + */ +class PmemUserspaceAllocator: public PmemAllocator { + + public: + + class Deps { + public: + + class Allocator { + public: + virtual ~Allocator(); + virtual ssize_t setSize(size_t size) = 0; + virtual size_t size() const = 0; + virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0; + virtual ssize_t deallocate(size_t offset) = 0; + }; + + virtual ~Deps(); + + // pmem + virtual size_t getPmemTotalSize(int fd, size_t* size) = 0; + virtual int connectPmem(int fd, int master_fd) = 0; + virtual int mapPmem(int fd, int offset, size_t size) = 0; + virtual int unmapPmem(int fd, int offset, size_t size) = 0; + + // C99 + virtual int getErrno() = 0; + + // POSIX + virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, + off_t offset) = 0; + virtual int open(const char* pathname, int flags, int mode) = 0; + virtual int close(int fd) = 0; + }; + + PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev); + virtual ~PmemUserspaceAllocator(); + + // Only valid after init_pmem_area() has completed successfully. + virtual void* get_base_address(); + + 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); + virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); + +#ifndef ANDROID_OS + // DO NOT USE: For testing purposes only. + void set_master_values(int fd, void* base) { + master_fd = fd; + master_base = base; + } +#endif // ANDROID_OS + + private: + + enum { + MASTER_FD_INIT = -1, + }; + + Deps& deps; + Deps::Allocator& allocator; + + pthread_mutex_t lock; + const char* pmemdev; + int master_fd; + void* master_base; +}; + + +/** + * A PMEM allocator that allocates each individual allocation from the kernel + * (using the kernel's allocator). This requires the kernel driver for the + * particular PMEM device being allocated from to support kernel allocation. + */ +class PmemKernelAllocator: public PmemAllocator { + + public: + + class Deps { + public: + + virtual ~Deps(); + + // C99 + virtual int getErrno() = 0; + + // POSIX + virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, + off_t offset) = 0; + 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; + }; + + PmemKernelAllocator(Deps& deps, const char* pmemdev); + 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); + 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 diff --git a/libgralloc-qsd8k/tests/Android.mk b/libgralloc-qsd8k/tests/Android.mk new file mode 100644 index 0000000..b9a7459 --- /dev/null +++ b/libgralloc-qsd8k/tests/Android.mk @@ -0,0 +1,55 @@ +# 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)) diff --git a/libgralloc-qsd8k/tests/pmemalloc_test.cpp b/libgralloc-qsd8k/tests/pmemalloc_test.cpp new file mode 100644 index 0000000..94e86bf --- /dev/null +++ b/libgralloc-qsd8k/tests/pmemalloc_test.cpp @@ -0,0 +1,601 @@ +/* + * 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 + +#include +#include +#include +#include + +#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); +} + +/******************************************************************************/ From 3f3bead8b61596d8990f53ca83149f4b0c8755c7 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 2 Jul 2010 16:37:27 -0700 Subject: [PATCH 280/435] make the gralloc test linux only Change-Id: Ib245f7936bbe71b34903172629e09763dd725d80 --- libgralloc-qsd8k/Android.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index cc92d04..b22541a 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -34,11 +34,14 @@ LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" 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 From fce1cc8a83f3fac981e9a350c1fe82d5f8dcc92a Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 7 Jul 2010 14:54:35 -0700 Subject: [PATCH 284/435] Remove the YV16 format. Change-Id: I3f7995ba0cf41bcde995df293bea78bce7d82fc9 --- libgralloc-qsd8k/gpu.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 2a2d6d5..bcca1eb 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -240,14 +240,9 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, case HAL_PIXEL_FORMAT_YV12: alignedw = ALIGN(w, 16); - alignedh = ALIGN(h, 16); - size = alignedw * alignedh; - size += size / 2; - break; - - case HAL_PIXEL_FORMAT_YV16: - alignedh = ALIGN(h, 16); - size = alignedw * alignedh * 2; + alignedh = ALIGN(h, 2); + size = alignedw*alignedh + + (ALIGN(alignedw/2, 16) * (alignedh/2))*2; break; default: From 041cfdf2cfeb413f415bc2e7dd7f40638d5de65e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 28 Jul 2010 18:12:39 -0700 Subject: [PATCH 285/435] fix [2855380] GRG19 monkey native crash in GraphicBufferAllocator we were dereferencing the null pointer when freeing ashmem buffers. Change-Id: I7be6e1ae064148bea1076193c21a73b5a3f90297 --- libgralloc-qsd8k/gpu.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index bcca1eb..a5c7442 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -282,8 +282,10 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) { pmem_allocator = &pmemAdspAllocator; } - pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base, - hnd->offset, hnd->fd); + if (pmem_allocator) { + pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base, + hnd->offset, hnd->fd); + } deps.terminateBuffer(&m->base, const_cast(hnd)); } From 38b90c13c4adea348a99b08b2493739a8e444041 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Fri, 6 Aug 2010 12:09:15 -0700 Subject: [PATCH 286/435] Change the constant name identifying the NV21 Adreno format. This updates the qsd8k gralloc to support the new name for the NV21 Adreno pixel format. Change-Id: I358bf12db058d3740a5e49ee30d95c2afb708295 --- libgralloc-qsd8k/gpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index a5c7442..c838cb6 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -225,7 +225,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, break; // adreno formats - case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21 + 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; From 7461d57ecaafa453b6265eacea567111404c510f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 19 Aug 2010 13:15:39 -0700 Subject: [PATCH 289/435] add qcom specific pixelformats Change-Id: I70395b93afc4dee13e805649ee2307ffe895aaf1 --- libgralloc-qsd8k/gralloc_priv.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 36e6796..c573941 100644 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -36,6 +36,25 @@ enum { /*****************************************************************************/ +enum { + /* OEM specific HAL formats */ + //HAL_PIXEL_FORMAT_YCbCr_422_SP = 0x100, // defined in hardware.h + //HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x101, // defined in hardware.h + HAL_PIXEL_FORMAT_YCbCr_422_P = 0x102, + HAL_PIXEL_FORMAT_YCbCr_420_P = 0x103, + //HAL_PIXEL_FORMAT_YCbCr_422_I = 0x104, // defined in hardware.h + HAL_PIXEL_FORMAT_YCbCr_420_I = 0x105, + HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x106, + HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x107, + HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x108, + HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109, + HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A, + HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B, + HAL_PIXEL_FORMAT_YCrCb_420_SP_INTERLACE = 0x10C, +}; + +/*****************************************************************************/ + struct private_module_t; struct private_handle_t; struct PmemAllocator; From 0ff47fbdac6e13c706117c3e6c227f77ee093150 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 20 Aug 2010 11:47:44 -0700 Subject: [PATCH 290/435] only set the PRIV_FLAGS_NEEDS_FLUSH flag on PMEM buffers PRIV_FLAGS_NEEDS_FLUSH will trigger an ioctl call into the PMEM driver in unlock(), so it makes not sense to set this flag for non pmem buffers. Change-Id: Ie1e077c10df86d3689b82fa6ce5d6c856fc95688 --- libgralloc-qsd8k/mapper.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index e8be6f6..26fadbc 100644 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -238,8 +238,14 @@ int gralloc_lock(gralloc_module_t const* module, // if requesting sw write for non-framebuffer handles, flag for // flushing at unlock + + const uint32_t pmemMask = + private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; + if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) && - !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + (hnd->flags & pmemMask) && + !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; } From 31f0df4eba92b22a6adc9d4573aee1363c6c0e5e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 20 Aug 2010 16:02:29 -0700 Subject: [PATCH 291/435] don't revert to ashmem if HW usage bits are set this wouldn't make sense, since the h/w wouldn't be able to use the buffer. in this case it it better to fail to let the caller a change to try again with different usage bits. Change-Id: Ibecaf069b6b58ee9c026affc95a45512660d5881 --- libgralloc-qsd8k/gpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index c838cb6..d577f96 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -164,7 +164,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // Allocate the buffer from pmem err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd); if (err < 0) { - if (((usage & GRALLOC_USAGE_HW_2D) == 0) && + if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { // the caller didn't request PMEM, so we can try something else flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; From 9efee771b2b0aea86f61dc11f0c83c712b66e8ab Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 10 Sep 2010 14:40:10 -0700 Subject: [PATCH 293/435] reject odd widths or heights for YV12 format Change-Id: I66cbb5fbc20630218947cd41552a95503b58e15e --- libgralloc-qsd8k/gpu.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index d577f96..90ff445 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -239,8 +239,12 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, break; case HAL_PIXEL_FORMAT_YV12: + if ((w&1) || (h&1)) { + LOGE("w or h is odd for HAL_PIXEL_FORMAT_YV12"); + return -EINVAL; + } alignedw = ALIGN(w, 16); - alignedh = ALIGN(h, 2); + alignedh = h; size = alignedw*alignedh + (ALIGN(alignedw/2, 16) * (alignedh/2))*2; break; From a709f0300c238042a33c4640d4321ea3475f12f2 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:31:51 -0800 Subject: [PATCH 302/435] libgralloc-qsd8k: Initial gralloc commit Update the gralloc HAL to match commit: commit 4d3c9ca6fabf2b0111ef6b567df7d244e124b9c2 Author: Arun Kumar K.R Date: Fri Dec 17 13:14:58 2010 -0800 libgralloc-qsd8k: Add support for non-aligned width on HDMI While creating overlay channel for HDMI consider the aligned width and set the crop rectangle to the actual width and height. Change-Id: I8858d71bb10b2be4c57edb605b5da680f53051dc --- libgralloc-qsd8k/Android.mk | 15 + libgralloc-qsd8k/framebuffer.cpp | 506 ++++++++++++++++++++++++++++--- libgralloc-qsd8k/gpu.cpp | 60 +++- libgralloc-qsd8k/gpu.h | 2 + libgralloc-qsd8k/gr.h | 8 +- libgralloc-qsd8k/gralloc.cpp | 11 +- libgralloc-qsd8k/gralloc_priv.h | 143 ++++++++- libgralloc-qsd8k/mapper.cpp | 151 ++++++++- libgralloc-qsd8k/pmemalloc.cpp | 1 + 9 files changed, 830 insertions(+), 67 deletions(-) mode change 100644 => 100755 libgralloc-qsd8k/gralloc_priv.h mode change 100644 => 100755 libgralloc-qsd8k/mapper.cpp diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index b22541a..2c32796 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -31,8 +31,23 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" + +ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT))) +LOCAL_CFLAGS += -DTARGET_MSM7x27 +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_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) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 11b303a..99ec2ad 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, 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. @@ -30,6 +31,7 @@ #include #include #include +#include #include #include @@ -41,12 +43,45 @@ #include "gralloc_priv.h" #include "gr.h" +#ifdef NO_SURFACEFLINGER_SWAPINTERVAL +#include +#endif + +#if defined(HDMI_DUAL_DISPLAY) +#define AS_1080_RATIO_H (4.25/100) // Default Action Safe vertical limit for 1080p +#define AS_1080_RATIO_W (4.25/100) // Default Action Safe horizontal limit for 1080p +#define AS_720_RATIO_H (6.0/100) // Default Action Safe vertical limit for 720p +#define AS_720_RATIO_W (4.25/100) // Default Action Safe horizontal limit for 720p +#define AS_480_RATIO_H (8.0/100) // Default Action Safe vertical limit for 480p +#define AS_480_RATIO_W (5.0/100) // Default Action Safe horizontal limit for 480p +#define HEIGHT_1080P 1080 +#define HEIGHT_720P 720 +#define HEIGHT_480P 480 +#define EVEN_OUT(x) if (x & 0x0001) {x--;} +using overlay::Overlay; +/** min of int a, b */ +static inline int min(int a, int b) { + return (ab) ? a : b; +} +/** align */ +static inline size_t ALIGN(size_t x, size_t align) { + return (x + align-1) & ~(align-1); +} +#endif /*****************************************************************************/ -// numbers of buffers for page flipping -#define NUM_BUFFERS 2 - +enum { + MDDI_PANEL = '1', + EBI2_PANEL = '2', + LCDC_PANEL = '3', + EXT_MDDI_PANEL = '4', + TV_PANEL = '5' +}; enum { PAGE_FLIP = 0x00000001, @@ -57,6 +92,7 @@ struct fb_context_t { framebuffer_device_t device; }; +static int neworientation; /*****************************************************************************/ static void @@ -68,9 +104,12 @@ static int fb_setSwapInterval(struct framebuffer_device_t* dev, int interval) { fb_context_t* ctx = (fb_context_t*)dev; + private_module_t* m = reinterpret_cast( + dev->common.module); if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval) return -EINVAL; - // FIXME: implement fb_setSwapInterval + + m->swapInterval = interval; return 0; } @@ -89,38 +128,341 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev, return 0; } +static void *disp_loop(void *ptr) +{ + struct qbuf_t nxtBuf; + static int cur_buf=-1; + private_module_t *m = reinterpret_cast(ptr); + + while (1) { + pthread_mutex_lock(&(m->qlock)); + + // wait (sleep) while display queue is empty; + if (m->disp.isEmpty()) { + pthread_cond_wait(&(m->qpost),&(m->qlock)); + } + + // dequeue next buff to display and lock it + nxtBuf = m->disp.getHeadValue(); + m->disp.pop(); + pthread_mutex_unlock(&(m->qlock)); + + // post buf out to display synchronously + private_handle_t const* hnd = reinterpret_cast + (nxtBuf.buf); + const size_t offset = hnd->base - m->framebuffer->base; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + +#if defined(HDMI_DUAL_DISPLAY) + pthread_mutex_lock(&m->overlayLock); + m->orientation = neworientation; + m->currentOffset = offset; + pthread_cond_signal(&(m->overlayPost)); + pthread_mutex_unlock(&m->overlayLock); +#endif + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { + LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed"); + } + + if (cur_buf == -1) { + pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock)); + m->avail[nxtBuf.idx].is_avail = true; + pthread_cond_signal(&(m->avail[nxtBuf.idx].cond)); + pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock)); + } else { + pthread_mutex_lock(&(m->avail[cur_buf].lock)); + m->avail[cur_buf].is_avail = true; + pthread_cond_signal(&(m->avail[cur_buf].cond)); + pthread_mutex_unlock(&(m->avail[cur_buf].lock)); + + } + cur_buf = nxtBuf.idx; + } + return NULL; +} + +#if defined(HDMI_DUAL_DISPLAY) +static void *hdmi_ui_loop(void *ptr) +{ + private_module_t* m = reinterpret_cast( + ptr); + while (1) { + pthread_mutex_lock(&m->overlayLock); + pthread_cond_wait(&(m->overlayPost), &(m->overlayLock)); + if (m->exitHDMIUILoop) { + pthread_mutex_unlock(&m->overlayLock); + return NULL; + } + 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) { + if (!pTemp->isChannelUP()) { + int alignedW = ALIGN(m->info.xres, 32); + if (pTemp->startChannel(alignedW, m->info.yres, + m->fbFormat, 1, false, true)) { + pTemp->setFd(m->framebuffer->fd); + pTemp->setCrop(0, 0, m->info.xres, m->info.yres); + } else + pTemp->closeChannel(); + } + + if (pTemp->isChannelUP()) { + int width = pTemp->getFBWidth(); + int height = pTemp->getFBHeight(); + int aswidth = width, asheight = height; + int final_width = width, final_height = height; + int x = 0, y = 0; // Used for calculating normal x,y co-ordinates + int x1 = 0, y1 = 0; // Action safe x, y co-ordinates + int xx = 0, yy = 0; // Final x, y co-ordinates + int fbwidth = m->info.xres, fbheight = m->info.yres; + float defaultASWidthRatio = 0.0f, defaultASHeightRatio = 0.0f; + if(HEIGHT_1080P == height) { + defaultASHeightRatio = AS_1080_RATIO_H; + defaultASWidthRatio = AS_1080_RATIO_W; + } else if(HEIGHT_720P == height) { + defaultASHeightRatio = AS_720_RATIO_H; + defaultASWidthRatio = AS_720_RATIO_W; + } else if(HEIGHT_480P == height) { + defaultASHeightRatio = AS_480_RATIO_H; + defaultASWidthRatio = AS_480_RATIO_W; + } + if(asWidthRatio <= 0.0f) + asWidthRatio = defaultASWidthRatio; + if(asHeightRatio <= 0.0f) + asHeightRatio = defaultASHeightRatio; + + aswidth = (int)((float)width - (float)(width * asWidthRatio)); + asheight = (int)((float)height - (float)(height * asHeightRatio)); + x1 = (int)(width * asWidthRatio) / 2; + y1 = (int)(height * asHeightRatio) / 2; + int rot = m->orientation; + if (fbwidth < fbheight) { + switch(rot) { + // ROT_0 + case 0: + // ROT_180 + case HAL_TRANSFORM_ROT_180: + x = (width - fbwidth) / 2; + if (x < 0) + x = 0; + if (fbwidth < width) + width = fbwidth; + if (fbheight < height) + height = fbheight; + if(rot == HAL_TRANSFORM_ROT_180) + rot = OVERLAY_TRANSFORM_ROT_180; + else + rot = 0; + break; + // ROT_90 + case HAL_TRANSFORM_ROT_90: + rot = OVERLAY_TRANSFORM_ROT_270; + break; + // ROT_270 + case HAL_TRANSFORM_ROT_270: + rot = OVERLAY_TRANSFORM_ROT_90; + break; + } + } + else if (fbwidth > fbheight) { + switch(rot) { + // ROT_0 + case 0: + rot = 0; + break; + // ROT_180 + case HAL_TRANSFORM_ROT_180: + rot = OVERLAY_TRANSFORM_ROT_180; + break; + // ROT_90 + case HAL_TRANSFORM_ROT_90: + // ROT_270 + case HAL_TRANSFORM_ROT_270: + //Swap width and height + int t = fbwidth; + fbwidth = fbheight; + fbheight = t; + x = (width - fbwidth) / 2; + if (x < 0) + x = 0; + if (fbwidth < width) + width = fbwidth; + if (fbheight < height) + height = fbheight; + if(rot == HAL_TRANSFORM_ROT_90) + rot = OVERLAY_TRANSFORM_ROT_270; + else + rot = OVERLAY_TRANSFORM_ROT_90; + break; + } + } + pTemp->setParameter(OVERLAY_TRANSFORM, + rot); + // Calculate the interection of final destination parameters + // Intersection of Action Safe rect and the orig rect will give the final dest rect + xx = max(x1, x); + yy = max(y1, y); + final_width = min((x1+aswidth), (x+width))- xx; + final_height = min((y1+asheight), (y+height))- yy; + EVEN_OUT(xx); + EVEN_OUT(yy); + EVEN_OUT(final_width); + EVEN_OUT(final_height); + pTemp->setPosition(xx, yy, final_width, final_height); + pTemp->queueBuffer(m->currentOffset); + } + } + else + pTemp->closeChannel(); + } + pthread_mutex_unlock(&m->overlayLock); + } + return NULL; +} + +static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->overlayLock); + Overlay* pTemp = m->pobjOverlay; + if (started && pTemp) { + pTemp->closeChannel(); + m->videoOverlay = true; + pthread_cond_signal(&(m->overlayPost)); + } + else { + m->videoOverlay = false; + pthread_cond_signal(&(m->overlayPost)); + } + pthread_mutex_unlock(&m->overlayLock); + return 0; +} + +static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + pthread_mutex_lock(&m->overlayLock); + Overlay* pTemp = m->pobjOverlay; + if (!enable && pTemp) + pTemp->closeChannel(); + m->enableHDMIOutput = enable; + 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( + 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( + 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( + dev->common.module); + pthread_mutex_lock(&m->overlayLock); + neworientation = orientation; + pthread_mutex_unlock(&m->overlayLock); + return 0; +} +#endif + static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) { if (private_handle_t::validate(buffer) < 0) return -EINVAL; + int nxtIdx; + bool reuse; + struct qbuf_t qb; fb_context_t* ctx = (fb_context_t*)dev; private_handle_t const* hnd = reinterpret_cast(buffer); private_module_t* m = reinterpret_cast( dev->common.module); - - if (m->currentBuffer) { - m->base.unlock(&m->base, m->currentBuffer); - m->currentBuffer = 0; - } if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { - m->base.lock(&m->base, buffer, - private_module_t::PRIV_USAGE_LOCKED_FOR_POST, - 0, 0, m->info.xres, m->info.yres, NULL); + reuse = false; + nxtIdx = (m->currentIdx + 1) % NUM_BUFFERS; - const size_t offset = hnd->base - m->framebuffer->base; - m->info.activate = FB_ACTIVATE_VBL; - m->info.yoffset = offset / m->finfo.line_length; - if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { - LOGE("FBIOPUT_VSCREENINFO failed"); - m->base.unlock(&m->base, buffer); - return -errno; + if (m->swapInterval == 0) { + // if SwapInterval = 0 and no buffers available then reuse + // current buf for next rendering so don't post new buffer + if (pthread_mutex_trylock(&(m->avail[nxtIdx].lock))) { + reuse = true; + } else { + if (! m->avail[nxtIdx].is_avail) + reuse = true; + pthread_mutex_unlock(&(m->avail[nxtIdx].lock)); + } } - m->currentBuffer = buffer; - + + if(!reuse){ + // unlock previous ("current") Buffer and lock the new buffer + m->base.lock(&m->base, buffer, + private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0,0, m->info.xres, m->info.yres, NULL); + + // post/queue the new buffer + pthread_mutex_lock(&(m->avail[nxtIdx].lock)); + m->avail[nxtIdx].is_avail = false; + pthread_mutex_unlock(&(m->avail[nxtIdx].lock)); + + qb.idx = nxtIdx; + qb.buf = buffer; + pthread_mutex_lock(&(m->qlock)); + m->disp.push(qb); + 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[m->currentIdx].lock)); + if (! m->avail[m->currentIdx].is_avail) { + pthread_cond_wait(&(m->avail[m->currentIdx].cond), + &(m->avail[m->currentIdx].lock)); + m->avail[m->currentIdx].is_avail = true; + } + pthread_mutex_unlock(&(m->avail[m->currentIdx].lock)); + } + m->base.unlock(&m->base, m->currentBuffer); + } + m->currentBuffer = buffer; + m->currentIdx = nxtIdx; + } else { + if (m->currentBuffer) + m->base.unlock(&m->base, m->currentBuffer); + m->base.lock(&m->base, buffer, + private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0,0, m->info.xres, m->info.yres, NULL); + m->currentBuffer = buffer; + } + } else { void* fb_vaddr; void* buffer_vaddr; @@ -206,28 +548,45 @@ int mapFrameBufferLocked(struct private_module_t* module) * big-endian byte order if bits_per_pixel is greater than 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 = 0; - - /* 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. */ - char property[PROPERTY_VALUE_MAX]; - if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) - module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; - else - module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; + 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; + /* 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. */ + char property[PROPERTY_VALUE_MAX]; + 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; + } /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) */ @@ -320,6 +679,38 @@ int mapFrameBufferLocked(struct private_module_t* module) module->ydpi = ydpi; module->fps = fps; +#ifdef NO_SURFACEFLINGER_SWAPINTERVAL + char pval[PROPERTY_VALUE_MAX]; + property_get("debug.gr.swapinterval", pval, "1"); + module->swapInterval = atoi(pval); + if (module->swapInterval < private_module_t::PRIV_MIN_SWAP_INTERVAL || + module->swapInterval > private_module_t::PRIV_MAX_SWAP_INTERVAL) { + module->swapInterval = 1; + LOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1", + private_module_t::PRIV_MIN_SWAP_INTERVAL, + private_module_t::PRIV_MAX_SWAP_INTERVAL); + } + +#else + /* when surfaceflinger supports swapInterval then can just do this */ + module->swapInterval = 1; +#endif + + module->currentIdx = -1; + pthread_cond_init(&(module->qpost), NULL); + pthread_mutex_init(&(module->qlock), NULL); + for (i = 0; i < NUM_BUFFERS; i++) { + pthread_mutex_init(&(module->avail[i].lock), NULL); + pthread_cond_init(&(module->avail[i].cond), NULL); + module->avail[i].is_avail = true; + } + + /* create display update thread */ + pthread_t thread1; + if (pthread_create(&thread1, NULL, &disp_loop, (void *) module)) { + return -errno; + } + /* * map the framebuffer */ @@ -339,6 +730,18 @@ int mapFrameBufferLocked(struct private_module_t* module) } module->framebuffer->base = intptr_t(vaddr); memset(vaddr, 0, fbSize); + +#if defined(HDMI_DUAL_DISPLAY) + /* Overlay for HDMI*/ + pthread_mutex_init(&(module->overlayLock), NULL); + pthread_cond_init(&(module->overlayPost), NULL); + module->pobjOverlay = new Overlay(); + module->currentOffset = 0; + module->exitHDMIUILoop = false; + pthread_t hdmiUIThread; + pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module); +#endif + return 0; } @@ -355,6 +758,14 @@ static int mapFrameBuffer(struct private_module_t* module) static int fb_close(struct hw_device_t *dev) { fb_context_t* ctx = (fb_context_t*)dev; +#if defined(HDMI_DUAL_DISPLAY) + private_module_t* m = reinterpret_cast( + ctx->device.common.module); + pthread_mutex_lock(&m->overlayLock); + m->exitHDMIUILoop = true; + pthread_cond_signal(&(m->overlayPost)); + pthread_mutex_unlock(&m->overlayLock); +#endif if (ctx) { free(ctx); } @@ -384,6 +795,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; +#if defined(HDMI_DUAL_DISPLAY) + dev->device.orientationChanged = fb_orientationChanged; + dev->device.videoOverlayStarted = fb_videoOverlayStarted; + dev->device.enableHDMIOutput = fb_enableHDMIOutput; + dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio; + dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio; +#endif private_module_t* m = (private_module_t*)module; status = mapFrameBuffer(m); @@ -397,8 +815,8 @@ int fb_device_open(hw_module_t const* module, const char* name, 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; + const_cast(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL; + const_cast(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL; if (m->finfo.reserved[0] == 0x5444 && m->finfo.reserved[1] == 0x5055) { diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 90ff445..a2ccd16 100644 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -79,7 +79,7 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, // 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), size, + 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); @@ -110,6 +110,46 @@ int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage, 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; + } + return err; +} int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle) { @@ -123,7 +163,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* 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. @@ -133,15 +173,25 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* if (usage & GRALLOC_USAGE_HW_2D) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } - +#else + if (usage & GRALLOC_USAGE_PRIVATE_PMEM){ + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; + } +#endif if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; } private_module_t* m = reinterpret_cast(common.module); - - if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 || + 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; diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h index 5da7b6a..5449999 100644 --- a/libgralloc-qsd8k/gpu.h +++ b/libgralloc-qsd8k/gpu.h @@ -71,6 +71,8 @@ class gpu_context_t : public alloc_device_t { Deps& deps; PmemAllocator& pmemAllocator; PmemAllocator& pmemAdspAllocator; + int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, + int* pOffset, int* pFd); }; #endif // GRALLOC_QSD8K_GPU_H diff --git a/libgralloc-qsd8k/gr.h b/libgralloc-qsd8k/gr.h index 1775bfa..49a0513 100644 --- a/libgralloc-qsd8k/gr.h +++ b/libgralloc-qsd8k/gr.h @@ -40,9 +40,15 @@ inline size_t roundUpToPageSize(size_t x) { return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); } +#define FALSE 0 +#define TRUE 1 + int mapFrameBufferLocked(struct private_module_t* module); int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); - +size_t calculateBufferSize(int width, int height, int format); +int decideBufferHandlingMechanism(int format, const char *compositionUsed, + int hasBlitEngine, int *needConversion, + int *useBufferDirectly); /*****************************************************************************/ class Locker { diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index bf60324..a0123d1 100644 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -65,11 +65,20 @@ class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps { virtual size_t getPmemTotalSize(int fd, size_t* size) { + int err = 0; +#ifndef TARGET_MSM7x27 pmem_region region; - int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion); + err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion); if (err == 0) { *size = region.len; } +#else +#ifdef USE_ASHMEM + *size = m->info.xres * m->info.yres * 2 * 2; +#else + *size = 23<<20; //23MB for 7x27 +#endif +#endif return err; } diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h old mode 100644 new mode 100755 index c573941..650ac6c --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, 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. @@ -29,12 +30,98 @@ #include +#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY) +#include "overlayLib.h" +using namespace overlay; +#endif + enum { /* gralloc usage bit indicating a pmem_adsp allocation should be used */ GRALLOC_USAGE_PRIVATE_PMEM_ADSP = GRALLOC_USAGE_PRIVATE_0, + GRALLOC_USAGE_PRIVATE_PMEM = GRALLOC_USAGE_PRIVATE_1, }; +#define NUM_BUFFERS 2 +#define NO_SURFACEFLINGER_SWAPINTERVAL +#define INTERLACE_MASK 0x80 /*****************************************************************************/ +#ifdef __cplusplus +template +struct Node +{ + T data; + Node *next; +}; + +template +class Queue +{ +public: + Queue(): front(NULL), back(NULL), len(0) {dummy = new T;} + ~Queue() + { + clear(); + delete dummy; + } + void push(const T& item) //add an item to the back of the queue + { + if(len != 0) { //if the queue is not empty + back->next = new Node; //create a new node + back = back->next; //set the new node as the back node + back->data = item; + back->next = NULL; + } else { + back = new Node; + back->data = item; + back->next = NULL; + front = back; + } + len++; + } + void pop() //remove the first item from the queue + { + if (isEmpty()) + return; //if the queue is empty, no node to dequeue + T item = front->data; + Node *tmp = front; + front = front->next; + delete tmp; + if(front == NULL) //if the queue is empty, update the back pointer + back = NULL; + len--; + return; + } + T& getHeadValue() const //return the value of the first item in the queue + { //without modification to the structure + if (isEmpty()) { + LOGE("Error can't get head of empty queue"); + return *dummy; + } + return front->data; + } + + bool isEmpty() const //returns true if no elements are in the queue + { + return (front == NULL); + } + + size_t size() const //returns the amount of elements in the queue + { + return len; + } + +private: + Node *front; + Node *back; + size_t len; + void clear() + { + while (!isEmpty()) + pop(); + } + T *dummy; +}; +#endif enum { /* OEM specific HAL formats */ @@ -50,7 +137,21 @@ enum { HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109, HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A, HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B, - HAL_PIXEL_FORMAT_YCrCb_420_SP_INTERLACE = 0x10C, + HAL_PIXEL_FORMAT_R_8 = 0x10D, + HAL_PIXEL_FORMAT_RG_88 = 0x10E, + HAL_PIXEL_FORMAT_INTERLACE = 0x180, + +}; + +/* possible formats for 3D content*/ +enum { + HAL_NO_3D = 0x00, + HAL_3D_IN_LR_SIDE = 0x10000, + HAL_3D_IN_LR_TOP = 0x20000, + HAL_3D_IN_LR_INTERLEAVE = 0x40000, + HAL_3D_OUT_LR_SIDE = 0x1, + HAL_3D_OUT_LR_TOP = 0x2, + HAL_3D_OUT_LR_INTERLEAVE = 0x4 }; /*****************************************************************************/ @@ -59,6 +160,19 @@ struct private_module_t; struct private_handle_t; struct PmemAllocator; +struct qbuf_t { + buffer_handle_t buf; + int idx; +}; + +struct avail_t { + pthread_mutex_t lock; + pthread_cond_t cond; +#ifdef __cplusplus + bool is_avail; +#endif +}; + struct private_module_t { gralloc_module_t base; @@ -75,11 +189,33 @@ struct private_module_t { float xdpi; float ydpi; float fps; - + int swapInterval; +#ifdef __cplusplus + Queue disp; // non-empty when buffer is ready for display +#endif + int currentIdx; + struct avail_t avail[NUM_BUFFERS]; + pthread_mutex_t qlock; + pthread_cond_t qpost; + enum { // flag to indicate we'll post this buffer - PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000, + PRIV_MIN_SWAP_INTERVAL = 0, + PRIV_MAX_SWAP_INTERVAL = 1, }; +#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY) + Overlay* pobjOverlay; + int orientation; + bool videoOverlay; + uint32_t currentOffset; + bool enableHDMIOutput; + bool exitHDMIUILoop; + float actionsafeWidthRatio; + float actionsafeHeightRatio; + pthread_mutex_t overlayLock; + pthread_cond_t overlayPost; +#endif }; /*****************************************************************************/ @@ -96,6 +232,7 @@ struct private_handle_t { PRIV_FLAGS_USES_PMEM = 0x00000002, PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004, PRIV_FLAGS_NEEDS_FLUSH = 0x00000008, + PRIV_FLAGS_USES_ASHMEM = 0x00000010, }; enum { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp old mode 100644 new mode 100755 index 26fadbc..9234c8d --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -25,9 +25,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -35,7 +37,7 @@ #include #include "gralloc_priv.h" - +#include "gr.h" // we need this for now because pmem cannot mmap at an offset #define PMEM_HACK 1 @@ -55,13 +57,19 @@ static int gralloc_map(gralloc_module_t const* module, void** vaddr) { private_handle_t* hnd = (private_handle_t*)handle; + void *mappedAddress; if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { size_t size = hnd->size; #if PMEM_HACK size += hnd->offset; #endif - void* mappedAddress = mmap(0, size, + 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); + } if (mappedAddress == MAP_FAILED) { LOGE("Could not mmap handle %p, fd=%d (%s)", handle, hnd->fd, strerror(errno)); @@ -171,8 +179,8 @@ 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_PMEM_ADSP)) { + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM || + hnd->flags & 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. @@ -239,12 +247,7 @@ int gralloc_lock(gralloc_module_t const* module, // if requesting sw write for non-framebuffer handles, flag for // flushing at unlock - const uint32_t pmemMask = - private_handle_t::PRIV_FLAGS_USES_PMEM | - private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; - if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) && - (hnd->flags & pmemMask) && !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; } @@ -279,12 +282,18 @@ int gralloc_unlock(gralloc_module_t const* module, int32_t current_value, new_value; if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { - struct pmem_region region; 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_CLEAN_RANGE, NULL); + } - region.offset = hnd->offset; - region.len = hnd->size; - err = ioctl(hnd->fd, PMEM_CACHE_FLUSH, ®ion); LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n", hnd, hnd->offset, hnd->size); hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; @@ -347,12 +356,128 @@ int gralloc_perform(struct gralloc_module_t const* module, 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; } + 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) { + *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) { + *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: { + /* 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; +} diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index e42e898..91dc527 100644 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -181,6 +181,7 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, } else { LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); memset((char*)base + offset, 0, size); + //cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); *pBase = base; *pOffset = offset; *pFd = fd; From 155d9fa5fb377881a593d0ed084f384b1ae8f8f1 Mon Sep 17 00:00:00 2001 From: David Ng Date: Mon, 7 Mar 2011 17:35:29 -0800 Subject: [PATCH 306/435] liboverlay: Add liboverlay and enable for MSM8660 target liboverlay based on MSM8660-1066 release. Change-Id: Ic9453d38c5a60b40728e2a3651f7a065d802817e --- liboverlay/Android.mk | 37 ++ liboverlay/overlay.cpp | 820 ++++++++++++++++++++++++++++++++++++ liboverlay/overlayLib.cpp | 849 ++++++++++++++++++++++++++++++++++++++ liboverlay/overlayLib.h | 153 +++++++ 4 files changed, 1859 insertions(+) create mode 100644 liboverlay/Android.mk create mode 100644 liboverlay/overlay.cpp create mode 100644 liboverlay/overlayLib.cpp create mode 100644 liboverlay/overlayLib.h diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk new file mode 100644 index 0000000..e32fbea --- /dev/null +++ b/liboverlay/Android.mk @@ -0,0 +1,37 @@ +# Copyright (C) 2008 The Android Open Source Project +# Copyright (c) 2009, 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 +LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k +LOCAL_SRC_FILES := overlayLib.cpp +LOCAL_MODULE := liboverlay +include $(BUILD_SHARED_LIBRARY) + +# HAL module implemenation, not prelinked and stored in +# hw/..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 += hardware/msm7k/libgralloc-qsd8k +LOCAL_SRC_FILES := overlay.cpp +LOCAL_MODULE := overlay.default +include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp new file mode 100644 index 0000000..988c18c --- /dev/null +++ b/liboverlay/overlay.cpp @@ -0,0 +1,820 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2009, 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. + */ + +#define LOG_TAG "Overlay" + +#include +#include "overlayLib.h" +#include +#include +#include +#include +#include + +using android::Mutex; + +#define USE_MSM_ROTATOR +#define EVEN_OUT(x) if (x & 0x0001) {x--;} + +#define SHARED_MEMORY_REGION_NAME "overlay_shared_memory" +/*****************************************************************************/ + +using namespace overlay; + +struct overlay_control_context_t { + struct overlay_control_device_t device; + void *sharedMemBase; +}; + +struct ov_crop_rect_t { + int x; + int y; + int w; + int h; +}; + +struct overlay_data_context_t { + struct overlay_data_device_t device; + OverlayDataChannel* pobjDataChannel[2]; + int setCrop; + struct ov_crop_rect_t cropRect; + void *sharedMemBase; +}; + +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 private_overlay_module_t { + overlay_module_t base; + Mutex *pobjMutex; +}; + +struct private_overlay_module_t HAL_MODULE_INFO_SYM = { + base: { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: OVERLAY_HARDWARE_MODULE_ID, + name: "QCT MSM OVERLAY module", + author: "QuIC, Inc.", + methods: &overlay_module_methods, + } + }, + pobjMutex: NULL, +}; + +struct handle_t : public native_handle { + int sharedMemoryFd; + int ovid[2]; + int rotid[2]; + int size; + int w; + int h; + int format; + OverlayControlChannel *pobjControlChannel[2]; +}; + +static int handle_get_ovId(const overlay_handle_t overlay, int index = 0) { + return static_cast(overlay)->ovid[index]; +} + +static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) { + return static_cast(overlay)->rotid[index]; +} + + +static int handle_get_size(const overlay_handle_t overlay) { + return static_cast(overlay)->size; +} + +static int handle_get_shared_fd(const overlay_handle_t overlay) { + return static_cast(overlay)->sharedMemoryFd; +} + +/* + * 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 { + 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)->mHandle); + } + +public: + overlay_object(int w, int h, int format, int fd) { + this->overlay_t::getHandleRef = getHandleRef; + mHandle.version = sizeof(native_handle); + mHandle.sharedMemoryFd = fd; + mHandle.numFds = 1; + mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4; + mHandle.ovid[0] = -1; + mHandle.ovid[1] = -1; + mHandle.rotid[0] = -1; + mHandle.rotid[1] = -1; + mHandle.size = -1; + mHandle.w = w; + mHandle.h = h; + mHandle.format = format; + mHandle.pobjControlChannel[0] = 0; + mHandle.pobjControlChannel[1] = 0; + } + + ~overlay_object() { + destroy_overlay(); + } + + int getHwOvId(int index = 0) { return mHandle.ovid[index]; } + int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } + int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} + + bool startControlChannel(int fbnum, bool norot = false) { + if (!mHandle.pobjControlChannel[fbnum]) + mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel(); + else { + mHandle.pobjControlChannel[fbnum]->closeControlChannel(); + mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel(); + } + bool ret = mHandle.pobjControlChannel[fbnum]->startControlChannel( + mHandle.w, mHandle.h, mHandle.format, fbnum, norot); + if (ret) { + if (!(mHandle.pobjControlChannel[fbnum]-> + getOvSessionID(mHandle.ovid[fbnum]) && + mHandle.pobjControlChannel[fbnum]-> + getRotSessionID(mHandle.rotid[fbnum]) && + mHandle.pobjControlChannel[fbnum]-> + getSize(mHandle.size))) + ret = false; + } + + if (!ret) { + closeControlChannel(fbnum); + } + + return ret; + } + + bool setPosition(int x, int y, uint32_t w, uint32_t h, int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->setPosition( + x, y, w, h); + } + + bool setParameter(int param, int value, int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->setParameter( + param, value); + } + + bool closeControlChannel(int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return true; + bool ret = mHandle.pobjControlChannel[fbnum]-> + closeControlChannel(); + delete mHandle.pobjControlChannel[fbnum]; + mHandle.pobjControlChannel[fbnum] = 0; + return ret; + } + + bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->getPosition( + *x, *y, *w, *h); + } + + bool getOrientation(int *orientation, int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->getOrientation( + *orientation); + } + + void destroy_overlay() { + close(mHandle.sharedMemoryFd); + closeControlChannel(0); + closeControlChannel(1); + } + + int getFBWidth(int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->getFBWidth(); + } + + int getFBHeight(int fbnum) { + if (!mHandle.pobjControlChannel[fbnum]) + return false; + return mHandle.pobjControlChannel[fbnum]->getFBHeight(); + } +}; + +// **************************************************************************** +// Control module +// **************************************************************************** + + static int overlay_get(struct overlay_control_device_t *dev, int name) { + int result = -1; + switch (name) { + case OVERLAY_MINIFICATION_LIMIT: + result = HW_OVERLAY_MINIFICATION_LIMIT; + break; + case OVERLAY_MAGNIFICATION_LIMIT: + result = HW_OVERLAY_MAGNIFICATION_LIMIT; + break; + case OVERLAY_SCALING_FRAC_BITS: + result = 32; + 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) { + overlay_object *overlay = NULL; + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + + // Open shared memory to store shared data + int size = sizeof(overlay_shared_data); + void *base; + int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, + size); + + if(fd < 0) { + LOGE("%s: create shared memory failed", __func__); + return NULL; + } + if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) { + LOGE("ashmem_set_prot_region(fd=%d, failed (%s)", + fd, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } else { + base = mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED|MAP_POPULATE, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d) failed (%s)", + fd, size, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } + } + ctx->sharedMemBase = base; + memset(ctx->sharedMemBase, 0, size); + + /* number of buffer is not being used as overlay buffers are coming from client */ + overlay = new overlay_object(w, h, format, fd); + + if (overlay == NULL) { + LOGE("%s: can't create overlay object!", __FUNCTION__); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + return NULL; + } + +#ifdef USE_MSM_ROTATOR + if (!overlay->startControlChannel(0)) { +#else + if (!overlay->startControlChannel(0, true)) { +#endif + LOGE("Failed to start control channel for framebuffer 0"); + overlay->closeControlChannel(0); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + + delete overlay; + return NULL; + } + + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + if (!atoi(value)) { + return overlay; + } + + if (!overlay->startControlChannel(1, true)) { + LOGE("Failed to start control channel for framebuffer 1"); + overlay->closeControlChannel(1); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + + delete overlay; + return NULL; + } + else { + int width = w, height = h, x, y; + int fbWidthHDMI = overlay->getFBWidth(1); + int fbHeightHDMI = overlay->getFBHeight(1); + // width and height for YUV TILE format + int tempWidth = w, tempHeight = h; + /* Caculate the width and height if it is YUV TILE format*/ + if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + tempWidth = w - ( (((w-1)/64 +1)*64) - w); + tempHeight = h - ((((h-1)/32 +1)*32) - h); + } + + if (width * fbHeightHDMI > + fbWidthHDMI * height) { + height = fbWidthHDMI * height / width; + EVEN_OUT(height); + width = fbWidthHDMI; + } else if (width * fbHeightHDMI < + fbWidthHDMI * height) { + width = fbHeightHDMI * width / height; + EVEN_OUT(width); + height = fbHeightHDMI; + } else { + width = fbWidthHDMI; + height = fbHeightHDMI; + } + /* Scaling of upto a max of 8 times supported */ + if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){ + width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth; + } + if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) { + height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight; + } + if (width > fbWidthHDMI) width = fbWidthHDMI; + if (height > fbHeightHDMI) height = fbHeightHDMI; + x = (fbWidthHDMI - width) / 2; + y = (fbHeightHDMI - height) / 2; + + if (!overlay->setPosition(x, y, width, height, 1)) + LOGE("Failed to upscale for framebuffer 1"); + } + + return overlay; + + } + + static void overlay_destroyOverlay(struct overlay_control_device_t *dev, + overlay_t* overlay) + { + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + obj->destroy_overlay(); + 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) */ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + + bool ret = obj->setPosition(x, y, w, h, 0); + if (!ret) + return -1; + return 0; + } + + static int overlay_commit(struct overlay_control_device_t *dev, + overlay_t* overlay) + { + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + + Mutex::Autolock objLock(m->pobjMutex); + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data data; + data.readyToQueue = 1; + memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data)); + } +return 0; + } + + 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 */ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + overlay_object * obj = static_cast(overlay); + bool ret = obj->getPosition(x, y, w, h, 0); + if (!ret) + return -1; + return 0; + } + + static int overlay_setParameter(struct overlay_control_device_t *dev, + overlay_t* overlay, int param, int value) { + + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + + Mutex::Autolock objLock(m->pobjMutex); + + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data data; + data.readyToQueue = 0; + memcpy(ctx->sharedMemBase, (void*)&data, sizeof(data)); + } + + bool ret = obj->setParameter(param, value, 0); + if (!ret) + return -1; + + return 0; + } + + 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 + * + */ + + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + int ovid = handle_get_ovId(handle); + int rotid = handle_get_rotId(handle); + int size = handle_get_size(handle); + int sharedFd = handle_get_shared_fd(handle); + + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + + ctx->sharedMemBase = MAP_FAILED; + + if(sharedFd > 0) { + void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, + MAP_SHARED|MAP_POPULATE, sharedFd, 0); + if(base == MAP_FAILED) { + LOGE("%s: map region failed %d", __func__, -errno); + return -1; + } + ctx->sharedMemBase = base; + } else { + LOGE("Received invalid shared memory fd"); + return -1; + } + + ctx->pobjDataChannel[0] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, + size, 0)) { + LOGE("Couldnt start data channel for framebuffer 0"); + delete ctx->pobjDataChannel[0]; + ctx->pobjDataChannel[0] = 0; + return -1; + } + + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + if (!atoi(value)) { + ctx->pobjDataChannel[1] = 0; + return 0; + } + + ovid = handle_get_ovId(handle, 1); + rotid = handle_get_rotId(handle, 1); + ctx->pobjDataChannel[1] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, + size, 1, true)) { + LOGE("Couldnt start data channel for framebuffer 1"); + delete ctx->pobjDataChannel[1]; + ctx->pobjDataChannel[1] = 0; + } + + return 0; + } + + 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. + */ + + /* no interal overlay buffer to dequeue */ + LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); + + return 0; + } + + 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. */ + struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + + // Check if readyToQueue is enabled. + overlay_shared_data data; + if(ctx->sharedMemBase != MAP_FAILED) + memcpy(&data, ctx->sharedMemBase, sizeof(data)); + else + return false; + + if(!data.readyToQueue) { + LOGE("Overlay is not ready to queue buffers"); + return -1; + } + if(ctx->setCrop) { + bool result = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]-> + setCrop(ctx->cropRect.x,ctx->cropRect.y,ctx->cropRect.w,ctx->cropRect.h)); + ctx->setCrop = 0; + if (!result) { + LOGE("set crop failed for framebuffer 0"); + return -1; + } + } + + bool result = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]-> + queueBuffer((uint32_t) buffer)); + if (!result) + LOGE("Queuebuffer failed for framebuffer 0"); + else { + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + if (!atoi(value)) { + return 0; + } + result = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> + queueBuffer((uint32_t) buffer)); + if (!result) { + LOGE("QueueBuffer failed for framebuffer 1"); + return -1; + } + } + + return -1; + } + + int overlay_setFd(struct overlay_data_device_t *dev, int fd) + { + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + Mutex::Autolock objLock(m->pobjMutex); + + bool ret = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]->setFd(fd)); + if (!ret) { + LOGE("set fd failed for framebuffer 0"); + return -1; + } + + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + if (!atoi(value)) { + return 0; + } + + ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]->setFd(fd)); + if (!ret) { + LOGE("set fd failed for framebuffer 1"); + } + + return 0; + } + + static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, + uint32_t y, uint32_t w, uint32_t h) + { + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + Mutex::Autolock objLock(m->pobjMutex); + + //For primary set Crop + ctx->setCrop = 1; + ctx->cropRect.x = x; + ctx->cropRect.y = y; + ctx->cropRect.w = w; + ctx->cropRect.h = h; + + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + if (!atoi(value)) { + return 0; + } + + bool ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> + setCrop(x, y, w, h)); + if (!ret) { + LOGE("set crop failed for framebuffer 1"); + return -1; + } + return 0; + } + + void *overlay_getBufferAddress(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) + { + /* overlay buffers are coming from client */ + return( NULL ); + } + + int overlay_getBufferCount(struct overlay_data_device_t *dev) + { + return( 0 ); + } + + + 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). + */ + + if (ctx->pobjDataChannel[0]) { + ctx->pobjDataChannel[0]->closeDataChannel(); + delete ctx->pobjDataChannel[0]; + ctx->pobjDataChannel[0] = 0; + } + + if (ctx->pobjDataChannel[1]) { + ctx->pobjDataChannel[1]->closeDataChannel(); + delete ctx->pobjDataChannel[1]; + ctx->pobjDataChannel[1] = 0; + } + + if(ctx->sharedMemBase != MAP_FAILED) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + + 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; + + private_overlay_module_t* m = reinterpret_cast + (const_cast(module)); + if (!m->pobjMutex) + m->pobjMutex = new Mutex(); + + if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { + struct overlay_control_context_t *dev; + dev = (overlay_control_context_t*)malloc(sizeof(*dev)); + + if (!dev) + return status; + + /* 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(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; + dev->device.commit = overlay_commit; + + *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)); + + if (!dev) + return status; + + /* 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(module); + dev->device.common.close = overlay_data_close; + + dev->device.initialize = overlay_initialize; + dev->device.setCrop = overlay_setCrop; + dev->device.dequeueBuffer = overlay_dequeueBuffer; + dev->device.queueBuffer = overlay_queueBuffer; + dev->device.setFd = overlay_setFd; + dev->device.getBufferAddress = overlay_getBufferAddress; + dev->device.getBufferCount = overlay_getBufferCount; + + *device = &dev->device.common; + status = 0; + } + return status; + } diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp new file mode 100644 index 0000000..222adb5 --- /dev/null +++ b/liboverlay/overlayLib.cpp @@ -0,0 +1,849 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, 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 "overlayLib.h" +#include "gralloc_priv.h" + +#define INTERLACE_MASK 0x80 +/* Helper functions */ + +static int get_mdp_format(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888 : + return MDP_RGBA_8888; + case HAL_PIXEL_FORMAT_BGRA_8888: + return MDP_BGRA_8888; + case HAL_PIXEL_FORMAT_RGB_565: + return MDP_RGB_565; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return MDP_Y_CBCR_H2V1; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return MDP_Y_CBCR_H2V2; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return MDP_Y_CRCB_H2V2; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + return MDP_Y_CRCB_H2V2_TILE; + } + return -1; +} + +static int get_size(int format, int w, int h) { + int size, aligned_height, pitch; + + size = w * h; + switch (format) { + case MDP_RGBA_8888: + case MDP_BGRA_8888: + size *= 4; + break; + case MDP_RGB_565: + case MDP_Y_CBCR_H2V1: + size *= 2; + break; + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + size = (size * 3) / 2; + break; + case MDP_Y_CRCB_H2V2_TILE: + aligned_height = (h + 31) & ~31; + pitch = (w + 127) & ~127; + size = pitch * aligned_height; + size = (size + 8191) & ~8191; + + aligned_height = ((h >> 1) + 31) & ~31; + size += pitch * aligned_height; + size = (size + 8191) & ~8191; + break; + default: + return 0; + } + return size; +} + +#define LOG_TAG "OverlayLIB" +static void reportError(const char* message) { + LOGE( "%s", message); +} + +using namespace overlay; + +Overlay::Overlay() : mChannelUP(false) { +} + +Overlay::~Overlay() { + closeChannel(); +} + +int Overlay::getFBWidth() const { + return objOvCtrlChannel.getFBWidth(); +} + +int Overlay::getFBHeight() const { + return objOvCtrlChannel.getFBHeight(); +} + +bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel) { + mChannelUP = objOvCtrlChannel.startControlChannel(w, h, format, fbnum, norot); + if (!mChannelUP) { + return mChannelUP; + } + return objOvDataChannel.startDataChannel(objOvCtrlChannel, fbnum, norot, uichannel); +} + +bool Overlay::closeChannel() { + if (!mChannelUP) + return true; + objOvCtrlChannel.closeControlChannel(); + objOvDataChannel.closeDataChannel(); + mChannelUP = false; + return true; +} + +bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h) { + return objOvCtrlChannel.getPosition(x, y, w, h); +} + +bool Overlay::getOrientation(int& orientation) const { + return objOvCtrlChannel.getOrientation(orientation); +} + +bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { + return objOvCtrlChannel.setPosition(x, y, w, h); +} + +bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation) { + if (!objOvCtrlChannel.setSource(w, h, format, orientation)) { + objOvCtrlChannel.closeControlChannel(); + objOvDataChannel.closeDataChannel(); + mChannelUP = false; + return startChannel(w, h, format, 0, !orientation); + } + else + return true; +} + +bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { + if (!mChannelUP) + return false; + return objOvDataChannel.setCrop(x, y, w, h); +} + +bool Overlay::setParameter(int param, int value) { + return objOvCtrlChannel.setParameter(param, value); +} + +bool Overlay::setOrientation(int value) { + return objOvCtrlChannel.setParameter(OVERLAY_TRANSFORM, value); +} + +bool Overlay::setFd(int fd) { + return objOvDataChannel.setFd(fd); +} + +bool Overlay::queueBuffer(uint32_t offset) { + return objOvDataChannel.queueBuffer(offset); +} + +bool Overlay::queueBuffer(buffer_handle_t buffer) { + private_handle_t const* hnd = reinterpret_cast + (buffer); + const size_t offset = hnd->offset; + const int fd = hnd->fd; + if (setFd(fd)) { + return queueBuffer(offset); + } + return false; +} + +OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1) { + memset(&mOVInfo, 0, sizeof(mOVInfo)); + memset(&mRotInfo, 0, sizeof(mRotInfo)); +} + + +OverlayControlChannel::~OverlayControlChannel() { + closeControlChannel(); +} + +bool OverlayControlChannel::openDevices(int fbnum) { + if (fbnum < 0) + return false; + + 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) { + reportError("Cant open framebuffer "); + return false; + } + + fb_fix_screeninfo finfo; + if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) { + reportError("FBIOGET_FSCREENINFO on fb1 failed"); + close(mFD); + mFD = -1; + return false; + } + + fb_var_screeninfo vinfo; + if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) { + reportError("FBIOGET_VSCREENINFO on fb1 failed"); + close(mFD); + mFD = -1; + return false; + } + mFBWidth = vinfo.xres; + mFBHeight = vinfo.yres; + mFBbpp = vinfo.bits_per_pixel; + mFBystride = finfo.line_length; + + if (!mNoRot) { + mRotFD = open("/dev/msm_rotator", O_RDWR, 0); + if (mRotFD < 0) { + reportError("Cant open rotator device"); + close(mFD); + mFD = -1; + return false; + } + } + + return true; +} + +bool OverlayControlChannel::setOverlayInformation(int w, int h, + int format, int flags) { + int origW, origH, xoff, yoff; + + mOVInfo.id = MSMFB_NEW_REQUEST; + mOVInfo.src.width = w; + mOVInfo.src.height = h; + mOVInfo.src_rect.x = 0; + mOVInfo.src_rect.y = 0; + mOVInfo.dst_rect.x = 0; + mOVInfo.dst_rect.y = 0; + mOVInfo.dst_rect.w = w; + mOVInfo.dst_rect.h = h; + if(format == MDP_Y_CRCB_H2V2_TILE) { + if (mNoRot) { + mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w); + mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h); + mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; + } else { + mOVInfo.src_rect.w = w; + mOVInfo.src_rect.h = h; + mOVInfo.src.width = (((w-1)/64 +1)*64); + mOVInfo.src.height = (((h-1)/32 +1)*32); + mOVInfo.src_rect.x = mOVInfo.src.width - w; + mOVInfo.src_rect.y = mOVInfo.src.height - h; + mOVInfo.src.format = MDP_Y_CRCB_H2V2; + } + } else { + mOVInfo.src_rect.w = w; + mOVInfo.src_rect.h = h; + mOVInfo.src.format = format; + } + + if (w > mFBWidth) + mOVInfo.dst_rect.w = mFBWidth; + if (h > mFBHeight) + mOVInfo.dst_rect.h = mFBHeight; + mOVInfo.z_order = 0; + mOVInfo.alpha = 0xff; + mOVInfo.transp_mask = 0xffffffff; + mOVInfo.flags = flags; + mOVInfo.is_fg = 0; + mSize = get_size(format, w, h); + return true; +} + +bool OverlayControlChannel::startOVRotatorSessions(int w, int h, + int format) { + bool ret = true; + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + reportError("startOVRotatorSessions, Overlay set failed"); + ret = false; + } + else if (mNoRot) + return true; + + if (ret) { + mRotInfo.src.format = format; + mRotInfo.src.width = w; + mRotInfo.src.height = h; + mRotInfo.src_rect.w = w; + mRotInfo.src_rect.h = h; + mRotInfo.dst.width = w; + mRotInfo.dst.height = h; + if(format == MDP_Y_CRCB_H2V2_TILE) { + mRotInfo.src.width = (((w-1)/64 +1)*64); + mRotInfo.src.height = (((h-1)/32 +1)*32); + mRotInfo.src_rect.w = (((w-1)/64 +1)*64); + mRotInfo.src_rect.h = (((h-1)/32 +1)*32); + mRotInfo.dst.width = (((w-1)/64 +1)*64); + mRotInfo.dst.height = (((h-1)/32 +1)*32); + mRotInfo.dst.format = MDP_Y_CRCB_H2V2; + } else { + mRotInfo.dst.format = format; + } + mRotInfo.dst_x = 0; + mRotInfo.dst_y = 0; + mRotInfo.src_rect.x = 0; + mRotInfo.src_rect.y = 0; + mRotInfo.rotations = 0; + mRotInfo.enable = 0; + mRotInfo.session_id = 0; + int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); + if (result) { + reportError("Rotator session failed"); + ret = false; + } + else + return ret; + } + + closeControlChannel(); + + return ret; +} + +bool OverlayControlChannel::startControlChannel(int w, int h, + int format, int fbnum, bool norot) { + mNoRot = norot; + fb_fix_screeninfo finfo; + fb_var_screeninfo vinfo; + int hw_format; + int flags = 0; + int colorFormat = format; + if (format & INTERLACE_MASK) { + flags |= MDP_DEINTERLACE; + + // Get the actual format + colorFormat = format ^ HAL_PIXEL_FORMAT_INTERLACE; + } + hw_format = get_mdp_format(colorFormat); + if (hw_format < 0) { + reportError("Unsupported format"); + return false; + } + + if (!openDevices(fbnum)) + return false; + + if (!setOverlayInformation(w, h, hw_format, flags)) + return false; + + return startOVRotatorSessions(w, h, hw_format); +} + +bool OverlayControlChannel::closeControlChannel() { + if (!isChannelUP()) + return true; + + if (!mNoRot && mRotFD > 0) { + ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id)); + close(mRotFD); + mRotFD = -1; + } + + int ovid = mOVInfo.id; + int ret = ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid); + close(mFD); + memset(&mOVInfo, 0, sizeof(mOVInfo)); + memset(&mRotInfo, 0, sizeof(mRotInfo)); + mFD = -1; + + return true; +} + +bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format, int orientation) { + format = get_mdp_format(format); + if ((orientation == mOrientation) && ((orientation == MDP_ROT_90) + || (orientation == MDP_ROT_270))) { + if (format == MDP_Y_CRCB_H2V2_TILE) { + format = MDP_Y_CRCB_H2V2; + w = (((w-1)/64 +1)*64); + h = (((h-1)/32 +1)*32); + } + int tmp = w; + w = h; + h = tmp; + } + if (w == mOVInfo.src.width && h == mOVInfo.src.height + && format == mOVInfo.src.format && orientation == mOrientation) + return true; + mOrientation = orientation; + return false; +} + +bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { + + int width = w, height = h; + if (!isChannelUP() || + (x < 0) || (y < 0) || ((x + w) > mFBWidth) || + ((y + h) > mFBHeight)) { + reportError("setPosition failed"); + return false; + } + + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("setPosition, overlay GET failed"); + return false; + } + + /* Scaling of upto a max of 8 times supported */ + if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){ + w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w; + } + if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) { + h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h; + } + ov.dst_rect.x = x; + ov.dst_rect.y = y; + ov.dst_rect.w = w; + ov.dst_rect.h = h; + + if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { + reportError("setPosition, Overlay SET failed"); + return false; + } + mOVInfo = ov; + + return true; +} + +void OverlayControlChannel::swapOVRotWidthHeight() { + int tmp = mOVInfo.src.width; + mOVInfo.src.width = mOVInfo.src.height; + mOVInfo.src.height = tmp; + + tmp = mOVInfo.src_rect.h; + mOVInfo.src_rect.h = mOVInfo.src_rect.w; + mOVInfo.src_rect.w = tmp; + + tmp = mRotInfo.dst.width; + mRotInfo.dst.width = mRotInfo.dst.height; + mRotInfo.dst.height = tmp; +} + +bool OverlayControlChannel::setParameter(int param, int value) { + if (!isChannelUP()) + return false; + + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("setParameter, overlay GET failed"); + return false; + } + mOVInfo = ov; + + switch (param) { + case OVERLAY_DITHER: + break; + case OVERLAY_TRANSFORM: + { + int val = mOVInfo.user_data[0]; + if (value && mNoRot) + return true; + + switch(value) { + case 0: + { + if (val == MDP_ROT_90) { + int tmp = mOVInfo.src_rect.y; + mOVInfo.src_rect.y = mOVInfo.src.width - + (mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.x = tmp; + swapOVRotWidthHeight(); + } + else if (val == MDP_ROT_270) { + int tmp = mOVInfo.src_rect.x; + mOVInfo.src_rect.x = mOVInfo.src.height - ( + mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.y = tmp; + swapOVRotWidthHeight(); + } + mOVInfo.user_data[0] = MDP_ROT_NOP; + break; + } + case OVERLAY_TRANSFORM_ROT_90: + { + if (val == MDP_ROT_270) { + mOVInfo.src_rect.x = mOVInfo.src.width - ( + mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.y = mOVInfo.src.height - ( + mOVInfo.src_rect.y + mOVInfo.src_rect.h); + } + else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { + int tmp = mOVInfo.src_rect.x; + mOVInfo.src_rect.x = mOVInfo.src.height - + (mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.y = tmp; + swapOVRotWidthHeight(); + } + mOVInfo.user_data[0] = MDP_ROT_90; + break; + } + case OVERLAY_TRANSFORM_ROT_180: + { + if (val == MDP_ROT_270) { + int tmp = mOVInfo.src_rect.y; + mOVInfo.src_rect.y = mOVInfo.src.width - + (mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.x = tmp; + swapOVRotWidthHeight(); + } + else if (val == MDP_ROT_90) { + int tmp = mOVInfo.src_rect.x; + mOVInfo.src_rect.x = mOVInfo.src.height - ( + mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.y = tmp; + swapOVRotWidthHeight(); + } + mOVInfo.user_data[0] = MDP_ROT_180; + break; + } + case OVERLAY_TRANSFORM_ROT_270: + { + if (val == MDP_ROT_90) { + mOVInfo.src_rect.y = mOVInfo.src.height - + (mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.x = mOVInfo.src.width - + (mOVInfo.src_rect.x + mOVInfo.src_rect.w); + } + else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { + int tmp = mOVInfo.src_rect.y; + mOVInfo.src_rect.y = mOVInfo.src.width - ( + mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.x = tmp; + swapOVRotWidthHeight(); + } + + mOVInfo.user_data[0] = MDP_ROT_270; + break; + } + default: return false; + } + mRotInfo.rotations = mOVInfo.user_data[0]; + if (mOVInfo.user_data[0]) + mRotInfo.enable = 1; + else { + if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) + mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; + mRotInfo.enable = 0; + } + if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { + reportError("setParameter, rotator start failed"); + return false; + } + + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + reportError("setParameter, overlay set failed"); + return false; + } + break; + } + default: + reportError("Unsupproted param"); + return false; + } + + return true; +} + +bool OverlayControlChannel::getPosition(int& x, int& y, + uint32_t& w, uint32_t& h) { + if (!isChannelUP()) + return false; + + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("getPosition, overlay GET failed"); + return false; + } + mOVInfo = ov; + + x = mOVInfo.dst_rect.x; + y = mOVInfo.dst_rect.y; + w = mOVInfo.dst_rect.w; + h = mOVInfo.dst_rect.h; + + return true; +} + +bool OverlayControlChannel::getOrientation(int& orientation) const { + if (!isChannelUP()) + return false; + + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("getOrientation, overlay GET failed"); + return false; + } + orientation = ov.user_data[0]; + return true; +} +bool OverlayControlChannel::getOvSessionID(int& sessionID) const { + if (!isChannelUP()) + return false; + sessionID = mOVInfo.id; + return true; +} + +bool OverlayControlChannel::getRotSessionID(int& sessionID) const { + if (!isChannelUP()) + return false; + sessionID = mRotInfo.session_id; + return true; +} + +bool OverlayControlChannel::getSize(int& size) const { + if (!isChannelUP()) + return false; + size = mSize; + return true; +} + +OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1), + mPmemFD(-1), mPmemAddr(0) { +} + +OverlayDataChannel::~OverlayDataChannel() { + closeDataChannel(); +} + +bool OverlayDataChannel::startDataChannel( + const OverlayControlChannel& objOvCtrlChannel, + int fbnum, bool norot, bool uichannel) { + int ovid, rotid, size; + mNoRot = norot; + memset(&mOvData, 0, sizeof(mOvData)); + memset(&mOvDataRot, 0, sizeof(mOvDataRot)); + memset(&mRotData, 0, sizeof(mRotData)); + if (objOvCtrlChannel.getOvSessionID(ovid) && + objOvCtrlChannel.getRotSessionID(rotid) && + objOvCtrlChannel.getSize(size)) { + return startDataChannel(ovid, rotid, size, fbnum, norot, uichannel); + } + else + return false; +} + +bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) { + if (fbnum < 0) + return false; + 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) { + reportError("Cant open framebuffer "); + return false; + } + if (!mNoRot) { + mRotFD = open("/dev/msm_rotator", O_RDWR, 0); + if (mRotFD < 0) { + reportError("Cant open rotator device"); + close(mFD); + mFD = -1; + return false; + } + + mPmemAddr = MAP_FAILED; + + if(!uichannel) { + mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC); + if(mPmemFD >= 0) + mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE, + MAP_SHARED, mPmemFD, 0); + } + + if (mPmemAddr == MAP_FAILED) { + mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC); + if (mPmemFD < 0) { + reportError("Cant open pmem_adsp "); + close(mFD); + mFD = -1; + close(mRotFD); + mRotFD = -1; + return false; + } else { + mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE, + MAP_SHARED, mPmemFD, 0); + if (mPmemAddr == MAP_FAILED) { + reportError("Cant map pmem_adsp "); + close(mFD); + mFD = -1; + close(mPmemFD); + mPmemFD = -1; + close(mRotFD); + mRotFD = -1; + return false; + } + } + } + + mOvDataRot.data.memory_id = mPmemFD; + mRotData.dst.memory_id = mPmemFD; + mRotData.dst.offset = 0; + } + + return true; +} + +bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size, + int fbnum, bool norot, bool uichannel) { + memset(&mOvData, 0, sizeof(mOvData)); + memset(&mOvDataRot, 0, sizeof(mOvDataRot)); + memset(&mRotData, 0, sizeof(mRotData)); + mNoRot = norot; + mOvData.data.memory_id = -1; + mOvData.id = ovid; + mOvDataRot = mOvData; + mPmemOffset = size; + mRotData.session_id = rotid; + + return openDevices(fbnum, uichannel); +} + +bool OverlayDataChannel::closeDataChannel() { + if (!isChannelUP()) + return true; + + if (!mNoRot && mRotFD > 0) { + munmap(mPmemAddr, mPmemOffset * 2); + close(mPmemFD); + mPmemFD = -1; + close(mRotFD); + mRotFD = -1; + } + close(mFD); + mFD = -1; + memset(&mOvData, 0, sizeof(mOvData)); + memset(&mOvDataRot, 0, sizeof(mOvDataRot)); + memset(&mRotData, 0, sizeof(mRotData)); + + return true; +} + +bool OverlayDataChannel::setFd(int fd) { + mOvData.data.memory_id = fd; + return true; +} + +bool OverlayDataChannel::queueBuffer(uint32_t offset) { + if ((!isChannelUP()) || mOvData.data.memory_id < 0) { + reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from"); + return false; + } + + msmfb_overlay_data *odPtr; + mOvData.data.offset = offset; + odPtr = &mOvData; + + if (!mNoRot) { + mRotData.src.memory_id = mOvData.data.memory_id; + mRotData.src.offset = offset; + mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset; + + int result = ioctl(mRotFD, + MSM_ROTATOR_IOCTL_ROTATE, &mRotData); + + if (!result) { + mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; + odPtr = &mOvDataRot; + } + } + + if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) { + reportError("overlay play failed."); + return false; + } + + return true; +} + +bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { + if (!isChannelUP()) { + reportError("Channel not set"); + return false; + } + + mdp_overlay ov; + ov.id = mOvData.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("setCrop, overlay GET failed"); + return false; + } + + if (ov.user_data[0] == MDP_ROT_90) { + int tmp = x; + x = ov.src.width - (y + h); + y = tmp; + + tmp = w; + w = h; + h = tmp; + } + else if (ov.user_data[0] == MDP_ROT_270) { + int tmp = y; + y = ov.src.height - (x + w); + x = tmp; + + tmp = w; + w = h; + h = tmp; + } + + if ((ov.src_rect.x == x) && + (ov.src_rect.y == y) && + (ov.src_rect.w == w) && + (ov.src_rect.h == h)) + return true; + if ( (int) x < 0 || (int) y < 0 || (int) w < 0 || (int) h < 0){ + LOGE("%s: invalid value for crop: x=%d,y=%d,w=%d,h=%d",__func__,x,y,w,h); + return false; + } + + ov.src_rect.x = x; + ov.src_rect.y = y; + ov.src_rect.w = w; + ov.src_rect.h = h; + + /* Scaling of upto a max of 8 times supported */ + if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){ + ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w; + } + if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) { + ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h; + } + if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { + reportError("setCrop, overlay set error"); + return false; + } + + return true; +} diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h new file mode 100644 index 0000000..f5b4279 --- /dev/null +++ b/liboverlay/overlayLib.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define HW_OVERLAY_MAGNIFICATION_LIMIT 8 +#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT + +namespace overlay { + +class OverlayControlChannel { + + bool mNoRot; + + int mFBWidth; + int mFBHeight; + int mFBbpp; + int mFBystride; + + int mFD; + int mRotFD; + int mSize; + int mOrientation; + mdp_overlay mOVInfo; + msm_rotator_img_info mRotInfo; + bool openDevices(int fbnum = -1); + bool setOverlayInformation(int w, int h, int format, int flags); + bool startOVRotatorSessions(int w, int h, int format); + void swapOVRotWidthHeight(); + +public: + OverlayControlChannel(); + ~OverlayControlChannel(); + bool startControlChannel(int w, int h, int format, + int fbnum, bool norot = false); + bool closeControlChannel(); + bool setPosition(int x, int y, uint32_t w, uint32_t h); + bool setParameter(int param, int value); + 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; } + bool getOrientation(int& orientation) const; + bool setSource(uint32_t w, uint32_t h, int format, int orientation); +}; + +class OverlayDataChannel { + + bool mNoRot; + int mFD; + int mRotFD; + int mPmemFD; + void* mPmemAddr; + uint32_t mPmemOffset; + msmfb_overlay_data mOvData; + msmfb_overlay_data mOvDataRot; + msm_rotator_data_info mRotData; + + bool openDevices(int fbnum = -1, bool uichannel = false); + +public: + OverlayDataChannel(); + ~OverlayDataChannel(); + bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel, + int fbnum, bool norot = false, bool uichannel = false); + bool startDataChannel(int ovid, int rotid, int size, + int fbnum, bool norot = false, bool uichannel = false); + 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 isChannelUP() const { return (mFD > 0); } +}; + +/* + * Overlay class for single thread application + * A multiple thread/process application need to use Overlay HAL + */ +class Overlay { + + bool mChannelUP; + + OverlayControlChannel objOvCtrlChannel; + OverlayDataChannel objOvDataChannel; + +public: + Overlay(); + ~Overlay(); + + bool startChannel(int w, int h, int format, int fbnum, bool norot = false, bool uichannel = false); + bool closeChannel(); + bool setPosition(int x, int y, uint32_t w, uint32_t h); + bool setParameter(int param, int value); + bool setOrientation(int value); + bool setFd(int fd); + bool queueBuffer(uint32_t offset); + bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h); + bool isChannelUP() const { return mChannelUP; } + int getFBWidth() const; + int getFBHeight() const; + bool getOrientation(int& orientation) const; + bool queueBuffer(buffer_handle_t buffer); + bool setSource(uint32_t w, uint32_t h, int format, int orientation); + bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h); +}; + +struct overlay_shared_data { + int readyToQueue; +}; + +}; +#endif From d1fc805f3464afbc30841a17c683d9ee4659f9af Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:35:59 -0800 Subject: [PATCH 307/435] libgralloc-qsd8k: Initial gralloc changes for honeycomb This commit contains the following changes in the gralloc: - Add buffertype in the gralloc handle i.e video buffer or UI buffer - Add support for allocating memory from the /dev/pmem_smipool - Add support for obtaining the buffer type and the HAL formats from the input format which could be an OMX format. - Add buffer type, format, width and height in the gralloc handle Change-Id: Ie801cfcf5cea9c4b718b75e88abf71be6b087de7 --- libgralloc-qsd8k/framebuffer.cpp | 2 +- libgralloc-qsd8k/gpu.cpp | 81 +++++++++++++++++++++++++++----- libgralloc-qsd8k/gpu.h | 4 +- libgralloc-qsd8k/gralloc.cpp | 3 +- libgralloc-qsd8k/gralloc_priv.h | 29 +++++++++--- libgralloc-qsd8k/pmemalloc.cpp | 72 +++++++++++++++++++++------- libgralloc-qsd8k/pmemalloc.h | 7 +-- 7 files changed, 157 insertions(+), 41 deletions(-) mode change 100644 => 100755 libgralloc-qsd8k/gpu.cpp mode change 100644 => 100755 libgralloc-qsd8k/gpu.h mode change 100644 => 100755 libgralloc-qsd8k/gralloc.cpp mode change 100644 => 100755 libgralloc-qsd8k/pmemalloc.cpp mode change 100644 => 100755 libgralloc-qsd8k/pmemalloc.h diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 99ec2ad..7669785 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -718,7 +718,7 @@ 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(dup(fd), fbSize, - private_handle_t::PRIV_FLAGS_USES_PMEM); + 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; diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp old mode 100644 new mode 100755 index a2ccd16..81b4579 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -69,7 +69,7 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, // 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); + return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres); } if (bufferMask >= ((1LU<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); + 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 ; ialloc_pmem_buffer(size, usage, &base, &offset, &fd); if (err < 0) { if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && @@ -234,7 +234,7 @@ try_ashmem: } if (err == 0) { - private_handle_t* hnd = new private_handle_t(fd, size, flags); + private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType, format, width, height); hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; @@ -250,6 +250,61 @@ 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, int *halFormat) +{ + *bufferType = BUFFER_TYPE_VIDEO; + *halFormat = inputFormat; + *colorFormat = inputFormat; + + switch(inputFormat) { + case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: + { + *colorFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; + *halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; + } break; + case (OMX_QCOM_COLOR_FormatYVU420SemiPlanar ^ QOMX_INTERLACE_FLAG): + { + *colorFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; + *halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP ^ HAL_PIXEL_FORMAT_INTERLACE; + } break; + case (QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ^ QOMX_INTERLACE_FLAG): + { + *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; + *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED ^ HAL_PIXEL_FORMAT_INTERLACE; + } break; + case (QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ^ QOMX_3D_VIDEO_FLAG): + { + *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; + *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED | HAL_3D_IN_LR_SIDE | HAL_3D_OUT_LR_SIDE; + } break; + case QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka: + { + *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; + *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; + } break; + default: + { + 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; + } + break; + } +} + +} + int gpu_context_t::alloc_impl(int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) { if (!pHandle || !pStride) @@ -259,7 +314,10 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, alignedw = ALIGN(w, 32); alignedh = ALIGN(h, 32); - switch (format) { + int colorFormat, bufferType, halFormat; + getGrallocInformationFromFormat(format, &colorFormat, &bufferType, &halFormat); + + switch (colorFormat) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRA_8888: @@ -287,10 +345,11 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, size = ALIGN( alignedw * alignedh, 8192); size += ALIGN( alignedw * ALIGN(h/2, 32), 4096); 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 HAL_PIXEL_FORMAT_YV12"); + LOGE("w or h is odd for the YUV format"); return -EINVAL; } alignedw = ALIGN(w, 16); @@ -311,7 +370,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(size, usage, pHandle); } else { - err = gralloc_alloc_buffer(size, usage, pHandle); + err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, halFormat, w, h); } if (err < 0) { diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h old mode 100644 new mode 100755 index 5449999..67a58d8 --- a/libgralloc-qsd8k/gpu.h +++ b/libgralloc-qsd8k/gpu.h @@ -56,7 +56,8 @@ class gpu_context_t : public alloc_device_t { 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 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); @@ -73,6 +74,7 @@ class gpu_context_t : public alloc_device_t { PmemAllocator& pmemAdspAllocator; int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, int* pOffset, int* pFd); + void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType, int *halFormat); }; #endif // GRALLOC_QSD8K_GPU_H diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp old mode 100644 new mode 100755 index a0123d1..019a8cd --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -149,8 +149,7 @@ static SimpleBestFitAllocator pmemAllocMgr; static PmemUserspaceAllocator pmemAllocator(pmemAllocatorDeviceDepsImpl, pmemAllocMgr, "/dev/pmem"); -static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl, - "/dev/pmem_adsp"); +static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl); /*****************************************************************************/ diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 650ac6c..e708452 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -38,12 +38,16 @@ using namespace overlay; enum { /* gralloc usage bit indicating a pmem_adsp allocation should be used */ GRALLOC_USAGE_PRIVATE_PMEM_ADSP = GRALLOC_USAGE_PRIVATE_0, - GRALLOC_USAGE_PRIVATE_PMEM = GRALLOC_USAGE_PRIVATE_1, + GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL = GRALLOC_USAGE_PRIVATE_1, }; #define NUM_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 template @@ -154,6 +158,15 @@ enum { HAL_3D_OUT_LR_INTERLEAVE = 0x4 }; +enum { + BUFFER_TYPE_UI = 0, + BUFFER_TYPE_VIDEO +}; + +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; /*****************************************************************************/ struct private_module_t; @@ -248,7 +261,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; @@ -256,15 +269,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; diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp old mode 100644 new mode 100755 index 91dc527..1d78333 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -225,9 +225,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; @@ -268,33 +267,66 @@ 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); - if (fd < 0) { + const char *device; + + if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { + device = DEVICE_PMEM_ADSP; + } else if (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) { + device = DEVICE_PMEM_SMIPOOL; + } else { + LOGE("Invalid device"); + return -EINVAL; + } + + int master_fd = deps.open(device, openFlags, 0); + if (master_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); - void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_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); + deps.close(master_fd); END_FUNC; return err; } - memset(base, 0, size); + + // Connect and map the PMEM region to give to the client process + int fd = deps.open(device, O_RDWR, 0); + err = fd < 0 ? fd : 0; - *pBase = base; - *pOffset = 0; - *pFd = fd; + // and connect to it + if (err == 0) { + err = deps.connectPmem(fd, master_fd); + } + + // and make it available to the client process + if (err == 0) { + err = deps.mapPmem(fd, offset, size); + } + + if (err == 0) { + *pBase = base; + *pOffset = 0; + *pFd = fd; + } else { + deps.munmap(base, size); + deps.unmapPmem(fd, offset, size); + deps.close(fd); + deps.close(master_fd); + return err; + } END_FUNC; return 0; @@ -306,12 +338,18 @@ int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, i BEGIN_FUNC; // 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); + int err = deps.unmapPmem(fd, offset, 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; + } + err = deps.munmap(base, size); + if (err < 0) { + err = deps.getErrno(); + LOGW("error unmapping pmem master_fd: %s", strerror(err)); return -err; } END_FUNC; diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h old mode 100644 new mode 100755 index b0f45c7..f433010 --- a/libgralloc-qsd8k/pmemalloc.h +++ b/libgralloc-qsd8k/pmemalloc.h @@ -139,9 +139,12 @@ 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 connectPmem(int fd, int master_fd) = 0; + virtual int mapPmem(int fd, int offset, size_t size) = 0; + virtual int unmapPmem(int fd, int offset, size_t size) = 0; }; - PmemKernelAllocator(Deps& deps, const char* pmemdev); + PmemKernelAllocator(Deps& deps); virtual ~PmemKernelAllocator(); // Only valid after init_pmem_area() has completed successfully. @@ -154,8 +157,6 @@ class PmemKernelAllocator: public PmemAllocator { private: Deps& deps; - - const char* pmemdev; }; #endif // GRALLOC_QSD8K_PMEMALLOC_H From 13ac17278df88573e6ed6cc0f1e9214b283d10a6 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:37:04 -0800 Subject: [PATCH 308/435] hwcomposer: Initial version of the Hardware Composer HAL Initial HWC changes - Add support to recognize video/camera buffers in the prepare phase - Use overlays to draw single video/camera layers Change-Id: I3351b3172fae12d9f6e016ff7e1a2f6a476799b3 --- libhwcomposer/Android.mk | 32 ++++ libhwcomposer/hwcomposer.cpp | 330 +++++++++++++++++++++++++++++++++++ 2 files changed, 362 insertions(+) create mode 100755 libhwcomposer/Android.mk create mode 100755 libhwcomposer/hwcomposer.cpp diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk new file mode 100755 index 0000000..4e3dba3 --- /dev/null +++ b/libhwcomposer/Android.mk @@ -0,0 +1,32 @@ +# Copyright (c) 2010, 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) + +# HAL module implemenation, not prelinked and stored in +# hw/..so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware liboverlay + +LOCAL_SRC_FILES := \ + hwcomposer.cpp + +LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" +LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k +LOCAL_C_INCLUDES += hardware/msm7k/liboverlay + +include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp new file mode 100755 index 0000000..66d9e2a --- /dev/null +++ b/libhwcomposer/hwcomposer.cpp @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (c) 2010, 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 +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/*****************************************************************************/ + +// Enum containing the supported composition types +enum { + COMPOSITION_TYPE_GPU, + COMPOSITION_TYPE_MDP, + COMPOSITION_TYPE_C2D, + COMPOSITION_TYPE_CPU +}; + +enum LayerType{ + GPU, // This layer is to be handled by Surfaceflinger + OVERLAY, // This layer is to be handled by the overlay + COPYBIT // This layer is to be handled by copybit +}; + +struct hwc_context_t { + hwc_composer_device_t device; + /* our private state goes below here */ + overlay::Overlay* mOverlayLibObject; +}; + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device); + +static struct hw_module_methods_t hwc_module_methods = { + open: hwc_device_open +}; + + +struct private_hwc_module_t { + hwc_module_t base; + overlay_control_device_t *overlayEngine; + copybit_device_t *copybitEngine; + int compositionType; +}; + +struct private_hwc_module_t HAL_MODULE_INFO_SYM = { + base: { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: HWC_HARDWARE_MODULE_ID, + name: "Hardware Composer Module", + author: "The Android Open Source Project", + methods: &hwc_module_methods, + } + }, + overlayEngine: NULL, + copybitEngine: NULL, + compositionType: 0, +}; + +/*****************************************************************************/ + +static void dump_layer(hwc_layer_t const* l) { + LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->compositionType, l->flags, l->handle, l->transform, l->blending, + l->sourceCrop.left, + l->sourceCrop.top, + l->sourceCrop.right, + l->sourceCrop.bottom, + l->displayFrame.left, + l->displayFrame.top, + l->displayFrame.right, + l->displayFrame.bottom); +} + + +static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { + + int yuvBufferCount = 0; + + if (list && (list->flags & HWC_GEOMETRY_CHANGED)) { + for (size_t i=0 ; inumHwLayers; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)) { + yuvBufferCount++; + if (yuvBufferCount > 1) { + break; + } + } + } + + for (size_t i=0 ; inumHwLayers ; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + // If there is a single Fullscreen layer, we can bypass it - TBD + // If there is only one video/camera buffer, we can bypass itn + if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { + list->hwLayers[i].compositionType = OVERLAY; + list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + } else { + // For other layers, check composition used. - C2D/MDP composition - TBD + list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + } + } + } + + return 0; +} + +static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) +{ + int ret = 0; + if (ctx && ctx->mOverlayLibObject) { + private_handle_t *hnd = (private_handle_t *)layer->handle; + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform); + if (!ret) { + LOGE("drawLayerUsingOverlay setSource failed"); + return -1; + } + + hwc_rect_t sourceCrop = layer->sourceCrop; + ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top, + (sourceCrop.right - sourceCrop.left), + (sourceCrop.bottom-sourceCrop.top)); + if (!ret) { + LOGE("drawLayerUsingOverlay setCrop failed"); + return -1; + } + + hwc_rect_t displayFrame = layer->displayFrame; + ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, + (displayFrame.right - displayFrame.left), + (displayFrame.bottom-displayFrame.top)); + if (!ret) { + LOGE("drawLayerUsingOverlay setPosition failed"); + return -1; + } + + int orientation; + ovLibObject->getOrientation(orientation); + if (orientation != layer->transform) + ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); + if (!ret) { + LOGE("drawLayerUsingOverlay setParameter failed transform %x", layer->transform); + return -1; + } + + ret = ovLibObject->queueBuffer(hnd); + if (!ret) { + LOGE("drawLayerUsingOverlay queueBuffer failed"); + return -1; + } + return 0; + } + return -1; +} + +static int hwc_set(hwc_composer_device_t *dev, + hwc_display_t dpy, + hwc_surface_t sur, + hwc_layer_list_t* list) +{ + + hwc_context_t* ctx = (hwc_context_t*)(dev); + if(!ctx) { + LOGE("hwc_set null context "); + return -1; + } + + private_hwc_module_t* hwcModule = reinterpret_cast( + dev->common.module); + if(!hwcModule) { + LOGE("hwc_set null module "); + return -1; + } + + for (size_t i=0 ; inumHwLayers ; i++) { + if (list->hwLayers[i].compositionType == HWC_OVERLAY) { + drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); + } else if ((hwcModule->compositionType == COMPOSITION_TYPE_C2D) || + (hwcModule->compositionType == COMPOSITION_TYPE_MDP)) { + // TBD + } + } + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + if (!sucess) { + return HWC_EGL_ERROR; + } + + return 0; +} + +static int hwc_device_close(struct hw_device_t *dev) +{ + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; + + private_hwc_module_t* hwcModule = reinterpret_cast( + ctx->device.common.module); + + // Close the overlay and copybit modules + if(hwcModule->copybitEngine) { + copybit_close(hwcModule->copybitEngine); + hwcModule->copybitEngine = NULL; + } + if(hwcModule->overlayEngine) { + overlay_control_close(hwcModule->overlayEngine); + hwcModule->overlayEngine = NULL; + } + + if (ctx) { + delete ctx->mOverlayLibObject; + ctx->mOverlayLibObject = NULL; + free(ctx); + } + return 0; +} + +/*****************************************************************************/ +static int hwc_module_initialize(struct private_hwc_module_t* hwcModule) +{ + + // Open the overlay and copybit modules + hw_module_t const *module; + + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + copybit_open(module, &(hwcModule->copybitEngine)); + } + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + overlay_control_open(module, &(hwcModule->overlayEngine)); + } + + // get the current composition type + char property[PROPERTY_VALUE_MAX]; + if (property_get("debug.sf.hw", property, NULL) > 0) { + if(atoi(property) == 0) { + //debug.sf.hw = 0 + hwcModule->compositionType = COMPOSITION_TYPE_CPU; + } else { //debug.sf.hw = 1 + // Get the composition type + property_get("debug.composition.type", property, NULL); + if (property == NULL) { + hwcModule->compositionType == COMPOSITION_TYPE_GPU; + } else if ((strncmp(property, "mdp", 3)) == 0) { + hwcModule->compositionType == COMPOSITION_TYPE_MDP; + } else if ((strncmp(property, "c2d", 3)) == 0) { + hwcModule->compositionType == COMPOSITION_TYPE_C2D; + } else { + hwcModule->compositionType == COMPOSITION_TYPE_GPU; + } + + if(!hwcModule->copybitEngine) + hwcModule->compositionType == COMPOSITION_TYPE_GPU; + } + } else { //debug.sf.hw is not set. Use cpu composition + hwcModule->compositionType = COMPOSITION_TYPE_CPU; + } + + return 0; +} + + +static int hwc_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { + private_hwc_module_t* hwcModule = reinterpret_cast + (const_cast(module)); + + hwc_module_initialize(hwcModule); + struct hwc_context_t *dev; + dev = (hwc_context_t*)malloc(sizeof(*dev)); + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + if(hwcModule->overlayEngine) { + dev->mOverlayLibObject = new overlay::Overlay(); + } else + dev->mOverlayLibObject = NULL; + + /* 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 = hwc_device_close; + + dev->device.prepare = hwc_prepare; + dev->device.set = hwc_set; + + *device = &dev->device.common; + + status = 0; + } + return status; +} From 7725e18ca342503d7a0c39ce9ff3a0486a7b5ce6 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:37:29 -0800 Subject: [PATCH 309/435] libcopybit: Add copybit and copybit_c2d changes from Gingerbread Change-Id: I39ccc7579f89d08eae809b47e434601aee6973a2 --- libcopybit/Android.mk | 67 ++- libcopybit/c2d2.h | 618 ++++++++++++++++++++++ libcopybit/copybit.cpp | 78 +-- libcopybit/copybit_c2d.cpp | 1008 ++++++++++++++++++++++++++++++++++++ 4 files changed, 1717 insertions(+), 54 deletions(-) create mode 100644 libcopybit/c2d2.h create mode 100644 libcopybit/copybit_c2d.cpp diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index 36b1416..a19de13 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -17,26 +17,51 @@ LOCAL_PATH:= $(call my-dir) # HAL module implemenation, not prelinked and stored in # hw/..so -ifeq ($(TARGET_BOARD_PLATFORM),msm7k) -include $(CLEAR_VARS) -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 += hardware/msm7k/libgralloc -LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 -include $(BUILD_SHARED_LIBRARY) -endif +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 += 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 -ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) -include $(CLEAR_VARS) -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 += hardware/libhardware/modules/gralloc -LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 -include $(BUILD_SHARED_LIBRARY) + 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 += 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 += hardware/msm7k/libgralloc-qsd8k + LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 + include $(BUILD_SHARED_LIBRARY) + endif + endif endif diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h new file mode 100644 index 0000000..10c94be --- /dev/null +++ b/libcopybit/c2d2.h @@ -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 /* 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_ */ diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 7130ca7..767b3ee 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -119,13 +119,15 @@ static void intersect(struct copybit_rect_t *out, /** convert COPYBIT_FORMAT to MDP format */ static int get_format(int format) { switch (format) { - case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; - case COPYBIT_FORMAT_RGBX_8888: return MDP_RGBX_8888; - case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; - case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; - case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; - case COPYBIT_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2; - case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1; + 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; } @@ -138,27 +140,23 @@ static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) img->height = rhs->h; img->format = get_format(rhs->format); img->offset = hnd->offset; -#if defined(COPYBIT_MSM7K) - if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { - img->offset += hnd->map_offset; - img->memory_id = hnd->gpu_fd; - if (img->format == MDP_RGBA_8888) { - // msm7201A GPU only supports BGRA_8888 destinations - img->format = MDP_BGRA_8888; - } - } else { - img->memory_id = hnd->fd; - } -#else - img->memory_id = hnd->fd; -#endif + #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) { + const struct copybit_rect_t *scissor, + uint32_t padding) { struct copybit_rect_t clip; intersect(&clip, scissor, dst); @@ -186,18 +184,30 @@ static void set_rects(struct copybit_context_t *dev, 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) { - e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - padding; + }else{ + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + } } + if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) { - e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w); + if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { + e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); + }else{ + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - padding; + } } } /** setup mdp request */ -static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { +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 | MDP_BLEND_FG_PREMULT; + req->flags = dev->mFlags | flags; +#if defined(COPYBIT_QSD8K) + req->flags |= MDP_BLEND_FG_PREMULT; +#endif } /** copy the bits */ @@ -355,10 +365,10 @@ static int stretch_copybit( if (ctx->mAlpha < 255) { switch (src->format) { // we don't support plane alpha with RGBA formats - case COPYBIT_FORMAT_RGBA_8888: - case COPYBIT_FORMAT_BGRA_8888: - case COPYBIT_FORMAT_RGBA_5551: - case COPYBIT_FORMAT_RGBA_4444: + 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; } } @@ -383,10 +393,12 @@ static int stretch_copybit( while ((status == 0) && region->next(region, &clip)) { intersect(&clip, &bounds, &clip); mdp_blit_req* req = &list.req[list.count]; - set_infos(ctx, req); + 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); + set_rects(ctx, req, dst_rect, src_rect, &clip, src->padding); if (req->src_rect.w<=0 || req->src_rect.h<=0) continue; @@ -462,7 +474,7 @@ static int open_copybit(const struct hw_module_t* module, const char* name, } else { struct fb_fix_screeninfo finfo; if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) { - if (strcmp(finfo.id, "msmfb") == 0) { + if (strncmp(finfo.id, "msmfb", 5) == 0) { /* Success */ status = 0; } else { diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp new file mode 100644 index 0000000..4159dbf --- /dev/null +++ b/libcopybit/copybit_c2d.cpp @@ -0,0 +1,1008 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010, 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. + */ + +#define LOG_TAG "copybit_c2d" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "c2d2.h" + +#include +C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id, + uint32 surface_bits, + C2D_SURFACE_TYPE surface_type, + void *surface_definition ); + +C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id, + C2D_SURFACE_TYPE surface_type, + void *surface_definition, + int32 x, int32 y ); + +C2D_STATUS (*LINK_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 ); + +C2D_STATUS (*LINK_c2dFinish)( uint32 target_id); + +C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp); + +C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp ); + +C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id ); + + +/******************************************************************************/ + +#if defined(COPYBIT_Z180) +#define MAX_SCALE_FACTOR (4096) +#define MAX_DIMENSION (4096) +#else +#error "Unsupported HW version" +#endif + +#define G12_DEVICE_NAME "/dev/kgsl-2d0" + +#define COPYBIT_SUCCESS 0 +#define COPYBIT_FAILURE -1 + +#define RGB_SURFACE 0 +#define YUV_SURFACE 1 +#define NUM_SRC_SURFACES 2 +#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +/******************************************************************************/ + +/** State information for each device instance */ +struct copybit_context_t { + struct copybit_device_t device; + unsigned int src[NUM_SRC_SURFACES]; + unsigned int dst; /* dst surface */ + unsigned int trg_transform; /* target transform */ + C2D_OBJECT blitState; + void *libc2d2; + int g12_device_fd; + int fb_width; + int fb_height; +}; + +struct blitlist{ + uint32_t count; + C2D_OBJECT blitObjects[12]; +}; + +/** + * 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 COPYBIT C2D 2.0 Module", + author: "Qualcomm", + methods: ©bit_module_methods + } +}; + + +/* convert COPYBIT_FORMAT to C2D format */ +static int get_format(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB; + case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; + case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; + case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB; + case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA; + case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED; + default: return -EINVAL; + } + return -EINVAL; +} + +/* ------------------------------------------------------------------- *//*! + * \internal + * \brief Get the bpp for a particular color format + * \param color format + * \return bits per pixel +*//* ------------------------------------------------------------------- */ +int c2diGetBpp(int32 colorformat) +{ + + int c2dBpp = 0; + + switch(colorformat&0xFF) + { + case C2D_COLOR_FORMAT_4444_RGBA: + case C2D_COLOR_FORMAT_4444_ARGB: + case C2D_COLOR_FORMAT_1555_ARGB: + case C2D_COLOR_FORMAT_565_RGB: + case C2D_COLOR_FORMAT_5551_RGBA: + c2dBpp = 16; + break; + case C2D_COLOR_FORMAT_8888_RGBA: + case C2D_COLOR_FORMAT_8888_ARGB: + c2dBpp = 32; + break; + case C2D_COLOR_FORMAT_8_L: + case C2D_COLOR_FORMAT_8_A: + c2dBpp = 8; + break; + case C2D_COLOR_FORMAT_4_A: + c2dBpp = 4; + break; + case C2D_COLOR_FORMAT_1: + c2dBpp = 1; + break; + default: + LOGE("%s ERROR", __func__); + break; + } + return c2dBpp; +} + +static uint32 c2d_get_gpuaddr(int device_fd, struct private_handle_t *handle) +{ + if(!handle) + return 0; + + struct kgsl_map_user_mem param; + memset(¶m, 0, sizeof(param)); + param.fd = handle->fd; + param.len = handle->size; + param.offset = handle->offset; + param.hostptr = handle->base; + + if (handle->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) + param.memtype = KGSL_USER_MEM_TYPE_PMEM; + else + param.memtype = KGSL_USER_MEM_TYPE_ASHMEM; + + if (!ioctl(device_fd, IOCTL_KGSL_MAP_USER_MEM, (void *)¶m, sizeof(param))) { + return param.gpuaddr; + } + + return 0; +} + +static uint32 c2d_unmap_gpuaddr(int device_fd, unsigned int gpuaddr) +{ + struct kgsl_sharedmem_free param; + + memset(¶m, 0, sizeof(param)); + param.gpuaddr = gpuaddr; + + ioctl(device_fd, IOCTL_KGSL_SHAREDMEM_FREE, (void *)¶m, sizeof(param)); + return COPYBIT_SUCCESS; +} + +static int is_supported_rgb_format(int format) +{ + switch(format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: { + return COPYBIT_SUCCESS; + } + default: + return COPYBIT_FAILURE; + } +} + +static int is_supported_yuv_format(int format) +{ + switch(format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { + return COPYBIT_SUCCESS; + } + default: + return COPYBIT_FAILURE; + } +} + +static int calculate_yuv_offset_and_stride(int format, int width, int height, int *offset, int *yStride, int *uvStride) +{ + int aligned_height = 0; + int aligned_width = 0, size = 0; + + switch (format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { + /* NV12 Tile buffers have their luma height aligned to 32bytes and width + * aligned to 128 bytes. The chroma offset starts at an 8K boundary + */ + aligned_height = ALIGN(height, 32); + aligned_width = ALIGN(width, 128); + size = aligned_width * aligned_height; + *offset = ALIGN(size,8192); + *yStride = aligned_width; + *uvStride = aligned_width; + break; + } + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: { + aligned_width = ALIGN(width, 32); + *offset = aligned_width * height; + *yStride = aligned_width; + *uvStride = aligned_width; + break; + } + default: { + return COPYBIT_FAILURE; + } + } + return COPYBIT_SUCCESS; +} + +/** create C2D surface from copybit image */ +static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + C2D_SURFACE_TYPE surfaceType; + int status = COPYBIT_SUCCESS; + + *cformat = get_format(rhs->format); + if(*cformat == -EINVAL) { + LOGE("%s: invalid format", __func__); + return -EINVAL; + } + + if (handle->gpuaddr == 0) { + handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); + if(!handle->gpuaddr) { + return COPYBIT_FAILURE; + } + *mapped = 1; + } + + /* create C2D surface */ + if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + + surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS); + + surfaceDef.phys = (void*) handle->gpuaddr; + surfaceDef.buffer = (void*) (handle->base); + + surfaceDef.format = *cformat; + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { + LOGE("%s: RGB Surface c2dUpdateSurface ERROR", __func__); + goto error; + status = COPYBIT_FAILURE; + } + } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { + C2D_YUV_SURFACE_DEF surfaceDef; + int offset = 0; + int yStride = 0; + int uvStride = 0; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); + surfaceDef.format = *cformat; + + status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + if(status != COPYBIT_SUCCESS) { + LOGE("calculate_yuv_offset_and_stride error"); + goto error; + } + + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.plane0 = (void*) (handle->base); + surfaceDef.phys0 = (void*) (handle->gpuaddr); + surfaceDef.stride0 = yStride; + + surfaceDef.plane1 = (void*) (handle->base + offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); + surfaceDef.stride1 = uvStride; + + if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { + LOGE("%s: YUV Surface c2dUpdateSurface ERROR", __func__); + goto error; + status = COPYBIT_FAILURE; + } + } else { + LOGE("%s: invalid format %x", __func__, rhs->format); + goto error; + status = COPYBIT_FAILURE; + } + + return status; + +error: + if(*mapped == 1) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + *mapped = 0; + } + return status; +} + +static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32 *mapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + *cformat = get_format(rhs->format); + C2D_SURFACE_TYPE surfaceType; + uint32 gpuaddr = (uint32)handle->gpuaddr; + int status = COPYBIT_SUCCESS; + + if (handle->gpuaddr == 0) + { + handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); + if(!handle->gpuaddr) + return COPYBIT_FAILURE; + + *mapped = 1; + } + + /* create C2D surface */ + if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS); + + surfaceDef.phys = (void*) handle->gpuaddr; + surfaceDef.buffer = (void*) (handle->base); + surfaceDef.buffer = (void*) (handle->base + handle->offset); + + surfaceDef.format = get_format(rhs->format); + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) { + LOGE("%s: LINK_c2dCreateSurface error", __func__); + status = COPYBIT_FAILURE; + goto error; + } + } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { + /* YUV */ + C2D_YUV_SURFACE_DEF surfaceDef; + int offset = 0; + int yStride = 0; + int uvStride = 0; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + + surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); + surfaceDef.format = get_format(rhs->format); + status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + if(status != COPYBIT_SUCCESS) { + LOGE("calculate_yuv_offset_and_stride error"); + goto error; + } + + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.plane0 = (void*) (handle->base); + surfaceDef.phys0 = (void*) handle->gpuaddr; + surfaceDef.stride0 = yStride; + + surfaceDef.plane1 = (void*) (handle->base + offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); + surfaceDef.stride1 = uvStride; + + if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType, (void*)&surfaceDef)) { + LOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__); + status = COPYBIT_FAILURE; + goto error; + } + } else { + LOGE("%s: Invalid format %x", __func__, rhs->format); + status = COPYBIT_FAILURE; + } + + return COPYBIT_SUCCESS; + +error: + if(*mapped == 1) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + *mapped = 0; + } + return status; +} + +void unset_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, uint32 mmapped) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + + if (mmapped && handle->gpuaddr) { + // Unmap this gpuaddr + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + } +} + +static int blit_to_target(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs) +{ + struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; + uint32 cformat = get_format(rhs->format); + C2D_SURFACE_TYPE surfaceType; + uint32 memoryMapped = 0; + int status = COPYBIT_SUCCESS; + + if (!handle->gpuaddr) { + handle->gpuaddr = c2d_get_gpuaddr(device_fd,handle); + if(!handle->gpuaddr) + return COPYBIT_FAILURE; + + memoryMapped = 1; + } + + /* create C2D surface */ + + if(cformat) { + /* RGB */ + C2D_RGB_SURFACE_DEF surfaceDef; + memset(&surfaceDef, 0, sizeof(surfaceDef)); + + surfaceDef.buffer = (void*) handle->base; + surfaceDef.phys = (void*) handle->gpuaddr; + + surfaceType = C2D_SURFACE_RGB_HOST; + surfaceDef.format = get_format(rhs->format); + surfaceDef.width = rhs->w; + surfaceDef.height = rhs->h; + surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); + + if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) { + LOGE("%s: LINK_c2dReadSurface ERROR", __func__); + status = COPYBIT_FAILURE; + goto done; + } + } + else { + /* YUV */ + /* TODO */ + } + +done: + if (memoryMapped) { + c2d_unmap_gpuaddr(device_fd, handle->gpuaddr); + handle->gpuaddr = 0; + } + return status; +} + +/** setup rectangles */ +static void set_rects(struct copybit_context_t *ctx, + C2D_OBJECT *c2dObject, + const struct copybit_rect_t *dst, + const struct copybit_rect_t *src, + const struct copybit_rect_t *scissor) +{ + + if((ctx->trg_transform & C2D_TARGET_ROTATE_90) && + (ctx->trg_transform & C2D_TARGET_ROTATE_180)) { + /* target rotation is 270 */ + c2dObject->target_rect.x = (dst->t)<<16; + c2dObject->target_rect.y = (ctx->fb_width - (dst->r))<<16; + c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16; + c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; + } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) { + c2dObject->target_rect.x = (ctx->fb_height - dst->b)<<16; + c2dObject->target_rect.y = (dst->l)<<16; + c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16; + c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; + } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) { + c2dObject->target_rect.y = (ctx->fb_height - dst->b)<<16; + c2dObject->target_rect.x = (ctx->fb_width - dst->r)<<16; + c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16; + c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16; + } else { + c2dObject->target_rect.x = (dst->l)<<16; + c2dObject->target_rect.y = (dst->t)<<16; + c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16; + c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16; + } + c2dObject->config_mask |= C2D_TARGET_RECT_BIT; + + c2dObject->source_rect.x = (src->l)<<16; + c2dObject->source_rect.y = (src->t)<<16; + c2dObject->source_rect.height = ((src->b) - (src->t))<<16; + c2dObject->source_rect.width = ((src->r) - (src->l))<<16; + c2dObject->config_mask |= C2D_SOURCE_RECT_BIT; + + c2dObject->scissor_rect.x = scissor->l; + c2dObject->scissor_rect.y = scissor->t; + c2dObject->scissor_rect.height = (scissor->b) - (scissor->t); + c2dObject->scissor_rect.width = (scissor->r) - (scissor->l); + + c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT; +} + +/** copy the bits */ +static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target) +{ + int objects; + + for(objects = 0; objects < list->count; objects++) { + list->blitObjects[objects].next = &(list->blitObjects[objects+1]); + } + + if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects, + list->count)) { + LOGE("%s: LINK_c2dDraw ERROR"); + return COPYBIT_FAILURE; + } + + return COPYBIT_SUCCESS; +} + +/*****************************************************************************/ + +/** 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; + if (!ctx) { + LOGE("%s: null context", __func__); + return -EINVAL; + } + + switch(name) { + case COPYBIT_ROTATION_DEG: + ctx->blitState.rotation = value<<16; + /* SRC rotation */ + if(!value) + ctx->blitState.config_mask &=~C2D_ROTATE_BIT;; + break; + case COPYBIT_PLANE_ALPHA: + if (value < 0) value = 0; + if (value >= 256) value = 255; + + ctx->blitState.global_alpha = value; + + if(ctx->blitState.global_alpha<255) + ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT; + else + ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT; + break; + case COPYBIT_DITHER: + /* TODO */ + break; + case COPYBIT_BLUR: + /* TODO */ + break; + case COPYBIT_TRANSFORM: + ctx->blitState.config_mask &=~C2D_ROTATE_BIT; + ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT; + ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT; + ctx->trg_transform = C2D_TARGET_ROTATE_0; + + if((value&0x7) == COPYBIT_TRANSFORM_ROT_180) + ctx->trg_transform = C2D_TARGET_ROTATE_180; + else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270) + ctx->trg_transform = C2D_TARGET_ROTATE_90; + else { + if(value©BIT_TRANSFORM_FLIP_H) + ctx->blitState.config_mask |= C2D_MIRROR_H_BIT; + if(value©BIT_TRANSFORM_FLIP_V) + ctx->blitState.config_mask |= C2D_MIRROR_V_BIT; + if(value©BIT_TRANSFORM_ROT_90) + ctx->trg_transform = C2D_TARGET_ROTATE_270; + } + break; + default: + LOGE("%s: default case", __func__); + return -EINVAL; + break; + } + + return COPYBIT_SUCCESS; +} + +/** 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) { + LOGE("%s: null context error", __func__); + return -EINVAL; + } + + 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 = 1; + break; + default: + LOGE("%s: default case", __func__); + value = -EINVAL; + } + return value; +} + +static int is_alpha(int cformat) +{ + int alpha = 0; + switch (cformat & 0xFF) { + case C2D_COLOR_FORMAT_8888_ARGB: + case C2D_COLOR_FORMAT_8888_RGBA: + case C2D_COLOR_FORMAT_5551_RGBA: + case C2D_COLOR_FORMAT_4444_ARGB: + alpha = 1; + break; + default: + alpha = 0; + break; + } + + if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA)) + alpha = 0; + + return alpha; +} + +/** 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 = COPYBIT_SUCCESS; + uint32 maxCount; + uint32 src_mapped = 0, trg_mapped = 0; + blitlist list; + C2D_OBJECT *req; + memset(&list, 0, sizeof(list)); + int cformat; + c2d_ts_handle timestamp; + uint32 surface_index = 0; + + if (!ctx) { + LOGE("%s: null context error", __func__); + return -EINVAL; + } + + if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) { + LOGE("%s: src dimension error", __func__); + return -EINVAL; + } + + if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { + LOGE("%s : dst dimension error dst w %d h %d", __func__, dst->w, dst->h); + return -EINVAL; + } + + maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT); + + struct copybit_rect_t clip; + list.count = 0; + + status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped); + if(status) { + LOGE("%s: set_image error", __func__); + return COPYBIT_FAILURE; + } + + if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) { + surface_index = RGB_SURFACE; + } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) { + surface_index = YUV_SURFACE; + } else { + LOGE("%s: Invalid source surface format %x", __func__, src->format); + return -EINVAL; + } + + status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped); + if(status) { + LOGE("%s: set_src_image error", __func__); + return COPYBIT_FAILURE; + } + + if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) { + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + if(!(ctx->blitState.global_alpha)) { + // src alpha is zero + unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + return status; + } + } else { + if(is_alpha(cformat)) + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + else + ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; + } + + ctx->blitState.surface_id = ctx->src[surface_index]; + + while ((status == 0) && region->next(region, &clip)) { + req = &(list.blitObjects[list.count]); + memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT)); + + set_rects(ctx, req, dst_rect, src_rect, &clip); + + if (++list.count == maxCount) { + status = msm_copybit(ctx, &list, ctx->dst); + list.count = 0; + } + } + if ((status == 0) && list.count) { + status = msm_copybit(ctx, &list, ctx->dst); + } + + if(LINK_c2dFinish(ctx->dst)) { + LOGE("%s: LINK_c2dFinish ERROR", __func__); + } + + + unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + + 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) { + LINK_c2dDestroySurface(ctx->dst); + for(int i = 0; i src[i]); + } + + if (ctx->libc2d2) { + ::dlclose(ctx->libc2d2); + LOGV("dlclose(libc2d2)"); + } + + if(ctx->g12_device_fd) + close(ctx->g12_device_fd); + 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 = COPYBIT_SUCCESS; + C2D_RGB_SURFACE_DEF surfDefinition = {0}; + C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ; + struct copybit_context_t *ctx; + char const * const device_template[] = { + "/dev/graphics/fb%u", + "/dev/fb%u", + 0 }; + + int fd = -1; + int i=0; + char fbName[64]; + + ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t)); + if(!ctx) { + LOGE("%s: malloc failed", __func__); + return COPYBIT_FAILURE; + } + + /* initialize drawstate */ + memset(ctx, 0, sizeof(*ctx)); + + ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW); + if (!ctx->libc2d2) { + LOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); + status = COPYBIT_FAILURE; + goto error; + } + *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2, + "c2dCreateSurface"); + *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2, + "c2dUpdateSurface"); + *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2, + "c2dReadSurface"); + *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw"); + *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush"); + *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish"); + *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2, + "c2dWaitTimestamp"); + *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2, + "c2dDestroySurface"); + + if(!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface + || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish + || !LINK_c2dDestroySurface) { + LOGE("%s: dlsym ERROR", __func__); + status = COPYBIT_FAILURE; + goto error1; + } + + ctx->device.common.tag = HARDWARE_DEVICE_TAG; + ctx->device.common.version = 1; + ctx->device.common.module = (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->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT; + ctx->trg_transform = C2D_TARGET_ROTATE_0; + ctx->g12_device_fd = open(G12_DEVICE_NAME, O_RDWR | O_SYNC); + if(ctx->g12_device_fd < 0) { + LOGE("%s: g12_device_fd open failed", __func__); + status = COPYBIT_FAILURE; + goto error1; + } + + /* Create RGB Surface */ + surfDefinition.buffer = (void*)0xdddddddd; + surfDefinition.phys = (void*)0xdddddddd; + surfDefinition.stride = 1 * 4; + surfDefinition.width = 1; + surfDefinition.height = 1; + surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB; + + if(LINK_c2dCreateSurface(&ctx->dst,C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | + C2D_SURFACE_WITH_PHYS), &surfDefinition)) { + LOGE("%s: create ctx->dst failed", __func__); + status = COPYBIT_FAILURE; + goto error2; + } + + if(LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | + C2D_SURFACE_WITH_PHYS), &surfDefinition)) { + LOGE("%s: create ctx->src[RGB_SURFACE] failed", __func__); + status = COPYBIT_FAILURE; + goto error3; + } + + /* Create YUV source surface */ + yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12; + + yuvSurfaceDef.width = 4; + yuvSurfaceDef.height = 4; + yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa; + yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa; + yuvSurfaceDef.stride0 = 4; + + yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa; + yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa; + yuvSurfaceDef.stride1 = 4; + + if(LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE]),C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &yuvSurfaceDef)) { + LOGE("%s: create ctx->src[YUV_SURFACE] failed", __func__); + status = COPYBIT_FAILURE; + goto error4; + } + + if (status == COPYBIT_SUCCESS) + *device = &ctx->device.common; + else { + close_copybit(&ctx->device.common); + goto error4; + } + + while ((fd==-1) && device_template[i]) { + snprintf(fbName, 64, device_template[i], 0); + fd = open(fbName, O_RDWR, 0); + i++; + } + if (fd < 0) + goto error4; + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + goto error5; + + ctx->fb_width = info.xres; + ctx->fb_height = info.yres; + close(fd); + return status; + +error5: + close(fd); + fd = -1; +error4: + LINK_c2dDestroySurface(ctx->src[RGB_SURFACE]); +error3: + LINK_c2dDestroySurface(ctx->dst); +error2: + close(ctx->g12_device_fd); +error1: + ::dlclose(ctx->libc2d2); +error: + free(ctx); + + return status; +} From 1e95e224d64175c5e92763affe9013ca4ca78ca0 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:38:49 -0800 Subject: [PATCH 310/435] libgralloc-qsd8k: Move the OMX format definitions to gpu.cpp Change-Id: Ieb6e1f07b6e676d6d9556572a61b70780e4483fc --- libgralloc-qsd8k/gpu.cpp | 5 +++++ libgralloc-qsd8k/gralloc_priv.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 81b4579..0dace4d 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -23,6 +23,11 @@ #include "gr.h" #include "gpu.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; + gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, PmemAllocator& pmemAdspAllocator, const private_module_t* module) : deps(deps), diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index e708452..6aec4d9 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -162,11 +162,6 @@ enum { BUFFER_TYPE_UI = 0, BUFFER_TYPE_VIDEO }; - -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; /*****************************************************************************/ struct private_module_t; From 6ec5b1553fedcd0366f50943d3bba97af0234d1c Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Mon, 7 Mar 2011 17:39:18 -0800 Subject: [PATCH 311/435] hardware/msm7k : Fix centering of low resolution clips Change-Id: I90825fd77376325fe9427d1a739be4bec13ff1e3 CRs-fixed: 269485 --- liboverlay/overlayLib.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 222adb5..0dad1d9 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -412,9 +412,11 @@ bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { /* Scaling of upto a max of 8 times supported */ if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){ w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w; + x = (mFBWidth - w) / 2; } if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) { h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h; + y = (mFBHeight - h) / 2; } ov.dst_rect.x = x; ov.dst_rect.y = y; From 5fe46458a5d0e303cb859fb8420e42e663091fc6 Mon Sep 17 00:00:00 2001 From: Chetan Kalyan Date: Mon, 7 Mar 2011 17:40:03 -0800 Subject: [PATCH 312/435] Overlay: Return error if crop values are invalid Return an error to the caller if input crop rectangle values are incorrect Change-Id: Ie1bf9ac0dbcfba0becee0864b44903abd4016873 --- liboverlay/overlayLib.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) mode change 100644 => 100755 liboverlay/overlayLib.cpp diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp old mode 100644 new mode 100755 index 0dad1d9..50e04ec --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -802,7 +802,10 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) } if (ov.user_data[0] == MDP_ROT_90) { - int tmp = x; + if (ov.src.width < (y + h)) + return false; + + uint32_t tmp = x; x = ov.src.width - (y + h); y = tmp; @@ -811,7 +814,10 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) h = tmp; } else if (ov.user_data[0] == MDP_ROT_270) { - int tmp = y; + if (ov.src.height < (x + w)) + return false; + + uint32_t tmp = y; y = ov.src.height - (x + w); x = tmp; @@ -825,10 +831,6 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) (ov.src_rect.w == w) && (ov.src_rect.h == h)) return true; - if ( (int) x < 0 || (int) y < 0 || (int) w < 0 || (int) h < 0){ - LOGE("%s: invalid value for crop: x=%d,y=%d,w=%d,h=%d",__func__,x,y,w,h); - return false; - } ov.src_rect.x = x; ov.src_rect.y = y; From 3a51941fe6bf7127fde1fae352a81d5f6dead8d5 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:40:33 -0800 Subject: [PATCH 313/435] Add support for S3D content over HDMI Add support in the overlay to display 3D content on the HDMI. The 3D input and out formats are passed along with the regular color format. Change-Id: I4e0338e8b2c07eca0f211c50a17bf7d82c35279b --- libgralloc-qsd8k/gralloc_priv.h | 6 +- liboverlay/overlay.cpp | 319 ++++++++++++++++++++++++++------ liboverlay/overlayLib.cpp | 20 +- liboverlay/overlayLib.h | 33 +++- 4 files changed, 309 insertions(+), 69 deletions(-) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 6aec4d9..9057eff 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -153,9 +153,9 @@ enum { HAL_3D_IN_LR_SIDE = 0x10000, HAL_3D_IN_LR_TOP = 0x20000, HAL_3D_IN_LR_INTERLEAVE = 0x40000, - HAL_3D_OUT_LR_SIDE = 0x1, - HAL_3D_OUT_LR_TOP = 0x2, - HAL_3D_OUT_LR_INTERLEAVE = 0x4 + HAL_3D_OUT_LR_SIDE = 0x1000, + HAL_3D_OUT_LR_TOP = 0x2000, + HAL_3D_OUT_LR_INTERLEAVE = 0x4000 }; enum { diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 988c18c..080705c 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -38,6 +38,7 @@ using namespace overlay; struct overlay_control_context_t { struct overlay_control_device_t device; void *sharedMemBase; + unsigned int format3D; //input and output 3D format, zero means no 3D }; struct ov_crop_rect_t { @@ -51,6 +52,7 @@ struct overlay_data_context_t { struct overlay_data_device_t device; OverlayDataChannel* pobjDataChannel[2]; int setCrop; + unsigned int format3D; struct ov_crop_rect_t cropRect; void *sharedMemBase; }; @@ -90,6 +92,7 @@ struct handle_t : public native_handle { int w; int h; int format; + unsigned int format3D; OverlayControlChannel *pobjControlChannel[2]; }; @@ -110,6 +113,10 @@ static int handle_get_shared_fd(const overlay_handle_t overlay) { return static_cast(overlay)->sharedMemoryFd; } +static int handle_get_format3D(const overlay_handle_t overlay) { + return static_cast(overlay)->format3D; +} + /* * This is the overlay_t object, it is returned to the user and represents * an overlay. @@ -125,7 +132,7 @@ class overlay_object : public overlay_t { } public: - overlay_object(int w, int h, int format, int fd) { + overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) { this->overlay_t::getHandleRef = getHandleRef; mHandle.version = sizeof(native_handle); mHandle.sharedMemoryFd = fd; @@ -139,6 +146,7 @@ public: mHandle.w = w; mHandle.h = h; mHandle.format = format; + mHandle.format3D = format3D; mHandle.pobjControlChannel[0] = 0; mHandle.pobjControlChannel[1] = 0; } @@ -151,67 +159,74 @@ public: int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} - bool startControlChannel(int fbnum, bool norot = false) { - if (!mHandle.pobjControlChannel[fbnum]) - mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel(); + bool startControlChannel(int fbnum, bool norot = false, + unsigned int format3D = 0, int zorder = 0) { + int index = 0; + if (format3D) + index = zorder; + else + index = fbnum; + if (!mHandle.pobjControlChannel[index]) + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); else { - mHandle.pobjControlChannel[fbnum]->closeControlChannel(); - mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel(); + mHandle.pobjControlChannel[index]->closeControlChannel(); + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); } - bool ret = mHandle.pobjControlChannel[fbnum]->startControlChannel( - mHandle.w, mHandle.h, mHandle.format, fbnum, norot); + bool ret = mHandle.pobjControlChannel[index]->startControlChannel( + mHandle.w, mHandle.h, mHandle.format, fbnum, norot, + format3D, zorder); if (ret) { - if (!(mHandle.pobjControlChannel[fbnum]-> - getOvSessionID(mHandle.ovid[fbnum]) && - mHandle.pobjControlChannel[fbnum]-> - getRotSessionID(mHandle.rotid[fbnum]) && - mHandle.pobjControlChannel[fbnum]-> + if (!(mHandle.pobjControlChannel[index]-> + getOvSessionID(mHandle.ovid[index]) && + mHandle.pobjControlChannel[index]-> + getRotSessionID(mHandle.rotid[index]) && + mHandle.pobjControlChannel[index]-> getSize(mHandle.size))) ret = false; } if (!ret) { - closeControlChannel(fbnum); + closeControlChannel(index); } return ret; } - bool setPosition(int x, int y, uint32_t w, uint32_t h, int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->setPosition( + return mHandle.pobjControlChannel[channel]->setPosition( x, y, w, h); } - bool setParameter(int param, int value, int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + bool setParameter(int param, int value, int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->setParameter( + return mHandle.pobjControlChannel[channel]->setParameter( param, value); } - bool closeControlChannel(int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + bool closeControlChannel(int channel) { + if (!mHandle.pobjControlChannel[channel]) return true; - bool ret = mHandle.pobjControlChannel[fbnum]-> + bool ret = mHandle.pobjControlChannel[channel]-> closeControlChannel(); - delete mHandle.pobjControlChannel[fbnum]; - mHandle.pobjControlChannel[fbnum] = 0; + delete mHandle.pobjControlChannel[channel]; + mHandle.pobjControlChannel[channel] = 0; return ret; } - bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->getPosition( + return mHandle.pobjControlChannel[channel]->getPosition( *x, *y, *w, *h); } - bool getOrientation(int *orientation, int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + bool getOrientation(int *orientation, int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->getOrientation( + return mHandle.pobjControlChannel[channel]->getOrientation( *orientation); } @@ -219,18 +234,24 @@ public: close(mHandle.sharedMemoryFd); closeControlChannel(0); closeControlChannel(1); + FILE *fp = NULL; + fp = fopen(FORMAT_3D_FILE, "wb"); + if(fp) { + fprintf(fp, "0"); //Sending hdmi info packet(2D) + fclose(fp); + } } - int getFBWidth(int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + int getFBWidth(int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->getFBWidth(); + return mHandle.pobjControlChannel[channel]->getFBWidth(); } - int getFBHeight(int fbnum) { - if (!mHandle.pobjControlChannel[fbnum]) + int getFBHeight(int channel) { + if (!mHandle.pobjControlChannel[channel]) return false; - return mHandle.pobjControlChannel[fbnum]->getFBHeight(); + return mHandle.pobjControlChannel[channel]->getFBHeight(); } }; @@ -304,11 +325,29 @@ public: return NULL; } } + + // Separate the color format from the 3D format. + // If there is 3D content; the effective format passed by the client is: + // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + unsigned int format3D = FORMAT_3D(format); + format = COLOR_FORMAT(format); + int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format + int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format + format3D = fIn3D | fOut3D; + // Use the same in/out format if not mentioned + if (!fIn3D) { + format3D |= fOut3D << SHIFT_3D; //Set the input format + } + if(!fOut3D) { + format3D |= fIn3D >> SHIFT_3D; //Set the output format + } + ctx->sharedMemBase = base; + ctx->format3D = format3D; memset(ctx->sharedMemBase, 0, size); /* number of buffer is not being used as overlay buffers are coming from client */ - overlay = new overlay_object(w, h, format, fd); + overlay = new overlay_object(w, h, format, fd, format3D); if (overlay == NULL) { LOGE("%s: can't create overlay object!", __FUNCTION__); @@ -321,6 +360,26 @@ public: return NULL; } + if (format3D) { + bool res1, res2; + res1 = overlay->startControlChannel(1, false, format3D, 0); + res2 = overlay->startControlChannel(1, false, format3D, 1); + if (!res1 || !res2) { + LOGE("Failed to start control channel for VG pipe 0 or 1"); + overlay->closeControlChannel(0); + overlay->closeControlChannel(1); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + + delete overlay; + return NULL; + } + return overlay; + } #ifdef USE_MSM_ROTATOR if (!overlay->startControlChannel(0)) { #else @@ -429,10 +488,38 @@ public: private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); - - bool ret = obj->setPosition(x, y, w, h, 0); - if (!ret) - return -1; + bool ret; + if(ctx->format3D){ + int wHDMI = obj->getFBWidth(1); + int hHDMI = obj->getFBHeight(1); + if(ctx->format3D & HAL_3D_OUT_LR_SIDE_MASK) { + ret = obj->setPosition(0, 0, wHDMI/2, hHDMI, 0); + if (!ret) + return -1; + ret = obj->setPosition(wHDMI/2, 0, wHDMI/2, hHDMI, 1); + if (!ret) + return -1; + } + else if (ctx->format3D & HAL_3D_OUT_LR_TOP_MASK) { + ret = obj->setPosition(0, 0, wHDMI, hHDMI/2, 0); + if (!ret) + return -1; + ret = obj->setPosition(0, hHDMI/2, wHDMI, hHDMI/2, 1); + if (!ret) + return -1; + } + else if (ctx->format3D & HAL_3D_OUT_LR_INTERLEAVE_MASK) { + //TBD + } + else { + LOGE("%s: Unsupported 3D output format!!!", __func__); + } + } + else { + ret = obj->setPosition(x, y, w, h, 0); + if (!ret) + return -1; + } return 0; } @@ -485,12 +572,21 @@ return 0; data.readyToQueue = 0; memcpy(ctx->sharedMemBase, (void*)&data, sizeof(data)); } - - bool ret = obj->setParameter(param, value, 0); - if (!ret) - return -1; - - return 0; + bool ret; + if (ctx->format3D) { + ret = obj->setParameter(param, value, 0); + if (!ret) + return -1; + ret = obj->setParameter(param, value, 1); + if (!ret) + return -1; + } + else { + ret = obj->setParameter(param, value, 0); + if (!ret) + return -1; + } + return 0; } static int overlay_control_close(struct hw_device_t *dev) @@ -528,12 +624,14 @@ return 0; int rotid = handle_get_rotId(handle); int size = handle_get_size(handle); int sharedFd = handle_get_shared_fd(handle); - + unsigned int format3D = handle_get_format3D(handle); + FILE *fp = NULL; private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); ctx->sharedMemBase = MAP_FAILED; + ctx->format3D = format3D; if(sharedFd > 0) { void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, @@ -548,6 +646,33 @@ return 0; return -1; } + if (ctx->format3D) { + bool res1, res2; + ctx->pobjDataChannel[0] = new OverlayDataChannel(); + ctx->pobjDataChannel[1] = new OverlayDataChannel(); + res1 = + ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, size, 1); + ovid = handle_get_ovId(handle, 1); + rotid = handle_get_rotId(handle, 1); + res2 = + ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, size, 1); + if (!res1 || !res2) { + LOGE("Couldnt start data channel for VG pipe 0 or 1"); + delete ctx->pobjDataChannel[0]; + ctx->pobjDataChannel[0] = 0; + delete ctx->pobjDataChannel[1]; + ctx->pobjDataChannel[1] = 0; + return -1; + } + //Sending hdmi info packet(3D output format) + fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", format3D & OUTPUT_MASK_3D); + fclose(fp); + fp = NULL; + } + return 0; + } ctx->pobjDataChannel[0] = new OverlayDataChannel(); if (!ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, size, 0)) { @@ -573,7 +698,12 @@ return 0; delete ctx->pobjDataChannel[1]; ctx->pobjDataChannel[1] = 0; } - + fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "0"); //Sending hdmi info packet(2D) + fclose(fp); + fp = NULL; + } return 0; } @@ -610,6 +740,29 @@ return 0; LOGE("Overlay is not ready to queue buffers"); return -1; } + + bool result; + if (ctx->format3D) { + if ( (ctx->format3D & HAL_3D_OUT_LR_SIDE_MASK) || + (ctx->format3D & HAL_3D_OUT_LR_TOP_MASK) ) { + result = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]-> + queueBuffer((uint32_t) buffer)); + if (!result) + LOGE("Queuebuffer failed for VG pipe 0"); + result = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> + queueBuffer((uint32_t) buffer)); + if (!result) + LOGE("Queuebuffer failed for VG pipe 1"); + } + else if (ctx->format3D & HAL_3D_OUT_LR_INTERLEAVE_MASK) { + } + else { + LOGE("%s:Unknown 3D Format...", __func__); + } + return 0; + } if(ctx->setCrop) { bool result = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]-> @@ -621,7 +774,7 @@ return 0; } } - bool result = (ctx->pobjDataChannel[0] && + result = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]-> queueBuffer((uint32_t) buffer)); if (!result) @@ -650,8 +803,23 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - - bool ret = (ctx->pobjDataChannel[0] && + bool ret; + if (ctx->format3D) { + ret = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]->setFd(fd)); + if (!ret) { + LOGE("set fd failed for VG pipe 0"); + return -1; + } + ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]->setFd(fd)); + if (!ret) { + LOGE("set fd failed for VG pipe 1"); + return -1; + } + return 0; + } + ret = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]->setFd(fd)); if (!ret) { LOGE("set fd failed for framebuffer 0"); @@ -680,7 +848,46 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - + bool ret; + // for the 3D usecase extract L and R channels from a frame + if(ctx->format3D) { + if (ctx->format3D & HAL_3D_IN_LR_SIDE) { + ret = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]-> + setCrop(0, 0, w/2, h)); + if (!ret) { + LOGE("set crop failed for VG pipe 0"); + return -1; + } + ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> + setCrop(w/2, 0, w/2, h)); + if (!ret) { + LOGE("set crop failed for VG pipe 1"); + return -1; + } + } + else if (ctx->format3D & HAL_3D_IN_LR_TOP) { + ret = (ctx->pobjDataChannel[0] && + ctx->pobjDataChannel[0]-> + setCrop(0, 0, w, h/2)); + if (!ret) { + LOGE("set crop failed for VG pipe 0"); + return -1; + } + ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> + setCrop(0, h/2, w, h/2)); + if (!ret) { + LOGE("set crop failed for VG pipe 1"); + return -1; + } + } + else if (ctx->format3D & HAL_3D_IN_LR_INTERLEAVE) { + //TBD + } + return 0; + } //For primary set Crop ctx->setCrop = 1; ctx->cropRect.x = x; @@ -694,8 +901,8 @@ return 0; return 0; } - bool ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> + ret = (ctx->pobjDataChannel[1] && + ctx->pobjDataChannel[1]-> setCrop(x, y, w, h)); if (!ret) { LOGE("set crop failed for framebuffer 1"); diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 50e04ec..396eb3e 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -96,8 +96,8 @@ int Overlay::getFBHeight() const { return objOvCtrlChannel.getFBHeight(); } -bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel) { - mChannelUP = objOvCtrlChannel.startControlChannel(w, h, format, fbnum, norot); +bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel, unsigned int format3D) { + mChannelUP = objOvCtrlChannel.startControlChannel(w, h, format, fbnum, norot, format3D); if (!mChannelUP) { return mChannelUP; } @@ -169,7 +169,7 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { return false; } -OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1) { +OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1), mFormat3D(0) { memset(&mOVInfo, 0, sizeof(mOVInfo)); memset(&mRotInfo, 0, sizeof(mRotInfo)); } @@ -228,7 +228,7 @@ bool OverlayControlChannel::openDevices(int fbnum) { } bool OverlayControlChannel::setOverlayInformation(int w, int h, - int format, int flags) { + int format, int flags, int zorder) { int origW, origH, xoff, yoff; mOVInfo.id = MSMFB_NEW_REQUEST; @@ -264,7 +264,7 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.dst_rect.w = mFBWidth; if (h > mFBHeight) mOVInfo.dst_rect.h = mFBHeight; - mOVInfo.z_order = 0; + mOVInfo.z_order = zorder; mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; mOVInfo.flags = flags; @@ -324,7 +324,8 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, } bool OverlayControlChannel::startControlChannel(int w, int h, - int format, int fbnum, bool norot) { + int format, int fbnum, bool norot, + unsigned int format3D, int zorder) { mNoRot = norot; fb_fix_screeninfo finfo; fb_var_screeninfo vinfo; @@ -343,10 +344,15 @@ bool OverlayControlChannel::startControlChannel(int w, int h, return false; } + mFormat3D = format3D; + if (!mFormat3D) { + // Set the share bit for sharing the VG pipe + flags |= MDP_OV_PIPE_SHARE; + } if (!openDevices(fbnum)) return false; - if (!setOverlayInformation(w, h, hw_format, flags)) + if (!setOverlayInformation(w, h, hw_format, flags, zorder)) return false; return startOVRotatorSessions(w, h, hw_format); diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index f5b4279..4c9675d 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -44,6 +44,29 @@ #define HW_OVERLAY_MAGNIFICATION_LIMIT 8 #define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT +#define EVEN_OUT(x) if (x & 0x0001) {x--;} + +/* ------------------------------- 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 FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> 12) +#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_LR_SIDE_MASK (HAL_3D_OUT_LR_SIDE >> 12) +#define HAL_3D_OUT_LR_TOP_MASK (HAL_3D_OUT_LR_TOP >> 12) +#define HAL_3D_OUT_LR_INTERLEAVE_MASK (HAL_3D_OUT_LR_INTERLEAVE >> 12) +#define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" +/* -------------------------- end 3D defines ----------------------------------------*/ + namespace overlay { class OverlayControlChannel { @@ -59,10 +82,11 @@ class OverlayControlChannel { int mRotFD; int mSize; int mOrientation; + unsigned int mFormat3D; mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; bool openDevices(int fbnum = -1); - bool setOverlayInformation(int w, int h, int format, int flags); + bool setOverlayInformation(int w, int h, int format, int flags, int zorder = 0); bool startOVRotatorSessions(int w, int h, int format); void swapOVRotWidthHeight(); @@ -70,7 +94,8 @@ public: OverlayControlChannel(); ~OverlayControlChannel(); bool startControlChannel(int w, int h, int format, - int fbnum, bool norot = false); + int fbnum, bool norot = false, + unsigned int format3D = 0, int zorder = 0); bool closeControlChannel(); bool setPosition(int x, int y, uint32_t w, uint32_t h); bool setParameter(int param, int value); @@ -81,6 +106,7 @@ public: 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 setSource(uint32_t w, uint32_t h, int format, int orientation); }; @@ -128,7 +154,8 @@ public: Overlay(); ~Overlay(); - bool startChannel(int w, int h, int format, int fbnum, bool norot = false, bool uichannel = false); + bool startChannel(int w, int h, int format, int fbnum, bool norot = false, + bool uichannel = false, unsigned int format3D = 0); bool closeChannel(); bool setPosition(int x, int y, uint32_t w, uint32_t h); bool setParameter(int param, int value); From 5a1bf4cb9ecde8efbfe79487dd674dd204b0b208 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:40:55 -0800 Subject: [PATCH 314/435] overlay: Add support for additional S3D formats Add support for Side-by-Side full, Side-By-Side-half formats in the overlay. The Side by Side half formats could either be in Left-Right or Right-Left mode. Change-Id: Ie1f0ccb5b1a8254f7256aafdd3f0ce9a3faa0df4 --- libgralloc-qsd8k/gpu.cpp | 2 +- libgralloc-qsd8k/gralloc_priv.h | 14 ++++---- liboverlay/overlay.cpp | 59 +++++++++++++++++++++++---------- liboverlay/overlayLib.h | 7 ++-- 4 files changed, 54 insertions(+), 28 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 0dace4d..0a3ac33 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -280,7 +280,7 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorF case (QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ^ QOMX_3D_VIDEO_FLAG): { *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED | HAL_3D_IN_LR_SIDE | HAL_3D_OUT_LR_SIDE; + *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED | HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R | HAL_3D_OUT_SIDE_BY_SIDE; } break; case QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka: { diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 9057eff..cdb18dc 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -150,12 +150,14 @@ enum { /* possible formats for 3D content*/ enum { HAL_NO_3D = 0x00, - HAL_3D_IN_LR_SIDE = 0x10000, - HAL_3D_IN_LR_TOP = 0x20000, - HAL_3D_IN_LR_INTERLEAVE = 0x40000, - HAL_3D_OUT_LR_SIDE = 0x1000, - HAL_3D_OUT_LR_TOP = 0x2000, - HAL_3D_OUT_LR_INTERLEAVE = 0x4000 + HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R = 0x10000, + HAL_3D_IN_TOP_BOTTOM = 0x20000, + HAL_3D_IN_INTERLEAVE = 0x40000, + HAL_3D_IN_SIDE_BY_SIDE_FULL = 0x80000, + HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L = 0xC0000, + HAL_3D_OUT_SIDE_BY_SIDE = 0x1000, + HAL_3D_OUT_TOP_BOTTOM = 0x2000, + HAL_3D_OUT_INTERLEAVE = 0x4000, }; enum { diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 080705c..5a08aff 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -339,7 +339,18 @@ public: format3D |= fOut3D << SHIFT_3D; //Set the input format } if(!fOut3D) { - format3D |= fIn3D >> SHIFT_3D; //Set the output format + switch (fIn3D) { + case HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R: + case HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L: + case HAL_3D_IN_SIDE_BY_SIDE_FULL: + // For all side by side formats, set the output + // format as Side-by-Side i.e 0x1 + format3D |= HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R >> SHIFT_3D; + break; + default: + format3D |= fIn3D >> SHIFT_3D; //Set the output format + break; + } } ctx->sharedMemBase = base; @@ -362,8 +373,14 @@ public: if (format3D) { bool res1, res2; - res1 = overlay->startControlChannel(1, false, format3D, 0); - res2 = overlay->startControlChannel(1, false, format3D, 1); + if (format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) { + // For R-L formats, set the Zorder of the second channel as 0 + res1 = overlay->startControlChannel(1, false, format3D, 1); + res2 = overlay->startControlChannel(1, false, format3D, 0); + } else { + res1 = overlay->startControlChannel(1, false, format3D, 0); + res2 = overlay->startControlChannel(1, false, format3D, 1); + } if (!res1 || !res2) { LOGE("Failed to start control channel for VG pipe 0 or 1"); overlay->closeControlChannel(0); @@ -492,7 +509,7 @@ public: if(ctx->format3D){ int wHDMI = obj->getFBWidth(1); int hHDMI = obj->getFBHeight(1); - if(ctx->format3D & HAL_3D_OUT_LR_SIDE_MASK) { + if(ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { ret = obj->setPosition(0, 0, wHDMI/2, hHDMI, 0); if (!ret) return -1; @@ -500,7 +517,7 @@ public: if (!ret) return -1; } - else if (ctx->format3D & HAL_3D_OUT_LR_TOP_MASK) { + else if (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) { ret = obj->setPosition(0, 0, wHDMI, hHDMI/2, 0); if (!ret) return -1; @@ -508,10 +525,11 @@ public: if (!ret) return -1; } - else if (ctx->format3D & HAL_3D_OUT_LR_INTERLEAVE_MASK) { + else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { //TBD - } - else { + } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { + //TBD + } else { LOGE("%s: Unsupported 3D output format!!!", __func__); } } @@ -743,8 +761,8 @@ return 0; bool result; if (ctx->format3D) { - if ( (ctx->format3D & HAL_3D_OUT_LR_SIDE_MASK) || - (ctx->format3D & HAL_3D_OUT_LR_TOP_MASK) ) { + if ( (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || + (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) ) { result = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]-> queueBuffer((uint32_t) buffer)); @@ -756,9 +774,11 @@ return 0; if (!result) LOGE("Queuebuffer failed for VG pipe 1"); } - else if (ctx->format3D & HAL_3D_OUT_LR_INTERLEAVE_MASK) { - } - else { + else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { + //TBD + } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { + //TBD + } else { LOGE("%s:Unknown 3D Format...", __func__); } return 0; @@ -851,7 +871,8 @@ return 0; bool ret; // for the 3D usecase extract L and R channels from a frame if(ctx->format3D) { - if (ctx->format3D & HAL_3D_IN_LR_SIDE) { + if ((ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || + (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L)) { ret = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]-> setCrop(0, 0, w/2, h)); @@ -867,7 +888,7 @@ return 0; return -1; } } - else if (ctx->format3D & HAL_3D_IN_LR_TOP) { + else if (ctx->format3D & HAL_3D_IN_TOP_BOTTOM) { ret = (ctx->pobjDataChannel[0] && ctx->pobjDataChannel[0]-> setCrop(0, 0, w, h/2)); @@ -883,10 +904,12 @@ return 0; return -1; } } - else if (ctx->format3D & HAL_3D_IN_LR_INTERLEAVE) { - //TBD + else if (ctx->format3D & HAL_3D_IN_INTERLEAVE) { + //TBD + } else if (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_FULL) { + //TBD } - return 0; + return 0; } //For primary set Crop ctx->setCrop = 1; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 4c9675d..b5f8992 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -61,9 +61,10 @@ #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_LR_SIDE_MASK (HAL_3D_OUT_LR_SIDE >> 12) -#define HAL_3D_OUT_LR_TOP_MASK (HAL_3D_OUT_LR_TOP >> 12) -#define HAL_3D_OUT_LR_INTERLEAVE_MASK (HAL_3D_OUT_LR_INTERLEAVE >> 12) +#define HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK ((HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R|HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) >> SHIFT_3D) +#define HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK (HAL_3D_IN_SIDE_BY_SIDE_FULL >> SHIFT_3D) +#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> 12) +#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> 12) #define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" /* -------------------------- end 3D defines ----------------------------------------*/ From 9c8bc18f792b611192f41910b689b64d3fa15024 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:41:08 -0800 Subject: [PATCH 315/435] overlay: Add support for enabling/disabling HDMI Add support in the overlayLib to enable/disable and queue the buffers to the primary or secondary based on the hdmi connected parameter. Change-Id: Ie6c780e4076b0b84e6457a0503ec511ff2b8c452 --- liboverlay/overlay.cpp | 50 ++++---------- liboverlay/overlayLib.cpp | 142 ++++++++++++++++++++++++++++++++------ liboverlay/overlayLib.h | 23 ++++-- 3 files changed, 148 insertions(+), 67 deletions(-) diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 5a08aff..96daca0 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -199,6 +199,13 @@ public: x, y, w, h); } + bool getAspectRatioPosition(overlay_rect *rect, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, + mHandle.h, mHandle.format, rect); + } + bool setParameter(int param, int value, int channel) { if (!mHandle.pobjControlChannel[channel]) return false; @@ -435,45 +442,12 @@ public: return NULL; } else { - int width = w, height = h, x, y; - int fbWidthHDMI = overlay->getFBWidth(1); - int fbHeightHDMI = overlay->getFBHeight(1); - // width and height for YUV TILE format - int tempWidth = w, tempHeight = h; - /* Caculate the width and height if it is YUV TILE format*/ - if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { - tempWidth = w - ( (((w-1)/64 +1)*64) - w); - tempHeight = h - ((((h-1)/32 +1)*32) - h); + overlay_rect rect; + if(overlay->getAspectRatioPosition(&rect, 1)) { + if (!overlay->setPosition(rect.x, rect.y, rect.width, rect.height, 1)) { + LOGE("Failed to upscale for framebuffer 1"); + } } - - if (width * fbHeightHDMI > - fbWidthHDMI * height) { - height = fbWidthHDMI * height / width; - EVEN_OUT(height); - width = fbWidthHDMI; - } else if (width * fbHeightHDMI < - fbWidthHDMI * height) { - width = fbHeightHDMI * width / height; - EVEN_OUT(width); - height = fbHeightHDMI; - } else { - width = fbWidthHDMI; - height = fbHeightHDMI; - } - /* Scaling of upto a max of 8 times supported */ - if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){ - width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth; - } - if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) { - height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight; - } - if (width > fbWidthHDMI) width = fbWidthHDMI; - if (height > fbHeightHDMI) height = fbHeightHDMI; - x = (fbWidthHDMI - width) / 2; - y = (fbHeightHDMI - height) / 2; - - if (!overlay->setPosition(x, y, width, height, 1)) - LOGE("Failed to upscale for framebuffer 1"); } return overlay; diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 396eb3e..0c4f8ad 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -81,56 +81,97 @@ static void reportError(const char* message) { using namespace overlay; -Overlay::Overlay() : mChannelUP(false) { +Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false) { } Overlay::~Overlay() { closeChannel(); } -int Overlay::getFBWidth() const { - return objOvCtrlChannel.getFBWidth(); +int Overlay::getFBWidth(int channel) const { + return objOvCtrlChannel[channel].getFBWidth(); } -int Overlay::getFBHeight() const { - return objOvCtrlChannel.getFBHeight(); +int Overlay::getFBHeight(int channel) const { + return objOvCtrlChannel[channel].getFBHeight(); } bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel, unsigned int format3D) { - mChannelUP = objOvCtrlChannel.startControlChannel(w, h, format, fbnum, norot, format3D); + mChannelUP = objOvCtrlChannel[0].startControlChannel(w, h, format, fbnum, norot, format3D); if (!mChannelUP) { + LOGE("startChannel for fb0 failed"); return mChannelUP; } - return objOvDataChannel.startDataChannel(objOvCtrlChannel, fbnum, norot, uichannel); + return objOvDataChannel[0].startDataChannel(objOvCtrlChannel[0], fbnum, norot, uichannel); +} + +bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { + + if(!mHDMIConnected) { + LOGE(" HDMI has been disabled - close the channel"); + objOvCtrlChannel[1].closeControlChannel(); + objOvDataChannel[1].closeDataChannel(); + return true; + } + bool ret = startChannel(w, h, format, 0, norot); + if(ret) { + if (!objOvCtrlChannel[1].startControlChannel(w, h, format, 1, 1)) { + LOGE("Failed to start control channel for framebuffer 1"); + objOvCtrlChannel[1].closeControlChannel(); + return false; + } else { + if(!objOvDataChannel[1].startDataChannel(objOvCtrlChannel[1], 1, 1)) { + LOGE("Failed to start data channel for framebuffer 1"); + return false; + } + overlay_rect rect; + if(objOvCtrlChannel[1].getAspectRatioPosition(w, h, format, &rect)) { + if(!objOvCtrlChannel[1].setPosition(rect.x, rect.y, rect.width, rect.height)) { + LOGE("Failed to upscale for framebuffer 1"); + return false; + } + } + } + } + return ret; } bool Overlay::closeChannel() { if (!mChannelUP) return true; - objOvCtrlChannel.closeControlChannel(); - objOvDataChannel.closeDataChannel(); + + objOvCtrlChannel[0].closeControlChannel(); + objOvDataChannel[0].closeDataChannel(); + + objOvCtrlChannel[1].closeControlChannel(); + objOvDataChannel[1].closeDataChannel(); + mChannelUP = false; return true; } bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h) { - return objOvCtrlChannel.getPosition(x, y, w, h); + return objOvCtrlChannel[0].getPosition(x, y, w, h); } bool Overlay::getOrientation(int& orientation) const { - return objOvCtrlChannel.getOrientation(orientation); + return objOvCtrlChannel[0].getOrientation(orientation); } bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { - return objOvCtrlChannel.setPosition(x, y, w, h); + return objOvCtrlChannel[0].setPosition(x, y, w, h); } -bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation) { - if (!objOvCtrlChannel.setSource(w, h, format, orientation)) { - objOvCtrlChannel.closeControlChannel(); - objOvDataChannel.closeDataChannel(); +bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected) { + if ((hdmiConnected != mHDMIConnected) || !objOvCtrlChannel[0].setSource(w, h, format, orientation)) { + closeChannel(); mChannelUP = false; - return startChannel(w, h, format, 0, !orientation); + mHDMIConnected = hdmiConnected; + if (mHDMIConnected) { + return startChannelHDMI(w, h, format, !orientation); + } else { + return startChannel(w, h, format, 0, !orientation); + } } else return true; @@ -139,23 +180,26 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation) { bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!mChannelUP) return false; - return objOvDataChannel.setCrop(x, y, w, h); + if(mHDMIConnected) { + objOvDataChannel[1].setCrop(x, y, w, h); + } + return objOvDataChannel[0].setCrop(x, y, w, h); } bool Overlay::setParameter(int param, int value) { - return objOvCtrlChannel.setParameter(param, value); + return objOvCtrlChannel[0].setParameter(param, value); } bool Overlay::setOrientation(int value) { - return objOvCtrlChannel.setParameter(OVERLAY_TRANSFORM, value); + return objOvCtrlChannel[0].setParameter(OVERLAY_TRANSFORM, value); } bool Overlay::setFd(int fd) { - return objOvDataChannel.setFd(fd); + return objOvDataChannel[0].setFd(fd); } bool Overlay::queueBuffer(uint32_t offset) { - return objOvDataChannel.queueBuffer(offset); + return objOvDataChannel[0].queueBuffer(offset); } bool Overlay::queueBuffer(buffer_handle_t buffer) { @@ -163,7 +207,17 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { (buffer); const size_t offset = hnd->offset; const int fd = hnd->fd; - if (setFd(fd)) { + bool ret = true; + + if(mHDMIConnected) { + ret = objOvDataChannel[1].setFd(fd); + if(!ret) { + reportError("Overlay::queueBuffer channel 1 setFd failed"); + return false; + } + ret = objOvDataChannel[1].queueBuffer(offset); + } + if (ret && setFd(fd)) { return queueBuffer(offset); } return false; @@ -179,6 +233,48 @@ OverlayControlChannel::~OverlayControlChannel() { closeControlChannel(); } +bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, overlay_rect *rect) +{ + int width = w, height = h, x, y; + int fbWidthHDMI = getFBWidth(); + int fbHeightHDMI = getFBHeight(); + // width and height for YUV TILE format + int tempWidth = w, tempHeight = h; + /* Calculate the width and height if it is YUV TILE format*/ + if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + tempWidth = w - ( (((w-1)/64 +1)*64) - w); + tempHeight = h - ((((h-1)/32 +1)*32) - h); + } + if (width * fbHeightHDMI > fbWidthHDMI * height) { + height = fbWidthHDMI * height / width; + EVEN_OUT(height); + width = fbWidthHDMI; + } else if (width * fbHeightHDMI < fbWidthHDMI * height) { + width = fbHeightHDMI * width / height; + EVEN_OUT(width); + height = fbHeightHDMI; + } else { + width = fbWidthHDMI; + height = fbHeightHDMI; + } + /* Scaling of upto a max of 8 times supported */ + if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){ + width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth; + } + if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) { + height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight; + } + if (width > fbWidthHDMI) width = fbWidthHDMI; + if (height > fbHeightHDMI) height = fbHeightHDMI; + x = (fbWidthHDMI - width) / 2; + y = (fbHeightHDMI - height) / 2; + rect->x = x; + rect->y = y; + rect->width = width; + rect->height = height; + return true; +} + bool OverlayControlChannel::openDevices(int fbnum) { if (fbnum < 0) return false; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index b5f8992..544ba3b 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -70,6 +70,13 @@ namespace overlay { +struct overlay_rect { + int x; + int y; + int width; + int height; +}; + class OverlayControlChannel { bool mNoRot; @@ -110,6 +117,7 @@ public: int getFormat3D() const { return mFormat3D; } bool getOrientation(int& orientation) const; bool setSource(uint32_t w, uint32_t h, int format, int orientation); + bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); }; class OverlayDataChannel { @@ -147,9 +155,10 @@ public: class Overlay { bool mChannelUP; + bool mHDMIConnected; - OverlayControlChannel objOvCtrlChannel; - OverlayDataChannel objOvDataChannel; + OverlayControlChannel objOvCtrlChannel[2]; + OverlayDataChannel objOvDataChannel[2]; public: Overlay(); @@ -165,17 +174,19 @@ public: bool queueBuffer(uint32_t offset); bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h); bool isChannelUP() const { return mChannelUP; } - int getFBWidth() const; - int getFBHeight() const; + int getFBWidth(int channel = 0) const; + int getFBHeight(int channel = 0) const; bool getOrientation(int& orientation) const; bool queueBuffer(buffer_handle_t buffer); - bool setSource(uint32_t w, uint32_t h, int format, int orientation); + bool setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected); bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h); + +private: + bool startChannelHDMI(int w, int h, int format, bool norot); }; struct overlay_shared_data { int readyToQueue; }; - }; #endif From 49d7fa781d73917ad06ba2d27d71cabd7763049c Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Mon, 7 Mar 2011 17:41:32 -0800 Subject: [PATCH 316/435] hwcomposer: Add support in the HWC to store the HDMI connection status Change-Id: Id9afe4da3b69465e356c16a227653896f2fd86c5 --- libhwcomposer/hwcomposer.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 66d9e2a..8fe8c3d 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -58,6 +58,7 @@ struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; + bool hdmiConnected; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -107,6 +108,12 @@ static void dump_layer(hwc_layer_t const* l) { l->displayFrame.bottom); } +static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { + hwc_context_t* ctx = (hwc_context_t*)(dev); + if(ctx) { + ctx->hdmiConnected = enable; + } +} static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { @@ -147,7 +154,7 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform); + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, false); if (!ret) { LOGE("drawLayerUsingOverlay setSource failed"); return -1; @@ -313,6 +320,8 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, } else dev->mOverlayLibObject = NULL; + dev->hdmiConnected = false; + /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; @@ -321,7 +330,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->device.prepare = hwc_prepare; dev->device.set = hwc_set; - + dev->device.enableHDMIOutput = hwc_enableHDMIOutput; *device = &dev->device.common; status = 0; From 7e5f14bb48987c68348cf4b13cbec441fc386c13 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Mon, 7 Mar 2011 17:41:41 -0800 Subject: [PATCH 317/435] Add support for video on HDMI Enable video on HDMI when cable is connected. Inform gralloc module when video playback starts and stops. Change-Id: Icc2a1b62fcd8cf75c1be98d88c3fa4dc49ef0278 --- libhwcomposer/hwcomposer.cpp | 48 +++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 8fe8c3d..b741593 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -59,6 +59,7 @@ struct hwc_context_t { /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; bool hdmiConnected; + bool videoHDMIStarted; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -73,6 +74,7 @@ struct private_hwc_module_t { hwc_module_t base; overlay_control_device_t *overlayEngine; copybit_device_t *copybitEngine; + framebuffer_device_t *fbDevice; int compositionType; }; @@ -90,6 +92,7 @@ struct private_hwc_module_t HAL_MODULE_INFO_SYM = { }, overlayEngine: NULL, copybitEngine: NULL, + fbDevice: NULL, compositionType: 0, }; @@ -117,6 +120,22 @@ static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { + hwc_context_t* ctx = (hwc_context_t*)(dev); + + if(!ctx) { + LOGE("hwc_prepare null context "); + return -1; + } + + private_hwc_module_t* hwcModule = reinterpret_cast( + dev->common.module); + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + + if(!hwcModule) { + LOGE("hwc_prepare null module "); + return -1; + } + int yuvBufferCount = 0; if (list && (list->flags & HWC_GEOMETRY_CHANGED)) { @@ -144,6 +163,25 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } + // Inform the gralloc to close the UI mirroring channel if HDMI is connected + // and we have a video buffer + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if ((yuvBufferCount == 1) && ctx->hdmiConnected && !ctx->videoHDMIStarted) { + if (fbDev) { + fbDev->videoOverlayStarted(fbDev, true); + } + ctx->videoHDMIStarted = true; + } + + if (ctx->videoHDMIStarted && yuvBufferCount != 1) { + if(ovLibObject) + ovLibObject->closeChannel(); + if (fbDev) { + fbDev->videoOverlayStarted(fbDev, false); + } + ctx->videoHDMIStarted = false; + } + return 0; } @@ -154,7 +192,7 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, false); + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, ctx->hdmiConnected); if (!ret) { LOGE("drawLayerUsingOverlay setSource failed"); return -1; @@ -248,6 +286,10 @@ static int hwc_device_close(struct hw_device_t *dev) overlay_control_close(hwcModule->overlayEngine); hwcModule->overlayEngine = NULL; } + if(hwcModule->fbDevice) { + framebuffer_close(hwcModule->fbDevice); + hwcModule->fbDevice = NULL; + } if (ctx) { delete ctx->mOverlayLibObject; @@ -270,6 +312,9 @@ static int hwc_module_initialize(struct private_hwc_module_t* hwcModule) if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { overlay_control_open(module, &(hwcModule->overlayEngine)); } + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + framebuffer_open(module, &(hwcModule->fbDevice)); + } // get the current composition type char property[PROPERTY_VALUE_MAX]; @@ -321,6 +366,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->mOverlayLibObject = NULL; dev->hdmiConnected = false; + dev->videoHDMIStarted = false; /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; From f59c70eab45f43df0d0a7e97489dd1e6607fc4f0 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:42:00 -0800 Subject: [PATCH 318/435] libhwcomposer: Add null checks SurfaceFlinger calls a hwc_set with a NULL context and list when it is releasing the HWC. Check the validity of the pointers before using it. Change-Id: I5b61cc50a85b9b660646789b2cf9a0f4ee6e4a5c --- libhwcomposer/hwcomposer.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index b741593..2da07ff 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -122,8 +122,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); - if(!ctx) { - LOGE("hwc_prepare null context "); + if(!ctx || !list) { + LOGE("hwc_prepare invalid context or list"); return -1; } @@ -242,8 +242,8 @@ static int hwc_set(hwc_composer_device_t *dev, { hwc_context_t* ctx = (hwc_context_t*)(dev); - if(!ctx) { - LOGE("hwc_set null context "); + if(!ctx || !list) { + LOGE("hwc_set invalid context or list"); return -1; } @@ -272,6 +272,11 @@ static int hwc_set(hwc_composer_device_t *dev, static int hwc_device_close(struct hw_device_t *dev) { + if(!dev) { + LOGE("hwc_device_close null device pointer"); + return -1; + } + struct hwc_context_t* ctx = (struct hwc_context_t*)dev; private_hwc_module_t* hwcModule = reinterpret_cast( From ac47ade63969f8c3ef5cec26884c59cf9dba9734 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:42:33 -0800 Subject: [PATCH 319/435] hwcomposer: Add support for C2D/MDP composition Add support in the HWC to use C2D and MDP composition via the copybit HAL Change-Id: I19a98d9821600fdfbadcab53329027ef17aa8f1f --- libhwcomposer/hwcomposer.cpp | 156 ++++++++++++++++++++++++++++++----- 1 file changed, 136 insertions(+), 20 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 2da07ff..7c43c06 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -36,22 +36,25 @@ #include #include +#include +#include #include /*****************************************************************************/ +#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) // Enum containing the supported composition types enum { - COMPOSITION_TYPE_GPU, - COMPOSITION_TYPE_MDP, - COMPOSITION_TYPE_C2D, - COMPOSITION_TYPE_CPU + COMPOSITION_TYPE_GPU = 0, + COMPOSITION_TYPE_MDP = 0x1, + COMPOSITION_TYPE_C2D = 0x2, + COMPOSITION_TYPE_CPU = 0x4 }; -enum LayerType{ - GPU, // This layer is to be handled by Surfaceflinger - OVERLAY, // This layer is to be handled by the overlay - COPYBIT // This layer is to be handled by copybit +enum HWCCompositionType { + HWC_USE_GPU, // This layer is to be handled by Surfaceflinger + HWC_USE_OVERLAY, // This layer is to be handled by the overlay + HWC_USE_COPYBIT // This layer is to be handled by copybit }; struct hwc_context_t { @@ -154,10 +157,11 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { - list->hwLayers[i].compositionType = OVERLAY; + list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + } else if (hnd && (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) { + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; } else { - // For other layers, check composition used. - C2D/MDP composition - TBD list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; } } @@ -184,6 +188,116 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { return 0; } +// --------------------------------------------------------------------------- +struct range { + int current; + int end; +}; +struct region_iterator : public copybit_region_t { + + region_iterator(hwc_region_t region) { + mRegion = region; + r.end = region.numRects; + r.current = 0; + this->next = iterate; + } + +private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { + if (!self || !rect) { + LOGE("iterate invalid parameters"); + return 0; + } + + region_iterator const* me = static_cast(self); + if (me->r.current != me->r.end) { + rect->l = me->mRegion.rects[me->r.current].left; + rect->t = me->mRegion.rects[me->r.current].top; + rect->r = me->mRegion.rects[me->r.current].right; + rect->b = me->mRegion.rects[me->r.current].bottom; + me->r.current++; + return 1; + } + return 0; + } + + hwc_region_t mRegion; + mutable range r; +}; + + +static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, EGLDisplay dpy, + EGLSurface surface) +{ + hwc_context_t* ctx = (hwc_context_t*)(dev); + if(!ctx) { + LOGE("drawLayerUsingCopybit null context "); + return -1; + } + + private_hwc_module_t* hwcModule = reinterpret_cast(dev->common.module); + if(!hwcModule) { + LOGE("drawLayerUsingCopybit null module "); + return -1; + } + + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + LOGE("drawLayerUsingCopybit invalid handle"); + return -1; + } + + // Set the copybit source: + copybit_image_t src; + src.w = ALIGN(hnd->width, 32); + src.h = hnd->height; + src.format = hnd->format; + src.base = (void *)hnd->base; + src.handle = (native_handle_t *)layer->handle; + + // Copybit source rect + hwc_rect_t sourceCrop = layer->sourceCrop; + copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top, + (sourceCrop.right - sourceCrop.left), + (sourceCrop.bottom-sourceCrop.top)}; + + // Copybit destination rect + hwc_rect_t displayFrame = layer->displayFrame; + copybit_rect_t dstRect = {displayFrame.left, displayFrame.top, + (displayFrame.right - displayFrame.left), + (displayFrame.bottom-displayFrame.top)}; + + // Copybit dst + copybit_image_t dst; + android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface); + if (!renderBuffer) { + LOGE("eglGetRenderBufferANDROID returned NULL buffer"); + } + private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; + if(!fbHandle) { + LOGE("Framebuffer handle is NULL"); + return -1; + } + dst.w = ALIGN(fbHandle->width,32); + dst.h = fbHandle->height; + dst.format = fbHandle->format; + dst.base = (void *)fbHandle->base; + dst.handle = (native_handle_t *)renderBuffer->handle; + + // Copybit region + hwc_region_t region = layer->visibleRegionScreen; + region_iterator copybitRegion(region); + + copybit_device_t *copybit = hwcModule->copybitEngine; + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->blending); + int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); + + if(err < 0) + LOGE("copybit stretch failed"); + + return err; +} static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { @@ -253,13 +367,15 @@ static int hwc_set(hwc_composer_device_t *dev, LOGE("hwc_set null module "); return -1; } - for (size_t i=0 ; inumHwLayers ; i++) { - if (list->hwLayers[i].compositionType == HWC_OVERLAY) { + if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { + continue; + } + + if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); - } else if ((hwcModule->compositionType == COMPOSITION_TYPE_C2D) || - (hwcModule->compositionType == COMPOSITION_TYPE_MDP)) { - // TBD + } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) { + drawLayerUsingCopybit(dev, &(list->hwLayers[i]), (EGLDisplay)dpy, (EGLSurface)sur); } } EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); @@ -331,17 +447,17 @@ static int hwc_module_initialize(struct private_hwc_module_t* hwcModule) // Get the composition type property_get("debug.composition.type", property, NULL); if (property == NULL) { - hwcModule->compositionType == COMPOSITION_TYPE_GPU; + hwcModule->compositionType = COMPOSITION_TYPE_GPU; } else if ((strncmp(property, "mdp", 3)) == 0) { - hwcModule->compositionType == COMPOSITION_TYPE_MDP; + hwcModule->compositionType = COMPOSITION_TYPE_MDP; } else if ((strncmp(property, "c2d", 3)) == 0) { - hwcModule->compositionType == COMPOSITION_TYPE_C2D; + hwcModule->compositionType = COMPOSITION_TYPE_C2D; } else { - hwcModule->compositionType == COMPOSITION_TYPE_GPU; + hwcModule->compositionType = COMPOSITION_TYPE_GPU; } if(!hwcModule->copybitEngine) - hwcModule->compositionType == COMPOSITION_TYPE_GPU; + hwcModule->compositionType = COMPOSITION_TYPE_GPU; } } else { //debug.sf.hw is not set. Use cpu composition hwcModule->compositionType = COMPOSITION_TYPE_CPU; From 05ff4bb6616ce13d09d02465140ad276110c71a7 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:45:41 -0800 Subject: [PATCH 320/435] copybit_c2d: Set the kgsl memory type as pmem for buffers with the PRIV_FLAGS_USES_PMEM_ADSP flag Gralloc buffers which have the PRIV_FLAGS_USES_PMEM_ADSP flag are allocated from a pmem region. Set the kgsl memory type to PMEM to reflect this change. Change-Id: Id5b84277ddec5cc9550aa97d2789df4d1bc2b2b5 --- libcopybit/copybit_c2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 4159dbf..8f99196 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -207,7 +207,7 @@ static uint32 c2d_get_gpuaddr(int device_fd, struct private_handle_t *handle) param.offset = handle->offset; param.hostptr = handle->base; - if (handle->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) + if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM|private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) param.memtype = KGSL_USER_MEM_TYPE_PMEM; else param.memtype = KGSL_USER_MEM_TYPE_ASHMEM; From 3be64f08f95919ea9b835f809b67f28f05d7ee77 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:46:28 -0800 Subject: [PATCH 322/435] libgralloc-qsd8k: Close the masterFd when freeing video/camera buffers Buffers allocated from the adsp or smipool regions have a masterFd associated with each buffer. Make sure both the fds are closed when the buffers are freed to avoid memory leaks. Change-Id: I7dd194bae9ebfffb5e8c1ed647bff6210409a731 --- libgralloc-qsd8k/gpu.cpp | 10 ++++++++-- libgralloc-qsd8k/gralloc_priv.h | 5 +++-- libgralloc-qsd8k/pmemalloc.cpp | 13 +++++-------- libgralloc-qsd8k/pmemalloc.h | 6 +++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 0a3ac33..9006528 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -168,6 +168,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // the PmemAllocator rather than getting the base & offset separately int offset = 0; int lockState = 0; + int masterFd = -1; size = roundUpToPageSize(size); #ifndef USE_ASHMEM if (usage & GRALLOC_USAGE_HW_TEXTURE) { @@ -217,7 +218,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // PMEM buffers are always mmapped lockState |= private_handle_t::LOCK_STATE_MAPPED; - err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd); + err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, &masterFd); if (err < 0) { if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { @@ -243,6 +244,7 @@ try_ashmem: hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; + hnd->masterFd = masterFd; *pHandle = hnd; } @@ -393,7 +395,7 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { const size_t bufferSize = m->finfo.line_length * m->info.yres; int index = (hnd->base - m->framebuffer->base) / bufferSize; m->bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { pmem_allocator = &pmemAllocator; @@ -404,10 +406,14 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base, hnd->offset, hnd->fd); } + deps.terminateBuffer(&m->base, const_cast(hnd)); } deps.close(hnd->fd); + if (hnd->masterFd != -1) { + deps.close(hnd->masterFd); + } delete hnd; // XXX JMG: move this to the deps return 0; } diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index cdb18dc..64d24cf 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -269,16 +269,17 @@ struct private_handle_t { int format; int width; int height; + int masterFd; #ifdef __cplusplus - static const int sNumInts = 13; + static const int sNumInts = 14; static const int sNumFds = 1; static const int sMagic = 'gmsm'; 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) + height(height), masterFd(-1) { version = sizeof(native_handle); numInts = sNumInts; diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index 1d78333..dc756be 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -143,7 +143,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* masterFd) { BEGIN_FUNC; int err = init_pmem_area(); @@ -185,6 +185,7 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, *pBase = base; *pOffset = offset; *pFd = fd; + *masterFd = -1; } //LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset); } @@ -259,7 +260,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* masterFd) { BEGIN_FUNC; @@ -320,6 +321,7 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, *pBase = base; *pOffset = 0; *pFd = fd; + *masterFd = master_fd; } else { deps.munmap(base, size); deps.unmapPmem(fd, offset, size); @@ -346,12 +348,7 @@ int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, i LOGW("error unmapping pmem fd: %s", strerror(err)); return -err; } - err = deps.munmap(base, size); - if (err < 0) { - err = deps.getErrno(); - LOGW("error unmapping pmem master_fd: %s", strerror(err)); - return -err; - } + END_FUNC; return 0; } diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h index f433010..dfe114e 100755 --- a/libgralloc-qsd8k/pmemalloc.h +++ b/libgralloc-qsd8k/pmemalloc.h @@ -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* masterFd) = 0; virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0; }; @@ -89,7 +89,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* masterFd); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); #ifndef ANDROID_OS @@ -151,7 +151,7 @@ class PmemKernelAllocator: public PmemAllocator { 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* masterFd); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); private: From aedeaccc6a521d524f266d40239dcf4b91c2356e Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 18:00:39 -0800 Subject: [PATCH 323/435] overlayLib: Set the MDP_OV_PLAY_NOWAIT flag for non RGB buffers Change-Id: I6e3323cbc59125e1d52883c3a41d0950b3caefef --- liboverlay/overlayLib.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 0c4f8ad..a510c88 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -74,6 +74,17 @@ static int get_size(int format, int w, int h) { return size; } +static bool isRGBType(int format) { + switch (format) { + case MDP_RGBA_8888: + case MDP_BGRA_8888: + case MDP_RGBX_8888: + case MDP_RGB_565: + return true; + } + return false; +} + #define LOG_TAG "OverlayLIB" static void reportError(const char* message) { LOGE( "%s", message); @@ -364,6 +375,9 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; mOVInfo.flags = flags; + if (!isRGBType(format)) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + mOVInfo.is_fg = 0; mSize = get_size(format, w, h); return true; From 06304d437b41ebb5caed9ac0d026d0472f501889 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 18:00:54 -0800 Subject: [PATCH 325/435] Align pmem for NV12 Tiled buffers The decoder requires the NV12Tiled buffers to be physically aligned to 8k. Change-Id: I07a40d2a390601192a01213a5de94df2ab1ee06c --- libgralloc-qsd8k/gpu.cpp | 2 +- libgralloc-qsd8k/gralloc.cpp | 7 +++++++ libgralloc-qsd8k/pmemalloc.cpp | 12 ++++++++++-- libgralloc-qsd8k/pmemalloc.h | 7 ++++--- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 9006528..b3a83ce 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -218,7 +218,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // PMEM buffers are always mmapped lockState |= private_handle_t::LOCK_STATE_MAPPED; - err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, &masterFd); + err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, &masterFd, format); if (err < 0) { if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 019a8cd..16f026e 100755 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -96,6 +96,13 @@ class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, return ioctl(fd, PMEM_UNMAP, &sub); } + virtual int alignPmem(int fd, size_t size, int align) { + struct pmem_allocation allocation; + allocation.size = size; + allocation.align = align; + return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation); + } + virtual int getErrno() { return errno; } diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index dc756be..ea30b2b 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -143,7 +143,7 @@ int PmemUserspaceAllocator::init_pmem_area() int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, - void** pBase, int* pOffset, int* pFd, int* masterFd) + void** pBase, int* pOffset, int* pFd, int* masterFd, int format) { BEGIN_FUNC; int err = init_pmem_area(); @@ -260,7 +260,7 @@ static unsigned clp2(unsigned x) { int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, - void** pBase,int* pOffset, int* pFd, int* masterFd) + void** pBase,int* pOffset, int* pFd, int* masterFd, int format) { BEGIN_FUNC; @@ -292,6 +292,14 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, // The size should already be page aligned, now round it up to a power of 2. //size = clp2(size); + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + // Tile format buffers need physical alignment to 8K + err = deps.alignPmem(master_fd, size, 8192); + if (err < 0) { + LOGE("alignPmem failed"); + } + } + void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); if (base == MAP_FAILED) { LOGE("%s: failed to map pmem fd: %s", device, diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h index dfe114e..a6d98b8 100755 --- a/libgralloc-qsd8k/pmemalloc.h +++ b/libgralloc-qsd8k/pmemalloc.h @@ -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, int* masterFd) = 0; + int* pOffset, int* pFd, int* masterFd, int format) = 0; virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0; }; @@ -89,7 +89,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* masterFd); + int* pOffset, int* pFd, int* masterFd, int format); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); #ifndef ANDROID_OS @@ -142,6 +142,7 @@ class PmemKernelAllocator: public PmemAllocator { virtual int connectPmem(int fd, int master_fd) = 0; virtual int mapPmem(int fd, int offset, size_t size) = 0; virtual int unmapPmem(int fd, int offset, size_t size) = 0; + virtual int alignPmem(int fd, size_t size, int align) = 0; }; PmemKernelAllocator(Deps& deps); @@ -151,7 +152,7 @@ class PmemKernelAllocator: public PmemAllocator { virtual void* get_base_address(); virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase, - int* pOffset, int* pFd, int* masterFd); + int* pOffset, int* pFd, int* masterFd, int format); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); private: From 9cdf0b93ca04c8a15df0fb2b09f363d19089559e Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 8 Mar 2011 20:07:20 -0800 Subject: [PATCH 326/435] libgralloc-qsd8k: Align the chroma size for NV12Tiled formats to 8K The video decoder requires the chroma and luma sizes to be aligned to 8K. Change-Id: Ie378728647348812197b48ca4a9299344e56c3af --- libgralloc-qsd8k/gpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index b3a83ce..68177a5 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -350,7 +350,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, // 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); + size += ALIGN( alignedw * ALIGN(h/2, 32), 8192); break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: case HAL_PIXEL_FORMAT_YCrCb_420_SP: From 2a50a0a8945df797569bbfef6075d066b856f995 Mon Sep 17 00:00:00 2001 From: Sridhar Parasuram Date: Fri, 11 Mar 2011 12:56:41 -0700 Subject: [PATCH 327/435] Fix copyright markings Change-Id: I2170d0dbd9270bcfd38ea2f8c7052ac387b9e0c9 --- libhwcomposer/Android.mk | 14 -------------- libhwcomposer/hwcomposer.cpp | 1 - 2 files changed, 15 deletions(-) diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 4e3dba3..4e4d66f 100755 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -1,17 +1,3 @@ -# Copyright (c) 2010, 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) # HAL module implemenation, not prelinked and stored in diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 7c43c06..51389df 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2010 The Android Open Source Project - * Copyright (c) 2010, 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. From 7b7b48531e7a185b3745e4dc08c3d46da8ff07b1 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 14 Mar 2011 18:32:59 -0700 Subject: [PATCH 328/435] libhwcomposer: Set the correct copybit parameters Set the correct parameters for the source and destination rectangles when drawing the layer using copybit. Change-Id: I6ab7e2b5ba7b457a5bc604fd3a0031e6bada82cb --- libhwcomposer/hwcomposer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 51389df..036a6ca 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -257,14 +257,14 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, // Copybit source rect hwc_rect_t sourceCrop = layer->sourceCrop; copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top, - (sourceCrop.right - sourceCrop.left), - (sourceCrop.bottom-sourceCrop.top)}; + sourceCrop.right, + sourceCrop.bottom}; // Copybit destination rect hwc_rect_t displayFrame = layer->displayFrame; copybit_rect_t dstRect = {displayFrame.left, displayFrame.top, - (displayFrame.right - displayFrame.left), - (displayFrame.bottom-displayFrame.top)}; + displayFrame.right, + displayFrame.bottom}; // Copybit dst copybit_image_t dst; @@ -289,7 +289,7 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, copybit_device_t *copybit = hwcModule->copybitEngine; copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->blending); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); if(err < 0) From cd8f8d8e84aa80dac27f64aef61cdb4fe7ea4bf0 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 9 Mar 2011 15:40:32 -0800 Subject: [PATCH 329/435] libhwcomposer: Close the overlay channel after video/camera playback. Change-Id: I321acdb5ff00d7d70399d044473ef9b5ad9f547e --- libhwcomposer/hwcomposer.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 036a6ca..621f292 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -61,7 +61,7 @@ struct hwc_context_t { /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; bool hdmiConnected; - bool videoHDMIStarted; + bool videoStarted; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -164,25 +164,26 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; } } - } - // Inform the gralloc to close the UI mirroring channel if HDMI is connected - // and we have a video buffer - framebuffer_device_t *fbDev = hwcModule->fbDevice; - if ((yuvBufferCount == 1) && ctx->hdmiConnected && !ctx->videoHDMIStarted) { - if (fbDev) { - fbDev->videoOverlayStarted(fbDev, true); + // Inform the gralloc to close the UI mirroring channel if HDMI is connected + // and we have a video buffer + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if ((yuvBufferCount == 1) && !ctx->videoStarted) { + if (ctx->hdmiConnected && fbDev) { + fbDev->videoOverlayStarted(fbDev, true); + } + ctx->videoStarted = true; } - ctx->videoHDMIStarted = true; - } - if (ctx->videoHDMIStarted && yuvBufferCount != 1) { - if(ovLibObject) - ovLibObject->closeChannel(); - if (fbDev) { - fbDev->videoOverlayStarted(fbDev, false); + if (ctx->videoStarted && yuvBufferCount != 1) { + if(ovLibObject) + ovLibObject->closeChannel(); + + if (ctx->hdmiConnected && fbDev) { + fbDev->videoOverlayStarted(fbDev, false); + } + ctx->videoStarted = false; } - ctx->videoHDMIStarted = false; } return 0; @@ -486,7 +487,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->mOverlayLibObject = NULL; dev->hdmiConnected = false; - dev->videoHDMIStarted = false; + dev->videoStarted = false; /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; From ed76fc69a8f61be92bc76cc7978d01907ea718fb Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 3 Jan 2011 12:53:06 -0800 Subject: [PATCH 330/435] libgralloc-qsd8k: Close the gralloc module Close the gralloc module in the fb_device_open api. CRs-fixed: 269234 Change-Id: Ifcb1909e0cf8bf40f2b505716cb624531309556b --- libgralloc-qsd8k/framebuffer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 7669785..e2b7ac1 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -826,6 +826,9 @@ int fb_device_open(hw_module_t const* module, const char* name, *device = &dev->device.common; } + + // Close the gralloc module + gralloc_close(gralloc_device); } return status; } From a2d029bef1259f9e137d7237813517c4529a8c22 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Mon, 22 Nov 2010 19:56:31 -0800 Subject: [PATCH 331/435] hardware/msm7k: Fix position, aspect ratio on HDMI UI Fix position, aspect ratio of HDMI UI when the primary panel type is MIPI, 8660 Panel or 7x30 Panel Change-Id: I8e9824520317e3facb4ef25bc25dd9b1de60b4ce CRs-fixed: 263690, 269433 --- libgralloc-qsd8k/framebuffer.cpp | 50 ++++++++++++++------------------ 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index e2b7ac1..97b12f7 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -247,18 +247,15 @@ static void *hdmi_ui_loop(void *ptr) // ROT_0 case 0: // ROT_180 - case HAL_TRANSFORM_ROT_180: - x = (width - fbwidth) / 2; - if (x < 0) - x = 0; - if (fbwidth < width) - width = fbwidth; - if (fbheight < height) - height = fbheight; - if(rot == HAL_TRANSFORM_ROT_180) - rot = OVERLAY_TRANSFORM_ROT_180; - else - rot = 0; + case HAL_TRANSFORM_ROT_180: { + int tmpWidth = (height * fbwidth) / fbheight; + x = (width - tmpWidth) / 2; + width = tmpWidth; + if(rot == HAL_TRANSFORM_ROT_180) + rot = OVERLAY_TRANSFORM_ROT_180; + else + rot = 0; + } break; // ROT_90 case HAL_TRANSFORM_ROT_90: @@ -283,22 +280,19 @@ static void *hdmi_ui_loop(void *ptr) // ROT_90 case HAL_TRANSFORM_ROT_90: // ROT_270 - case HAL_TRANSFORM_ROT_270: - //Swap width and height - int t = fbwidth; - fbwidth = fbheight; - fbheight = t; - x = (width - fbwidth) / 2; - if (x < 0) - x = 0; - if (fbwidth < width) - width = fbwidth; - if (fbheight < height) - height = fbheight; - if(rot == HAL_TRANSFORM_ROT_90) - rot = OVERLAY_TRANSFORM_ROT_270; - else - rot = OVERLAY_TRANSFORM_ROT_90; + case HAL_TRANSFORM_ROT_270: { + //Swap width and height + int t = fbwidth; + fbwidth = fbheight; + fbheight = t; + int tmpWidth = (height * fbwidth) / fbheight; + x = (width - tmpWidth) / 2; + width = tmpWidth; + if(rot == HAL_TRANSFORM_ROT_90) + rot = OVERLAY_TRANSFORM_ROT_270; + else + rot = OVERLAY_TRANSFORM_ROT_90; + } break; } } From 76595c17bd528374a726ec55bdda59c9ad823598 Mon Sep 17 00:00:00 2001 From: Shubhraprakash Das Date: Tue, 18 Jan 2011 17:59:30 -0700 Subject: [PATCH 332/435] libgralloc-qsd8k: Port part of change Ice6a7c28 Port over part of change Ice6a7c28 that frees ashmem memory. Change-Id: I467617f3bc35a0e448fbf41207853e669aed657a --- libgralloc-qsd8k/gpu.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 68177a5..a2c35b4 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -401,6 +401,16 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { 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, From f7c637113722f4dabcfe66c77c1884b2fe2763b6 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Wed, 12 Jan 2011 11:35:53 -0800 Subject: [PATCH 333/435] hardware/msm7k: Fix aspect ratio in HDMI UI For portrait mode: Actionsafe width depends on actionsafe height, thus maintaining the aspect ratio. User entered value for actionsafe width doesn't matter. For landscape mode: Both, user entered actionsafe width and height matter. Aspect ratio may change, in an attempt to fill up the TV screen till the edges to avoid overscan/underscan. Picks actionsafe rectangle as the final rectangle. Change-Id: I4e16a2d57978d3443283e9311c2efdc6494f8a94 CRs-fixed: 271567 --- libgralloc-qsd8k/framebuffer.cpp | 37 +++++++++++--------------------- 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 97b12f7..fd6b36d 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -216,10 +216,7 @@ static void *hdmi_ui_loop(void *ptr) int width = pTemp->getFBWidth(); int height = pTemp->getFBHeight(); int aswidth = width, asheight = height; - int final_width = width, final_height = height; - int x = 0, y = 0; // Used for calculating normal x,y co-ordinates - int x1 = 0, y1 = 0; // Action safe x, y co-ordinates - int xx = 0, yy = 0; // Final x, y co-ordinates + int asX = 0, asY = 0; // Action safe x, y co-ordinates int fbwidth = m->info.xres, fbheight = m->info.yres; float defaultASWidthRatio = 0.0f, defaultASHeightRatio = 0.0f; if(HEIGHT_1080P == height) { @@ -239,8 +236,8 @@ static void *hdmi_ui_loop(void *ptr) aswidth = (int)((float)width - (float)(width * asWidthRatio)); asheight = (int)((float)height - (float)(height * asHeightRatio)); - x1 = (int)(width * asWidthRatio) / 2; - y1 = (int)(height * asHeightRatio) / 2; + asX = (width - aswidth) / 2; + asY = (height - asheight) / 2; int rot = m->orientation; if (fbwidth < fbheight) { switch(rot) { @@ -248,9 +245,8 @@ static void *hdmi_ui_loop(void *ptr) case 0: // ROT_180 case HAL_TRANSFORM_ROT_180: { - int tmpWidth = (height * fbwidth) / fbheight; - x = (width - tmpWidth) / 2; - width = tmpWidth; + aswidth = (asheight * fbwidth) / fbheight; + asX = (width - aswidth) / 2; if(rot == HAL_TRANSFORM_ROT_180) rot = OVERLAY_TRANSFORM_ROT_180; else @@ -285,9 +281,8 @@ static void *hdmi_ui_loop(void *ptr) int t = fbwidth; fbwidth = fbheight; fbheight = t; - int tmpWidth = (height * fbwidth) / fbheight; - x = (width - tmpWidth) / 2; - width = tmpWidth; + aswidth = (asheight * fbwidth) / fbheight; + asX = (width - aswidth) / 2; if(rot == HAL_TRANSFORM_ROT_90) rot = OVERLAY_TRANSFORM_ROT_270; else @@ -296,19 +291,13 @@ static void *hdmi_ui_loop(void *ptr) break; } } - pTemp->setParameter(OVERLAY_TRANSFORM, + pTemp->setParameter(OVERLAY_TRANSFORM, rot); - // Calculate the interection of final destination parameters - // Intersection of Action Safe rect and the orig rect will give the final dest rect - xx = max(x1, x); - yy = max(y1, y); - final_width = min((x1+aswidth), (x+width))- xx; - final_height = min((y1+asheight), (y+height))- yy; - EVEN_OUT(xx); - EVEN_OUT(yy); - EVEN_OUT(final_width); - EVEN_OUT(final_height); - pTemp->setPosition(xx, yy, final_width, final_height); + EVEN_OUT(asX); + EVEN_OUT(asY); + EVEN_OUT(aswidth); + EVEN_OUT(asheight); + pTemp->setPosition(asX, asY, aswidth, asheight); pTemp->queueBuffer(m->currentOffset); } } From 8864a8d0754783bce91ef3635d0fd9cd140c9944 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Fri, 28 Jan 2011 18:59:05 +0530 Subject: [PATCH 334/435] gralloc: Fix compilation issue with ashmem on 7x27 Change-Id: I02fcbd7bdefd83be4a55a79ccd82c0df4b74f7ae --- libgralloc-qsd8k/gralloc.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index 16f026e..ab574a7 100755 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -64,6 +64,8 @@ extern int gralloc_perform(struct gralloc_module_t const* module, 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 @@ -74,7 +76,10 @@ class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, } #else #ifdef USE_ASHMEM - *size = m->info.xres * m->info.yres * 2 * 2; + if(module != NULL) + *size = module->info.xres * module->info.yres * 2 * 2; + else + return -ENOMEM; #else *size = 23<<20; //23MB for 7x27 #endif @@ -123,6 +128,12 @@ class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, 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 { @@ -199,6 +210,7 @@ int gralloc_device_open(const hw_module_t* module, const char* name, if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { const private_module_t* m = reinterpret_cast( module); + pmemAllocatorDeviceDepsImpl.setModule(m); gpu_context_t *dev; dev = new gpu_context_t(gpuContextDeviceDepsImpl, pmemAllocator, pmemAdspAllocator, m); From 36342178c2f5a5c952eb9f058dfa2356a82945bd Mon Sep 17 00:00:00 2001 From: Harshad Bhutada Date: Fri, 21 Jan 2011 20:05:52 +0530 Subject: [PATCH 335/435] libgralloc-qsd8k: Add support for triple buffering Change-Id: I15c0a2c76f4ee1a87a8b2be369c24ab8d4c38101 --- libgralloc-qsd8k/framebuffer.cpp | 107 ++++++++++++++++++++++++++----- libgralloc-qsd8k/gralloc_priv.h | 16 ++++- 2 files changed, 106 insertions(+), 17 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index fd6b36d..6a4e3f7 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ #include #endif +#define FB_DEBUG 0 + #if defined(HDMI_DUAL_DISPLAY) #define AS_1080_RATIO_H (4.25/100) // Default Action Safe vertical limit for 1080p #define AS_1080_RATIO_W (4.25/100) // Default Action Safe horizontal limit for 1080p @@ -73,6 +76,8 @@ static inline size_t ALIGN(size_t x, size_t align) { } #endif +char framebufferStateName[] = {'S', 'R', 'A'}; + /*****************************************************************************/ enum { @@ -166,16 +171,32 @@ static void *disp_loop(void *ptr) } if (cur_buf == -1) { + int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers); pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock)); m->avail[nxtBuf.idx].is_avail = true; - pthread_cond_signal(&(m->avail[nxtBuf.idx].cond)); + m->avail[nxtBuf.idx].state = REF; + pthread_cond_broadcast(&(m->avail[nxtBuf.idx].cond)); pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock)); } else { + pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock)); + if (m->avail[nxtBuf.idx].state != SUB) { + LOGE("[%d] state %c, expected %c", nxtBuf.idx, + framebufferStateName[m->avail[nxtBuf.idx].state], + framebufferStateName[SUB]); + } + m->avail[nxtBuf.idx].state = REF; + pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock)); + pthread_mutex_lock(&(m->avail[cur_buf].lock)); m->avail[cur_buf].is_avail = true; - pthread_cond_signal(&(m->avail[cur_buf].cond)); + if (m->avail[cur_buf].state != REF) { + LOGE("[%d] state %c, expected %c", cur_buf, + framebufferStateName[m->avail[cur_buf].state], + framebufferStateName[REF]); + } + m->avail[cur_buf].state = AVL; + pthread_cond_broadcast(&(m->avail[cur_buf].cond)); pthread_mutex_unlock(&(m->avail[cur_buf].lock)); - } cur_buf = nxtBuf.idx; } @@ -377,7 +398,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) if (private_handle_t::validate(buffer) < 0) return -EINVAL; - int nxtIdx; + int nxtIdx, futureIdx = -1; bool reuse; struct qbuf_t qb; fb_context_t* ctx = (fb_context_t*)dev; @@ -389,7 +410,8 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { reuse = false; - nxtIdx = (m->currentIdx + 1) % NUM_BUFFERS; + nxtIdx = (m->currentIdx + 1) % m->numBuffers; + futureIdx = (nxtIdx + 1) % m->numBuffers; if (m->swapInterval == 0) { // if SwapInterval = 0 and no buffers available then reuse @@ -411,7 +433,19 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) // post/queue the new buffer pthread_mutex_lock(&(m->avail[nxtIdx].lock)); + if (m->avail[nxtIdx].is_avail != true) { + LOGE("Found %d buf to be not avail", nxtIdx); + } + m->avail[nxtIdx].is_avail = false; + + if (m->avail[nxtIdx].state != AVL) { + LOGD("[%d] state %c, expected %c", nxtIdx, + framebufferStateName[m->avail[nxtIdx].state], + framebufferStateName[AVL]); + } + + m->avail[nxtIdx].state = SUB; pthread_mutex_unlock(&(m->avail[nxtIdx].lock)); qb.idx = nxtIdx; @@ -425,18 +459,22 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) // (current) buffer if (m->currentBuffer) { if (m->swapInterval != 0) { - pthread_mutex_lock(&(m->avail[m->currentIdx].lock)); - if (! m->avail[m->currentIdx].is_avail) { - pthread_cond_wait(&(m->avail[m->currentIdx].cond), - &(m->avail[m->currentIdx].lock)); - m->avail[m->currentIdx].is_avail = true; + 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[m->currentIdx].lock)); + pthread_mutex_unlock(&(m->avail[futureIdx].lock)); } m->base.unlock(&m->base, m->currentBuffer); } m->currentBuffer = buffer; m->currentIdx = nxtIdx; + if (m->avail[futureIdx].state != AVL) { + LOGE("[%d] != AVL!", futureIdx); + } } else { if (m->currentBuffer) m->base.unlock(&m->base, m->currentBuffer); @@ -472,6 +510,10 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->base.unlock(&m->base, m->framebuffer); } + LOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c", + framebufferStateName[m->avail[0].state], + framebufferStateName[m->avail[1].state], + framebufferStateName[m->avail[2].state]); return 0; } @@ -483,6 +525,25 @@ static int fb_compositionComplete(struct framebuffer_device_t* dev) return 0; } +static int fb_dequeueBuffer(struct framebuffer_device_t* dev, int index) +{ + private_module_t* m = reinterpret_cast( + dev->common.module); + + // Return immediately if the buffer is available + if (m->avail[index].state == AVL) + return 0; + + pthread_mutex_lock(&(m->avail[index].lock)); + while (m->avail[index].state != AVL) { + pthread_cond_wait(&(m->avail[index].cond), + &(m->avail[index].lock)); + } + pthread_mutex_unlock(&(m->avail[index].lock)); + + return 0; +} + /*****************************************************************************/ int mapFrameBufferLocked(struct private_module_t* module) @@ -500,6 +561,7 @@ int mapFrameBufferLocked(struct private_module_t* module) int fd = -1; int i=0; char name[64]; + char property[PROPERTY_VALUE_MAX]; while ((fd==-1) && device_template[i]) { snprintf(name, 64, device_template[i], 0); @@ -548,7 +610,6 @@ int mapFrameBufferLocked(struct private_module_t* module) /* 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. */ - char property[PROPERTY_VALUE_MAX]; 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)) @@ -573,8 +634,22 @@ int mapFrameBufferLocked(struct private_module_t* module) /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) */ - info.yres_virtual = info.yres * NUM_BUFFERS; + int numberOfBuffers = (int)(finfo.smem_len/(info.yres * info.xres * (info.bits_per_pixel/8))); + LOGV("num supported framebuffers in kernel = %d", numberOfBuffers); + if (property_get("debug.gr.numframebuffers", property, NULL) > 0) { + int num = atoi(property); + if ((num >= NUM_FRAMEBUFFERS_MIN) && (num <= NUM_FRAMEBUFFERS_MAX)) { + numberOfBuffers = num; + } + } + + if (numberOfBuffers > NUM_FRAMEBUFFERS_MAX) + numberOfBuffers = NUM_FRAMEBUFFERS_MAX; + + LOGD("We support %d buffers", numberOfBuffers); + + info.yres_virtual = info.yres * numberOfBuffers; uint32_t flags = PAGE_FLIP; if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { @@ -654,7 +729,6 @@ int mapFrameBufferLocked(struct private_module_t* module) if (finfo.smem_len <= 0) return -errno; - module->flags = flags; module->info = info; module->finfo = finfo; @@ -682,10 +756,11 @@ int mapFrameBufferLocked(struct private_module_t* module) module->currentIdx = -1; pthread_cond_init(&(module->qpost), NULL); pthread_mutex_init(&(module->qlock), NULL); - for (i = 0; i < NUM_BUFFERS; i++) { + for (i = 0; i < NUM_FRAMEBUFFERS_MAX; i++) { pthread_mutex_init(&(module->avail[i].lock), NULL); pthread_cond_init(&(module->avail[i].cond), NULL); module->avail[i].is_avail = true; + module->avail[i].state = AVL; } /* create display update thread */ @@ -778,6 +853,7 @@ 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; #if defined(HDMI_DUAL_DISPLAY) dev->device.orientationChanged = fb_orientationChanged; dev->device.videoOverlayStarted = fb_videoOverlayStarted; @@ -800,6 +876,7 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.fps) = m->fps; const_cast(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL; const_cast(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL; + const_cast(dev->device.numFramebuffers) = m->numBuffers; if (m->finfo.reserved[0] == 0x5444 && m->finfo.reserved[1] == 0x5055) { diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 64d24cf..72160a1 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -41,7 +41,12 @@ enum { GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL = GRALLOC_USAGE_PRIVATE_1, }; -#define NUM_BUFFERS 2 +/* numbers of max buffers for page flipping */ +#define NUM_FRAMEBUFFERS_MIN 2 +#define NUM_FRAMEBUFFERS_MAX 3 + +/* number of default bufers for page flipping */ +#define NUM_DEF_FRAME_BUFFERS 2 #define NO_SURFACEFLINGER_SWAPINTERVAL #define INTERLACE_MASK 0x80 #define S3D_FORMAT_MASK 0xFF000 @@ -175,11 +180,18 @@ struct qbuf_t { int idx; }; +enum buf_state { + SUB, + REF, + AVL +}; + struct avail_t { pthread_mutex_t lock; pthread_cond_t cond; #ifdef __cplusplus bool is_avail; + buf_state state; #endif }; @@ -204,7 +216,7 @@ struct private_module_t { Queue disp; // non-empty when buffer is ready for display #endif int currentIdx; - struct avail_t avail[NUM_BUFFERS]; + struct avail_t avail[NUM_FRAMEBUFFERS_MAX]; pthread_mutex_t qlock; pthread_cond_t qpost; From e03a345a1187024b5d8eb3d969f19a4a3a4381c3 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 10 Feb 2011 10:27:59 -0800 Subject: [PATCH 336/435] libgralloc-qsd8k: Flush the cache after buffer allocation Change-Id: Idb720b8c64b323216f77de834c83c328caccd6ef --- libgralloc-qsd8k/Android.mk | 2 +- libgralloc-qsd8k/pmemalloc.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index 2c32796..0d69b03 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -30,7 +30,7 @@ LOCAL_SRC_FILES := \ pmemalloc.cpp LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) -LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT))) LOCAL_CFLAGS += -DTARGET_MSM7x27 diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index ea30b2b..6604e25 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -181,7 +181,9 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, } else { LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); memset((char*)base + offset, 0, size); - //cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); +#ifdef HOST + cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); +#endif *pBase = base; *pOffset = offset; *pFd = fd; From 71a74457f12ced3d3ac06c5cac0a06ffe6522796 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Sat, 13 Nov 2010 12:31:17 +0530 Subject: [PATCH 337/435] overlay: Add support for flipping the source image Add support for source horizonal and vertical flipping in the overlay. Based on the final orientation and the flip information, set the correct rotation value for the MDP. Change-Id: Ie20022a8bf8f9725f01b4213b814cbe0af44625e --- liboverlay/overlayLib.cpp | 180 ++++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 67 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index a510c88..756fb12 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -85,6 +85,42 @@ static bool isRGBType(int format) { return false; } +static int get_mdp_orientation(int rotation, int flip) { + switch(flip) { + case HAL_TRANSFORM_FLIP_H: + switch(rotation) { + case 0: return MDP_FLIP_UD; + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); + case HAL_TRANSFORM_ROT_180: return MDP_FLIP_LR; + case HAL_TRANSFORM_ROT_270: return (MDP_ROT_90 | MDP_FLIP_UD); + default: return -1; + break; + } + break; + case HAL_TRANSFORM_FLIP_V: + switch(rotation) { + case 0: return MDP_FLIP_LR; + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); + case HAL_TRANSFORM_ROT_180: return MDP_FLIP_UD; + case HAL_TRANSFORM_ROT_270: return (MDP_ROT_90 | MDP_FLIP_LR); + default: return -1; + break; + } + break; + default: + switch(rotation) { + case 0: return MDP_ROT_NOP; + case HAL_TRANSFORM_ROT_90: return MDP_ROT_90; + case HAL_TRANSFORM_ROT_180: return MDP_ROT_180; + case HAL_TRANSFORM_ROT_270: return MDP_ROT_270; + default: return -1; + break; + } + break; + } + return -1; +} + #define LOG_TAG "OverlayLIB" static void reportError(const char* message) { LOGE( "%s", message); @@ -578,111 +614,121 @@ bool OverlayControlChannel::setParameter(int param, int value) { case OVERLAY_DITHER: break; case OVERLAY_TRANSFORM: - { - int val = mOVInfo.user_data[0]; - if (value && mNoRot) - return true; + { + int val = mOVInfo.user_data[0]; + if (value && mNoRot) + return true; - switch(value) { - case 0: - { - if (val == MDP_ROT_90) { + int rot = value; + int flip = 0; + if(value & HAL_TRANSFORM_FLIP_SRC_H) { + flip = HAL_TRANSFORM_FLIP_H; + } else if(value & HAL_TRANSFORM_FLIP_SRC_V) { + flip = HAL_TRANSFORM_FLIP_V; + } + rot = value & HAL_TRANSFORM_ROT_MASK; + + switch(rot) { + case 0: + { + if (val == MDP_ROT_90) { int tmp = mOVInfo.src_rect.y; mOVInfo.src_rect.y = mOVInfo.src.width - - (mOVInfo.src_rect.x + mOVInfo.src_rect.w); + (mOVInfo.src_rect.x + mOVInfo.src_rect.w); mOVInfo.src_rect.x = tmp; swapOVRotWidthHeight(); - } - else if (val == MDP_ROT_270) { + } + else if (val == MDP_ROT_270) { int tmp = mOVInfo.src_rect.x; mOVInfo.src_rect.x = mOVInfo.src.height - ( - mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.y + mOVInfo.src_rect.h); mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); - } - mOVInfo.user_data[0] = MDP_ROT_NOP; - break; - } - case OVERLAY_TRANSFORM_ROT_90: - { - if (val == MDP_ROT_270) { + } + break; + } + case OVERLAY_TRANSFORM_ROT_90: + { + if (val == MDP_ROT_270) { mOVInfo.src_rect.x = mOVInfo.src.width - ( - mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.x + mOVInfo.src_rect.w); mOVInfo.src_rect.y = mOVInfo.src.height - ( - mOVInfo.src_rect.y + mOVInfo.src_rect.h); - } - else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { + mOVInfo.src_rect.y + mOVInfo.src_rect.h); + } + else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { int tmp = mOVInfo.src_rect.x; mOVInfo.src_rect.x = mOVInfo.src.height - (mOVInfo.src_rect.y + mOVInfo.src_rect.h); mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); - } - mOVInfo.user_data[0] = MDP_ROT_90; - break; - } - case OVERLAY_TRANSFORM_ROT_180: - { - if (val == MDP_ROT_270) { + } + break; + } + case OVERLAY_TRANSFORM_ROT_180: + { + if (val == MDP_ROT_270) { int tmp = mOVInfo.src_rect.y; mOVInfo.src_rect.y = mOVInfo.src.width - (mOVInfo.src_rect.x + mOVInfo.src_rect.w); mOVInfo.src_rect.x = tmp; swapOVRotWidthHeight(); - } - else if (val == MDP_ROT_90) { + } + else if (val == MDP_ROT_90) { int tmp = mOVInfo.src_rect.x; mOVInfo.src_rect.x = mOVInfo.src.height - ( - mOVInfo.src_rect.y + mOVInfo.src_rect.h); + mOVInfo.src_rect.y + mOVInfo.src_rect.h); mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); - } - mOVInfo.user_data[0] = MDP_ROT_180; - break; - } - case OVERLAY_TRANSFORM_ROT_270: - { - if (val == MDP_ROT_90) { + } + break; + } + case OVERLAY_TRANSFORM_ROT_270: + { + if (val == MDP_ROT_90) { mOVInfo.src_rect.y = mOVInfo.src.height - (mOVInfo.src_rect.y + mOVInfo.src_rect.h); mOVInfo.src_rect.x = mOVInfo.src.width - (mOVInfo.src_rect.x + mOVInfo.src_rect.w); - } - else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { + } + else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { int tmp = mOVInfo.src_rect.y; mOVInfo.src_rect.y = mOVInfo.src.width - ( - mOVInfo.src_rect.x + mOVInfo.src_rect.w); + mOVInfo.src_rect.x + mOVInfo.src_rect.w); mOVInfo.src_rect.x = tmp; swapOVRotWidthHeight(); - } - - mOVInfo.user_data[0] = MDP_ROT_270; - break; - } - default: return false; - } - mRotInfo.rotations = mOVInfo.user_data[0]; - if (mOVInfo.user_data[0]) - mRotInfo.enable = 1; - else { - if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) - mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; - mRotInfo.enable = 0; + } + break; } - if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { - reportError("setParameter, rotator start failed"); - return false; - } + default: return false; + } + int mdp_format = get_mdp_orientation(rot, flip); + if(mdp_format == -1) + return false; - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { - reportError("setParameter, overlay set failed"); - return false; - } + mOVInfo.user_data[0] = mdp_format; + mRotInfo.rotations = mOVInfo.user_data[0]; + + if (mOVInfo.user_data[0]) + mRotInfo.enable = 1; + else { + if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) + mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; + mRotInfo.enable = 0; + } + if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { + reportError("setParameter, rotator start failed"); + return false; + } + + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + reportError("setParameter, overlay set failed"); + return false; + } break; - } + } default: reportError("Unsupproted param"); - return false; + return false; } return true; From 553c4b501fa92ea150db742b3e32512e535bc6fc Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Sat, 15 Jan 2011 13:44:54 -0800 Subject: [PATCH 338/435] overlay: Composition bypass changes This change adds following to Overlay class - is_fg, client could pass whether, FB need not be scaned. - RGBX_8888 format is now supported. - number of rotator buffers also could be passed which could be up to 3 Change-Id: I85519abc21e34642ef8f728948f1bd61f09a18cb --- liboverlay/overlayLib.cpp | 182 +++++++++++++++++++++++++++----------- liboverlay/overlayLib.h | 31 +++++-- 2 files changed, 153 insertions(+), 60 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 756fb12..c149269 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -29,6 +29,8 @@ static int get_mdp_format(int format) { return MDP_BGRA_8888; case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565; + case HAL_PIXEL_FORMAT_RGBX_8888: + return MDP_RGBX_8888; case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; case HAL_PIXEL_FORMAT_YCbCr_420_SP: @@ -48,6 +50,7 @@ static int get_size(int format, int w, int h) { switch (format) { case MDP_RGBA_8888: case MDP_BGRA_8888: + case MDP_RGBX_8888: size *= 4; break; case MDP_RGB_565: @@ -74,17 +77,6 @@ static int get_size(int format, int w, int h) { return size; } -static bool isRGBType(int format) { - switch (format) { - case MDP_RGBA_8888: - case MDP_BGRA_8888: - case MDP_RGBX_8888: - case MDP_RGB_565: - return true; - } - return false; -} - static int get_mdp_orientation(int rotation, int flip) { switch(flip) { case HAL_TRANSFORM_FLIP_H: @@ -121,6 +113,29 @@ static int get_mdp_orientation(int rotation, int flip) { return -1; } +static bool isRGBType(int format) { + switch (format) { + case MDP_RGBA_8888: + case MDP_BGRA_8888: + case MDP_RGBX_8888: + case MDP_RGB_565: + return true; + } + return false; +} + +static int getRGBBpp(int format) { + switch (format) { + case MDP_RGBA_8888: + case MDP_BGRA_8888: + case MDP_RGBX_8888: + return 4; + case MDP_RGB_565: + return 2; + } + return -1; +} + #define LOG_TAG "OverlayLIB" static void reportError(const char* message) { LOGE( "%s", message); @@ -128,7 +143,8 @@ static void reportError(const char* message) { using namespace overlay; -Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false) { +Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), + mCloseChannel(false) { } Overlay::~Overlay() { @@ -143,13 +159,18 @@ int Overlay::getFBHeight(int channel) const { return objOvCtrlChannel[channel].getFBHeight(); } -bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel, unsigned int format3D) { - mChannelUP = objOvCtrlChannel[0].startControlChannel(w, h, format, fbnum, norot, format3D); +bool Overlay::startChannel(int w, int h, int format, int fbnum, + bool norot, bool uichannel, + unsigned int format3D, bool ignoreFB, + int num_buffers) { + mChannelUP = objOvCtrlChannel[0].startControlChannel(w, h, format, fbnum, + norot, format3D, 0, ignoreFB); if (!mChannelUP) { LOGE("startChannel for fb0 failed"); return mChannelUP; } - return objOvDataChannel[0].startDataChannel(objOvCtrlChannel[0], fbnum, norot, uichannel); + return objOvDataChannel[0].startDataChannel(objOvCtrlChannel[0], fbnum, + norot, uichannel, num_buffers); } bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { @@ -184,7 +205,8 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { } bool Overlay::closeChannel() { - if (!mChannelUP) + + if (!mCloseChannel && !mChannelUP) return true; objOvCtrlChannel[0].closeControlChannel(); @@ -194,6 +216,7 @@ bool Overlay::closeChannel() { objOvDataChannel[1].closeDataChannel(); mChannelUP = false; + mCloseChannel = false; return true; } @@ -209,15 +232,26 @@ bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { return objOvCtrlChannel[0].setPosition(x, y, w, h); } -bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected) { - if ((hdmiConnected != mHDMIConnected) || !objOvCtrlChannel[0].setSource(w, h, format, orientation)) { +bool Overlay::setSource(uint32_t w, uint32_t h, int format, + int orientation, bool hdmiConnected, bool ignoreFB, int num_buffers) { + if (mCloseChannel) closeChannel(); - mChannelUP = false; + + if ((hdmiConnected != mHDMIConnected) + || !objOvCtrlChannel[0].setSource(w, h, format, + orientation, ignoreFB)) { + if (mChannelUP) { + mCloseChannel = true; + return false; + } mHDMIConnected = hdmiConnected; + int hw_format = get_mdp_format(format); + bool uichannel = isRGBType(hw_format); if (mHDMIConnected) { return startChannelHDMI(w, h, format, !orientation); } else { - return startChannel(w, h, format, 0, !orientation); + return startChannel(w, h, format, 0, !orientation, + uichannel, 0, ignoreFB, num_buffers); } } else @@ -371,7 +405,8 @@ bool OverlayControlChannel::openDevices(int fbnum) { } bool OverlayControlChannel::setOverlayInformation(int w, int h, - int format, int flags, int zorder) { + int format, int flags, int zorder, + bool ignoreFB) { int origW, origH, xoff, yoff; mOVInfo.id = MSMFB_NEW_REQUEST; @@ -411,10 +446,12 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; mOVInfo.flags = flags; + if (isRGBType(format)) + mOVInfo.is_fg = ignoreFB; + if (ignoreFB && isRGBType(format) && getRGBBpp(format) == 4) + mOVInfo.flags &= ~MDP_OV_PIPE_SHARE; if (!isRGBType(format)) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; - - mOVInfo.is_fg = 0; mSize = get_size(format, w, h); return true; } @@ -422,14 +459,12 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, bool OverlayControlChannel::startOVRotatorSessions(int w, int h, int format) { bool ret = true; - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { - reportError("startOVRotatorSessions, Overlay set failed"); - ret = false; - } - else if (mNoRot) - return true; - if (ret) { + if (!mNoRot) { + if (isRGBType(format) && mOVInfo.is_fg) { + w = (w + 31) & ~31; + h = (h + 31) & ~31; + } mRotInfo.src.format = format; mRotInfo.src.width = w; mRotInfo.src.height = h; @@ -460,18 +495,32 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, reportError("Rotator session failed"); ret = false; } - else - return ret; } - closeControlChannel(); + if (!mNoRot && isRGBType(format) && mOrientation && mOVInfo.is_fg) { + mOVInfo.dst_rect.w = mFBWidth; + mOVInfo.dst_rect.h = mFBHeight; + ret = setParameter(OVERLAY_TRANSFORM, mOrientation, false); + if (!ret) { + reportError("Overlay set failed.. "); + return false; + } + } + else if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + reportError("startOVRotatorSessions, Overlay set failed"); + ret = false; + } + + if (!ret) + closeControlChannel(); return ret; } bool OverlayControlChannel::startControlChannel(int w, int h, int format, int fbnum, bool norot, - unsigned int format3D, int zorder) { + unsigned int format3D, int zorder, + bool ignoreFB) { mNoRot = norot; fb_fix_screeninfo finfo; fb_var_screeninfo vinfo; @@ -498,7 +547,7 @@ bool OverlayControlChannel::startControlChannel(int w, int h, if (!openDevices(fbnum)) return false; - if (!setOverlayInformation(w, h, hw_format, flags, zorder)) + if (!setOverlayInformation(w, h, hw_format, flags, zorder, ignoreFB)) return false; return startOVRotatorSessions(w, h, hw_format); @@ -524,10 +573,12 @@ bool OverlayControlChannel::closeControlChannel() { return true; } -bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format, int orientation) { +bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, + int format, int orientation, bool ignoreFB) { format = get_mdp_format(format); - if ((orientation == mOrientation) && ((orientation == MDP_ROT_90) - || (orientation == MDP_ROT_270))) { + if ((orientation == mOrientation) + && ((orientation == OVERLAY_TRANSFORM_ROT_90) + || (orientation == OVERLAY_TRANSFORM_ROT_270))) { if (format == MDP_Y_CRCB_H2V2_TILE) { format = MDP_Y_CRCB_H2V2; w = (((w-1)/64 +1)*64); @@ -538,8 +589,21 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format, int or h = tmp; } if (w == mOVInfo.src.width && h == mOVInfo.src.height - && format == mOVInfo.src.format && orientation == mOrientation) + && format == mOVInfo.src.format && orientation == mOrientation) { + if (!isRGBType(format)) + return true; + if (ignoreFB == mOVInfo.is_fg) + return true; + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) + return false; + mOVInfo = ov; + mOVInfo.is_fg = ignoreFB; + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) + return false; return true; + } mOrientation = orientation; return false; } @@ -598,13 +662,12 @@ void OverlayControlChannel::swapOVRotWidthHeight() { mRotInfo.dst.height = tmp; } -bool OverlayControlChannel::setParameter(int param, int value) { +bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { if (!isChannelUP()) return false; - mdp_overlay ov; - ov.id = mOVInfo.id; - if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + mdp_overlay ov = mOVInfo; + if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { reportError("setParameter, overlay GET failed"); return false; } @@ -799,7 +862,7 @@ OverlayDataChannel::~OverlayDataChannel() { bool OverlayDataChannel::startDataChannel( const OverlayControlChannel& objOvCtrlChannel, - int fbnum, bool norot, bool uichannel) { + int fbnum, bool norot, bool uichannel, int num_buffers) { int ovid, rotid, size; mNoRot = norot; memset(&mOvData, 0, sizeof(mOvData)); @@ -808,13 +871,14 @@ bool OverlayDataChannel::startDataChannel( if (objOvCtrlChannel.getOvSessionID(ovid) && objOvCtrlChannel.getRotSessionID(rotid) && objOvCtrlChannel.getSize(size)) { - return startDataChannel(ovid, rotid, size, fbnum, norot, uichannel); + return startDataChannel(ovid, rotid, size, fbnum, + norot, uichannel, num_buffers); } else return false; } -bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) { +bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) { if (fbnum < 0) return false; char const * const device_template = @@ -841,7 +905,7 @@ bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) { if(!uichannel) { mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC); if(mPmemFD >= 0) - mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE, + mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, MAP_SHARED, mPmemFD, 0); } @@ -855,7 +919,7 @@ bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) { mRotFD = -1; return false; } else { - mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE, + mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, MAP_SHARED, mPmemFD, 0); if (mPmemAddr == MAP_FAILED) { reportError("Cant map pmem_adsp "); @@ -873,13 +937,18 @@ bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) { mOvDataRot.data.memory_id = mPmemFD; mRotData.dst.memory_id = mPmemFD; mRotData.dst.offset = 0; + mNumBuffers = num_buffers; + mCurrentItem = 0; + for (int i = 0; i < num_buffers; i++) + mRotOffset[i] = i * mPmemOffset; } return true; } bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size, - int fbnum, bool norot, bool uichannel) { + int fbnum, bool norot, + bool uichannel, int num_buffers) { memset(&mOvData, 0, sizeof(mOvData)); memset(&mOvDataRot, 0, sizeof(mOvDataRot)); memset(&mRotData, 0, sizeof(mRotData)); @@ -889,8 +958,10 @@ bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size, mOvDataRot = mOvData; mPmemOffset = size; mRotData.session_id = rotid; + mNumBuffers = 0; + mCurrentItem = 0; - return openDevices(fbnum, uichannel); + return openDevices(fbnum, uichannel, num_buffers); } bool OverlayDataChannel::closeDataChannel() { @@ -898,7 +969,7 @@ bool OverlayDataChannel::closeDataChannel() { return true; if (!mNoRot && mRotFD > 0) { - munmap(mPmemAddr, mPmemOffset * 2); + munmap(mPmemAddr, mPmemOffset * mNumBuffers); close(mPmemFD); mPmemFD = -1; close(mRotFD); @@ -910,6 +981,9 @@ bool OverlayDataChannel::closeDataChannel() { memset(&mOvDataRot, 0, sizeof(mOvDataRot)); memset(&mRotData, 0, sizeof(mRotData)); + mNumBuffers = 0; + mCurrentItem = 0; + return true; } @@ -932,6 +1006,8 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { mRotData.src.memory_id = mOvData.data.memory_id; mRotData.src.offset = offset; mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset; + mRotData.dst.offset = mRotOffset[mCurrentItem]; + mCurrentItem = (mCurrentItem + 1) % mNumBuffers; int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_ROTATE, &mRotData); @@ -940,6 +1016,10 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; odPtr = &mOvDataRot; } + else if (max_num_buffers == mNumBuffers) { + reportError("Rotator failed.."); + return false; + } } if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 544ba3b..09d5a11 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -70,6 +70,7 @@ namespace overlay { +const int max_num_buffers = 3; struct overlay_rect { int x; int y; @@ -94,7 +95,8 @@ class OverlayControlChannel { mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; bool openDevices(int fbnum = -1); - bool setOverlayInformation(int w, int h, int format, int flags, int zorder = 0); + bool setOverlayInformation(int w, int h, int format, + int flags, int zorder = 0, bool ignoreFB = false); bool startOVRotatorSessions(int w, int h, int format); void swapOVRotWidthHeight(); @@ -103,10 +105,11 @@ public: ~OverlayControlChannel(); bool startControlChannel(int w, int h, int format, int fbnum, bool norot = false, - unsigned int format3D = 0, int zorder = 0); + 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 setParameter(int param, int value, bool fetch = true); bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h); bool getOvSessionID(int& sessionID) const; bool getRotSessionID(int& sessionID) const; @@ -116,7 +119,8 @@ public: int getFBHeight() const { return mFBHeight; } int getFormat3D() const { return mFormat3D; } bool getOrientation(int& orientation) const; - bool setSource(uint32_t w, uint32_t h, int format, int orientation); + bool setSource(uint32_t w, uint32_t h, int format, + int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); }; @@ -131,16 +135,21 @@ class OverlayDataChannel { msmfb_overlay_data mOvData; msmfb_overlay_data mOvDataRot; msm_rotator_data_info mRotData; + int mRotOffset[max_num_buffers]; + int mCurrentItem; + int mNumBuffers; - bool openDevices(int fbnum = -1, bool uichannel = false); + bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2); public: OverlayDataChannel(); ~OverlayDataChannel(); bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel, - int fbnum, bool norot = false, bool uichannel = false); + 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 fbnum, bool norot = false, bool uichannel = false, + int num_buffers = 2); bool closeDataChannel(); bool setFd(int fd); bool queueBuffer(uint32_t offset); @@ -156,6 +165,7 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; + bool mCloseChannel; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -165,7 +175,8 @@ public: ~Overlay(); bool startChannel(int w, int h, int format, int fbnum, bool norot = false, - bool uichannel = false, unsigned int format3D = 0); + bool uichannel = false, unsigned int format3D = 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); @@ -178,7 +189,9 @@ public: int getFBHeight(int channel = 0) const; bool getOrientation(int& orientation) const; bool queueBuffer(buffer_handle_t buffer); - bool setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected); + bool setSource(uint32_t w, uint32_t h, int format, + int orientation, bool hdmiConnected, + bool ignoreFB = false, int numBuffers = 2); bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h); private: From 67b9bd9154d6e9bf9d2672069ea212c3b2b944aa Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 11 Feb 2011 21:25:14 -0800 Subject: [PATCH 339/435] liboverlay: Set MDP_OV_PLAY_NOWAIT flag in overlay Set the MDP_OV_PLAY_NOWAIT flag when there is a UI update during video playback Change-Id: I0e71087a879fceaaab204bbd3acabcaaad676fe3 --- liboverlay/overlay.cpp | 2 +- liboverlay/overlayLib.cpp | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 96daca0..e30e107 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -174,7 +174,7 @@ public: } bool ret = mHandle.pobjControlChannel[index]->startControlChannel( mHandle.w, mHandle.h, mHandle.format, fbnum, norot, - format3D, zorder); + format3D, zorder, true); if (ret) { if (!(mHandle.pobjControlChannel[index]-> getOvSessionID(mHandle.ovid[index]) && diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index c149269..9a794c4 100755 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -240,12 +240,13 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, if ((hdmiConnected != mHDMIConnected) || !objOvCtrlChannel[0].setSource(w, h, format, orientation, ignoreFB)) { - if (mChannelUP) { + int hw_format = get_mdp_format(format); + if (mChannelUP && isRGBType(hw_format)) { mCloseChannel = true; return false; } + closeChannel(); mHDMIConnected = hdmiConnected; - int hw_format = get_mdp_format(format); bool uichannel = isRGBType(hw_format); if (mHDMIConnected) { return startChannelHDMI(w, h, format, !orientation); @@ -450,7 +451,7 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.is_fg = ignoreFB; if (ignoreFB && isRGBType(format) && getRGBBpp(format) == 4) mOVInfo.flags &= ~MDP_OV_PIPE_SHARE; - if (!isRGBType(format)) + if (!ignoreFB) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; mSize = get_size(format, w, h); return true; @@ -590,16 +591,23 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, } if (w == mOVInfo.src.width && h == mOVInfo.src.height && format == mOVInfo.src.format && orientation == mOrientation) { - if (!isRGBType(format)) - return true; - if (ignoreFB == mOVInfo.is_fg) + if ((ignoreFB == mOVInfo.is_fg) && isRGBType(format)) return true; mdp_overlay ov; ov.id = mOVInfo.id; if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) return false; mOVInfo = ov; - mOVInfo.is_fg = ignoreFB; + + if (isRGBType(format)) + mOVInfo.is_fg = ignoreFB; + + if (!isRGBType(format)) { + if (!ignoreFB) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + else + mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; + } if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) return false; return true; From 8bd9729c721c7e69762c656afe6d2092a68172bf Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 27 Jan 2011 22:07:16 -0800 Subject: [PATCH 340/435] overlay: Add S3D support over HDMI in the overlayLib Change-Id: I1f650237f2de414fe248d4281ce22344049d2956 --- liboverlay/overlay.cpp | 2 +- liboverlay/overlayLib.cpp | 341 ++++++++++++++++++++++++++++++-------- liboverlay/overlayLib.h | 28 +++- 3 files changed, 292 insertions(+), 79 deletions(-) mode change 100755 => 100644 liboverlay/overlayLib.cpp diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index e30e107..f97827d 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -842,7 +842,7 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - bool ret; + bool ret = false; // for the 3D usecase extract L and R channels from a frame if(ctx->format3D) { if ((ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp old mode 100755 new mode 100644 index 9a794c4..647fbdb --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -52,15 +52,15 @@ static int get_size(int format, int w, int h) { case MDP_BGRA_8888: case MDP_RGBX_8888: size *= 4; - break; + break; case MDP_RGB_565: case MDP_Y_CBCR_H2V1: size *= 2; - break; + break; case MDP_Y_CBCR_H2V2: case MDP_Y_CRCB_H2V2: size = (size * 3) / 2; - break; + break; case MDP_Y_CRCB_H2V2_TILE: aligned_height = (h + 31) & ~31; pitch = (w + 127) & ~127; @@ -70,7 +70,7 @@ static int get_size(int format, int w, int h) { aligned_height = ((h >> 1) + 31) & ~31; size += pitch * aligned_height; size = (size + 8191) & ~8191; - break; + break; default: return 0; } @@ -144,7 +144,7 @@ static void reportError(const char* message) { using namespace overlay; Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mCloseChannel(false) { + mCloseChannel(false), mS3DFormat(0) { } Overlay::~Overlay() { @@ -161,98 +161,171 @@ int Overlay::getFBHeight(int channel) const { bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel, - unsigned int format3D, bool ignoreFB, - int num_buffers) { - mChannelUP = objOvCtrlChannel[0].startControlChannel(w, h, format, fbnum, - norot, format3D, 0, ignoreFB); + unsigned int format3D, int channel, + bool ignoreFB, int num_buffers) { + int zorder = 0; + if (format3D) + zorder = channel; + mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, + norot, format3D, zorder, ignoreFB); if (!mChannelUP) { - LOGE("startChannel for fb0 failed"); + LOGE("startChannel for fb%d failed", fbnum); return mChannelUP; } - return objOvDataChannel[0].startDataChannel(objOvCtrlChannel[0], fbnum, + return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum, norot, uichannel, num_buffers); } bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { - if(!mHDMIConnected) { - LOGE(" HDMI has been disabled - close the channel"); - objOvCtrlChannel[1].closeControlChannel(); - objOvDataChannel[1].closeDataChannel(); - return true; - } - bool ret = startChannel(w, h, format, 0, norot); + bool ret = startChannel(w, h, format, FRAMEBUFFER_0, norot); if(ret) { - if (!objOvCtrlChannel[1].startControlChannel(w, h, format, 1, 1)) { - LOGE("Failed to start control channel for framebuffer 1"); - objOvCtrlChannel[1].closeControlChannel(); - return false; - } else { - if(!objOvDataChannel[1].startDataChannel(objOvCtrlChannel[1], 1, 1)) { - LOGE("Failed to start data channel for framebuffer 1"); + ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); + overlay_rect rect; + if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, format, &rect)) { + if(!setChannelPosition(rect.x, rect.y, rect.width, rect.height, VG1_PIPE)) { + LOGE("Failed to upscale for framebuffer 1"); return false; } - overlay_rect rect; - if(objOvCtrlChannel[1].getAspectRatioPosition(w, h, format, &rect)) { - if(!objOvCtrlChannel[1].setPosition(rect.x, rect.y, rect.width, rect.height)) { - LOGE("Failed to upscale for framebuffer 1"); - return false; - } - } } } return ret; } +bool Overlay::startChannelS3D(int w, int h, int format, bool norot, int s3DFormat) { + + if (!mHDMIConnected) { + // S3D without HDMI is not supported yet + return true; + } + // Start both the channels for the S3D content + bool ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); + if (ret) { + ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); + } + if (ret) { + FILE *fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", mS3DFormat & OUTPUT_MASK_3D); + fclose(fp); + fp = NULL; + } + } + + if (!ret) { + closeChannel(); + } + return ret; +} + bool Overlay::closeChannel() { if (!mCloseChannel && !mChannelUP) return true; - objOvCtrlChannel[0].closeControlChannel(); - objOvDataChannel[0].closeDataChannel(); - - objOvCtrlChannel[1].closeControlChannel(); - objOvDataChannel[1].closeDataChannel(); - + if(mS3DFormat) { + FILE *fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "0"); + fclose(fp); + fp = NULL; + } + } + for (int i = 0; i < NUM_CHANNELS; i++) { + objOvCtrlChannel[i].closeControlChannel(); + objOvDataChannel[i].closeDataChannel(); + } mChannelUP = false; mCloseChannel = false; + mHDMIConnected = false; + mS3DFormat = 0; return true; } -bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h) { - return objOvCtrlChannel[0].getPosition(x, y, w, h); +bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel) { + return objOvCtrlChannel[channel].getPosition(x, y, w, h); } -bool Overlay::getOrientation(int& orientation) const { - return objOvCtrlChannel[0].getOrientation(orientation); +bool Overlay::getOrientation(int& orientation, int channel) const { + return objOvCtrlChannel[channel].getOrientation(orientation); } bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { - return objOvCtrlChannel[0].setPosition(x, y, w, h); + if(mS3DFormat && mHDMIConnected) { + return setPositionS3D(x, y, w, h); + } else { + return setChannelPosition(x, y, w, h, VG0_PIPE); + } } -bool Overlay::setSource(uint32_t w, uint32_t h, int format, - int orientation, bool hdmiConnected, bool ignoreFB, int num_buffers) { +bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) { + return objOvCtrlChannel[channel].setPosition(x, y, w, h); +} + +bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { + bool ret = false; + + for (int i = 0; i < NUM_CHANNELS; i++) { + overlay_rect rect; + ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); + if (ret) { + setChannelPosition(rect.x, rect.y, rect.width, rect.height, i); + } + } + return ret; +} + +bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, + bool hdmiConnected, bool ignoreFB, int num_buffers) { if (mCloseChannel) closeChannel(); - if ((hdmiConnected != mHDMIConnected) - || !objOvCtrlChannel[0].setSource(w, h, format, - orientation, ignoreFB)) { - int hw_format = get_mdp_format(format); - if (mChannelUP && isRGBType(hw_format)) { + // Separate the color format from the 3D format. + // If there is 3D content; the effective format passed by the client is: + // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + unsigned int format3D = FORMAT_3D(format); + int colorFormat = COLOR_FORMAT(format); + int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format + int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format + format3D = fIn3D | fOut3D; + // Use the same in/out format if not mentioned + if (!fIn3D) { + format3D |= fOut3D << SHIFT_3D; //Set the input format + } + if (!fOut3D) { + format3D |= fIn3D >> SHIFT_3D; //Set the output format + } + + int stateChanged = 0; + int hw_format = get_mdp_format(colorFormat); + bool uichannel = isRGBType(hw_format); + int s3dChanged =0, hdmiChanged = 0; + + if (format3D != mS3DFormat) + s3dChanged = 0x10; + if (hdmiConnected != mHDMIConnected) + hdmiChanged = 0x1; + + stateChanged = s3dChanged|hdmiChanged; + if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { + if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) { mCloseChannel = true; return false; } closeChannel(); mHDMIConnected = hdmiConnected; - bool uichannel = isRGBType(hw_format); + mS3DFormat = format3D; + if (mHDMIConnected) { - return startChannelHDMI(w, h, format, !orientation); + if (format3D) { + // Start both the VG pipes + return startChannelS3D(w, h, colorFormat, !orientation, format3D); + } else { + return startChannelHDMI(w, h, colorFormat, !orientation); + } } else { - return startChannel(w, h, format, 0, !orientation, - uichannel, 0, ignoreFB, num_buffers); + return startChannel(w, h, colorFormat, 0, !orientation, + uichannel, 0, ignoreFB, num_buffers); } } else @@ -262,26 +335,61 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!mChannelUP) return false; - if(mHDMIConnected) { - objOvDataChannel[1].setCrop(x, y, w, h); + bool ret; + + if (mHDMIConnected) { + if (mS3DFormat) { + overlay_rect rect; + overlay_rect inRect; + inRect.x = x; inRect.y = y; inRect.width = w; inRect.height = h; + + // Set the crop for both VG pipes + for (int i = 0; i < NUM_CHANNELS; i++) { + objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect); + ret = setChannelCrop(rect.x, rect.y, rect.width, rect.height, i); + } + return ret; + } else { + setChannelCrop(x, y, w, h, VG1_PIPE); } - return objOvDataChannel[0].setCrop(x, y, w, h); + } + return setChannelCrop(x, y, w, h, VG0_PIPE); +} + +bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel) { + return objOvDataChannel[channel].setCrop(x, y, w, h); } bool Overlay::setParameter(int param, int value) { - return objOvCtrlChannel[0].setParameter(param, value); + if (mS3DFormat && mHDMIConnected) + return setParameterS3D(param, value); + else { + return objOvCtrlChannel[VG0_PIPE].setParameter(param, value); + } } -bool Overlay::setOrientation(int value) { - return objOvCtrlChannel[0].setParameter(OVERLAY_TRANSFORM, value); +bool Overlay::setParameterS3D(int param, int value) { + bool ret = false; + if (mHDMIConnected) { + // Set the S3D parameter for both VG pipes + ret = objOvCtrlChannel[VG0_PIPE].setParameter(param, value); + if (ret) + ret = objOvCtrlChannel[VG1_PIPE].setParameter(param, value); + } + + return ret; } -bool Overlay::setFd(int fd) { - return objOvDataChannel[0].setFd(fd); +bool Overlay::setOrientation(int value, int channel) { + return objOvCtrlChannel[channel].setParameter(OVERLAY_TRANSFORM, value); } -bool Overlay::queueBuffer(uint32_t offset) { - return objOvDataChannel[0].queueBuffer(offset); +bool Overlay::setFd(int fd, int channel) { + return objOvDataChannel[channel].setFd(fd); +} + +bool Overlay::queueBuffer(uint32_t offset, int channel) { + return objOvDataChannel[channel].queueBuffer(offset); } bool Overlay::queueBuffer(buffer_handle_t buffer) { @@ -291,13 +399,16 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { const int fd = hnd->fd; bool ret = true; - if(mHDMIConnected) { - ret = objOvDataChannel[1].setFd(fd); - if(!ret) { - reportError("Overlay::queueBuffer channel 1 setFd failed"); - return false; + if (mHDMIConnected) { + if (mS3DFormat) { + // Queue the buffer on VG1 pipe + if ((mS3DFormat & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || + (mS3DFormat & HAL_3D_OUT_TOP_BOTTOM_MASK)) { + ret = queueBuffer(fd, offset, VG1_PIPE); + } + } else { + ret = queueBuffer(fd, offset, VG1_PIPE); } - ret = objOvDataChannel[1].queueBuffer(offset); } if (ret && setFd(fd)) { return queueBuffer(offset); @@ -305,6 +416,21 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { return false; } +bool Overlay::queueBuffer(int fd, uint32_t offset, int channel) { + bool ret = false; + ret = setFd(fd, channel); + if(!ret) { + LOGE("Overlay::queueBuffer channel %d setFd failed", channel); + return false; + } + ret = queueBuffer(offset, channel); + if(!ret) { + LOGE("Overlay::queueBuffer channel %d queueBuffer failed", channel); + return false; + } + return ret; +} + OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1), mFormat3D(0) { memset(&mOVInfo, 0, sizeof(mOVInfo)); memset(&mRotInfo, 0, sizeof(mRotInfo)); @@ -357,6 +483,43 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove return true; } +bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) { + int wHDMI = getFBWidth(); + int hHDMI = getFBHeight(); + + if (format & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { + if (channel == VG0_PIPE) { + rect->x = 0; + rect->y = 0; + rect->width = wHDMI/2; + rect->height = hHDMI; + } else { + rect->x = wHDMI/2; + rect->y = 0; + rect->width = wHDMI/2; + rect->height = hHDMI; + } + } else if (format & HAL_3D_OUT_TOP_BOTTOM_MASK) { + if (channel == VG0_PIPE) { + rect->x = 0; + rect->y = 0; + rect->width = wHDMI; + rect->height = hHDMI/2; + } else { + rect->x = 0; + rect->y = hHDMI/2; + rect->width = wHDMI; + rect->height = hHDMI/2; + } + } else if (format & HAL_3D_OUT_INTERLEAVE_MASK) { + //TBD + } else if (format & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { + //TBD + } else { + reportError("Unsupported 3D output format"); + } + return true; +} bool OverlayControlChannel::openDevices(int fbnum) { if (fbnum < 0) return false; @@ -577,7 +740,7 @@ bool OverlayControlChannel::closeControlChannel() { bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format, int orientation, bool ignoreFB) { format = get_mdp_format(format); - if ((orientation == mOrientation) + if ((orientation == mOrientation) && ((orientation == OVERLAY_TRANSFORM_ROT_90) || (orientation == OVERLAY_TRANSFORM_ROT_270))) { if (format == MDP_Y_CRCB_H2V2_TILE) { @@ -1038,6 +1201,42 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { return true; } +bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format, + overlay_rect *rect) { + + bool ret; + // for the 3D usecase extract L and R channels from a frame + if ( (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || + (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) ) { + if(channel == 0) { + rect->x = 0; + rect->y = 0; + rect->width = inRect->width/2; + rect->height = inRect->height; + } else { + rect->x = inRect->width/2; + rect->y = 0; + rect->width = inRect->width/2; + rect->height = inRect->height; + } + } else if (format & HAL_3D_IN_TOP_BOTTOM) { + if(channel == 0) { + rect->x = 0; + rect->y = 0; + rect->width = inRect->width; + rect->height = inRect->height/2; + } else { + rect->x = 0; + rect->y = inRect->height/2; + rect->width = inRect->width; + rect->height = inRect->height/2; + } + } else if (format & HAL_3D_IN_INTERLEAVE) { + //TBD + } + return true; +} + bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!isChannelUP()) { reportError("Channel not set"); diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 09d5a11..fed1d59 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -45,7 +45,11 @@ #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 /* ------------------------------- 3D defines ---------------------------------------*/ // The compound format passed to the overlay is // ABCCC where A is the input 3D format, @@ -122,6 +126,7 @@ public: bool setSource(uint32_t w, uint32_t h, int format, int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); + bool getPositionS3D(int channel, int format, overlay_rect *rect); }; class OverlayDataChannel { @@ -154,6 +159,7 @@ public: 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); } }; @@ -165,6 +171,7 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; + int mS3DFormat; bool mCloseChannel; OverlayControlChannel objOvCtrlChannel[2]; @@ -176,18 +183,19 @@ public: bool startChannel(int w, int h, int format, int fbnum, bool norot = false, bool uichannel = false, unsigned int format3D = 0, - bool ignoreFB = false, int num_buffers = 2); + 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); - bool setFd(int fd); - bool queueBuffer(uint32_t offset); - bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h); + 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) const; + bool getOrientation(int& orientation, int channel = 0) const; bool queueBuffer(buffer_handle_t buffer); bool setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected, @@ -196,6 +204,12 @@ public: private: bool startChannelHDMI(int w, int h, int format, bool norot); + bool startChannelS3D(int w, int h, int format, bool norot, int s3DFormat); + bool setPositionS3D(int x, int y, uint32_t w, uint32_t h); + bool setParameterS3D(int param, int value); + 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); }; struct overlay_shared_data { From c096d185f1a0af161465d24f4055dc3de6df3c57 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Feb 2011 14:00:08 -0800 Subject: [PATCH 341/435] overlayLib: Add support for flipping the source When the FLIP_H is passed, the overlay needs to flip the image along the vertical axis and similarly when the FLIP_V is passed, the flip needs to happen along the horizontal axis Change-Id: Iae31a1ca266e7e0bb9e598c88cb0728f35028052 --- liboverlay/overlayLib.cpp | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 647fbdb..9f4f1fe 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -79,22 +79,18 @@ static int get_size(int format, int w, int h) { static int get_mdp_orientation(int rotation, int flip) { switch(flip) { - case HAL_TRANSFORM_FLIP_H: + case HAL_TRANSFORM_FLIP_V: switch(rotation) { case 0: return MDP_FLIP_UD; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); - case HAL_TRANSFORM_ROT_180: return MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_270: return (MDP_ROT_90 | MDP_FLIP_UD); + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); default: return -1; break; } break; - case HAL_TRANSFORM_FLIP_V: + case HAL_TRANSFORM_FLIP_H: switch(rotation) { case 0: return MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); - case HAL_TRANSFORM_ROT_180: return MDP_FLIP_UD; - case HAL_TRANSFORM_ROT_270: return (MDP_ROT_90 | MDP_FLIP_LR); + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); default: return -1; break; } @@ -855,15 +851,11 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { int rot = value; int flip = 0; - if(value & HAL_TRANSFORM_FLIP_SRC_H) { - flip = HAL_TRANSFORM_FLIP_H; - } else if(value & HAL_TRANSFORM_FLIP_SRC_V) { - flip = HAL_TRANSFORM_FLIP_V; - } - rot = value & HAL_TRANSFORM_ROT_MASK; switch(rot) { case 0: + case HAL_TRANSFORM_FLIP_H: + case HAL_TRANSFORM_FLIP_V: { if (val == MDP_ROT_90) { int tmp = mOVInfo.src_rect.y; @@ -879,9 +871,13 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); } + rot = 0; + flip = value & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; } - case OVERLAY_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_90: + case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H): + case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): { if (val == MDP_ROT_270) { mOVInfo.src_rect.x = mOVInfo.src.width - ( @@ -896,9 +892,11 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); } + rot = HAL_TRANSFORM_ROT_90; + flip = value & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; } - case OVERLAY_TRANSFORM_ROT_180: + case HAL_TRANSFORM_ROT_180: { if (val == MDP_ROT_270) { int tmp = mOVInfo.src_rect.y; @@ -916,7 +914,7 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { } break; } - case OVERLAY_TRANSFORM_ROT_270: + case HAL_TRANSFORM_ROT_270: { if (val == MDP_ROT_90) { mOVInfo.src_rect.y = mOVInfo.src.height - @@ -935,11 +933,11 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { } default: return false; } - int mdp_format = get_mdp_orientation(rot, flip); - if(mdp_format == -1) + int mdp_rotation = get_mdp_orientation(rot, flip); + if (mdp_rotation == -1) return false; - mOVInfo.user_data[0] = mdp_format; + mOVInfo.user_data[0] = mdp_rotation; mRotInfo.rotations = mOVInfo.user_data[0]; if (mOVInfo.user_data[0]) From 5abeb9b1ea0a32739dbe7557b4a900fc4671ccbe Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Mon, 14 Feb 2011 14:14:12 -0800 Subject: [PATCH 342/435] liboverlay: Calculate x and y values in setCrop on 180 degree rotation This change calculates x and y values based on setcrop parameters and current overlay values on 180 degree rotation. CRs-Fixed: 274707 Change-Id: Ibfe20c1a53e832424a880d99e73bd4a1c7b95173 --- liboverlay/overlayLib.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 9f4f1fe..ec727fd 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1272,6 +1272,14 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) w = h; h = tmp; } + else if(ov.user_data[0] == MDP_ROT_180) { + if ((ov.src.height < (y + h)) || (ov.src.width < ( x + w))) + return false; + + x = ov.src.width - (x + w); + y = ov.src.height - (y + h); + } + if ((ov.src_rect.x == x) && (ov.src_rect.y == y) && From 7e948c3238dd08b15ad0bbba81c69a68ea507dad Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Tue, 22 Feb 2011 18:06:22 -0800 Subject: [PATCH 343/435] overlay: Update startChannel function call startChannel function prototype has changed. One of the places it uses old signature, update it with new signature. Change-Id: Id0510187ffa13d7d750ad101030649134353b14b --- liboverlay/overlayLib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index ec727fd..73ea4fc 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * 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. @@ -321,7 +321,7 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, } } else { return startChannel(w, h, colorFormat, 0, !orientation, - uichannel, 0, ignoreFB, num_buffers); + uichannel, 0, VG0_PIPE, ignoreFB, num_buffers); } } else From 1c9191bda5da1b5f409ceefd8fe09c1203cac8b9 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Tue, 22 Feb 2011 19:32:26 -0800 Subject: [PATCH 344/435] liboverlay: Use rotator during video on MDDI panel Always use rotator on the MDDI panel, irrespective of rotation. CRs-fixed: 271109 Change-Id: Ief0a7d3fc1bd3254ef50931cf7ee5c5bf02dfdee --- liboverlay/overlayLib.cpp | 57 ++++++++++++++++++++++++++++++++------- liboverlay/overlayLib.h | 4 ++- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 73ea4fc..0d35e9b 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -19,6 +19,9 @@ #include "gralloc_priv.h" #define INTERLACE_MASK 0x80 +#define FBDEV_0 "/dev/graphics/fb0" +#define FBDEV_LEN strlen("msmfbXX_") +#define MDDI_PANEL '1' /* Helper functions */ static int get_mdp_format(int format) { @@ -140,7 +143,23 @@ static void reportError(const char* message) { using namespace overlay; Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mCloseChannel(false), mS3DFormat(0) { + mCloseChannel(false), mS3DFormat(0), mRotate(false) { + fb_fix_screeninfo finfo; + memset(&finfo, 0, sizeof(finfo)); + int fd = open(FBDEV_0, O_RDWR, 0); + if (fd < 0) { + reportError("Cant open framebuffer "); + return; + } else { + if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + reportError("FBIOGET_FSCREENINFO on fb0 failed"); + close(fd); + return; + } + if((finfo.id)[FBDEV_LEN] == MDDI_PANEL) + mRotate = true; + close(fd); + } } Overlay::~Overlay() { @@ -160,6 +179,9 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; + if( mRotate) + norot = 0; + if (format3D) zorder = channel; mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, @@ -303,7 +325,7 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, hdmiChanged = 0x1; stateChanged = s3dChanged|hdmiChanged; - if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { + if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB, mRotate)) { if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) { mCloseChannel = true; return false; @@ -539,6 +561,8 @@ bool OverlayControlChannel::openDevices(int fbnum) { return false; } + mFBPanelType = finfo.id[FBDEV_LEN]; + fb_var_screeninfo vinfo; if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) { reportError("FBIOGET_VSCREENINFO on fb1 failed"); @@ -648,7 +672,10 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, mRotInfo.src_rect.x = 0; mRotInfo.src_rect.y = 0; mRotInfo.rotations = 0; - mRotInfo.enable = 0; + if(mFBPanelType == MDDI_PANEL) + mRotInfo.enable = 1; + else + mRotInfo.enable = 0; mRotInfo.session_id = 0; int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); if (result) { @@ -734,19 +761,26 @@ bool OverlayControlChannel::closeControlChannel() { } bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, - int format, int orientation, bool ignoreFB) { + int format, int orientation, bool ignoreFB, bool useRot) { format = get_mdp_format(format); - if ((orientation == mOrientation) - && ((orientation == OVERLAY_TRANSFORM_ROT_90) - || (orientation == OVERLAY_TRANSFORM_ROT_270))) { + if (useRot || ((orientation == mOrientation) && orientation)) { if (format == MDP_Y_CRCB_H2V2_TILE) { format = MDP_Y_CRCB_H2V2; w = (((w-1)/64 +1)*64); h = (((h-1)/32 +1)*32); } - int tmp = w; - w = h; - h = tmp; + switch(orientation){ + case OVERLAY_TRANSFORM_ROT_90: + case OVERLAY_TRANSFORM_ROT_270: + { + int tmp = w; + w = h; + h = tmp; + break; + } + default: + break; + } } if (w == mOVInfo.src.width && h == mOVInfo.src.height && format == mOVInfo.src.format && orientation == mOrientation) { @@ -945,6 +979,9 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { else { if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; + if(mFBPanelType == MDDI_PANEL) + mRotInfo.enable = 1; + else mRotInfo.enable = 0; } if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index fed1d59..2b8cda8 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -90,6 +90,7 @@ class OverlayControlChannel { int mFBHeight; int mFBbpp; int mFBystride; + char mFBPanelType; int mFD; int mRotFD; @@ -124,7 +125,7 @@ public: int getFormat3D() const { return mFormat3D; } bool getOrientation(int& orientation) const; bool setSource(uint32_t w, uint32_t h, int format, - int orientation, bool ignoreFB); + int orientation, bool ignoreFB, bool userot = false); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); }; @@ -173,6 +174,7 @@ class Overlay { bool mHDMIConnected; int mS3DFormat; bool mCloseChannel; + bool mRotate; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; From a3742036fc508a8a55854d8edd1ce47cfe449e9c Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Thu, 3 Mar 2011 14:06:29 -0800 Subject: [PATCH 345/435] liboverlay: Remove RGB specific checks liboverlay assumes RGB format comes from UI, which is incorrect. Remove RGB format checks. Change-Id: I001d36dcc6bdec043c29b21c072be91bd45d4999 --- liboverlay/overlayLib.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 0d35e9b..f2ea2fa 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -630,10 +630,6 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; mOVInfo.flags = flags; - if (isRGBType(format)) - mOVInfo.is_fg = ignoreFB; - if (ignoreFB && isRGBType(format) && getRGBBpp(format) == 4) - mOVInfo.flags &= ~MDP_OV_PIPE_SHARE; if (!ignoreFB) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; mSize = get_size(format, w, h); @@ -784,23 +780,17 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, } if (w == mOVInfo.src.width && h == mOVInfo.src.height && format == mOVInfo.src.format && orientation == mOrientation) { - if ((ignoreFB == mOVInfo.is_fg) && isRGBType(format)) - return true; mdp_overlay ov; ov.id = mOVInfo.id; if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) return false; mOVInfo = ov; - if (isRGBType(format)) - mOVInfo.is_fg = ignoreFB; + if (!ignoreFB) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + else + mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; - if (!isRGBType(format)) { - if (!ignoreFB) - mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; - else - mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; - } if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) return false; return true; From 7017323f14650e103f8fb30423e752b2de7d4e49 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Thu, 3 Mar 2011 22:13:49 -0800 Subject: [PATCH 346/435] liboverlay: enable rotator only for primary display Enable rotator only for primary if the panel type is MDDI Change-Id: I513de9c022e2a92e8bcd8f683f332903f708e6fa --- liboverlay/overlayLib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index f2ea2fa..ddcd145 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -179,7 +179,7 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; - if( mRotate) + if(mRotate && !fbnum) norot = 0; if (format3D) From 73a28215fa92da6bf5edbcd9e2d2e582fd6ce57b Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 7 Mar 2011 17:47:56 -0800 Subject: [PATCH 347/435] liboverlay: Remove additional overlay SET ioctl calls. The MSMFB_OVERLAY_SET ioctl gets called everytime there is a setSource called. This is an expensive call and should not be done unnecessarily. Change-Id: I2d9be394f48b9dea31b9f4f39b1b576c4ad42b47 --- liboverlay/overlayLib.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index ddcd145..1b17f8b 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -785,14 +785,18 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) return false; mOVInfo = ov; + int flags = mOVInfo.flags; if (!ignoreFB) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; else mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) - return false; + if (flags != mOVInfo.flags) { + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) + return false; + } + return true; } mOrientation = orientation; From 64527a8af14dab5796c2fbef42b463e4dea566cf Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Tue, 8 Mar 2011 18:59:54 +0530 Subject: [PATCH 348/435] Cleanup copyrights in Makefiles As per Copyright Markings guidelines, Makefiles shouldn't contain any Copyright in them. Change-Id: Iefa61b8713d2bfec21eb885dfe999b492da43681 --- liboverlay/Android.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index e32fbea..59827a9 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -1,5 +1,4 @@ # Copyright (C) 2008 The Android Open Source Project -# Copyright (c) 2009, 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. From 1ae5a28caa0e1801a4d688e2423fffaf016aed62 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Tue, 8 Mar 2011 19:03:09 -0800 Subject: [PATCH 349/435] gralloc: Avoid unnecessary overlay set calls for HDMI Call setPosition and setParameter for HDMI only when there is a change in the rotation or position. Change-Id: Id11b58408607c2f9799bb332c30d52f52957ec4e --- libgralloc-qsd8k/framebuffer.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 6a4e3f7..8e78164 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * 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. @@ -312,13 +312,24 @@ static void *hdmi_ui_loop(void *ptr) break; } } - pTemp->setParameter(OVERLAY_TRANSFORM, - rot); + int currentOrientation = 0; + pTemp->getOrientation(currentOrientation); + if(rot != currentOrientation) { + pTemp->setParameter(OVERLAY_TRANSFORM, + rot); + } EVEN_OUT(asX); EVEN_OUT(asY); EVEN_OUT(aswidth); EVEN_OUT(asheight); - pTemp->setPosition(asX, asY, aswidth, asheight); + int currentX = 0, currentY = 0; + uint32_t currentW = width, currentH = height; + if (pTemp->getPosition(currentX, currentY, currentW, currentH)) { + if ((currentX != asX) || (currentY != asY) || (currentW != aswidth) + || (currentH != asheight)) { + pTemp->setPosition(asX, asY, aswidth, asheight); + } + } pTemp->queueBuffer(m->currentOffset); } } From e10754c16c6f9a36a438abec261212f0dcf92c66 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Wed, 16 Mar 2011 13:23:20 -0700 Subject: [PATCH 350/435] gralloc: Avoid multiple signals from videoOverlayStarted Signal hdmi_ui_loop from fb_videoOverlayStarted only if there is a state change CRs-fixed: 279095 Change-Id: I43bc87b4d78fae139bcfc0318ad8b271a6a325c7 --- libgralloc-qsd8k/framebuffer.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 8e78164..5fbb5ad 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -347,14 +347,16 @@ static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started) dev->common.module); pthread_mutex_lock(&m->overlayLock); Overlay* pTemp = m->pobjOverlay; - if (started && pTemp) { - pTemp->closeChannel(); - m->videoOverlay = true; - pthread_cond_signal(&(m->overlayPost)); - } - else { - m->videoOverlay = false; - pthread_cond_signal(&(m->overlayPost)); + if(started != m->videoOverlay) { + if (started && pTemp) { + pTemp->closeChannel(); + m->videoOverlay = true; + pthread_cond_signal(&(m->overlayPost)); + } + else { + m->videoOverlay = false; + pthread_cond_signal(&(m->overlayPost)); + } } pthread_mutex_unlock(&m->overlayLock); return 0; From 7a23eb34e1cff1fd3a696a75d3916d3e1bd96e57 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 16 Mar 2011 13:32:07 -0700 Subject: [PATCH 353/435] libgralloc-qsd8k: support for specifying buffer size during allocation Add support in the gralloc to specify the desired buffer size during buffer allocation. This is done via a new function in the gralloc(allocSize). If the specified size is lesser that the calculated size, set the buffer size to the calculated size. Change-Id: Iad9609d3b9074dcf3af07430966590078081ab72 --- libgralloc-qsd8k/gpu.cpp | 17 +++++++++++++++-- libgralloc-qsd8k/gpu.h | 4 +++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index a2c35b4..6f1420c 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -43,6 +43,7 @@ gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, common.module = const_cast(&module->base.common); common.close = gralloc_close; alloc = gralloc_alloc; + allocSize = gralloc_alloc_size; free = gralloc_free; } @@ -313,7 +314,7 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorF } int gpu_context_t::alloc_impl(int w, int h, int format, int usage, - buffer_handle_t* pHandle, int* pStride) { + buffer_handle_t* pHandle, int* pStride, int bufferSize) { if (!pHandle || !pStride) return -EINVAL; @@ -373,6 +374,8 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, if ((ssize_t)size <= 0) return -EINVAL; + size = (bufferSize >= size)? bufferSize : size; + int err; if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(size, usage, pHandle); @@ -439,7 +442,17 @@ int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format, return -EINVAL; } gpu_context_t* gpu = reinterpret_cast(dev); - return gpu->alloc_impl(w, h, format, usage, pHandle, pStride); + 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(dev); + return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize); } int gpu_context_t::gralloc_free(alloc_device_t* dev, diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h index 67a58d8..3789f6c 100755 --- a/libgralloc-qsd8k/gpu.h +++ b/libgralloc-qsd8k/gpu.h @@ -60,11 +60,13 @@ class gpu_context_t : public alloc_device_t { 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); + buffer_handle_t* pHandle, int* pStride, int 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); private: From e825316b00d015bf7359e5d2e15c6485bfbbb2ee Mon Sep 17 00:00:00 2001 From: Kobi Cohen Arazi Date: Wed, 23 Mar 2011 10:25:38 -0700 Subject: [PATCH 354/435] Revert "liboverlay: Use rotator during video on MDDI panel" This reverts commit b2809b02b6dfc5111150d178135673eb535c4ff5. CRs-fixed: 271109, 278129, 273572 Change-Id: Ie50679b6600e7151cac17136a322009b80b55871 --- liboverlay/overlayLib.cpp | 56 +++++++-------------------------------- liboverlay/overlayLib.h | 4 +-- 2 files changed, 11 insertions(+), 49 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 1b17f8b..af6a07c 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -19,9 +19,6 @@ #include "gralloc_priv.h" #define INTERLACE_MASK 0x80 -#define FBDEV_0 "/dev/graphics/fb0" -#define FBDEV_LEN strlen("msmfbXX_") -#define MDDI_PANEL '1' /* Helper functions */ static int get_mdp_format(int format) { @@ -143,23 +140,7 @@ static void reportError(const char* message) { using namespace overlay; Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mCloseChannel(false), mS3DFormat(0), mRotate(false) { - fb_fix_screeninfo finfo; - memset(&finfo, 0, sizeof(finfo)); - int fd = open(FBDEV_0, O_RDWR, 0); - if (fd < 0) { - reportError("Cant open framebuffer "); - return; - } else { - if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { - reportError("FBIOGET_FSCREENINFO on fb0 failed"); - close(fd); - return; - } - if((finfo.id)[FBDEV_LEN] == MDDI_PANEL) - mRotate = true; - close(fd); - } + mCloseChannel(false), mS3DFormat(0) { } Overlay::~Overlay() { @@ -179,8 +160,6 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; - if(mRotate && !fbnum) - norot = 0; if (format3D) zorder = channel; @@ -325,7 +304,7 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, hdmiChanged = 0x1; stateChanged = s3dChanged|hdmiChanged; - if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB, mRotate)) { + if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) { mCloseChannel = true; return false; @@ -561,8 +540,6 @@ bool OverlayControlChannel::openDevices(int fbnum) { return false; } - mFBPanelType = finfo.id[FBDEV_LEN]; - fb_var_screeninfo vinfo; if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) { reportError("FBIOGET_VSCREENINFO on fb1 failed"); @@ -668,10 +645,7 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, mRotInfo.src_rect.x = 0; mRotInfo.src_rect.y = 0; mRotInfo.rotations = 0; - if(mFBPanelType == MDDI_PANEL) - mRotInfo.enable = 1; - else - mRotInfo.enable = 0; + mRotInfo.enable = 0; mRotInfo.session_id = 0; int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); if (result) { @@ -757,26 +731,19 @@ bool OverlayControlChannel::closeControlChannel() { } bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, - int format, int orientation, bool ignoreFB, bool useRot) { + int format, int orientation, bool ignoreFB) { format = get_mdp_format(format); - if (useRot || ((orientation == mOrientation) && orientation)) { + if ((orientation == mOrientation) + && ((orientation == OVERLAY_TRANSFORM_ROT_90) + || (orientation == OVERLAY_TRANSFORM_ROT_270))) { if (format == MDP_Y_CRCB_H2V2_TILE) { format = MDP_Y_CRCB_H2V2; w = (((w-1)/64 +1)*64); h = (((h-1)/32 +1)*32); } - switch(orientation){ - case OVERLAY_TRANSFORM_ROT_90: - case OVERLAY_TRANSFORM_ROT_270: - { - int tmp = w; - w = h; - h = tmp; - break; - } - default: - break; - } + int tmp = w; + w = h; + h = tmp; } if (w == mOVInfo.src.width && h == mOVInfo.src.height && format == mOVInfo.src.format && orientation == mOrientation) { @@ -973,9 +940,6 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { else { if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; - if(mFBPanelType == MDDI_PANEL) - mRotInfo.enable = 1; - else mRotInfo.enable = 0; } if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 2b8cda8..fed1d59 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -90,7 +90,6 @@ class OverlayControlChannel { int mFBHeight; int mFBbpp; int mFBystride; - char mFBPanelType; int mFD; int mRotFD; @@ -125,7 +124,7 @@ public: int getFormat3D() const { return mFormat3D; } bool getOrientation(int& orientation) const; bool setSource(uint32_t w, uint32_t h, int format, - int orientation, bool ignoreFB, bool userot = false); + int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); }; @@ -174,7 +173,6 @@ class Overlay { bool mHDMIConnected; int mS3DFormat; bool mCloseChannel; - bool mRotate; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; From ed35d42ee4f4da6f199cca268bcf7c33c5c43e45 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Thu, 31 Mar 2011 20:27:26 -0700 Subject: [PATCH 355/435] liboverlay: Always use rotator for UI mirroring on HDMI - Use rotator buffer for UI mirroring on HDMI - Avoid ioctl calls on getPosition CRs-fixed: 278858 Change-Id: Id390e2b85fe939d8388ed17f5f9c7fcd30499755 --- libgralloc-qsd8k/framebuffer.cpp | 15 ++++++++++----- libgralloc-qsd8k/gralloc_priv.h | 2 ++ liboverlay/overlay.cpp | 2 +- liboverlay/overlayLib.cpp | 23 ++++++++++------------- liboverlay/overlayLib.h | 2 ++ 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 5fbb5ad..f27ea5f 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -163,6 +163,7 @@ static void *disp_loop(void *ptr) pthread_mutex_lock(&m->overlayLock); m->orientation = neworientation; m->currentOffset = offset; + m->hdmiStateChanged = true; pthread_cond_signal(&(m->overlayPost)); pthread_mutex_unlock(&m->overlayLock); #endif @@ -210,7 +211,9 @@ static void *hdmi_ui_loop(void *ptr) ptr); while (1) { pthread_mutex_lock(&m->overlayLock); - pthread_cond_wait(&(m->overlayPost), &(m->overlayLock)); + while(!(m->hdmiStateChanged)) + pthread_cond_wait(&(m->overlayPost), &(m->overlayLock)); + m->hdmiStateChanged = false; if (m->exitHDMIUILoop) { pthread_mutex_unlock(&m->overlayLock); return NULL; @@ -226,7 +229,7 @@ static void *hdmi_ui_loop(void *ptr) if (!pTemp->isChannelUP()) { int alignedW = ALIGN(m->info.xres, 32); if (pTemp->startChannel(alignedW, m->info.yres, - m->fbFormat, 1, false, true)) { + m->fbFormat, 1, false, true, 0, VG0_PIPE, true)) { pTemp->setFd(m->framebuffer->fd); pTemp->setCrop(0, 0, m->info.xres, m->info.yres); } else @@ -312,11 +315,10 @@ static void *hdmi_ui_loop(void *ptr) break; } } - int currentOrientation = 0; - pTemp->getOrientation(currentOrientation); - if(rot != currentOrientation) { + if(rot != m->currentOrientation) { pTemp->setParameter(OVERLAY_TRANSFORM, rot); + m->currentOrientation = rot; } EVEN_OUT(asX); EVEN_OUT(asY); @@ -348,6 +350,7 @@ static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started) pthread_mutex_lock(&m->overlayLock); Overlay* pTemp = m->pobjOverlay; if(started != m->videoOverlay) { + m->hdmiStateChanged = true; if (started && pTemp) { pTemp->closeChannel(); m->videoOverlay = true; @@ -371,6 +374,7 @@ static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable) if (!enable && pTemp) pTemp->closeChannel(); m->enableHDMIOutput = enable; + m->hdmiStateChanged = true; pthread_cond_signal(&(m->overlayPost)); pthread_mutex_unlock(&m->overlayLock); return 0; @@ -809,6 +813,7 @@ int mapFrameBufferLocked(struct private_module_t* module) module->pobjOverlay = new Overlay(); module->currentOffset = 0; module->exitHDMIUILoop = false; + module->hdmiStateChanged = false; pthread_t hdmiUIThread; pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module); #endif diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 72160a1..04a15ce 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -235,6 +235,8 @@ struct private_module_t { bool exitHDMIUILoop; float actionsafeWidthRatio; float actionsafeHeightRatio; + int currentOrientation; + bool hdmiStateChanged; pthread_mutex_t overlayLock; pthread_cond_t overlayPost; #endif diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index f97827d..aa2b524 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -173,7 +173,7 @@ public: mHandle.pobjControlChannel[index] = new OverlayControlChannel(); } bool ret = mHandle.pobjControlChannel[index]->startControlChannel( - mHandle.w, mHandle.h, mHandle.format, fbnum, norot, + mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, format3D, zorder, true); if (ret) { if (!(mHandle.pobjControlChannel[index]-> diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index af6a07c..08b5bc4 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -164,7 +164,7 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, if (format3D) zorder = channel; mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, - norot, format3D, zorder, ignoreFB); + norot, uichannel, format3D, zorder, ignoreFB); if (!mChannelUP) { LOGE("startChannel for fb%d failed", fbnum); return mChannelUP; @@ -295,7 +295,6 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, int stateChanged = 0; int hw_format = get_mdp_format(colorFormat); - bool uichannel = isRGBType(hw_format); int s3dChanged =0, hdmiChanged = 0; if (format3D != mS3DFormat) @@ -322,7 +321,7 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, } } else { return startChannel(w, h, colorFormat, 0, !orientation, - uichannel, 0, VG0_PIPE, ignoreFB, num_buffers); + false, 0, VG0_PIPE, ignoreFB, num_buffers); } } else @@ -646,6 +645,8 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, mRotInfo.src_rect.y = 0; mRotInfo.rotations = 0; mRotInfo.enable = 0; + if(mUIChannel) + mRotInfo.enable = 1; mRotInfo.session_id = 0; int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); if (result) { @@ -676,9 +677,11 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, bool OverlayControlChannel::startControlChannel(int w, int h, int format, int fbnum, bool norot, + bool uichannel, unsigned int format3D, int zorder, bool ignoreFB) { mNoRot = norot; + mUIChannel = uichannel; fb_fix_screeninfo finfo; fb_var_screeninfo vinfo; int hw_format; @@ -940,7 +943,9 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { else { if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; - mRotInfo.enable = 0; + mRotInfo.enable = 0; + if(mUIChannel) + mRotInfo.enable = 1; } if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { reportError("setParameter, rotator start failed"); @@ -965,15 +970,7 @@ bool OverlayControlChannel::getPosition(int& x, int& y, uint32_t& w, uint32_t& h) { if (!isChannelUP()) return false; - - mdp_overlay ov; - ov.id = mOVInfo.id; - if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { - reportError("getPosition, overlay GET failed"); - return false; - } - mOVInfo = ov; - + //mOVInfo has the current Overlay Position x = mOVInfo.dst_rect.x; y = mOVInfo.dst_rect.y; w = mOVInfo.dst_rect.w; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index fed1d59..4551b51 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -96,6 +96,7 @@ class OverlayControlChannel { int mSize; int mOrientation; unsigned int mFormat3D; + bool mUIChannel; mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; bool openDevices(int fbnum = -1); @@ -109,6 +110,7 @@ public: ~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(); From 3ea7a7fc380b795edefca0d0d162d832d377101f Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 5 Apr 2011 19:14:55 -0700 Subject: [PATCH 356/435] overlay: Separate the interlace information from the color format When getting the MDP format in the setSource api, separate the color format from the interlace information. Change-Id: I6a92d2d6d2c9f70b0c0bd6486227032716f70914 CRs-fixed: 282157 --- liboverlay/overlayLib.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 08b5bc4..cbaff7e 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -734,7 +734,9 @@ bool OverlayControlChannel::closeControlChannel() { } bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, - int format, int orientation, bool ignoreFB) { + int cFormat, int orientation, bool ignoreFB) { + int format = cFormat & INTERLACE_MASK ? + (cFormat ^ HAL_PIXEL_FORMAT_INTERLACE) : cFormat; format = get_mdp_format(format); if ((orientation == mOrientation) && ((orientation == OVERLAY_TRANSFORM_ROT_90) From b10f481ae26c74576f4b3d99ee29cd60e3f4f96c Mon Sep 17 00:00:00 2001 From: Harshad Bhutada Date: Fri, 15 Apr 2011 14:14:33 +0530 Subject: [PATCH 357/435] libgralloc-qsd8k: disable framebuffer state related error reporting when swapinterval set to 0 Change-Id: Idf0d8b7d261240f6300c5df805cc42dee8098310 --- libgralloc-qsd8k/framebuffer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index f27ea5f..6d9a929 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -181,7 +181,7 @@ static void *disp_loop(void *ptr) } else { pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock)); if (m->avail[nxtBuf.idx].state != SUB) { - LOGE("[%d] state %c, expected %c", nxtBuf.idx, + LOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx, framebufferStateName[m->avail[nxtBuf.idx].state], framebufferStateName[SUB]); } @@ -191,7 +191,7 @@ static void *disp_loop(void *ptr) pthread_mutex_lock(&(m->avail[cur_buf].lock)); m->avail[cur_buf].is_avail = true; if (m->avail[cur_buf].state != REF) { - LOGE("[%d] state %c, expected %c", cur_buf, + LOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf, framebufferStateName[m->avail[cur_buf].state], framebufferStateName[REF]); } @@ -451,7 +451,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) // post/queue the new buffer pthread_mutex_lock(&(m->avail[nxtIdx].lock)); if (m->avail[nxtIdx].is_avail != true) { - LOGE("Found %d buf to be not avail", nxtIdx); + LOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx); } m->avail[nxtIdx].is_avail = false; @@ -490,7 +490,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->currentBuffer = buffer; m->currentIdx = nxtIdx; if (m->avail[futureIdx].state != AVL) { - LOGE("[%d] != AVL!", futureIdx); + LOGE_IF(m->swapInterval != 0, "[%d] != AVL!", futureIdx); } } else { if (m->currentBuffer) @@ -548,7 +548,7 @@ static int fb_dequeueBuffer(struct framebuffer_device_t* dev, int index) dev->common.module); // Return immediately if the buffer is available - if (m->avail[index].state == AVL) + if ((m->avail[index].state == AVL) || (m->swapInterval == 0)) return 0; pthread_mutex_lock(&(m->avail[index].lock)); From cc2834b226974fd7e2f488feb2b7f3fe5c5acfb9 Mon Sep 17 00:00:00 2001 From: Kinjal Bhavsar Date: Tue, 15 Feb 2011 12:45:05 -0800 Subject: [PATCH 359/435] msm7k: Use sanitized kernel headers Add the exported sanitized kernel headers to include path in C2D/ copybit, gralloc and overlay HAL libraries. (cherry picked from commit a70f426e8695cc5bbf8a45b987b5715784f7e924) Change-Id: I1dbb79a086e9cb062e1264c1c354ac5ce1a05f27 --- libcopybit/Android.mk | 6 ++++++ libgralloc-qsd8k/Android.mk | 4 +++- liboverlay/Android.mk | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index a19de13..9e425e0 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -24,6 +24,8 @@ ifeq ($(TARGET_USES_C2D_COMPOSITION),true) 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) @@ -43,6 +45,8 @@ else 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) @@ -59,6 +63,8 @@ else 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) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index 0d69b03..be1b23c 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -21,6 +21,8 @@ LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM +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 \ @@ -38,7 +40,7 @@ endif ifeq ($(TARGET_HAVE_HDMI_OUT),true) LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY -LOCAL_C_INCLUDES := $(LOCAL_PATH)/../liboverlay +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../liboverlay LOCAL_SHARED_LIBRARIES += liboverlay endif diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index 59827a9..0beefbe 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -19,6 +19,8 @@ include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) LOCAL_SHARED_LIBRARIES := liblog libcutils +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_SRC_FILES := overlayLib.cpp LOCAL_MODULE := liboverlay @@ -30,6 +32,8 @@ 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/msm7k/libgralloc-qsd8k LOCAL_SRC_FILES := overlay.cpp LOCAL_MODULE := overlay.default From 8818296680c99f5fb1788847cf8e595db5a064a9 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 28 Apr 2011 13:16:15 -0700 Subject: [PATCH 360/435] libhwcomposer: Use sanitized kernel headers (cherry picked from commit 68e70474c2acaf35e42c4656e19d5f35012d0d70) Change-Id: I8f77453d64f1c2c1e974b96c0727616bf0a8bf87 --- libhwcomposer/Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 4e4d66f..632190b 100755 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -14,5 +14,7 @@ LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k 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 include $(BUILD_SHARED_LIBRARY) From 9ff34af7fa594f41cc28e29a7710830d292b1d96 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 24 Mar 2011 18:25:46 -0700 Subject: [PATCH 361/435] copybit_c2d: Disable blend during blit When performing the copybit blit operation, do a blind blit of the surfaces. The blending operation should be done when the stretch operation is invoked. --- libcopybit/copybit_c2d.cpp | 44 ++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 8f99196..d3d757a 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -710,13 +710,14 @@ static int is_alpha(int cformat) } /** do a stretch blit type operation */ -static int stretch_copybit( +static int stretch_copybit_internal( 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_region_t const *region, + bool enableBlend) { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; int status = COPYBIT_SUCCESS; @@ -770,19 +771,23 @@ static int stretch_copybit( return COPYBIT_FAILURE; } - if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) { - ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; - if(!(ctx->blitState.global_alpha)) { - // src alpha is zero - unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); - unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); - return status; + if (enableBlend) { + if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) { + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + if(!(ctx->blitState.global_alpha)) { + // src alpha is zero + unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + return status; + } + } else { + if(is_alpha(cformat)) + ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + else + ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; } } else { - if(is_alpha(cformat)) - ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; - else - ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; + ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; } ctx->blitState.surface_id = ctx->src[surface_index]; @@ -813,6 +818,17 @@ static int stretch_copybit( return status; } +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) +{ + return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect, region, true); +} + /** Perform a blit type operation */ static int blit_copybit( struct copybit_device_t *dev, @@ -822,7 +838,7 @@ static int blit_copybit( { 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); + return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false); } /*****************************************************************************/ From 2e44876757cc75a8daf59e310e1b748443802869 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 22 Apr 2011 10:39:09 -0700 Subject: [PATCH 362/435] libgralloc-qsd8k: Add perform api to update the handle The new perform api will update the width, height and format of the buffer in the gralloc handle. The GRALLOC_MODULE_PERFORM_DECIDE_PUSH_BUFFER_HANDLING perform is not longer used in Honeycomb. Remove unused code. CRs-fixed: 283849 --- libgralloc-qsd8k/mapper.cpp | 124 ++++-------------------------------- 1 file changed, 11 insertions(+), 113 deletions(-) diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 9234c8d..e25a3cd 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -361,22 +361,17 @@ int gralloc_perform(struct gralloc_module_t const* module, res = 0; 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; - } + 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; + hnd->format = f; + break; + } default: break; } @@ -384,100 +379,3 @@ int gralloc_perform(struct gralloc_module_t const* module, 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) { - *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) { - *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: { - /* 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; -} From f90406e9e126abde623fcb5cf21f0152bda99d6b Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 25 Mar 2011 14:18:34 -0700 Subject: [PATCH 363/435] copybit_c2d: Use the framebuffer stride to calculate position Use the framebuffer stride instead of the framebuffer width when calculating the position for rotation. CRs-fixed: 280765 --- libcopybit/copybit_c2d.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index d3d757a..cf3df66 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * 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. @@ -538,7 +538,7 @@ static void set_rects(struct copybit_context_t *ctx, (ctx->trg_transform & C2D_TARGET_ROTATE_180)) { /* target rotation is 270 */ c2dObject->target_rect.x = (dst->t)<<16; - c2dObject->target_rect.y = (ctx->fb_width - (dst->r))<<16; + c2dObject->target_rect.y = (ALIGN(ctx->fb_width,32) - (dst->r))<<16; c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16; c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) { @@ -548,7 +548,7 @@ static void set_rects(struct copybit_context_t *ctx, c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16; } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) { c2dObject->target_rect.y = (ctx->fb_height - dst->b)<<16; - c2dObject->target_rect.x = (ctx->fb_width - dst->r)<<16; + c2dObject->target_rect.x = (ALIGN(ctx->fb_width,32) - dst->r)<<16; c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16; c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16; } else { From 0818f64a0e101c80e483d3d701719ab3011be1ae Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 29 Mar 2011 11:33:18 -0700 Subject: [PATCH 364/435] copybit_c2d: Disable alpha for the RGBX format Set the C2D_FORMAT_DISABLE_ALPHA for the RGBX format. --- libcopybit/copybit_c2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index cf3df66..dca60ad 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -141,7 +141,7 @@ struct copybit_module_t HAL_MODULE_INFO_SYM = { static int get_format(int format) { switch (format) { case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB; - case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; + case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB | C2D_FORMAT_DISABLE_ALPHA; case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB; case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB; case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA; From f60705b3f4c0f5a1bf52cf4ab1ceb2f166e324d4 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 30 Mar 2011 20:20:55 -0700 Subject: [PATCH 365/435] overlay: Inform the overlay of source rotation If there is a 90 or 270 degree rotation, inform the overlay that the source has been rotated. CRs-fixed: 281389 --- liboverlay/overlayLib.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index cbaff7e..10a83d0 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -948,11 +948,15 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mRotInfo.enable = 0; if(mUIChannel) mRotInfo.enable = 1; - } - if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { - reportError("setParameter, rotator start failed"); - return false; - } + } + if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { + reportError("setParameter, rotator start failed"); + return false; + } + + if ((mOVInfo.user_data[0] == MDP_ROT_90) || + (mOVInfo.user_data[0] == MDP_ROT_270)) + mOVInfo.flags |= MDP_SOURCE_ROTATED_90; if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { reportError("setParameter, overlay set failed"); From 56a78ad2331c31873c076942b4b52bb4088a9fce Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 21 Apr 2011 16:33:39 -0700 Subject: [PATCH 366/435] libhwcomposer: Add support for maintaining original resolution When the layer flags are marked to maintain the original surface resolution, draw the layer using the overlay. Store the HDMI status in the overlay object instead of the HWC context. --- libhwcomposer/hwcomposer.cpp | 104 ++++++++++++++++++++++++----------- liboverlay/overlayLib.cpp | 15 +++-- liboverlay/overlayLib.h | 13 +++++ 3 files changed, 96 insertions(+), 36 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 621f292..b33cf97 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -56,12 +56,21 @@ enum HWCCompositionType { HWC_USE_COPYBIT // This layer is to be handled by copybit }; +enum HWCPrivateFlags { + HWC_USE_ORIGINAL_RESOLUTION = 0x10000000, // This layer is to be drawn using overlays +}; + +enum HWCLayerType{ + HWC_SINGLE_VIDEO = 0x1, + HWC_ORIG_RESOLUTION = 0x2, + HWC_S3D_LAYER = 0x4, + HWC_STOP_UI_MIRRORING_MASK = 0xF +}; + struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; - bool hdmiConnected; - bool videoStarted; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -115,11 +124,45 @@ static void dump_layer(hwc_layer_t const* l) { static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { hwc_context_t* ctx = (hwc_context_t*)(dev); - if(ctx) { - ctx->hdmiConnected = enable; + if(ctx && ctx->mOverlayLibObject) { + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + ovLibObject->setHDMIStatus(enable); } } +static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { + + private_hwc_module_t* hwcModule = reinterpret_cast( + ctx->device.common.module); + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + if(!hwcModule || !ovLibObject) { + LOGE("hwc_set_hdmi_status invalid params"); + return -1; + } + + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (!fbDev) { + LOGE("hwc_set_hdmi_status fbDev is NULL"); + return -1; + } + + if ((layerType & HWC_STOP_UI_MIRRORING_MASK) && + (OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus())) { + // Inform the gralloc to stop UI mirroring + fbDev->videoOverlayStarted(fbDev, true); + } + + if ((OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) && + !(layerType & HWC_STOP_UI_MIRRORING_MASK)) { + // Video mirroring is going on, and we do not have any layers to + // mirror directly. Close the current video channel and inform the + // gralloc to start UI mirroring + ovLibObject->closeChannel(); + fbDev->videoOverlayStarted(fbDev, false); + } + return 0; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -131,7 +174,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); - overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; if(!hwcModule) { LOGE("hwc_prepare null module "); @@ -139,7 +181,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } int yuvBufferCount = 0; - + int layerType = 0; if (list && (list->flags & HWC_GEOMETRY_CHANGED)) { for (size_t i=0 ; inumHwLayers; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; @@ -155,9 +197,13 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn - if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { + if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) { + list->hwLayers[i].compositionType = HWC_USE_OVERLAY; + list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + layerType |= HWC_ORIG_RESOLUTION; } else if (hnd && (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) { list->hwLayers[i].compositionType = HWC_USE_COPYBIT; } else { @@ -165,25 +211,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } - // Inform the gralloc to close the UI mirroring channel if HDMI is connected - // and we have a video buffer - framebuffer_device_t *fbDev = hwcModule->fbDevice; - if ((yuvBufferCount == 1) && !ctx->videoStarted) { - if (ctx->hdmiConnected && fbDev) { - fbDev->videoOverlayStarted(fbDev, true); - } - ctx->videoStarted = true; - } - - if (ctx->videoStarted && yuvBufferCount != 1) { - if(ovLibObject) - ovLibObject->closeChannel(); - - if (ctx->hdmiConnected && fbDev) { - fbDev->videoOverlayStarted(fbDev, false); - } - ctx->videoStarted = false; - } + layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; + // Inform the gralloc of the current HDMI status + hwc_updateOverlayStatus(ctx, layerType); } return 0; @@ -303,10 +333,17 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { int ret = 0; if (ctx && ctx->mOverlayLibObject) { + private_hwc_module_t* hwcModule = reinterpret_cast(ctx->device.common.module); + if (!hwcModule) { + LOGE("drawLayerUsingLayer null module "); + return -1; + } + private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, ctx->hdmiConnected); + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, + (ovLibObject->getHDMIStatus()?true:false), false); if (!ret) { LOGE("drawLayerUsingOverlay setSource failed"); return -1; @@ -321,10 +358,16 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) return -1; } - hwc_rect_t displayFrame = layer->displayFrame; - ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, + if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { + framebuffer_device_t* fbDev = hwcModule->fbDevice; + ret = ovLibObject->setPosition(0, 0, + fbDev->width, fbDev->height); + } else { + hwc_rect_t displayFrame = layer->displayFrame; + ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, (displayFrame.right - displayFrame.left), (displayFrame.bottom-displayFrame.top)); + } if (!ret) { LOGE("drawLayerUsingOverlay setPosition failed"); return -1; @@ -486,9 +529,6 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, } else dev->mOverlayLibObject = NULL; - dev->hdmiConnected = false; - dev->videoStarted = false; - /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 10a83d0..39afe4d 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -234,7 +234,6 @@ bool Overlay::closeChannel() { } mChannelUP = false; mCloseChannel = false; - mHDMIConnected = false; mS3DFormat = 0; return true; } @@ -299,8 +298,17 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, if (format3D != mS3DFormat) s3dChanged = 0x10; - if (hdmiConnected != mHDMIConnected) - hdmiChanged = 0x1; + if (mHDMIConnected) { + // If HDMI is connected and both channels are not up, set the status + if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) { + hdmiChanged = 0x1; + } + } else { + // HDMI is disconnected and both channels are up, set the status + if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) { + hdmiChanged = 0x1; + } + } stateChanged = s3dChanged|hdmiChanged; if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { @@ -309,7 +317,6 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, return false; } closeChannel(); - mHDMIConnected = hdmiConnected; mS3DFormat = format3D; if (mHDMIConnected) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 4551b51..42760bc 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -50,6 +50,16 @@ #define NUM_CHANNELS 2 #define FRAMEBUFFER_0 0 #define FRAMEBUFFER_1 1 + +enum { + HDMI_OFF, + HDMI_ON +}; + +enum { + OVERLAY_CHANNEL_DOWN, + OVERLAY_CHANNEL_UP +}; /* ------------------------------- 3D defines ---------------------------------------*/ // The compound format passed to the overlay is // ABCCC where A is the input 3D format, @@ -203,6 +213,9 @@ public: 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; } + int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); } private: bool startChannelHDMI(int w, int h, int format, bool norot); From 9c2ba115fd218b40679999053a68e28694ea6998 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 2 May 2011 13:46:44 -0700 Subject: [PATCH 367/435] Add support for dynamic resolution change with overlays Whenever there is a change in the buffer geometry, set a flag in the gralloc handle stating that the buffer geometry has changed. In the HWC, whenever we encounter an update in the geometry, if the channel is already open, we just call the necessary ioctls to update the overlay information and not unnecessarily open/close channels. Change-Id: I27db8fc497ebc514e262d6b7854739f312644714 --- libgralloc-qsd8k/gralloc_priv.h | 1 + libgralloc-qsd8k/mapper.cpp | 5 +- libhwcomposer/hwcomposer.cpp | 28 +++++-- liboverlay/overlayLib.cpp | 129 +++++++++++++++++++++++++++++--- liboverlay/overlayLib.h | 3 + 5 files changed, 148 insertions(+), 18 deletions(-) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 04a15ce..7e41906 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -257,6 +257,7 @@ struct private_handle_t { PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004, PRIV_FLAGS_NEEDS_FLUSH = 0x00000008, PRIV_FLAGS_USES_ASHMEM = 0x00000010, + PRIV_FLAGS_FORMAT_CHANGED = 0x00000020, }; enum { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index e25a3cd..444a2ff 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -369,7 +369,10 @@ int gralloc_perform(struct gralloc_module_t const* module, private_handle_t* hnd = (private_handle_t*)handle; hnd->width = w; hnd->height = h; - hnd->format = f; + if (hnd->format != f) { + hnd->format = f; + hnd->flags |= private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; + } break; } default: diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index b33cf97..c21b210 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -341,12 +341,31 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + int orientation = 0; + if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) + ovLibObject->getOrientation(orientation); - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, + if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) + || (layer->transform != orientation) || + (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { + // Overlay channel is not started, or we have an orientation change or there is a + // format change, call setSource to open the overlay if necessary + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, (ovLibObject->getHDMIStatus()?true:false), false); - if (!ret) { - LOGE("drawLayerUsingOverlay setSource failed"); - return -1; + if (!ret) { + LOGE("drawLayerUsingOverlay setSource failed"); + return -1; + } + // Reset this flag so that we don't keep opening and closing channels unnecessarily + hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; + } else { + // The overlay goemetry may have changed, we only need to update the overlay + ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, hnd->format, + layer->transform); + if (!ret) { + LOGE("drawLayerUsingOverlay updateOverlaySource failed"); + return -1; + } } hwc_rect_t sourceCrop = layer->sourceCrop; @@ -373,7 +392,6 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) return -1; } - int orientation; ovLibObject->getOrientation(orientation); if (orientation != layer->transform) ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 39afe4d..8904951 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -271,6 +271,37 @@ bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { return ret; } +bool Overlay::updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation) { + if (hasHDMIStatusChanged()) { + return setSource(w, h, format, orientation, mHDMIConnected); + } + + bool ret = true; + // Set the overlay source info + if (objOvCtrlChannel[0].isChannelUP()) { + ret = objOvCtrlChannel[0].updateOverlaySource(w, h); + if (ret && objOvCtrlChannel[1].isChannelUP()) + ret = objOvCtrlChannel[1].updateOverlaySource(w, h); + } + return ret; +} + +int Overlay::hasHDMIStatusChanged() { + int hdmiChanged = 0; + if (mHDMIConnected) { + // If HDMI is connected and both channels are not up, set the status + if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) { + hdmiChanged = 0x1; + } + } else { + // HDMI is disconnected and both channels are up, set the status + if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) { + hdmiChanged = 0x1; + } + } + return hdmiChanged; +} + bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected, bool ignoreFB, int num_buffers) { if (mCloseChannel) @@ -298,19 +329,8 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, if (format3D != mS3DFormat) s3dChanged = 0x10; - if (mHDMIConnected) { - // If HDMI is connected and both channels are not up, set the status - if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) { - hdmiChanged = 0x1; - } - } else { - // HDMI is disconnected and both channels are up, set the status - if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) { - hdmiChanged = 0x1; - } - } - stateChanged = s3dChanged|hdmiChanged; + stateChanged = s3dChanged|hasHDMIStatusChanged(); if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) { mCloseChannel = true; @@ -682,6 +702,91 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, return ret; } +bool OverlayControlChannel::updateOverlaySource(uint32_t w, uint32_t h) +{ + // Set Rotator info + if (mRotFD >=0) { + if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) { + if ((mRotInfo.src.width == (((w-1)/64 +1)*64)) && + (mRotInfo.src.height == (((h-1)/32 +1)*32))) + return true; + + mRotInfo.src.width = (((w-1)/64 +1)*64); + mRotInfo.src.height = (((h-1)/32 +1)*32); + mRotInfo.src_rect.w = (((w-1)/64 +1)*64); + mRotInfo.src_rect.h = (((h-1)/32 +1)*32); + mRotInfo.dst.height = (((w-1)/64 +1)*64); + mRotInfo.dst.width = (((h-1)/32 +1)*32); + mRotInfo.dst.format = MDP_Y_CRCB_H2V2; + } else { + if ((mRotInfo.src.width == w) && + (mRotInfo.src.height == h)) + return true; + + mRotInfo.src.width = w; + mRotInfo.src.height = h; + mRotInfo.src_rect.w = w; + mRotInfo.src_rect.h = h; + mRotInfo.dst.width = h; + mRotInfo.dst.height = w; + } + + if (mOVInfo.user_data[0] == MDP_ROT_NOP) + mRotInfo.enable = 0; + + if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { + LOGE("updateOverlaySource MSM_ROTATOR_IOCTL_START failed"); + return true; + } + } + + // Set overlay info + switch (mOVInfo.user_data[0]) { + case MDP_ROT_90: + case (MDP_ROT_90 | MDP_FLIP_UD): + case (MDP_ROT_90 | MDP_FLIP_LR): + case MDP_ROT_270: { + if ((mOVInfo.src.height == (((w-1)/64 +1)*64)) && + (mOVInfo.src.width == (((h-1)/32 +1)*32))) + return true; + + mOVInfo.src_rect.w = h; + mOVInfo.src_rect.h = w; + mOVInfo.src.height = (((w-1)/64 +1)*64); + mOVInfo.src.width = (((h-1)/32 +1)*32); + mOVInfo.src_rect.x = 0; + mOVInfo.src_rect.y = 0;; + } break; + case MDP_ROT_180: + case MDP_ROT_NOP: { + if ((mOVInfo.src.width == w) && + (mOVInfo.src.height == h)) + return true; + + mOVInfo.src.width = w; + mOVInfo.src.height = h; + mOVInfo.src_rect.x = 0; + mOVInfo.src_rect.y = 0; + if(mOVInfo.src.format == MDP_Y_CRCB_H2V2_TILE) { + mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w); + mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h); + } else { + mOVInfo.src_rect.w = w; + mOVInfo.src_rect.h = h; + } + } break; + default: + LOGE("updateOverlaySource: Invalid rotation parameter"); + return false; + } + + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + LOGE("updateOverlaySource MSMFB_OVERLAY_SET failed"); + return true; + } + return true; +} + bool OverlayControlChannel::startControlChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel, diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 42760bc..55af19f 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -139,6 +139,7 @@ public: int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); + bool updateOverlaySource(uint32_t w, uint32_t h); }; class OverlayDataChannel { @@ -216,6 +217,7 @@ public: int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); } void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; } int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); } + bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation); private: bool startChannelHDMI(int w, int h, int format, bool norot); @@ -225,6 +227,7 @@ 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); + int hasHDMIStatusChanged(); }; struct overlay_shared_data { From c99d13825e915a13d598d923d8a4b9d92ab79d31 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 9 May 2011 14:53:08 -0700 Subject: [PATCH 368/435] libhwcomposer: Enable COPYBIT_PREMULTIPLIED_ALPHA if the layer blending is premutliplied Change-Id: Iefe0ddeaa20b4411074079bc77ac17cc0e38c27e --- libhwcomposer/hwcomposer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index c21b210..78c15a6 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -321,6 +321,8 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, copybit_device_t *copybit = hwcModule->copybitEngine; copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, + (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); if(err < 0) From 95c239e6be422217691a2ed351251296bc0e5110 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 1 Apr 2011 12:26:58 -0700 Subject: [PATCH 369/435] copybit_c2d: Set the C2D_FORMAT_PREMULTIPLIED format for premultiplied surfaces Set the premultiplied format for the source and destination formats if COPYBIT_PREMULTIPLIED_ALPHA has been enabled Change-Id: I89113a1f1160b921d8e49b5dd6fc01001307648f CRs-fixed: 279449 --- libcopybit/copybit_c2d.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index dca60ad..3d5ab6d 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -103,6 +103,7 @@ struct copybit_context_t { int g12_device_fd; int fb_width; int fb_height; + bool isPremultipliedAlpha; }; struct blitlist{ @@ -293,7 +294,8 @@ static int calculate_yuv_offset_and_stride(int format, int width, int height, in } /** create C2D surface from copybit image */ -static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped) +static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped, + const bool isPremultipliedAlpha) { struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; C2D_SURFACE_TYPE surfaceType; @@ -323,7 +325,7 @@ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image surfaceDef.phys = (void*) handle->gpuaddr; surfaceDef.buffer = (void*) (handle->base); - surfaceDef.format = *cformat; + surfaceDef.format = *cformat | (isPremultipliedAlpha ? C2D_FORMAT_PREMULTIPLIED : 0); surfaceDef.width = rhs->w; surfaceDef.height = rhs->h; surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); @@ -648,6 +650,10 @@ static int set_parameter_copybit( ctx->trg_transform = C2D_TARGET_ROTATE_270; } break; + case COPYBIT_PREMULTIPLIED_ALPHA: + (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true : + ctx->isPremultipliedAlpha = false; + break; default: LOGE("%s: default case", __func__); return -EINVAL; @@ -750,7 +756,7 @@ static int stretch_copybit_internal( struct copybit_rect_t clip; list.count = 0; - status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped); + status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped, ctx->isPremultipliedAlpha); if(status) { LOGE("%s: set_image error", __func__); return COPYBIT_FAILURE; @@ -765,7 +771,7 @@ static int stretch_copybit_internal( return -EINVAL; } - status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped); + status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped, ctx->isPremultipliedAlpha); if(status) { LOGE("%s: set_src_image error", __func__); return COPYBIT_FAILURE; @@ -814,7 +820,7 @@ static int stretch_copybit_internal( unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); - + ctx->isPremultipliedAlpha = false; return status; } @@ -1004,6 +1010,7 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->fb_width = info.xres; ctx->fb_height = info.yres; close(fd); + ctx->isPremultipliedAlpha = false; return status; error5: From 16b703db645e258ffff5866030a827e9884c4740 Mon Sep 17 00:00:00 2001 From: Chetan Kalyan Date: Wed, 6 Apr 2011 11:18:03 -0700 Subject: [PATCH 370/435] liboverlay: Set overlay src format for tiled input Rotator always outputs non-tiled formats. For tiled inputs,if rotation occurs, set overlay's input to non-tiled format. CRs-fixed: 278408 Change-Id: I20e8a4109903f3162aa80f94a8c90ecd70e15772 --- liboverlay/overlayLib.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 8904951..1dc8549 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1052,8 +1052,15 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mOVInfo.user_data[0] = mdp_rotation; mRotInfo.rotations = mOVInfo.user_data[0]; - if (mOVInfo.user_data[0]) + /* Rotator always outputs non-tiled formats. + If rotator is used, set Overlay input to non-tiled + Else, overlay input remains tiled */ + + if (mOVInfo.user_data[0]) { + if (mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) + mOVInfo.src.format = MDP_Y_CRCB_H2V2; mRotInfo.enable = 1; + } else { if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; From de3c0ac14e4a9cec8fb6fb326a0eb8dadca4cc62 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 7 Apr 2011 10:03:09 -0700 Subject: [PATCH 371/435] overlay: Reset the rotation flag Reset the MDP source rotation flag if there is no 90/270 degree rotation. Change-Id: I36ef62e52213149f7ce84677534de969d18972a4 --- liboverlay/overlayLib.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 1dc8549..53d430b 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1076,6 +1076,8 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { if ((mOVInfo.user_data[0] == MDP_ROT_90) || (mOVInfo.user_data[0] == MDP_ROT_270)) mOVInfo.flags |= MDP_SOURCE_ROTATED_90; + else + mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90; if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { reportError("setParameter, overlay set failed"); From 1b5cb629f4a890140d0507002e53c110839c6bd5 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Wed, 6 Apr 2011 18:30:28 -0700 Subject: [PATCH 372/435] hardware/msm7k: Remove ioctl call from getOrientation - The ioctl call from getOrientation is removed. - In gralloc use getOrientation instead of storing the orientation. Change-Id: Idb08568ff5d46ce99e0a9a8c6f492b90bb666f0c --- libgralloc-qsd8k/framebuffer.cpp | 5 +++-- libgralloc-qsd8k/gralloc_priv.h | 1 - liboverlay/overlayLib.cpp | 10 ++-------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 6d9a929..794adb4 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -315,10 +315,11 @@ static void *hdmi_ui_loop(void *ptr) break; } } - if(rot != m->currentOrientation) { + int currOrientation = 0; + pTemp->getOrientation(currOrientation); + if(rot != currOrientation) { pTemp->setParameter(OVERLAY_TRANSFORM, rot); - m->currentOrientation = rot; } EVEN_OUT(asX); EVEN_OUT(asY); diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 7e41906..39b488e 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -235,7 +235,6 @@ struct private_module_t { bool exitHDMIUILoop; float actionsafeWidthRatio; float actionsafeHeightRatio; - int currentOrientation; bool hdmiStateChanged; pthread_mutex_t overlayLock; pthread_cond_t overlayPost; diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 53d430b..00a5ccb 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1109,14 +1109,8 @@ bool OverlayControlChannel::getPosition(int& x, int& y, bool OverlayControlChannel::getOrientation(int& orientation) const { if (!isChannelUP()) return false; - - mdp_overlay ov; - ov.id = mOVInfo.id; - if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { - reportError("getOrientation, overlay GET failed"); - return false; - } - orientation = ov.user_data[0]; + // mOVInfo has the current orientation + orientation = mOVInfo.user_data[0]; return true; } bool OverlayControlChannel::getOvSessionID(int& sessionID) const { From 9d4f87e88cc7c1422a4816d23e9a15135853b7e8 Mon Sep 17 00:00:00 2001 From: Sravank Date: Wed, 20 Apr 2011 19:22:42 +0530 Subject: [PATCH 373/435] libOverlay : Set correct crop values for overlay with flip When front camera is in use, overlay is created with 90 degree rotation and vertical flip. This change considers 90 degree rotation with flip, and updates the crop rectangle accordingly. CRs-Fixed : 283348, 284193 Change-Id: Ia0d7830f12d607ae698b019396cd0e2bef168a6a --- liboverlay/overlayLib.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 00a5ccb..6064fab 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1361,7 +1361,9 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) return false; } - if (ov.user_data[0] == MDP_ROT_90) { + if ((ov.user_data[0] == MDP_ROT_90) || + (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_UD)) || + (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_LR))){ if (ov.src.width < (y + h)) return false; From b078d08fdce3a3f779f4db0bb5107d83a8dab769 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 6 May 2011 10:40:42 -0700 Subject: [PATCH 374/435] overlay: Set the correct MDP format enums The MDP kernel interprets the CRCB enum opposite to what Android interprets it. Set the correct MDP enum value. Change-Id: Iba9744fadadc42467dbf8979d6ed7d896c00ca10 --- liboverlay/overlayLib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 6064fab..33dd458 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -34,9 +34,9 @@ static int get_mdp_format(int format) { case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; case HAL_PIXEL_FORMAT_YCbCr_420_SP: - return MDP_Y_CBCR_H2V2; - case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CRCB_H2V2; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return MDP_Y_CBCR_H2V2; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return MDP_Y_CRCB_H2V2_TILE; } From d71c65326e39d6bde042174b0810a3129f8e011d Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 12 May 2011 13:07:20 -0700 Subject: [PATCH 375/435] libgralloc-qsd8k: Clean getGrallocInformationFromFormat function - Stagefright no longer sends the OMX Formats to the gralloc, remove unnecessary code from the function. - Add support for the YV12 format in getGrallocInformationFromFormat Change-Id: Id21baf8890f07ef8fb8a32d3b0d218540005f469 --- libgralloc-qsd8k/gpu.cpp | 71 +++++++++++----------------------------- libgralloc-qsd8k/gpu.h | 2 +- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 6f1420c..1dfe191 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -258,61 +258,30 @@ 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, int *halFormat) +void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType) { *bufferType = BUFFER_TYPE_VIDEO; - *halFormat = inputFormat; *colorFormat = inputFormat; - switch(inputFormat) { - case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: - { - *colorFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; - *halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; - } break; - case (OMX_QCOM_COLOR_FormatYVU420SemiPlanar ^ QOMX_INTERLACE_FLAG): - { - *colorFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; - *halFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP ^ HAL_PIXEL_FORMAT_INTERLACE; - } break; - case (QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ^ QOMX_INTERLACE_FLAG): - { - *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED ^ HAL_PIXEL_FORMAT_INTERLACE; - } break; - case (QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka ^ QOMX_3D_VIDEO_FLAG): - { - *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED | HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R | HAL_3D_OUT_SIDE_BY_SIDE; - } break; - case QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka: - { - *colorFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - *halFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED; - } break; - default: - { - 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; - } - break; + if (inputFormat == HAL_PIXEL_FORMAT_YV12) { + *bufferType = BUFFER_TYPE_UI; // There is no overlay support for this format yet. + } 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, int bufferSize) { if (!pHandle || !pStride) @@ -322,8 +291,8 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, alignedw = ALIGN(w, 32); alignedh = ALIGN(h, 32); - int colorFormat, bufferType, halFormat; - getGrallocInformationFromFormat(format, &colorFormat, &bufferType, &halFormat); + int colorFormat, bufferType; + getGrallocInformationFromFormat(format, &colorFormat, &bufferType); switch (colorFormat) { case HAL_PIXEL_FORMAT_RGBA_8888: @@ -380,7 +349,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(size, usage, pHandle); } else { - err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, halFormat, w, h); + err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, w, h); } if (err < 0) { diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h index 3789f6c..dc0f96c 100755 --- a/libgralloc-qsd8k/gpu.h +++ b/libgralloc-qsd8k/gpu.h @@ -76,7 +76,7 @@ class gpu_context_t : public alloc_device_t { PmemAllocator& pmemAdspAllocator; int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, int* pOffset, int* pFd); - void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType, int *halFormat); + void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType); }; #endif // GRALLOC_QSD8K_GPU_H From 7c3d92ed0be26bf4955536cb5bf947c05df4932b Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 19 May 2011 13:53:49 -0700 Subject: [PATCH 376/435] libhwcomposer: Handle HDMI disconnect event - Inform the gralloc of the HDMI status. - If the HDMI is disconnected, close the overlay and also inform the gralloc that video mirroring has stopped. Change-Id: Ie89ffe860c0f9c9142d6c7f5d7a6c555884561ce CRs-fixed: 286954 --- libhwcomposer/hwcomposer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 78c15a6..afea6d4 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -124,9 +124,25 @@ static void dump_layer(hwc_layer_t const* l) { static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { hwc_context_t* ctx = (hwc_context_t*)(dev); + private_hwc_module_t* hwcModule = reinterpret_cast( + dev->common.module); + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (fbDev) { + fbDev->enableHDMIOutput(fbDev, enable); + } + if(ctx && ctx->mOverlayLibObject) { overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; ovLibObject->setHDMIStatus(enable); + + if (!enable) { + // Close the overlay channels if HDMI is disconnected + ovLibObject->closeChannel(); + // Inform the gralloc that video mirroring is stopped + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (fbDev) + fbDev->videoOverlayStarted(fbDev, false); + } } } From dc7076e724d072ace78f11bc6535a48cb8b9b184 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 20 May 2011 11:49:29 -0700 Subject: [PATCH 377/435] libgralloc-qsd8k: Modify buffer sizes for NV12, NV21 and YV12 formats Allocate buffer sizes that are multiples of 4K for the NV21, NV12 and YV12 formats. Change-Id: I3febaef9dda2586ef3b35945f30f655e07f5e369 CRs-fixed: 287882 --- libgralloc-qsd8k/gpu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 1dfe191..85680b8 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -333,6 +333,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, alignedh = h; size = alignedw*alignedh + (ALIGN(alignedw/2, 16) * (alignedh/2))*2; + size = ALIGN(size, 4096); break; default: From 1b51063e0db44d90cc8da021a7ee05ce24975d71 Mon Sep 17 00:00:00 2001 From: Kinjal Bhavsar Date: Thu, 10 Feb 2011 20:05:58 -0800 Subject: [PATCH 378/435] liboverlay: Add TV detection and monoscopic display for S3D Add the state machine for overlay configuration. When connected, check whether the TV on HDMI is 3D capable or not using the EDID info. Show L channel on primary panel; and R channel on 2D TV if non 3DTV is connected via HDMI, else switch TV to 3D mode. Change-Id: I3109f8b0b81a8f5ad542db038262fd668e225e96 --- libgralloc-qsd8k/gralloc_priv.h | 16 +- liboverlay/overlay.cpp | 884 +++++++++++++++++++------------- liboverlay/overlayLib.cpp | 313 ++++++----- liboverlay/overlayLib.h | 51 +- 4 files changed, 770 insertions(+), 494 deletions(-) diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 39b488e..228b6be 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * 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. @@ -154,15 +154,15 @@ enum { /* possible formats for 3D content*/ enum { - HAL_NO_3D = 0x00, - HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R = 0x10000, + HAL_NO_3D = 0x0000, + HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000, HAL_3D_IN_TOP_BOTTOM = 0x20000, HAL_3D_IN_INTERLEAVE = 0x40000, - HAL_3D_IN_SIDE_BY_SIDE_FULL = 0x80000, - HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L = 0xC0000, - HAL_3D_OUT_SIDE_BY_SIDE = 0x1000, - HAL_3D_OUT_TOP_BOTTOM = 0x2000, - HAL_3D_OUT_INTERLEAVE = 0x4000, + HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000, + HAL_3D_OUT_SIDE_BY_SIDE = 0x1000, + HAL_3D_OUT_TOP_BOTTOM = 0x2000, + HAL_3D_OUT_INTERLEAVE = 0x4000, + HAL_3D_OUT_MONOSCOPIC = 0x8000 }; enum { diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index aa2b524..db8468b 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -39,21 +39,20 @@ struct overlay_control_context_t { struct overlay_control_device_t device; void *sharedMemBase; unsigned int format3D; //input and output 3D format, zero means no 3D -}; - -struct ov_crop_rect_t { - int x; - int y; - int w; - int h; + unsigned int state; + unsigned int orientation; + overlay_rect posPanel; }; struct overlay_data_context_t { struct overlay_data_device_t device; OverlayDataChannel* pobjDataChannel[2]; - int setCrop; unsigned int format3D; - struct ov_crop_rect_t cropRect; + unsigned int state; + bool setCrop; + overlay_rect cropRect; + int srcFD; //store the FD as it will needed for fb1 + int size; //size of the overlay created void *sharedMemBase; }; @@ -65,7 +64,7 @@ static struct hw_module_methods_t overlay_module_methods = { }; struct private_overlay_module_t { - overlay_module_t base; + overlay_module_t base; Mutex *pobjMutex; }; @@ -104,7 +103,6 @@ static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) { return static_cast(overlay)->rotid[index]; } - static int handle_get_size(const overlay_handle_t overlay) { return static_cast(overlay)->size; } @@ -159,13 +157,10 @@ public: int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} - bool startControlChannel(int fbnum, bool norot = false, - unsigned int format3D = 0, int zorder = 0) { - int index = 0; - if (format3D) + bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { + int index = fbnum; + if (mHandle.format3D) index = zorder; - else - index = fbnum; if (!mHandle.pobjControlChannel[index]) mHandle.pobjControlChannel[index] = new OverlayControlChannel(); else { @@ -174,7 +169,7 @@ public: } bool ret = mHandle.pobjControlChannel[index]->startControlChannel( mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, - format3D, zorder, true); + mHandle.format3D, zorder, true); if (ret) { if (!(mHandle.pobjControlChannel[index]-> getOvSessionID(mHandle.ovid[index]) && @@ -223,6 +218,16 @@ public: return ret; } + bool getPositionS3D(overlay_rect *rect, int channel) { + if (!mHandle.pobjControlChannel[channel]) { + LOGE("%s:Failed got channel %d", __func__, channel); + return false; + } + + return mHandle.pobjControlChannel[channel]->getPositionS3D( + channel, mHandle.format3D, rect); + } + bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { if (!mHandle.pobjControlChannel[channel]) return false; @@ -241,12 +246,7 @@ public: close(mHandle.sharedMemoryFd); closeControlChannel(0); closeControlChannel(1); - FILE *fp = NULL; - fp = fopen(FORMAT_3D_FILE, "wb"); - if(fp) { - fprintf(fp, "0"); //Sending hdmi info packet(2D) - fclose(fp); - } + send3DInfoPacket (0); } int getFBWidth(int channel) { @@ -260,6 +260,10 @@ public: return false; return mHandle.pobjControlChannel[channel]->getFBHeight(); } + + inline void setFormat3D(unsigned int format3D) { + mHandle.format3D = format3D; + } }; // **************************************************************************** @@ -297,6 +301,19 @@ public: return result; } + static void error_cleanup_control(overlay_control_context_t *ctx, overlay_object *overlay, int fd, int index) { + LOGE("Failed to start control channel %d", index); + for (int i = 0; i < index; i++) + overlay->closeControlChannel(i); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + delete overlay; + } + static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, uint32_t w, uint32_t h, int32_t format) { overlay_object *overlay = NULL; @@ -307,10 +324,9 @@ public: // Open shared memory to store shared data int size = sizeof(overlay_shared_data); - void *base; + void *base; int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, size); - if(fd < 0) { LOGE("%s: create shared memory failed", __func__); return NULL; @@ -347,26 +363,30 @@ public: } if(!fOut3D) { switch (fIn3D) { - case HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R: - case HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L: - case HAL_3D_IN_SIDE_BY_SIDE_FULL: + case HAL_3D_IN_SIDE_BY_SIDE_L_R: + case HAL_3D_IN_SIDE_BY_SIDE_R_L: // For all side by side formats, set the output // format as Side-by-Side i.e 0x1 - format3D |= HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R >> SHIFT_3D; + format3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_3D; break; default: format3D |= fIn3D >> SHIFT_3D; //Set the output format break; } } - + unsigned int curState = overlay::getOverlayConfig(format3D); + if (curState == OV_3D_VIDEO_2D_PANEL || curState == OV_3D_VIDEO_2D_TV) { + LOGI("3D content on 2D display: set the output format as monoscopic"); + format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + LOGD("createOverlay: creating overlay with format3D: 0x%x, curState: %d", format3D, curState); ctx->sharedMemBase = base; ctx->format3D = format3D; + ctx->state = curState; memset(ctx->sharedMemBase, 0, size); /* number of buffer is not being used as overlay buffers are coming from client */ overlay = new overlay_object(w, h, format, fd, format3D); - if (overlay == NULL) { LOGE("%s: can't create overlay object!", __FUNCTION__); if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { @@ -377,81 +397,49 @@ public: close(fd); return NULL; } - - if (format3D) { - bool res1, res2; - if (format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) { - // For R-L formats, set the Zorder of the second channel as 0 - res1 = overlay->startControlChannel(1, false, format3D, 1); - res2 = overlay->startControlChannel(1, false, format3D, 0); - } else { - res1 = overlay->startControlChannel(1, false, format3D, 0); - res2 = overlay->startControlChannel(1, false, format3D, 1); - } - if (!res1 || !res2) { - LOGE("Failed to start control channel for VG pipe 0 or 1"); - overlay->closeControlChannel(0); - overlay->closeControlChannel(1); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; - } - if(fd > 0) - close(fd); - - delete overlay; + bool noRot; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot)) { + error_cleanup_control(ctx, overlay, fd, FRAMEBUFFER_0); return NULL; } - return overlay; - } -#ifdef USE_MSM_ROTATOR - if (!overlay->startControlChannel(0)) { -#else - if (!overlay->startControlChannel(0, true)) { -#endif - LOGE("Failed to start control channel for framebuffer 0"); - overlay->closeControlChannel(0); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, VG0_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG0_PIPE); + return NULL; } - if(fd > 0) - close(fd); - - delete overlay; - return NULL; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return overlay; - } - - if (!overlay->startControlChannel(1, true)) { - LOGE("Failed to start control channel for framebuffer 1"); - overlay->closeControlChannel(1); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; + if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG1_PIPE); + return NULL; } - if(fd > 0) - close(fd); - - delete overlay; - return NULL; - } - else { - overlay_rect rect; - if(overlay->getAspectRatioPosition(&rect, 1)) { - if (!overlay->setPosition(rect.x, rect.y, rect.width, rect.height, 1)) { - LOGE("Failed to upscale for framebuffer 1"); + break; + case OV_3D_VIDEO_3D_TV: + for (int i=0; istartControlChannel(FRAMEBUFFER_1, true, i)) { + error_cleanup_control(ctx, overlay, fd, i); + return NULL; } } + break; + default: + break; + } + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->state = ctx->state; + for (int i=0; iovid[i] = overlay->getHwOvId(i); + data->rotid[i] = overlay->getRotSessionId(i); } - return overlay; - } static void overlay_destroyOverlay(struct overlay_control_device_t *dev, @@ -480,37 +468,47 @@ public: dev->common.module); Mutex::Autolock objLock(m->pobjMutex); bool ret; - if(ctx->format3D){ - int wHDMI = obj->getFBWidth(1); - int hHDMI = obj->getFBHeight(1); - if(ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { - ret = obj->setPosition(0, 0, wHDMI/2, hHDMI, 0); - if (!ret) - return -1; - ret = obj->setPosition(wHDMI/2, 0, wHDMI/2, hHDMI, 1); - if (!ret) - return -1; - } - else if (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) { - ret = obj->setPosition(0, 0, wHDMI, hHDMI/2, 0); - if (!ret) - return -1; - ret = obj->setPosition(0, hHDMI/2, wHDMI, hHDMI/2, 1); - if (!ret) - return -1; - } - else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - LOGE("%s: Unsupported 3D output format!!!", __func__); - } - } - else { - ret = obj->setPosition(x, y, w, h, 0); - if (!ret) + overlay_rect rect; + // saving the position for the disconnection event + ctx->posPanel.x = x; + ctx->posPanel.y = y; + ctx->posPanel.w = w; + ctx->posPanel.h = h; + + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); + return -1; + } + obj->getAspectRatioPosition(&rect, VG1_PIPE); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { + LOGE("%s:Failed for channel 1", __func__); + return -1; + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->getPositionS3D(&rect, i)) + ret = obj->setPosition(x, y, w, h, i); + else + ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + break; } return 0; } @@ -530,7 +528,7 @@ public: data.readyToQueue = 1; memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data)); } -return 0; + return 0; } static int overlay_getPosition(struct overlay_control_device_t *dev, @@ -542,12 +540,91 @@ return 0; dev->common.module); Mutex::Autolock objLock(m->pobjMutex); overlay_object * obj = static_cast(overlay); - bool ret = obj->getPosition(x, y, w, h, 0); - if (!ret) - return -1; - return 0; + return obj->getPosition(x, y, w, h, 0) ? 0 : -1; } - +#if 0 + static bool overlay_configPipes(overlay_control_context_t *ctx, + overlay_object *obj, int enable, + unsigned int curState) { + bool noRot = true; + overlay_rect rect; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + if(enable) { + if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || + (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_2D_TV) ) { + LOGI("2D TV connected, Open a new control channel for TV."); + //Start a new channel for mirroring on HDMI + if (!obj->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + obj->closeControlChannel(FRAMEBUFFER_1); + return false; + } + if (ctx->format3D) + obj->getPositionS3D(&rect, FRAMEBUFFER_1); + else + obj->getAspectRatioPosition(&rect, FRAMEBUFFER_1); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, FRAMEBUFFER_1)) { + LOGE("%s:Failed to set position for framebuffer 1", __func__); + return false; + } + } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_3D_TV) ) { + LOGI("3D TV connected, close old ctl channel and open two ctl channels for 3DTV."); + //close the channel 0 as it is configured for panel + obj->closeControlChannel(FRAMEBUFFER_0); + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->startControlChannel(FRAMEBUFFER_1, true, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + obj->getPositionS3D(&rect, i); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s: failed for channel %d", __func__, i); + return false; + } + } + } + } else { + if ( (ctx->state == OV_2D_VIDEO_ON_TV) || + (ctx->state == OV_3D_VIDEO_2D_TV && curState == OV_3D_VIDEO_2D_PANEL) ) { + LOGI("2D TV disconnected, close the control channel."); + obj->closeControlChannel(VG1_PIPE); + } else if (ctx->state == OV_3D_VIDEO_3D_TV && curState == OV_3D_VIDEO_2D_PANEL) { + LOGI("3D TV disconnected, close the control channels & open one for panel."); + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + obj->setFormat3D(ctx->format3D); + LOGI("Control: New format3D: 0x%x", ctx->format3D); + //now open the channel 0 + if (!obj->startControlChannel(FRAMEBUFFER_0, noRot)) { + LOGE("%s:Failed to open control channel for pipe 0", __func__); + return false; + } + if(!obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, ctx->posPanel.w, ctx->posPanel.h, FRAMEBUFFER_0)) { + LOGE("%s:Failed to set position for framebuffer 0", __func__); + return false; + } + if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, VG0_PIPE)) { + LOGE("%s: Failed to set orienatation for channel 0", __func__); + return -1; + } + } + } + //update the context's state + ctx->state = curState; + return true; + } +#endif static int overlay_setParameter(struct overlay_control_device_t *dev, overlay_t* overlay, int param, int value) { @@ -555,28 +632,60 @@ return 0; overlay_object *obj = static_cast(overlay); private_overlay_module_t* m = reinterpret_cast( dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); if (obj && (obj->getSharedMemoryFD() > 0) && (ctx->sharedMemBase != MAP_FAILED)) { - overlay_shared_data data; - data.readyToQueue = 0; - memcpy(ctx->sharedMemBase, (void*)&data, sizeof(data)); + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->readyToQueue = 0; +#if 0 + /* SF will inform Overlay HAL the HDMI cable connection. + This avoids polling on the system property hw.hdmiON */ + if(param == OVERLAY_HDMI_ENABLE) { + unsigned int curState = getOverlayConfig(ctx->format3D); + if(ctx->state != curState) { + LOGI("Overlay Configured for : %d Current state: %d", ctx->state, curState); + if(!overlay_configPipes(ctx, obj, value, curState)) { + LOGE("In overlay_setParameter: reconfiguring of Overlay failed !!"); + return -1; + } + else { + data->state = ctx->state; + for (int i=0; iovid[i] = obj->getHwOvId(i); + data->rotid[i] = obj->getRotSessionId(i); + } + } + } + } +#endif } - bool ret; - if (ctx->format3D) { - ret = obj->setParameter(param, value, 0); - if (!ret) - return -1; - ret = obj->setParameter(param, value, 1); - if (!ret) - return -1; - } - else { - ret = obj->setParameter(param, value, 0); - if (!ret) - return -1; +// if(param != OVERLAY_HDMI_ENABLE) + { + //Save the panel orientation + if (param == OVERLAY_TRANSFORM) + ctx->orientation = value; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setParameter(param, value, VG0_PIPE)) { + LOGE("%s: Failed for channel 0", __func__); + return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; isetParameter(param, value, i)) { + LOGE("%s: Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + break; + } } return 0; } @@ -597,6 +706,15 @@ return 0; // Data module // **************************************************************************** + static void error_cleanup_data(struct overlay_data_context_t* ctx, int index) + { + LOGE("Couldn't start data channel %d", index); + for (int i = 0; ipobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + } + int overlay_initialize(struct overlay_data_device_t *dev, overlay_handle_t handle) { @@ -617,11 +735,20 @@ return 0; int size = handle_get_size(handle); int sharedFd = handle_get_shared_fd(handle); unsigned int format3D = handle_get_format3D(handle); - FILE *fp = NULL; private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); - + bool noRot = true; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + //default: set crop info to src size. + ctx->cropRect.x = 0; + ctx->cropRect.y = 0; + //ctx->cropRect.w = handle_get_width(handle); + //ctx->cropRect.h = handle_get_height(handle); ctx->sharedMemBase = MAP_FAILED; ctx->format3D = format3D; @@ -637,64 +764,67 @@ return 0; LOGE("Received invalid shared memory fd"); return -1; } - - if (ctx->format3D) { - bool res1, res2; - ctx->pobjDataChannel[0] = new OverlayDataChannel(); - ctx->pobjDataChannel[1] = new OverlayDataChannel(); - res1 = - ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, size, 1); - ovid = handle_get_ovId(handle, 1); - rotid = handle_get_rotId(handle, 1); - res2 = - ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, size, 1); - if (!res1 || !res2) { - LOGE("Couldnt start data channel for VG pipe 0 or 1"); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; + overlay_shared_data* data = static_cast + (ctx->sharedMemBase); + if (data == NULL){ + LOGE("%s:Shared data is NULL!!", __func__); + return -1; + } + ctx->state = data->state; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); return -1; } - //Sending hdmi info packet(3D output format) - fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "%d", format3D & OUTPUT_MASK_3D); - fclose(fp); - fp = NULL; + //setting the crop value + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe 0", __func__); } - return 0; - } - ctx->pobjDataChannel[0] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, - size, 0)) { - LOGE("Couldnt start data channel for framebuffer 0"); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - return -1; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - ctx->pobjDataChannel[1] = 0; - return 0; - } - - ovid = handle_get_ovId(handle, 1); - rotid = handle_get_rotId(handle, 1); - ctx->pobjDataChannel[1] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, - size, 1, true)) { - LOGE("Couldnt start data channel for framebuffer 1"); - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; - } - fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "0"); //Sending hdmi info packet(2D) - fclose(fp); - fp = NULL; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, true)) { + error_cleanup_data(ctx, i); + return -1; + } + //setting the crop value + if(!ctx->pobjDataChannel[i]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe %d", __func__, i); + } + } + break; + case OV_3D_VIDEO_3D_TV: + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop channel %d", __func__, i); + //return -1; + } + } + if(!send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D)) + LOGI("%s:Error setting the 3D mode for TV", __func__); + break; + default: + break; } return 0; } @@ -706,7 +836,7 @@ return 0; * representing this buffer. */ - /* no interal overlay buffer to dequeue */ + /* no internal overlay buffer to dequeue */ LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); return 0; @@ -720,7 +850,12 @@ return 0; private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); - + bool noRot = true; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif // Check if readyToQueue is enabled. overlay_shared_data data; if(ctx->sharedMemBase != MAP_FAILED) @@ -732,60 +867,150 @@ return 0; LOGE("Overlay is not ready to queue buffers"); return -1; } - - bool result; - if (ctx->format3D) { - if ( (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || - (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) ) { - result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for VG pipe 0"); - result = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for VG pipe 1"); +#if 0 + if(data->state != ctx->state) { + LOGI("Data: State has changed from %d to %d", ctx->state, data->state); + if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || + (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_2D_TV) ) { + LOGI("2D TV connected, Open a new data channel for TV."); + //Start a new channel for mirroring on HDMI + ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel( + data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size, + FRAMEBUFFER_1, true)) { + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + return -1; + } + //setting the crop value + if(ctx->format3D) { + overlay_rect rect; + ctx->pobjDataChannel[VG1_PIPE]->getCropS3D(&ctx->cropRect, VG1_PIPE, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[VG1_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe 1", __func__); + } + } else { + if(!ctx->pobjDataChannel[VG1_PIPE]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe 1", __func__); + } + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe 1", __func__); + return -1; + } + } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_3D_TV) ) { + LOGI("3D TV connected, close data channel and open both data channels for 3DTV."); + //close the channel 0 as it is configured for panel + ctx->pobjDataChannel[VG0_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG0_PIPE]; + ctx->pobjDataChannel[VG0_PIPE] = NULL; + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + LOGI("Data: New S3D format : 0x%x", ctx->format3D); + //now open both the channels + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, + FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe %d", __func__, i); + return -1; + } + if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe %d", __func__, i); + return -1; + } + } + send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); + } else if( (ctx->state == OV_2D_VIDEO_ON_TV) || + (ctx->state == OV_3D_VIDEO_2D_TV && data->state == OV_3D_VIDEO_2D_PANEL) ) { + LOGI("2D TV disconnected, close the data channel for TV."); + ctx->pobjDataChannel[VG1_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + } else if (ctx->state == OV_3D_VIDEO_3D_TV && data->state == OV_3D_VIDEO_2D_PANEL) { + LOGI("3D TV disconnected, close the data channels for 3DTV and open one for panel."); + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + send3DInfoPacket(0); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + //now open the channel 0 + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel( + data->ovid[VG0_PIPE], data->rotid[VG0_PIPE], ctx->size, + FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); + return -1; + } + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); + //setting the crop value + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( rect.x, rect.y,rect.w, rect.h)) { + LOGE("%s:failed to crop pipe 0", __func__); + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG0_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed set fd for pipe 0", __func__); + return -1; + } } - else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - LOGE("%s:Unknown 3D Format...", __func__); - } - return 0; + //update the context's state + ctx->state = data->state; } - if(ctx->setCrop) { - bool result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(ctx->cropRect.x,ctx->cropRect.y,ctx->cropRect.w,ctx->cropRect.h)); - ctx->setCrop = 0; - if (!result) { - LOGE("set crop failed for framebuffer 0"); +#endif + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + if (ctx->setCrop) { + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(ctx->cropRect.x, ctx->cropRect.y, ctx->cropRect.w, ctx->cropRect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); return -1; } - } - - result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for framebuffer 0"); - else { - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - result = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - queueBuffer((uint32_t) buffer)); - if (!result) { - LOGE("QueueBuffer failed for framebuffer 1"); - return -1; - } + break; + case OV_3D_VIDEO_2D_PANEL: + if (ctx->setCrop) { + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); + return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; } return -1; @@ -797,41 +1022,28 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - bool ret; - if (ctx->format3D) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for VG pipe 0"); + ctx->srcFD = fd; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!ctx->pobjDataChannel[VG0_PIPE]->setFd(fd)) { + LOGE("%s: failed for VG pipe 0", __func__); return -1; } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for VG pipe 1"); - return -1; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->setFd(fd)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } } - return 0; + break; + default: + break; } - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for framebuffer 0"); - return -1; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for framebuffer 1"); - } - return 0; } @@ -842,68 +1054,36 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - bool ret = false; - // for the 3D usecase extract L and R channels from a frame - if(ctx->format3D) { - if ((ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || - (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L)) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(0, 0, w/2, h)); - if (!ret) { - LOGE("set crop failed for VG pipe 0"); - return -1; - } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(w/2, 0, w/2, h)); - if (!ret) { - LOGE("set crop failed for VG pipe 1"); - return -1; - } - } - else if (ctx->format3D & HAL_3D_IN_TOP_BOTTOM) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(0, 0, w, h/2)); - if (!ret) { - LOGE("set crop failed for VG pipe 0"); - return -1; - } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(0, h/2, w, h/2)); - if (!ret) { - LOGE("set crop failed for VG pipe 1"); - return -1; - } - } - else if (ctx->format3D & HAL_3D_IN_INTERLEAVE) { - //TBD - } else if (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_FULL) { - //TBD - } - return 0; - } - //For primary set Crop - ctx->setCrop = 1; + overlay_rect rect; ctx->cropRect.x = x; ctx->cropRect.y = y; ctx->cropRect.w = w; ctx->cropRect.h = h; - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(x, y, w, h)); - if (!ret) { - LOGE("set crop failed for framebuffer 1"); - return -1; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->setCrop = true; + break; + case OV_2D_VIDEO_ON_TV: + for (int i=0; ipobjDataChannel[i]->setCrop(x, y, w, h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; } return 0; } @@ -917,7 +1097,7 @@ return 0; int overlay_getBufferCount(struct overlay_data_device_t *dev) { - return( 0 ); + return 0; } @@ -1010,7 +1190,7 @@ return 0; dev->device.common.close = overlay_data_close; dev->device.initialize = overlay_initialize; - dev->device.setCrop = overlay_setCrop; + dev->device.setCrop = overlay_setCrop; dev->device.dequeueBuffer = overlay_dequeueBuffer; dev->device.queueBuffer = overlay_queueBuffer; dev->device.setFd = overlay_setFd; diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 33dd458..ba35210 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -139,6 +139,60 @@ static void reportError(const char* message) { using namespace overlay; +bool overlay::isHDMIConnected () { + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + int isHDMI = atoi(value); + return isHDMI ? true : false; +} + +bool overlay::is3DTV() { + char is3DTV = '0'; + FILE *fp = fopen(EDID_3D_INFO_FILE, "r"); + if (fp) { + fread(&is3DTV, 1, 1, fp); + fclose(fp); + } + LOGI("3DTV EDID flag: %d", is3DTV); + return (is3DTV == '0') ? false : true; +} + +bool overlay::send3DInfoPacket (unsigned int format3D) { + FILE *fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", format3D); + fclose(fp); + fp = NULL; + return true; + } + LOGE("%s:no sysfs entry for setting 3d mode!", __func__); + return false; +} + +unsigned int overlay::getOverlayConfig (unsigned int format3D) { + bool isTV3D = false, isHDMI = false; + unsigned int curState = 0; + isHDMI = overlay::isHDMIConnected(); + if (isHDMI) { + LOGD("%s: HDMI connected... checking the TV type", __func__); + isTV3D = overlay::is3DTV(); + if (format3D) { + if (isTV3D) + curState = OV_3D_VIDEO_3D_TV; + else + curState = OV_3D_VIDEO_2D_TV; + } else + curState = OV_2D_VIDEO_ON_TV; + } else { + LOGD("%s: HDMI not connected...", __func__); + if(format3D) + curState = OV_3D_VIDEO_2D_PANEL; + else + curState = OV_2D_VIDEO_ON_PANEL; + } + return curState; +} + Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), mCloseChannel(false), mS3DFormat(0) { } @@ -160,7 +214,6 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; - if (format3D) zorder = channel; mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, @@ -180,7 +233,7 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); overlay_rect rect; if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, format, &rect)) { - if(!setChannelPosition(rect.x, rect.y, rect.width, rect.height, VG1_PIPE)) { + if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { LOGE("Failed to upscale for framebuffer 1"); return false; } @@ -189,29 +242,20 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { return ret; } -bool Overlay::startChannelS3D(int w, int h, int format, bool norot, int s3DFormat) { - - if (!mHDMIConnected) { - // S3D without HDMI is not supported yet - return true; - } +bool Overlay::startChannelS3D(int w, int h, int format, bool norot) { + bool ret = false; // Start both the channels for the S3D content - bool ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); + if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) + ret = startChannel(w, h, format, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); + else + ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); if (ret) { ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); } - if (ret) { - FILE *fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "%d", mS3DFormat & OUTPUT_MASK_3D); - fclose(fp); - fp = NULL; - } - } - if (!ret) { closeChannel(); - } + } else if (!(mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK)) + ret = overlay::send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D); return ret; } @@ -221,12 +265,7 @@ bool Overlay::closeChannel() { return true; if(mS3DFormat) { - FILE *fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "0"); - fclose(fp); - fp = NULL; - } + overlay::send3DInfoPacket(0); } for (int i = 0; i < NUM_CHANNELS; i++) { objOvCtrlChannel[i].closeControlChannel(); @@ -260,12 +299,16 @@ bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int chann bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { bool ret = false; - for (int i = 0; i < NUM_CHANNELS; i++) { overlay_rect rect; ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); - if (ret) { - setChannelPosition(rect.x, rect.y, rect.width, rect.height, i); + if (!ret) + ret = setChannelPosition(x, y, w, h, i); + else + ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s: failed for channel %d", __func__, i); + return ret; } } return ret; @@ -322,7 +365,15 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, if (!fOut3D) { format3D |= fIn3D >> SHIFT_3D; //Set the output format } - + if (format3D) { + bool isTV3D = false; + if (hdmiConnected) + isTV3D = overlay::is3DTV(); + if (!isTV3D) { + LOGD("Set the output format as monoscopic"); + format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + } int stateChanged = 0; int hw_format = get_mdp_format(colorFormat); int s3dChanged =0, hdmiChanged = 0; @@ -340,9 +391,9 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, mS3DFormat = format3D; if (mHDMIConnected) { - if (format3D) { + if (mS3DFormat) { // Start both the VG pipes - return startChannelS3D(w, h, colorFormat, !orientation, format3D); + return startChannelS3D(w, h, colorFormat, !orientation); } else { return startChannelHDMI(w, h, colorFormat, !orientation); } @@ -359,22 +410,31 @@ bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!mChannelUP) return false; bool ret; + overlay_rect rect, inRect; + inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h; if (mHDMIConnected) { if (mS3DFormat) { - overlay_rect rect; - overlay_rect inRect; - inRect.x = x; inRect.y = y; inRect.width = w; inRect.height = h; - // Set the crop for both VG pipes for (int i = 0; i < NUM_CHANNELS; i++) { objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect); - ret = setChannelCrop(rect.x, rect.y, rect.width, rect.height, i); + ret = setChannelCrop(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s: Failure for channel %d", __func__, i); + return ret; + } } return ret; } else { - setChannelCrop(x, y, w, h, VG1_PIPE); + ret = setChannelCrop(x, y, w, h, VG1_PIPE); + if (!ret) { + LOGE("%s: Failure for channel 1", __func__); + return ret; + } } + } else if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) { + objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect); + return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE); } return setChannelCrop(x, y, w, h, VG0_PIPE); } @@ -423,15 +483,8 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { bool ret = true; if (mHDMIConnected) { - if (mS3DFormat) { - // Queue the buffer on VG1 pipe - if ((mS3DFormat & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || - (mS3DFormat & HAL_3D_OUT_TOP_BOTTOM_MASK)) { - ret = queueBuffer(fd, offset, VG1_PIPE); - } - } else { - ret = queueBuffer(fd, offset, VG1_PIPE); - } + // Queue the buffer on VG1 pipe + ret = queueBuffer(fd, offset, VG1_PIPE); } if (ret && setFd(fd)) { return queueBuffer(offset); @@ -467,8 +520,8 @@ OverlayControlChannel::~OverlayControlChannel() { bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, overlay_rect *rect) { int width = w, height = h, x, y; - int fbWidthHDMI = getFBWidth(); - int fbHeightHDMI = getFBHeight(); + int fbWidth = getFBWidth(); + int fbHeight = getFBHeight(); // width and height for YUV TILE format int tempWidth = w, tempHeight = h; /* Calculate the width and height if it is YUV TILE format*/ @@ -476,17 +529,17 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove tempWidth = w - ( (((w-1)/64 +1)*64) - w); tempHeight = h - ((((h-1)/32 +1)*32) - h); } - if (width * fbHeightHDMI > fbWidthHDMI * height) { - height = fbWidthHDMI * height / width; + if (width * fbHeight > fbWidth * height) { + height = fbWidth * height / width; EVEN_OUT(height); - width = fbWidthHDMI; - } else if (width * fbHeightHDMI < fbWidthHDMI * height) { - width = fbHeightHDMI * width / height; + width = fbWidth; + } else if (width * fbHeight < fbWidth * height) { + width = fbHeight * width / height; EVEN_OUT(width); - height = fbHeightHDMI; + height = fbHeight; } else { - width = fbWidthHDMI; - height = fbHeightHDMI; + width = fbWidth; + height = fbHeight; } /* Scaling of upto a max of 8 times supported */ if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){ @@ -495,54 +548,66 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) { height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight; } - if (width > fbWidthHDMI) width = fbWidthHDMI; - if (height > fbHeightHDMI) height = fbHeightHDMI; - x = (fbWidthHDMI - width) / 2; - y = (fbHeightHDMI - height) / 2; + if (width > fbWidth) width = fbWidth; + if (height > fbHeight) height = fbHeight; + x = (fbWidth - width) / 2; + y = (fbHeight - height) / 2; rect->x = x; rect->y = y; - rect->width = width; - rect->height = height; + rect->w = width; + rect->h = height; return true; } bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) { - int wHDMI = getFBWidth(); - int hHDMI = getFBHeight(); - - if (format & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { + int wDisp = getFBWidth(); + int hDisp = getFBHeight(); + switch (format & OUTPUT_MASK_3D) { + case HAL_3D_OUT_SIDE_BY_SIDE_MASK: if (channel == VG0_PIPE) { rect->x = 0; rect->y = 0; - rect->width = wHDMI/2; - rect->height = hHDMI; + rect->w = wDisp/2; + rect->h = hDisp; } else { - rect->x = wHDMI/2; + rect->x = wDisp/2; rect->y = 0; - rect->width = wHDMI/2; - rect->height = hHDMI; + rect->w = wDisp/2; + rect->h = hDisp; } - } else if (format & HAL_3D_OUT_TOP_BOTTOM_MASK) { + break; + case HAL_3D_OUT_TOP_BOTTOM_MASK: if (channel == VG0_PIPE) { rect->x = 0; rect->y = 0; - rect->width = wHDMI; - rect->height = hHDMI/2; + rect->w = wDisp; + rect->h = hDisp/2; } else { rect->x = 0; - rect->y = hHDMI/2; - rect->width = wHDMI; - rect->height = hHDMI/2; + rect->y = hDisp/2; + rect->w = wDisp; + rect->h = hDisp/2; } - } else if (format & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (format & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - reportError("Unsupported 3D output format"); + break; + case HAL_3D_OUT_MONOSCOPIC_MASK: + if (channel == VG1_PIPE) { + rect->x = 0; + rect->y = 0; + rect->w = wDisp; + rect->h = hDisp; + } + else + return false; + break; + case HAL_3D_OUT_INTERLEAVE_MASK: + break; + default: + reportError("Unsupported 3D output format"); + break; } return true; } + bool OverlayControlChannel::openDevices(int fbnum) { if (fbnum < 0) return false; @@ -675,11 +740,11 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, if(mUIChannel) mRotInfo.enable = 1; mRotInfo.session_id = 0; - int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); - if (result) { + int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); + if (result) { reportError("Rotator session failed"); - ret = false; - } + ret = false; + } } if (!mNoRot && isRGBType(format) && mOrientation && mOVInfo.is_fg) { @@ -807,12 +872,12 @@ bool OverlayControlChannel::startControlChannel(int w, int h, } hw_format = get_mdp_format(colorFormat); if (hw_format < 0) { - reportError("Unsupported format"); + reportError("Unsupported format"); return false; } mFormat3D = format3D; - if (!mFormat3D) { + if ( !mFormat3D || (mFormat3D && HAL_3D_OUT_MONOSCOPIC_MASK) ) { // Set the share bit for sharing the VG pipe flags |= MDP_OV_PIPE_SHARE; } @@ -920,7 +985,7 @@ bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { reportError("setPosition, Overlay SET failed"); - return false; + return false; } mOVInfo = ov; @@ -958,7 +1023,7 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { case OVERLAY_TRANSFORM: { int val = mOVInfo.user_data[0]; - if (value && mNoRot) + if (mNoRot) return true; int rot = value; @@ -1152,7 +1217,7 @@ bool OverlayDataChannel::startDataChannel( memset(&mRotData, 0, sizeof(mRotData)); if (objOvCtrlChannel.getOvSessionID(ovid) && objOvCtrlChannel.getRotSessionID(rotid) && - objOvCtrlChannel.getSize(size)) { + objOvCtrlChannel.getSize(size)) { return startDataChannel(ovid, rotid, size, fbnum, norot, uichannel, num_buffers); } @@ -1277,7 +1342,7 @@ bool OverlayDataChannel::setFd(int fd) { bool OverlayDataChannel::queueBuffer(uint32_t offset) { if ((!isChannelUP()) || mOvData.data.memory_id < 0) { reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from"); - return false; + return false; } msmfb_overlay_data *odPtr; @@ -1296,7 +1361,7 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { if (!result) { mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; - odPtr = &mOvDataRot; + odPtr = &mOvDataRot; } else if (max_num_buffers == mNumBuffers) { reportError("Rotator failed.."); @@ -1306,7 +1371,7 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) { reportError("overlay play failed."); - return false; + return false; } return true; @@ -1314,51 +1379,67 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect) { - - bool ret; - // for the 3D usecase extract L and R channels from a frame - if ( (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || - (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) ) { + // for the 3D usecase extract channels from a frame + switch (format & INPUT_MASK_3D) { + case HAL_3D_IN_SIDE_BY_SIDE_L_R: if(channel == 0) { rect->x = 0; rect->y = 0; - rect->width = inRect->width/2; - rect->height = inRect->height; + rect->w = inRect->w/2; + rect->h = inRect->h; } else { - rect->x = inRect->width/2; + rect->x = inRect->w/2; rect->y = 0; - rect->width = inRect->width/2; - rect->height = inRect->height; + rect->w = inRect->w/2; + rect->h = inRect->h; } - } else if (format & HAL_3D_IN_TOP_BOTTOM) { + break; + case HAL_3D_IN_SIDE_BY_SIDE_R_L: + if(channel == 1) { + rect->x = 0; + rect->y = 0; + rect->w = inRect->w/2; + rect->h = inRect->h; + } else { + rect->x = inRect->w/2; + rect->y = 0; + rect->w = inRect->w/2; + rect->h = inRect->h; + } + break; + case HAL_3D_IN_TOP_BOTTOM: if(channel == 0) { rect->x = 0; rect->y = 0; - rect->width = inRect->width; - rect->height = inRect->height/2; + rect->w = inRect->w; + rect->h = inRect->h/2; } else { rect->x = 0; - rect->y = inRect->height/2; - rect->width = inRect->width; - rect->height = inRect->height/2; + rect->y = inRect->h/2; + rect->w = inRect->w; + rect->h = inRect->h/2; } - } else if (format & HAL_3D_IN_INTERLEAVE) { - //TBD + break; + case HAL_3D_IN_INTERLEAVE: + break; + default: + reportError("Unsupported 3D format..."); + break; } return true; } bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!isChannelUP()) { - reportError("Channel not set"); - return false; + reportError("Channel not set"); + return false; } mdp_overlay ov; ov.id = mOvData.id; if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { reportError("setCrop, overlay GET failed"); - return false; + return false; } if ((ov.user_data[0] == MDP_ROT_90) || diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 55af19f..c7ac671 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * 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. @@ -69,29 +69,41 @@ enum { #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 FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> 12) -#define FORMAT_3D_INPUT(x) (x & 0xF0000) -#define INPUT_MASK_3D 0xFFFF0000 -#define OUTPUT_MASK_3D 0x0000FFFF -#define SHIFT_3D 16 +#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_HALF_MASK ((HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R|HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) >> SHIFT_3D) -#define HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK (HAL_3D_IN_SIDE_BY_SIDE_FULL >> SHIFT_3D) -#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> 12) -#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> 12) +#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) + #define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" +#define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present" /* -------------------------- end 3D defines ----------------------------------------*/ namespace overlay { -const int max_num_buffers = 3; -struct overlay_rect { - int x; - int y; - int width; - int height; +enum { + OV_2D_VIDEO_ON_PANEL = 0, + 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 send3DInfoPacket(unsigned int format3D); +unsigned int getOverlayConfig (unsigned int format3D); + +const int max_num_buffers = 3; +typedef struct mdp_rect overlay_rect; + class OverlayControlChannel { bool mNoRot; @@ -184,8 +196,8 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; - int mS3DFormat; bool mCloseChannel; + unsigned int mS3DFormat; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -221,7 +233,7 @@ public: private: bool startChannelHDMI(int w, int h, int format, bool norot); - bool startChannelS3D(int w, int h, int format, bool norot, int s3DFormat); + bool startChannelS3D(int w, int h, int format, bool norot); bool setPositionS3D(int x, int y, uint32_t w, uint32_t h); bool setParameterS3D(int param, int value); bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0); @@ -232,6 +244,9 @@ private: struct overlay_shared_data { int readyToQueue; + unsigned int state; + int rotid[2]; + int ovid[2]; }; }; #endif From 49f32e10cb859541dcad22f6c0e9b4464b60d4fe Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 24 May 2011 18:03:49 -0700 Subject: [PATCH 379/435] libhwcomposer: Use layer alpha value Set the copybit plane alpha equal to the layer alpha value. Change-Id: Idcb5a23cc5e99061ddd31a3da7bedda2867d579d CRs-fixed: 288257 --- libhwcomposer/hwcomposer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index afea6d4..5eefc66 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -336,7 +336,7 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, copybit_device_t *copybit = hwcModule->copybitEngine; copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->alpha); copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); From c004f71e010429f9252663a7b978dc85d415b47f Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 25 May 2011 22:36:44 -0700 Subject: [PATCH 380/435] liboverlay: Remove RGB specific checks liboverlay assumes RGB format comes from UI, which is incorrect. Remove RGB format checks. Change-Id: I4d3f69db272b0a229fbd449c9c8863d77e7b0a2f --- liboverlay/overlayLib.cpp | 42 +-------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index ba35210..01760bf 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -109,29 +109,6 @@ static int get_mdp_orientation(int rotation, int flip) { return -1; } -static bool isRGBType(int format) { - switch (format) { - case MDP_RGBA_8888: - case MDP_BGRA_8888: - case MDP_RGBX_8888: - case MDP_RGB_565: - return true; - } - return false; -} - -static int getRGBBpp(int format) { - switch (format) { - case MDP_RGBA_8888: - case MDP_BGRA_8888: - case MDP_RGBX_8888: - return 4; - case MDP_RGB_565: - return 2; - } - return -1; -} - #define LOG_TAG "OverlayLIB" static void reportError(const char* message) { LOGE( "%s", message); @@ -383,10 +360,6 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, stateChanged = s3dChanged|hasHDMIStatusChanged(); if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { - if (mChannelUP && isRGBType(hw_format) && (stateChanged != 0x10)) { - mCloseChannel = true; - return false; - } closeChannel(); mS3DFormat = format3D; @@ -709,10 +682,6 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, bool ret = true; if (!mNoRot) { - if (isRGBType(format) && mOVInfo.is_fg) { - w = (w + 31) & ~31; - h = (h + 31) & ~31; - } mRotInfo.src.format = format; mRotInfo.src.width = w; mRotInfo.src.height = h; @@ -747,16 +716,7 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, } } - if (!mNoRot && isRGBType(format) && mOrientation && mOVInfo.is_fg) { - mOVInfo.dst_rect.w = mFBWidth; - mOVInfo.dst_rect.h = mFBHeight; - ret = setParameter(OVERLAY_TRANSFORM, mOrientation, false); - if (!ret) { - reportError("Overlay set failed.. "); - return false; - } - } - else if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { reportError("startOVRotatorSessions, Overlay set failed"); ret = false; } From 371fe1a4428b868e53273db89e8ec6d5ffd21c4a Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 26 May 2011 12:51:11 -0700 Subject: [PATCH 381/435] liboverlay: Update overlay and rotator during resolution change Whenever there is a resolution change, update the overlay, rotator paramters. Map the rotator memory according to the new size required, and unmap the previously mapped memory. Change the size calculation for NV21 formats, since the gralloc allocates memory which is rounded up to the next 4K. Change-Id: Idb4037422cbd80083e6ba14f229511a17cb61873 CRs-fixed: 287347 --- liboverlay/overlayLib.cpp | 291 +++++++++++++++++++------------------- liboverlay/overlayLib.h | 19 ++- 2 files changed, 164 insertions(+), 146 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 01760bf..1f5b816 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -20,6 +20,9 @@ #define INTERLACE_MASK 0x80 /* Helper functions */ +static inline size_t ALIGN(size_t x, size_t align) { + return (x + align-1) & ~(align-1); +} static int get_mdp_format(int format) { switch (format) { @@ -58,9 +61,13 @@ static int get_size(int format, int w, int h) { size *= 2; break; case MDP_Y_CBCR_H2V2: - case MDP_Y_CRCB_H2V2: - size = (size * 3) / 2; - break; + case MDP_Y_CRCB_H2V2: { + int alignedw = ALIGN(w, 16); + int alignedh = h; + size = alignedw*alignedh + + (ALIGN(alignedw/2, 16) * (alignedh/2))*2; + size = ALIGN(size, 4096); + } break; case MDP_Y_CRCB_H2V2_TILE: aligned_height = (h + 31) & ~31; pitch = (w + 127) & ~127; @@ -171,7 +178,8 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { } Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mCloseChannel(false), mS3DFormat(0) { + mCloseChannel(false), mS3DFormat(0), + mWidth(0), mHeight(0) { } Overlay::~Overlay() { @@ -251,6 +259,8 @@ bool Overlay::closeChannel() { mChannelUP = false; mCloseChannel = false; mS3DFormat = 0; + mWidth = 0; + mHeight = 0; return true; } @@ -296,13 +306,32 @@ bool Overlay::updateOverlaySource(uint32_t w, uint32_t h, int format, int orient return setSource(w, h, format, orientation, mHDMIConnected); } - bool ret = true; + bool ret = false; + if (w == mWidth && h == mHeight) { + objOvDataChannel[0].updateDataChannel(0, 0); + return true; + } + // Set the overlay source info if (objOvCtrlChannel[0].isChannelUP()) { - ret = objOvCtrlChannel[0].updateOverlaySource(w, h); + ret = objOvCtrlChannel[0].updateOverlaySource(w, h, format, orientation); + if (!ret) { + LOGE("objOvCtrlChannel[0].updateOverlaySource failed"); + return false; + } + int updateDataChannel = orientation ? 1:0; + int size = get_size(get_mdp_format(format), w, h); + ret = objOvDataChannel[0].updateDataChannel(updateDataChannel, size); + if (ret && objOvCtrlChannel[1].isChannelUP()) - ret = objOvCtrlChannel[1].updateOverlaySource(w, h); + ret = objOvCtrlChannel[1].updateOverlaySource(w, h, format, orientation); } + + if (ret) { + mWidth = w; + mHeight = h; + } else + LOGE("update failed"); return ret; } @@ -363,6 +392,8 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, closeChannel(); mS3DFormat = format3D; + mWidth = w; + mHeight = h; if (mHDMIConnected) { if (mS3DFormat) { // Start both the VG pipes @@ -630,11 +661,8 @@ bool OverlayControlChannel::openDevices(int fbnum) { } bool OverlayControlChannel::setOverlayInformation(int w, int h, - int format, int flags, int zorder, - bool ignoreFB) { - int origW, origH, xoff, yoff; - - mOVInfo.id = MSMFB_NEW_REQUEST; + int format, int flags, int orientation, int zorder, + bool ignoreFB, int requestType) { mOVInfo.src.width = w; mOVInfo.src.height = h; mOVInfo.src_rect.x = 0; @@ -644,7 +672,7 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.dst_rect.w = w; mOVInfo.dst_rect.h = h; if(format == MDP_Y_CRCB_H2V2_TILE) { - if (mNoRot) { + if (!orientation) { mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w); mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h); mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE; @@ -667,21 +695,25 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, mOVInfo.dst_rect.w = mFBWidth; if (h > mFBHeight) mOVInfo.dst_rect.h = mFBHeight; - mOVInfo.z_order = zorder; - mOVInfo.alpha = 0xff; - mOVInfo.transp_mask = 0xffffffff; - mOVInfo.flags = flags; - if (!ignoreFB) - mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + + if (requestType == NEW_REQUEST) { + mOVInfo.id = MSMFB_NEW_REQUEST; + mOVInfo.z_order = zorder; + mOVInfo.alpha = 0xff; + mOVInfo.transp_mask = 0xffffffff; + mOVInfo.flags = flags; + if (!ignoreFB) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + } mSize = get_size(format, w, h); return true; } bool OverlayControlChannel::startOVRotatorSessions(int w, int h, - int format) { + int format, int orientation, int requestType) { bool ret = true; - if (!mNoRot) { + if (orientation) { mRotInfo.src.format = format; mRotInfo.src.width = w; mRotInfo.src.height = h; @@ -704,11 +736,16 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, mRotInfo.dst_y = 0; mRotInfo.src_rect.x = 0; mRotInfo.src_rect.y = 0; - mRotInfo.rotations = 0; - mRotInfo.enable = 0; - if(mUIChannel) + + if (requestType == NEW_REQUEST) { + mRotInfo.rotations = 0; + mRotInfo.enable = 0; + if(mUIChannel) + mRotInfo.enable = 1; + mRotInfo.session_id = 0; + } else mRotInfo.enable = 1; - mRotInfo.session_id = 0; + int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); if (result) { reportError("Rotator session failed"); @@ -727,89 +764,13 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, return ret; } -bool OverlayControlChannel::updateOverlaySource(uint32_t w, uint32_t h) +bool OverlayControlChannel::updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation) { - // Set Rotator info - if (mRotFD >=0) { - if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE) { - if ((mRotInfo.src.width == (((w-1)/64 +1)*64)) && - (mRotInfo.src.height == (((h-1)/32 +1)*32))) - return true; - - mRotInfo.src.width = (((w-1)/64 +1)*64); - mRotInfo.src.height = (((h-1)/32 +1)*32); - mRotInfo.src_rect.w = (((w-1)/64 +1)*64); - mRotInfo.src_rect.h = (((h-1)/32 +1)*32); - mRotInfo.dst.height = (((w-1)/64 +1)*64); - mRotInfo.dst.width = (((h-1)/32 +1)*32); - mRotInfo.dst.format = MDP_Y_CRCB_H2V2; - } else { - if ((mRotInfo.src.width == w) && - (mRotInfo.src.height == h)) - return true; - - mRotInfo.src.width = w; - mRotInfo.src.height = h; - mRotInfo.src_rect.w = w; - mRotInfo.src_rect.h = h; - mRotInfo.dst.width = h; - mRotInfo.dst.height = w; - } - - if (mOVInfo.user_data[0] == MDP_ROT_NOP) - mRotInfo.enable = 0; - - if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) { - LOGE("updateOverlaySource MSM_ROTATOR_IOCTL_START failed"); - return true; - } - } - - // Set overlay info - switch (mOVInfo.user_data[0]) { - case MDP_ROT_90: - case (MDP_ROT_90 | MDP_FLIP_UD): - case (MDP_ROT_90 | MDP_FLIP_LR): - case MDP_ROT_270: { - if ((mOVInfo.src.height == (((w-1)/64 +1)*64)) && - (mOVInfo.src.width == (((h-1)/32 +1)*32))) - return true; - - mOVInfo.src_rect.w = h; - mOVInfo.src_rect.h = w; - mOVInfo.src.height = (((w-1)/64 +1)*64); - mOVInfo.src.width = (((h-1)/32 +1)*32); - mOVInfo.src_rect.x = 0; - mOVInfo.src_rect.y = 0;; - } break; - case MDP_ROT_180: - case MDP_ROT_NOP: { - if ((mOVInfo.src.width == w) && - (mOVInfo.src.height == h)) - return true; - - mOVInfo.src.width = w; - mOVInfo.src.height = h; - mOVInfo.src_rect.x = 0; - mOVInfo.src_rect.y = 0; - if(mOVInfo.src.format == MDP_Y_CRCB_H2V2_TILE) { - mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w); - mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h); - } else { - mOVInfo.src_rect.w = w; - mOVInfo.src_rect.h = h; - } - } break; - default: - LOGE("updateOverlaySource: Invalid rotation parameter"); + int hw_format = get_mdp_format(format); + if (!setOverlayInformation(w, h, hw_format, 0, orientation, 0, 0, UPDATE_REQUEST)) return false; - } - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { - LOGE("updateOverlaySource MSMFB_OVERLAY_SET failed"); - return true; - } - return true; + return startOVRotatorSessions(w, h, hw_format, orientation, UPDATE_REQUEST); } bool OverlayControlChannel::startControlChannel(int w, int h, @@ -844,10 +805,11 @@ bool OverlayControlChannel::startControlChannel(int w, int h, if (!openDevices(fbnum)) return false; - if (!setOverlayInformation(w, h, hw_format, flags, zorder, ignoreFB)) + int orientation = mNoRot ? 0: 1; + if (!setOverlayInformation(w, h, hw_format, flags, orientation, zorder, ignoreFB, NEW_REQUEST)) return false; - return startOVRotatorSessions(w, h, hw_format); + return startOVRotatorSessions(w, h, hw_format, orientation, NEW_REQUEST); } bool OverlayControlChannel::closeControlChannel() { @@ -1160,7 +1122,7 @@ bool OverlayControlChannel::getSize(int& size) const { } OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1), - mPmemFD(-1), mPmemAddr(0) { + mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(0) { } OverlayDataChannel::~OverlayDataChannel() { @@ -1207,49 +1169,61 @@ bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) return false; } - mPmemAddr = MAP_FAILED; + return mapRotatorMemory(num_buffers, uichannel, NEW_REQUEST); + } + return true; +} - if(!uichannel) { - mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC); - if(mPmemFD >= 0) - mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, - MAP_SHARED, mPmemFD, 0); - } +bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int requestType) +{ + mPmemAddr = MAP_FAILED; - if (mPmemAddr == MAP_FAILED) { - mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC); - if (mPmemFD < 0) { - reportError("Cant open pmem_adsp "); + if((requestType == NEW_REQUEST) && !uiChannel) { + mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC); + if(mPmemFD >= 0) + mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, + MAP_SHARED, mPmemFD, 0); + } + + if (mPmemAddr == MAP_FAILED) { + mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC); + if (mPmemFD < 0) { + reportError("Cant open pmem_adsp "); + close(mFD); + mFD = -1; + close(mRotFD); + mRotFD = -1; + return false; + } else { + mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, + MAP_SHARED, mPmemFD, 0); + if (mPmemAddr == MAP_FAILED) { + reportError("Cant map pmem_adsp "); close(mFD); mFD = -1; + close(mPmemFD); + mPmemFD = -1; close(mRotFD); mRotFD = -1; return false; - } else { - mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE, - MAP_SHARED, mPmemFD, 0); - if (mPmemAddr == MAP_FAILED) { - reportError("Cant map pmem_adsp "); - close(mFD); - mFD = -1; - close(mPmemFD); - mPmemFD = -1; - close(mRotFD); - mRotFD = -1; - return false; - } } } - - mOvDataRot.data.memory_id = mPmemFD; - mRotData.dst.memory_id = mPmemFD; - mRotData.dst.offset = 0; - mNumBuffers = num_buffers; - mCurrentItem = 0; - for (int i = 0; i < num_buffers; i++) - mRotOffset[i] = i * mPmemOffset; } + mOvDataRot.data.memory_id = mPmemFD; + mRotData.dst.memory_id = mPmemFD; + mRotData.dst.offset = 0; + mNumBuffers = num_buffers; + mCurrentItem = 0; + for (int i = 0; i < num_buffers; i++) + mRotOffset[i] = i * mPmemOffset; + + return true; +} + +bool OverlayDataChannel::updateDataChannel(int updateStatus, int size) { + mUpdateDataChannel = updateStatus; + mNewPmemOffset = size; return true; } @@ -1277,6 +1251,7 @@ bool OverlayDataChannel::closeDataChannel() { if (!mNoRot && mRotFD > 0) { munmap(mPmemAddr, mPmemOffset * mNumBuffers); + close(mPmemFD); mPmemFD = -1; close(mRotFD); @@ -1305,10 +1280,41 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { return false; } + int oldPmemFD = -1; + void* oldPmemAddr = MAP_FAILED; + uint32_t oldPmemOffset = -1; + bool result; + if (!mNoRot) { + if (mUpdateDataChannel) { + oldPmemFD = mPmemFD; + oldPmemAddr = mPmemAddr; + oldPmemOffset = mPmemOffset; + mPmemOffset = mNewPmemOffset; + mNewPmemOffset = -1; + // Map the new PMEM memory + result = mapRotatorMemory(mNumBuffers, 0, UPDATE_REQUEST); + if (!result) { + LOGE("queueBuffer: mapRotatorMemory failed"); + return false; + } + } + } + + result = queue(offset); + + // Unmap the old PMEM memory after the queueBuffer has returned + if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) { + munmap(oldPmemAddr, oldPmemOffset * mNumBuffers); + close(oldPmemFD); + oldPmemFD = -1; + } + return result; +} + +bool OverlayDataChannel::queue(uint32_t offset) { msmfb_overlay_data *odPtr; mOvData.data.offset = offset; odPtr = &mOvData; - if (!mNoRot) { mRotData.src.memory_id = mOvData.data.memory_id; mRotData.src.offset = offset; @@ -1317,7 +1323,7 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { mCurrentItem = (mCurrentItem + 1) % mNumBuffers; int result = ioctl(mRotFD, - MSM_ROTATOR_IOCTL_ROTATE, &mRotData); + MSM_ROTATOR_IOCTL_ROTATE, &mRotData); if (!result) { mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; @@ -1333,7 +1339,6 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { reportError("overlay play failed."); return false; } - return true; } diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index c7ac671..3636b20 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -60,6 +60,11 @@ 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, @@ -123,8 +128,9 @@ class OverlayControlChannel { msm_rotator_img_info mRotInfo; bool openDevices(int fbnum = -1); bool setOverlayInformation(int w, int h, int format, - int flags, int zorder = 0, bool ignoreFB = false); - bool startOVRotatorSessions(int w, int h, int format); + int flags, int orientation, int zorder = 0, bool ignoreFB = false, + int requestType = NEW_REQUEST); + bool startOVRotatorSessions(int w, int h, int format, int orientation, int requestType); void swapOVRotWidthHeight(); public: @@ -151,7 +157,7 @@ public: int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); - bool updateOverlaySource(uint32_t w, uint32_t h); + bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation); }; class OverlayDataChannel { @@ -162,14 +168,18 @@ class OverlayDataChannel { 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; 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(); @@ -186,6 +196,7 @@ public: 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); }; /* @@ -198,6 +209,8 @@ class Overlay { bool mHDMIConnected; bool mCloseChannel; unsigned int mS3DFormat; + int mWidth; + int mHeight; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; From c17c053935bed196ef4a295129a3f6a29baaa180 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Wed, 1 Jun 2011 10:23:25 -0700 Subject: [PATCH 382/435] libhwcomposer: Disable alpha if layer blending is disabled If the layer blending has been disabled, disable copybit alpha so that copybit does not perform any blend operation. Change-Id: I9a83fad0f126adaf9540bc72d17e7dcb1c55cd0f CRs-fixed: 288527 --- libhwcomposer/hwcomposer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 5eefc66..a504de9 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -336,7 +336,8 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, copybit_device_t *copybit = hwcModule->copybitEngine; copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->alpha); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, + (layer->blending == HWC_BLENDING_NONE) ? 0xFF : layer->alpha); copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); From 58c70bc3e59ac241aa25cb28d17fbd03fc814a4f Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Fri, 20 May 2011 13:57:35 -0700 Subject: [PATCH 383/435] Fix positioning of small videos. Small videos (width < 128) have their stride as 128. For HDMI destination position was set only once, before the actual width was supplied through crop. Now the position is set during a setPosition API call. Change-Id: If49ac23b9294951aaf4ad9d5432653082b4a7802 CRs-fixed: 286953 --- liboverlay/overlay.cpp | 2 +- liboverlay/overlayLib.cpp | 15 ++++++++++----- liboverlay/overlayLib.h | 5 +++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index db8468b..9f9075f 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -198,7 +198,7 @@ public: if (!mHandle.pobjControlChannel[channel]) return false; return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, - mHandle.h, mHandle.format, rect); + mHandle.h, rect); } bool setParameter(int param, int value, int channel) { diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 1f5b816..ce79f6e 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -217,7 +217,7 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { if(ret) { ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); overlay_rect rect; - if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, format, &rect)) { + if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, &rect)) { if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { LOGE("Failed to upscale for framebuffer 1"); return false; @@ -275,9 +275,13 @@ bool Overlay::getOrientation(int& orientation, int channel) const { bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { if(mS3DFormat && mHDMIConnected) { return setPositionS3D(x, y, w, h); - } else { - return setChannelPosition(x, y, w, h, VG0_PIPE); } + if(mHDMIConnected) { + overlay_rect rect; + objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, &rect); + setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE); + } + return setChannelPosition(x, y, w, h, VG0_PIPE); } bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) { @@ -521,7 +525,7 @@ OverlayControlChannel::~OverlayControlChannel() { closeControlChannel(); } -bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, overlay_rect *rect) +bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *rect) { int width = w, height = h, x, y; int fbWidth = getFBWidth(); @@ -529,7 +533,7 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove // width and height for YUV TILE format int tempWidth = w, tempHeight = h; /* Calculate the width and height if it is YUV TILE format*/ - if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + if(getFormat() == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { tempWidth = w - ( (((w-1)/64 +1)*64) - w); tempHeight = h - ((((h-1)/32 +1)*32) - h); } @@ -779,6 +783,7 @@ bool OverlayControlChannel::startControlChannel(int w, int h, unsigned int format3D, int zorder, bool ignoreFB) { mNoRot = norot; + mFormat = format; mUIChannel = uichannel; fb_fix_screeninfo finfo; fb_var_screeninfo vinfo; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 3636b20..be87445 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -117,7 +117,7 @@ class OverlayControlChannel { int mFBHeight; int mFBbpp; int mFBystride; - + int mFormat; int mFD; int mRotFD; int mSize; @@ -155,9 +155,10 @@ public: bool getOrientation(int& orientation) const; bool setSource(uint32_t w, uint32_t h, int format, int orientation, bool ignoreFB); - bool getAspectRatioPosition(int w, int h, int format, overlay_rect *rect); + bool getAspectRatioPosition(int w, int h, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation); + bool getFormat() const { return mFormat; } }; class OverlayDataChannel { From 3ce61a332f86066bc0073928739bb95f0ade1715 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Wed, 1 Jun 2011 16:41:33 -0700 Subject: [PATCH 384/435] Set Position for HDMI in setPosition This is necessary to adjust aspect ratio based on the crop, since src values are modified in crop. Change-Id: Icfb20df5b6ac4e93dfa85b73c4f74b738a4d3e59 CRs-fixed: 290069 --- liboverlay/overlayLib.cpp | 28 ++++++++++++++-------------- liboverlay/overlayLib.h | 4 +++- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index ce79f6e..f4b4609 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -179,7 +179,8 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), mCloseChannel(false), mS3DFormat(0), - mWidth(0), mHeight(0) { + mWidth(0), mHeight(0), + mCroppedSrcWidth(0), mCroppedSrcHeight(0) { } Overlay::~Overlay() { @@ -199,6 +200,8 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; + mCroppedSrcWidth = w; + mCroppedSrcHeight = h; if (format3D) zorder = channel; mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, @@ -216,13 +219,6 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { bool ret = startChannel(w, h, format, FRAMEBUFFER_0, norot); if(ret) { ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); - overlay_rect rect; - if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, &rect)) { - if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { - LOGE("Failed to upscale for framebuffer 1"); - return false; - } - } } return ret; } @@ -273,13 +269,15 @@ bool Overlay::getOrientation(int& orientation, int channel) const { } bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { - if(mS3DFormat && mHDMIConnected) { - return setPositionS3D(x, y, w, h); - } if(mHDMIConnected) { - overlay_rect rect; - objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, &rect); - setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE); + if(mS3DFormat) { + return setPositionS3D(x, y, w, h); + } else { + overlay_rect rect; + objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth, + mCroppedSrcHeight, &rect); + setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE); + } } return setChannelPosition(x, y, w, h, VG0_PIPE); } @@ -420,6 +418,8 @@ bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { bool ret; overlay_rect rect, inRect; inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h; + mCroppedSrcWidth = w; + mCroppedSrcHeight = h; if (mHDMIConnected) { if (mS3DFormat) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index be87445..4d7f2ea 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -212,7 +212,9 @@ class Overlay { unsigned int mS3DFormat; int mWidth; int mHeight; - + //Actual cropped source width and height of overlay + int mCroppedSrcWidth; + int mCroppedSrcHeight; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; From 42c6d7297720070286bf3b316019ae2fdb0f2190 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 26 May 2011 12:37:07 -0700 Subject: [PATCH 385/435] libgralloc-qsd8k: Remove submaps for PmemKernelAllocators Removing submapping for buffers allocated by the PmemKernelAllocator This can be done since the restriction on multiple master maps has been removed from the kernel Change-Id: Iabe9cdfaa121bbffbfaf6503e037afebf5ac8455 --- libgralloc-qsd8k/gpu.cpp | 8 ++---- libgralloc-qsd8k/gralloc_priv.h | 5 ++-- libgralloc-qsd8k/pmemalloc.cpp | 46 ++++++++------------------------- libgralloc-qsd8k/pmemalloc.h | 9 +++---- 4 files changed, 18 insertions(+), 50 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 85680b8..9f70fbe 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -169,7 +169,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // the PmemAllocator rather than getting the base & offset separately int offset = 0; int lockState = 0; - int masterFd = -1; + size = roundUpToPageSize(size); #ifndef USE_ASHMEM if (usage & GRALLOC_USAGE_HW_TEXTURE) { @@ -219,7 +219,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // PMEM buffers are always mmapped lockState |= private_handle_t::LOCK_STATE_MAPPED; - err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, &masterFd, format); + err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format); if (err < 0) { if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { @@ -245,7 +245,6 @@ try_ashmem: hnd->offset = offset; hnd->base = int(base)+offset; hnd->lockState = lockState; - hnd->masterFd = masterFd; *pHandle = hnd; } @@ -394,9 +393,6 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { } deps.close(hnd->fd); - if (hnd->masterFd != -1) { - deps.close(hnd->masterFd); - } delete hnd; // XXX JMG: move this to the deps return 0; } diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 228b6be..6804c41 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -283,17 +283,16 @@ struct private_handle_t { int format; int width; int height; - int masterFd; #ifdef __cplusplus - static const int sNumInts = 14; + static const int sNumInts = 13; static const int sNumFds = 1; static const int sMagic = 'gmsm'; 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), masterFd(-1) + height(height) { version = sizeof(native_handle); numInts = sNumInts; diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index 6604e25..126004d 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -143,7 +143,7 @@ int PmemUserspaceAllocator::init_pmem_area() int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, - void** pBase, int* pOffset, int* pFd, int* masterFd, int format) + void** pBase, int* pOffset, int* pFd, int format) { BEGIN_FUNC; int err = init_pmem_area(); @@ -187,7 +187,6 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, *pBase = base; *pOffset = offset; *pFd = fd; - *masterFd = -1; } //LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset); } @@ -262,7 +261,7 @@ static unsigned clp2(unsigned x) { int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, - void** pBase,int* pOffset, int* pFd, int* masterFd, int format) + void** pBase,int* pOffset, int* pFd, int format) { BEGIN_FUNC; @@ -283,8 +282,8 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, return -EINVAL; } - int master_fd = deps.open(device, openFlags, 0); - if (master_fd < 0) { + int fd = deps.open(device, openFlags, 0); + if (fd < 0) { err = -deps.getErrno(); END_FUNC; LOGE("Error opening %s", device); @@ -296,49 +295,26 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { // Tile format buffers need physical alignment to 8K - err = deps.alignPmem(master_fd, size, 8192); + err = deps.alignPmem(fd, size, 8192); if (err < 0) { LOGE("alignPmem failed"); } } - void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); + 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", device, strerror(deps.getErrno())); err = -deps.getErrno(); - deps.close(master_fd); + deps.close(fd); END_FUNC; return err; } memset(base, 0, size); - - // Connect and map the PMEM region to give to the client process - int fd = deps.open(device, O_RDWR, 0); - err = fd < 0 ? fd : 0; - // and connect to it - if (err == 0) { - err = deps.connectPmem(fd, master_fd); - } - - // and make it available to the client process - if (err == 0) { - err = deps.mapPmem(fd, offset, size); - } - - if (err == 0) { - *pBase = base; - *pOffset = 0; - *pFd = fd; - *masterFd = master_fd; - } else { - deps.munmap(base, size); - deps.unmapPmem(fd, offset, size); - deps.close(fd); - deps.close(master_fd); - return err; - } + *pBase = base; + *pOffset = 0; + *pFd = fd; END_FUNC; return 0; @@ -352,7 +328,7 @@ int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, i // like we did when allocating. //size = clp2(size); - int err = deps.unmapPmem(fd, offset, size); + int err = deps.munmap(base, size); if (err < 0) { err = deps.getErrno(); LOGW("error unmapping pmem fd: %s", strerror(err)); diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h index a6d98b8..c64d9be 100755 --- a/libgralloc-qsd8k/pmemalloc.h +++ b/libgralloc-qsd8k/pmemalloc.h @@ -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, int* masterFd, int format) = 0; + int* pOffset, int* pFd, int format) = 0; virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0; }; @@ -89,7 +89,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* masterFd, int format); + int* pOffset, int* pFd, int format); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); #ifndef ANDROID_OS @@ -139,9 +139,6 @@ 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 connectPmem(int fd, int master_fd) = 0; - virtual int mapPmem(int fd, int offset, size_t size) = 0; - virtual int unmapPmem(int fd, int offset, size_t size) = 0; virtual int alignPmem(int fd, size_t size, int align) = 0; }; @@ -152,7 +149,7 @@ class PmemKernelAllocator: public PmemAllocator { virtual void* get_base_address(); virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase, - int* pOffset, int* pFd, int* masterFd, int format); + int* pOffset, int* pFd, int format); virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd); private: From 9d25efb3610cde920cd1024280f47143ab7b4acd Mon Sep 17 00:00:00 2001 From: Jeff Boody Date: Wed, 1 Jun 2011 16:07:40 -0600 Subject: [PATCH 386/435] libhwcomposer: return error if Android native buffer is null Change-Id: I78d35779aa0d15086828ad1cf10ce6ff8b844336 --- libhwcomposer/hwcomposer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index a504de9..d71f703 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -318,6 +318,7 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface); if (!renderBuffer) { LOGE("eglGetRenderBufferANDROID returned NULL buffer"); + return -1; } private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; if(!fbHandle) { From dac6f95b569afab7e3beac95c56d270fa6767e42 Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Sat, 5 Mar 2011 09:30:05 -0800 Subject: [PATCH 387/435] liboverlay: comp. bypass changes. This change addresses following: 1. Add new classes for comp. bypass. 2. Remove comp. bypas specific code from exisiting flow. Change-Id: Id9424b42a9a113cfbb18ceac8d59bbe07ea8e773 --- liboverlay/Android.mk | 6 +- liboverlay/overlayLib.cpp | 19 +- liboverlay/overlayLib.h | 6 +- liboverlay/overlayLibUI.cpp | 491 ++++++++++++++++++++++++++++++++++++ liboverlay/overlayLibUI.h | 152 +++++++++++ 5 files changed, 657 insertions(+), 17 deletions(-) create mode 100644 liboverlay/overlayLibUI.cpp create mode 100644 liboverlay/overlayLibUI.h diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index 0beefbe..d271fb5 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -1,4 +1,5 @@ # 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. @@ -22,7 +23,10 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils 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_SRC_FILES := overlayLib.cpp +LOCAL_SRC_FILES := \ + overlayLib.cpp \ + overlayLibUI.cpp \ +LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\" LOCAL_MODULE := liboverlay include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index f4b4609..f9bd8b0 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -24,7 +24,7 @@ static inline size_t ALIGN(size_t x, size_t align) { return (x + align-1) & ~(align-1); } -static int get_mdp_format(int format) { +int overlay::get_mdp_format(int format) { switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888 : return MDP_RGBA_8888; @@ -46,7 +46,7 @@ static int get_mdp_format(int format) { return -1; } -static int get_size(int format, int w, int h) { +int overlay::get_size(int format, int w, int h) { int size, aligned_height, pitch; size = w * h; @@ -84,7 +84,7 @@ static int get_size(int format, int w, int h) { return size; } -static int get_mdp_orientation(int rotation, int flip) { +int overlay::get_mdp_orientation(int rotation, int flip) { switch(flip) { case HAL_TRANSFORM_FLIP_V: switch(rotation) { @@ -178,8 +178,7 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { } Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mCloseChannel(false), mS3DFormat(0), - mWidth(0), mHeight(0), + mS3DFormat(0), mWidth(0), mHeight(0), mCroppedSrcWidth(0), mCroppedSrcHeight(0) { } @@ -242,7 +241,7 @@ bool Overlay::startChannelS3D(int w, int h, int format, bool norot) { bool Overlay::closeChannel() { - if (!mCloseChannel && !mChannelUP) + if (!mChannelUP) return true; if(mS3DFormat) { @@ -253,7 +252,6 @@ bool Overlay::closeChannel() { objOvDataChannel[i].closeDataChannel(); } mChannelUP = false; - mCloseChannel = false; mS3DFormat = 0; mWidth = 0; mHeight = 0; @@ -355,9 +353,6 @@ int Overlay::hasHDMIStatusChanged() { bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, bool hdmiConnected, bool ignoreFB, int num_buffers) { - if (mCloseChannel) - closeChannel(); - // Separate the color format from the 3D format. // If there is 3D content; the effective format passed by the client is: // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat @@ -1334,10 +1329,6 @@ bool OverlayDataChannel::queue(uint32_t offset) { mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; odPtr = &mOvDataRot; } - else if (max_num_buffers == mNumBuffers) { - reportError("Rotator failed.."); - return false; - } } if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 4d7f2ea..fbc6c60 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -100,12 +100,15 @@ enum { OV_3D_VIDEO_3D_PANEL, OV_3D_VIDEO_3D_TV }; - bool isHDMIConnected(); bool is3DTV(); bool send3DInfoPacket(unsigned int format3D); unsigned int getOverlayConfig (unsigned int format3D); +int get_mdp_format(int format); +int get_size(int format, int w, int h); +int get_mdp_orientation(int rotation, int flip); + const int max_num_buffers = 3; typedef struct mdp_rect overlay_rect; @@ -208,7 +211,6 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; - bool mCloseChannel; unsigned int mS3DFormat; int mWidth; int mHeight; diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp new file mode 100644 index 0000000..5066681 --- /dev/null +++ b/liboverlay/overlayLibUI.cpp @@ -0,0 +1,491 @@ +/* + * 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" + +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; + } + + bool displayAttrsCheck = ((w == ov.src.width) && (h == 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; + ovInfo.src.width = w; + ovInfo.src.height = h; + 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; + w = (w + 31) & ~31; + h = (h + 31) & ~31; + rotInfo.src.width = w; + rotInfo.src.height = h; + rotInfo.src_rect.w = w; + rotInfo.src_rect.h = h; + rotInfo.dst.width = w; + rotInfo.dst.height = h; + + int rot = orientation; + int flip = 0; + switch(rot) { + case 0: + case HAL_TRANSFORM_FLIP_H: + case HAL_TRANSFORM_FLIP_V: + rot = 0; + flip = orientation & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); + 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; + flip = orientation & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); + 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, flip); + 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 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; + } + + mSessionID = rotInfo.session_id; + mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC); + if (mPmemFD < 0) { + closeRotSession(); + return NO_INIT; + } + + mSize = get_size(rotInfo.src.format, rotInfo.src.width, rotInfo.src.height); + mPmemAddr = (void *) mmap(NULL, mSize* mNumBuffers, PROT_READ | PROT_WRITE, + MAP_SHARED, mPmemFD, 0); + if (mPmemAddr == MAP_FAILED) { + closeRotSession(); + return NO_INIT; + } + + 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); + munmap(mPmemAddr, mSize * mNumBuffers); + 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(int w, int h, int format, int orientation, + bool useVGPipe, bool ignoreFB, + int fbnum, int zorder) { + status_t ret = NO_INIT; + + int format3D = FORMAT_3D(format); + int colorFormat = COLOR_FORMAT(format); + 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(w, h, 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(w, h, 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); + return ret; +} + +status_t OverlayUI::startChannel(int fbnum, mdp_overlay& ovInfo, + msm_rotator_img_info& rotInfo) { + status_t ret = BAD_VALUE; + if (mChannelState == UP) + return ret; + + ret = mobjOVHelper.startOVSession(ovInfo, fbnum); + if (ret == NO_ERROR && mOrientation) + ret = mobjRotator.startRotSession(rotInfo); + + 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 + (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; +} + +}; diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h new file mode 100644 index 0000000..bf749fa --- /dev/null +++ b/liboverlay/overlayLibUI.h @@ -0,0 +1,152 @@ +/* + * 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 + +#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; + Rotator(const Rotator& objROtator); + Rotator& operator=(const Rotator& objRotator); + +public: + explicit Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1) { }; + ~Rotator() { closeRotSession(); } + status_t startRotSession(msm_rotator_img_info& rotInfo, 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); +public: + + enum fbnum_t { FB0, FB1 }; + + explicit OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT), mFBNum(NO_INIT) { }; + ~OverlayUI() { closeChannel(); }; + status_t setSource(int w, int h, int format, 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 From d739bf81ce71efa845d6169351e6f240993dcb3c Mon Sep 17 00:00:00 2001 From: Sushil Chauhan Date: Thu, 9 Jun 2011 09:13:31 -0700 Subject: [PATCH 388/435] copybit_c2d.cpp: Return the correct status in open_copybit() The patch sets the status as COPYBIT_FAILURE in case of an error in open_copybit() as it needs to return the correct status. It also sets the copybit device handle as NULL. Change-Id: I3c35d163049763427ad92030cb1d88d72f7680fb --- libcopybit/copybit_c2d.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 3d5ab6d..63493d7 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -901,7 +901,6 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW); if (!ctx->libc2d2) { LOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); - status = COPYBIT_FAILURE; goto error; } *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2, @@ -922,7 +921,6 @@ static int open_copybit(const struct hw_module_t* module, const char* name, || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish || !LINK_c2dDestroySurface) { LOGE("%s: dlsym ERROR", __func__); - status = COPYBIT_FAILURE; goto error1; } @@ -939,7 +937,6 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->g12_device_fd = open(G12_DEVICE_NAME, O_RDWR | O_SYNC); if(ctx->g12_device_fd < 0) { LOGE("%s: g12_device_fd open failed", __func__); - status = COPYBIT_FAILURE; goto error1; } @@ -955,7 +952,6 @@ static int open_copybit(const struct hw_module_t* module, const char* name, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), &surfDefinition)) { LOGE("%s: create ctx->dst failed", __func__); - status = COPYBIT_FAILURE; goto error2; } @@ -963,7 +959,6 @@ static int open_copybit(const struct hw_module_t* module, const char* name, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), &surfDefinition)) { LOGE("%s: create ctx->src[RGB_SURFACE] failed", __func__); - status = COPYBIT_FAILURE; goto error3; } @@ -984,16 +979,10 @@ static int open_copybit(const struct hw_module_t* module, const char* name, (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), &yuvSurfaceDef)) { LOGE("%s: create ctx->src[YUV_SURFACE] failed", __func__); - status = COPYBIT_FAILURE; goto error4; } - if (status == COPYBIT_SUCCESS) - *device = &ctx->device.common; - else { - close_copybit(&ctx->device.common); - goto error4; - } + *device = &ctx->device.common; while ((fd==-1) && device_template[i]) { snprintf(fbName, 64, device_template[i], 0); @@ -1001,11 +990,11 @@ static int open_copybit(const struct hw_module_t* module, const char* name, i++; } if (fd < 0) - goto error4; + goto error5; struct fb_var_screeninfo info; if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - goto error5; + goto error6; ctx->fb_width = info.xres; ctx->fb_height = info.yres; @@ -1013,9 +1002,11 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->isPremultipliedAlpha = false; return status; -error5: +error6: close(fd); fd = -1; +error5: + LINK_c2dDestroySurface(ctx->src[YUV_SURFACE]); error4: LINK_c2dDestroySurface(ctx->src[RGB_SURFACE]); error3: @@ -1026,6 +1017,8 @@ error1: ::dlclose(ctx->libc2d2); error: free(ctx); + status = COPYBIT_FAILURE; + *device = NULL; return status; } From 07e8ae7fe48bf3d1c0ae46dff260c4bccf32f64c Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 7 Jun 2011 11:59:40 -0700 Subject: [PATCH 389/435] libhwcomposer: Skip composition if there is no UI update If we have only one overlay layer, and the rest of the layers are not updating, set the HWC_SKIP_COMPOSITION flag to inform SurfaceFlinger not to compose anything. Also skip the drawing of any UI frames and swapping the buffers. Change-Id: I2f6554c905756a08880cba531c0210a58396179b CRs-fixed: 289477 --- libhwcomposer/hwcomposer.cpp | 43 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index d71f703..32d0b3f 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -71,6 +71,7 @@ struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; + int previousLayerCount; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -198,7 +199,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { int yuvBufferCount = 0; int layerType = 0; - if (list && (list->flags & HWC_GEOMETRY_CHANGED)) { + int numLayersNotUpdating = 0; + if (list) { for (size_t i=0 ; inumHwLayers; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)) { @@ -206,6 +208,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { if (yuvBufferCount > 1) { break; } + } else if (list->hwLayers[i].flags & HWC_LAYER_NOT_UPDATING) { + numLayersNotUpdating++; } } @@ -227,9 +231,23 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } - layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; - // Inform the gralloc of the current HDMI status - hwc_updateOverlayStatus(ctx, layerType); + bool compCountChanged = false; + if (list->numHwLayers != ctx->previousLayerCount) { + compCountChanged = true; + ctx->previousLayerCount = list->numHwLayers; + } + if ((yuvBufferCount == 1) && ((list->numHwLayers-1) == numLayersNotUpdating) + && !compCountChanged) { + list->flags |= HWC_SKIP_COMPOSITION; + } else { + list->flags &= ~HWC_SKIP_COMPOSITION; + } + + if (list->flags & HWC_GEOMETRY_CHANGED) { + layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; + // Inform the gralloc of the current HDMI status + hwc_updateOverlayStatus(ctx, layerType); + } } return 0; @@ -448,22 +466,27 @@ static int hwc_set(hwc_composer_device_t *dev, LOGE("hwc_set null module "); return -1; } - for (size_t i=0 ; inumHwLayers ; i++) { + for (size_t i=0; inumHwLayers; i++) { if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; } if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); + } else if (list->flags & HWC_SKIP_COMPOSITION) { + break; } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) { - drawLayerUsingCopybit(dev, &(list->hwLayers[i]), (EGLDisplay)dpy, (EGLSurface)sur); + drawLayerUsingCopybit(dev, &(list->hwLayers[i]), (EGLDisplay)dpy, (EGLSurface)sur); } } - EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); - if (!sucess) { - return HWC_EGL_ERROR; - } + // Do not call eglSwapBuffers if we the skip composition flag is set on the list. + if (!(list->flags & HWC_SKIP_COMPOSITION)) { + EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + if (!sucess) { + return HWC_EGL_ERROR; + } + } return 0; } From 3a6d435d3593e4dca950414488add7cf179595ce Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 23 May 2011 11:50:50 -0700 Subject: [PATCH 390/435] liboverlay: Set the correct FLIP information Android expects the flip to be done before the rotation. The rotator however performs the rotate operation first followed by flip operations. Set the flip information to take this into account. Change-Id: Ib59a08e72fad522b0cf70c2ac2c434e19683c356 CRs-fixed: 289118 --- liboverlay/overlayLib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index f9bd8b0..e9365ee 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -89,7 +89,7 @@ int overlay::get_mdp_orientation(int rotation, int flip) { case HAL_TRANSFORM_FLIP_V: switch(rotation) { case 0: return MDP_FLIP_UD; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); default: return -1; break; } @@ -97,7 +97,7 @@ int overlay::get_mdp_orientation(int rotation, int flip) { case HAL_TRANSFORM_FLIP_H: switch(rotation) { case 0: return MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); + case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); default: return -1; break; } From 4066a02c8328193a98fd033de20c287cb223f933 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 14 Jun 2011 13:52:22 -0700 Subject: [PATCH 391/435] libhwcomposer: Honor the HWC_DO_NOT_USE_OVERLAY flag If SurfaceFlinger marks a layer with the HWC_DO_NOT_USE_OVERLAY flag, do not use the overlay to draw the layer (cherry picked from commit 9271a839b6bbbdc7b22bd7f1dca6f4c0c63de965) Change-Id: Ie44586a1254a2dc2ad41ae902debc5bb442cbfde --- libhwcomposer/hwcomposer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 32d0b3f..c3d8f29 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -57,7 +57,8 @@ enum HWCCompositionType { }; enum HWCPrivateFlags { - HWC_USE_ORIGINAL_RESOLUTION = 0x10000000, // This layer is to be drawn using overlays + HWC_USE_ORIGINAL_RESOLUTION = HWC_FLAGS_PRIVATE_0, // This layer is to be drawn using overlays + HWC_DO_NOT_USE_OVERLAY = HWC_FLAGS_PRIVATE_1, // Do not use overlays to draw this layer }; enum HWCLayerType{ @@ -203,7 +204,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { if (list) { for (size_t i=0 ; inumHwLayers; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; - if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)) { + if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && + !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) { yuvBufferCount++; if (yuvBufferCount > 1) { break; From 1efe8832e953eeb6798aaa6f358c07480e0df047 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 21 Jun 2011 17:53:39 -0700 Subject: [PATCH 392/435] libgralloc-qsd8k: ashmem changes - Remove unused GRALLOC_USAGE_PRIVATE_PMEM flag. This flag is no longer used. - Flush ashmem region cache instead of Invalidating it. (cherry picked from commit 12254ff74f5a97dcf5ded90f53e9d6fd0fa47b9c) Change-Id: I92e4dcd8c89eb9ae0c0484f039d152b7bbb28bbe --- libgralloc-qsd8k/gpu.cpp | 4 ---- libgralloc-qsd8k/mapper.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index 9f70fbe..b4e00ca 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -181,10 +181,6 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* if (usage & GRALLOC_USAGE_HW_2D) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } -#else - if (usage & GRALLOC_USAGE_PRIVATE_PMEM){ - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - } #endif if ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) || (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL)) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 444a2ff..d32fc28 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -291,7 +291,7 @@ int gralloc_unlock(gralloc_module_t const* module, 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_CLEAN_RANGE, NULL); + err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL); } LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n", From fc966d144884be2e6ef01780ed30d1dc720b9c06 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Fri, 6 May 2011 19:13:59 -0700 Subject: [PATCH 393/435] Remove FPS calculations from userspace. The FPS is stored in reserved[4] field of fb_var_screeninfo structure. Read directly from this field. CRs-fixed: 283750 (cherry picked from commit 0dec3f333db5b58c5ddd9c65fb7fd5c61cc5ef59) Change-Id: I26632dc489ed8a95502b9071fed5b7527b33e54d --- libgralloc-qsd8k/framebuffer.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 794adb4..dd961b2 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -687,18 +687,6 @@ int mapFrameBufferLocked(struct private_module_t* module) if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) return -errno; - int refreshRate = 1000000000000000LLU / - ( - uint64_t( info.upper_margin + info.lower_margin + info.yres ) - * ( info.left_margin + info.right_margin + info.xres ) - * info.pixclock - ); - - if (refreshRate == 0) { - // bleagh, bad info from the driver - refreshRate = 60*1000; // 60 Hz - } - if (int(info.width) <= 0 || int(info.height) <= 0) { // the driver doesn't return that information // default to 160 dpi @@ -708,7 +696,8 @@ int mapFrameBufferLocked(struct private_module_t* module) float xdpi = (info.xres * 25.4f) / info.width; float ydpi = (info.yres * 25.4f) / info.height; - float fps = refreshRate / 1000.0f; + //The reserved[4] field is used to store FPS by the driver. + float fps = info.reserved[4]; LOGI( "using (fd=%d)\n" "id = %s\n" From cb098e76e82b432eb937f8aa884bc1522f43c1fd Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Thu, 16 Jun 2011 15:35:56 -0700 Subject: [PATCH 394/435] Handle overlay setup failure Separate overlay setup and overlay play. On setup failure, mark the layer to use C2D if enabled. Else mark the layer to use GPU. CRs-fixed: 292398 (cherry picked from commit b1459b0b1106ed66810b1c5a09878fae353c123c) Change-Id: Id4c27384193612ab13e87d18492b0fef662eb8b4 --- libhwcomposer/hwcomposer.cpp | 167 +++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 67 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index c3d8f29..3ec53fa 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -41,6 +41,8 @@ /*****************************************************************************/ #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) // Enum containing the supported composition types enum { @@ -181,6 +183,88 @@ static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { return 0; } +/* + * Configures mdp pipes + */ +static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { + int ret = 0; + if (LIKELY(ctx && ctx->mOverlayLibObject)) { + private_hwc_module_t* hwcModule = + reinterpret_cast(ctx->device.common.module); + if (UNLIKELY(!hwcModule)) { + LOGE("prepareOverlay null module "); + return -1; + } + + private_handle_t *hnd = (private_handle_t *)layer->handle; + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + int orientation = 0; + if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) + ovLibObject->getOrientation(orientation); + + if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) + || (layer->transform != orientation) || + (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { + // Overlay channel is not started, or we have an orientation change + // or there is a format change, call setSource to open the overlay + // if necessary + ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, + layer->transform, (ovLibObject->getHDMIStatus()?true:false), + false); + if (!ret) { + LOGE("prepareOverlay setSource failed"); + return -1; + } + // Reset this flag so that we don't keep opening and closing channels + // unnecessarily + hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; + } else { + // The overlay goemetry may have changed, we only need to update the + // overlay + ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, + hnd->format, layer->transform); + if (!ret) { + LOGE("prepareOverlay updateOverlaySource failed"); + return -1; + } + } + + hwc_rect_t sourceCrop = layer->sourceCrop; + ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top, + (sourceCrop.right - sourceCrop.left), + (sourceCrop.bottom - sourceCrop.top)); + if (!ret) { + LOGE("prepareOverlay setCrop failed"); + return -1; + } + + if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { + framebuffer_device_t* fbDev = hwcModule->fbDevice; + ret = ovLibObject->setPosition(0, 0, + fbDev->width, fbDev->height); + } else { + hwc_rect_t displayFrame = layer->displayFrame; + ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, + (displayFrame.right - displayFrame.left), + (displayFrame.bottom - displayFrame.top)); + } + if (!ret) { + LOGE("prepareOverlay setPosition failed"); + return -1; + } + + ovLibObject->getOrientation(orientation); + if (orientation != layer->transform) + ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); + if (!ret) { + LOGE("prepareOverlay setParameter failed transform %x", + layer->transform); + return -1; + } + } + return 0; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -220,8 +304,19 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { - list->hwLayers[i].compositionType = HWC_USE_OVERLAY; - list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + if(prepareOverlay(ctx, &(list->hwLayers[i])) == 0) { + list->hwLayers[i].compositionType = HWC_USE_OVERLAY; + list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) { + //Fail safe path: If drawing with overlay fails, + //Use C2D if available. + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + yuvBufferCount = 0; + } else { + //If C2D is not enabled fall back to GPU. + list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + yuvBufferCount = 0; + } } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; @@ -371,83 +466,22 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { - int ret = 0; - if (ctx && ctx->mOverlayLibObject) { + if (ctx && ctx->mOverlayLibObject) { private_hwc_module_t* hwcModule = reinterpret_cast(ctx->device.common.module); if (!hwcModule) { LOGE("drawLayerUsingLayer null module "); return -1; } - private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - int orientation = 0; - if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) - ovLibObject->getOrientation(orientation); - - if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) - || (layer->transform != orientation) || - (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { - // Overlay channel is not started, or we have an orientation change or there is a - // format change, call setSource to open the overlay if necessary - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, - (ovLibObject->getHDMIStatus()?true:false), false); - if (!ret) { - LOGE("drawLayerUsingOverlay setSource failed"); - return -1; - } - // Reset this flag so that we don't keep opening and closing channels unnecessarily - hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; - } else { - // The overlay goemetry may have changed, we only need to update the overlay - ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, hnd->format, - layer->transform); - if (!ret) { - LOGE("drawLayerUsingOverlay updateOverlaySource failed"); - return -1; - } - } - - hwc_rect_t sourceCrop = layer->sourceCrop; - ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top, - (sourceCrop.right - sourceCrop.left), - (sourceCrop.bottom-sourceCrop.top)); - if (!ret) { - LOGE("drawLayerUsingOverlay setCrop failed"); - return -1; - } - - if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { - framebuffer_device_t* fbDev = hwcModule->fbDevice; - ret = ovLibObject->setPosition(0, 0, - fbDev->width, fbDev->height); - } else { - hwc_rect_t displayFrame = layer->displayFrame; - ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top, - (displayFrame.right - displayFrame.left), - (displayFrame.bottom-displayFrame.top)); - } - if (!ret) { - LOGE("drawLayerUsingOverlay setPosition failed"); - return -1; - } - - ovLibObject->getOrientation(orientation); - if (orientation != layer->transform) - ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); - if (!ret) { - LOGE("drawLayerUsingOverlay setParameter failed transform %x", layer->transform); - return -1; - } - + int ret = 0; ret = ovLibObject->queueBuffer(hnd); if (!ret) { LOGE("drawLayerUsingOverlay queueBuffer failed"); return -1; } - return 0; } - return -1; + return 0; } static int hwc_set(hwc_composer_device_t *dev, @@ -472,7 +506,6 @@ static int hwc_set(hwc_composer_device_t *dev, if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; } - if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); } else if (list->flags & HWC_SKIP_COMPOSITION) { From 49dbd79cf76c02ce3896df807adad40c0da98a98 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 23 Jun 2011 15:28:41 -0700 Subject: [PATCH 395/435] Add overlay_buffer_info structure to hold the buffer geometry The overlay_buffer_info buffer geometry and size. When calling the overlay from the gralloc or hardware composer, populate this structure with the information from the gralloc handle. (cherry picked from commit 128adc3b8177ef72f2bf21f4022d7ef06ed9281b) Change-Id: I2f60f691ac01e67f150c753f168be754b14f94e6 --- libgralloc-qsd8k/framebuffer.cpp | 15 ++- libhwcomposer/hwcomposer.cpp | 15 ++- liboverlay/overlayLib.cpp | 184 +++++++++++++++---------------- liboverlay/overlayLib.h | 31 ++++-- liboverlay/overlayLibUI.cpp | 25 +++-- liboverlay/overlayLibUI.h | 7 +- 6 files changed, 147 insertions(+), 130 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index dd961b2..b8454ad 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -227,9 +227,18 @@ static void *hdmi_ui_loop(void *ptr) pTemp->closeChannel(); 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(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 diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 3ec53fa..f1b32a5 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -199,6 +199,12 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; int orientation = 0; + overlay_buffer_info info; + info.width = hnd->width; + info.height = hnd->height; + info.format = hnd->format; + info.size = hnd->size; + if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) ovLibObject->getOrientation(orientation); @@ -208,9 +214,8 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { // Overlay channel is not started, or we have an orientation change // or there is a format change, call setSource to open the overlay // if necessary - ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, - layer->transform, (ovLibObject->getHDMIStatus()?true:false), - false); + ret = ovLibObject->setSource(info, layer->transform, + (ovLibObject->getHDMIStatus()?true:false), false); if (!ret) { LOGE("prepareOverlay setSource failed"); return -1; @@ -221,8 +226,7 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { } else { // The overlay goemetry may have changed, we only need to update the // overlay - ret = ovLibObject->updateOverlaySource(hnd->width, hnd->height, - hnd->format, layer->transform); + ret = ovLibObject->updateOverlaySource(info, layer->transform); if (!ret) { LOGE("prepareOverlay updateOverlaySource failed"); return -1; @@ -475,6 +479,7 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; int ret = 0; + ret = ovLibObject->queueBuffer(hnd); if (!ret) { LOGE("drawLayerUsingOverlay queueBuffer failed"); diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index e9365ee..90fa9bf 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -46,44 +46,6 @@ int overlay::get_mdp_format(int format) { return -1; } -int overlay::get_size(int format, int w, int h) { - int size, aligned_height, pitch; - - size = w * h; - switch (format) { - case MDP_RGBA_8888: - case MDP_BGRA_8888: - case MDP_RGBX_8888: - size *= 4; - break; - case MDP_RGB_565: - case MDP_Y_CBCR_H2V1: - size *= 2; - break; - case MDP_Y_CBCR_H2V2: - case MDP_Y_CRCB_H2V2: { - int alignedw = ALIGN(w, 16); - int alignedh = h; - size = alignedw*alignedh + - (ALIGN(alignedw/2, 16) * (alignedh/2))*2; - size = ALIGN(size, 4096); - } break; - case MDP_Y_CRCB_H2V2_TILE: - aligned_height = (h + 31) & ~31; - pitch = (w + 127) & ~127; - size = pitch * aligned_height; - size = (size + 8191) & ~8191; - - aligned_height = ((h >> 1) + 31) & ~31; - size += pitch * aligned_height; - size = (size + 8191) & ~8191; - break; - default: - return 0; - } - return size; -} - int overlay::get_mdp_orientation(int rotation, int flip) { switch(flip) { case HAL_TRANSFORM_FLIP_V: @@ -178,8 +140,10 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { } Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), - mS3DFormat(0), mWidth(0), mHeight(0), - mCroppedSrcWidth(0), mCroppedSrcHeight(0) { + mS3DFormat(0), mCroppedSrcWidth(0), + mCroppedSrcHeight(0) { + mOVBufferInfo.width = mOVBufferInfo.height = 0; + mOVBufferInfo.format = mOVBufferInfo.size = 0; } Overlay::~Overlay() { @@ -194,43 +158,47 @@ int Overlay::getFBHeight(int channel) const { return objOvCtrlChannel[channel].getFBHeight(); } -bool Overlay::startChannel(int w, int h, int format, int fbnum, +bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum, bool norot, bool uichannel, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; - mCroppedSrcWidth = w; - mCroppedSrcHeight = h; + int format = getColorFormat(info.format); + mCroppedSrcWidth = info.width; + mCroppedSrcHeight = info.height; if (format3D) zorder = channel; - mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, - norot, uichannel, format3D, zorder, ignoreFB); + mChannelUP = objOvCtrlChannel[channel].startControlChannel(info.width, + info.height, format, fbnum, + norot, uichannel, + format3D, zorder, ignoreFB); if (!mChannelUP) { LOGE("startChannel for fb%d failed", fbnum); return mChannelUP; } + objOvCtrlChannel[channel].setSize(info.size); return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum, norot, uichannel, num_buffers); } -bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { +bool Overlay::startChannelHDMI(const overlay_buffer_info& info, bool norot) { - bool ret = startChannel(w, h, format, FRAMEBUFFER_0, norot); + bool ret = startChannel(info, FRAMEBUFFER_0, norot); if(ret) { - ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); + ret = startChannel(info, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); } return ret; } -bool Overlay::startChannelS3D(int w, int h, int format, bool norot) { +bool Overlay::startChannelS3D(const overlay_buffer_info& info, bool norot) { bool ret = false; // Start both the channels for the S3D content if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) - ret = startChannel(w, h, format, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); + ret = startChannel(info, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); else - ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); + ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); if (ret) { - ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); + ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); } if (!ret) { closeChannel(); @@ -253,8 +221,10 @@ bool Overlay::closeChannel() { } mChannelUP = false; mS3DFormat = 0; - mWidth = 0; - mHeight = 0; + mOVBufferInfo.width = 0; + mOVBufferInfo.height = 0; + mOVBufferInfo.format = 0; + mOVBufferInfo.size = 0; return true; } @@ -301,35 +271,33 @@ bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { return ret; } -bool Overlay::updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation) { +bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation) { if (hasHDMIStatusChanged()) { - return setSource(w, h, format, orientation, mHDMIConnected); + return setSource(info, orientation, mHDMIConnected); } bool ret = false; - if (w == mWidth && h == mHeight) { + if (info.width == mOVBufferInfo.width && + info.height == mOVBufferInfo.height) { objOvDataChannel[0].updateDataChannel(0, 0); return true; } // Set the overlay source info - if (objOvCtrlChannel[0].isChannelUP()) { - ret = objOvCtrlChannel[0].updateOverlaySource(w, h, format, orientation); - if (!ret) { - LOGE("objOvCtrlChannel[0].updateOverlaySource failed"); - return false; + for (int i = 0; i < NUM_CHANNELS; i++) { + if (objOvCtrlChannel[i].isChannelUP()) { + ret = objOvCtrlChannel[i].updateOverlaySource(info, orientation); + if (!ret) { + LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i); + return false; + } + objOvCtrlChannel[i].setSize(info.size); + int updateDataChannel = orientation ? 1:0; + ret = objOvDataChannel[i].updateDataChannel(updateDataChannel, info.size); } - int updateDataChannel = orientation ? 1:0; - int size = get_size(get_mdp_format(format), w, h); - ret = objOvDataChannel[0].updateDataChannel(updateDataChannel, size); - - if (ret && objOvCtrlChannel[1].isChannelUP()) - ret = objOvCtrlChannel[1].updateOverlaySource(w, h, format, orientation); } - if (ret) { - mWidth = w; - mHeight = h; + mOVBufferInfo = info; } else LOGE("update failed"); return ret; @@ -351,23 +319,28 @@ int Overlay::hasHDMIStatusChanged() { return hdmiChanged; } -bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, - bool hdmiConnected, bool ignoreFB, int num_buffers) { - // Separate the color format from the 3D format. - // If there is 3D content; the effective format passed by the client is: - // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat - unsigned int format3D = FORMAT_3D(format); - int colorFormat = COLOR_FORMAT(format); +int Overlay::getS3DFormat(int format) { + int format3D = FORMAT_3D(format); int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format format3D = fIn3D | fOut3D; - // Use the same in/out format if not mentioned if (!fIn3D) { format3D |= fOut3D << SHIFT_3D; //Set the input format } if (!fOut3D) { format3D |= fIn3D >> SHIFT_3D; //Set the output format } + return format3D; +} + +bool Overlay::setSource(const overlay_buffer_info& info, int orientation, + bool hdmiConnected, bool ignoreFB, int num_buffers) { + // Separate the color format from the 3D format. + // If there is 3D content; the effective format passed by the client is: + // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + unsigned int format3D = getS3DFormat(info.format); + int colorFormat = getColorFormat(info.format); + if (format3D) { bool isTV3D = false; if (hdmiConnected) @@ -385,21 +358,20 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, s3dChanged = 0x10; stateChanged = s3dChanged|hasHDMIStatusChanged(); - if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) { + if (stateChanged || !objOvCtrlChannel[0].setSource(info.width, info.height, colorFormat, orientation, ignoreFB)) { closeChannel(); mS3DFormat = format3D; - mWidth = w; - mHeight = h; + mOVBufferInfo = info; if (mHDMIConnected) { if (mS3DFormat) { // Start both the VG pipes - return startChannelS3D(w, h, colorFormat, !orientation); + return startChannelS3D(info, !orientation); } else { - return startChannelHDMI(w, h, colorFormat, !orientation); + return startChannelHDMI(info, !orientation); } } else { - return startChannel(w, h, colorFormat, 0, !orientation, + return startChannel(info, 0, !orientation, false, 0, VG0_PIPE, ignoreFB, num_buffers); } } @@ -481,6 +453,10 @@ bool Overlay::queueBuffer(uint32_t offset, int channel) { bool Overlay::queueBuffer(buffer_handle_t buffer) { private_handle_t const* hnd = reinterpret_cast (buffer); + if (!hnd) { + LOGE("Overlay::queueBuffer invalid handle"); + return false; + } const size_t offset = hnd->offset; const int fd = hnd->fd; bool ret = true; @@ -659,9 +635,13 @@ bool OverlayControlChannel::openDevices(int fbnum) { return true; } -bool OverlayControlChannel::setOverlayInformation(int w, int h, - int format, int flags, int orientation, int zorder, +bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& info, + int flags, int orientation, int zorder, bool ignoreFB, int requestType) { + int w = info.width; + int h = info.height; + int format = info.format; + mOVInfo.src.width = w; mOVInfo.src.height = h; mOVInfo.src_rect.x = 0; @@ -704,13 +684,16 @@ bool OverlayControlChannel::setOverlayInformation(int w, int h, if (!ignoreFB) mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; } - mSize = get_size(format, w, h); return true; } -bool OverlayControlChannel::startOVRotatorSessions(int w, int h, - int format, int orientation, int requestType) { +bool OverlayControlChannel::startOVRotatorSessions( + const overlay_buffer_info& info, + int orientation, int requestType) { bool ret = true; + int w = info.width; + int h = info.height; + int format = info.format; if (orientation) { mRotInfo.src.format = format; @@ -763,13 +746,18 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, return ret; } -bool OverlayControlChannel::updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation) +bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info, + int orientation) { - int hw_format = get_mdp_format(format); - if (!setOverlayInformation(w, h, hw_format, 0, orientation, 0, 0, UPDATE_REQUEST)) + int hw_format = get_mdp_format(info.format); + overlay_buffer_info ovBufInfo; + ovBufInfo.width = info.width; + ovBufInfo.height = info.height; + ovBufInfo.format = hw_format; + if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, 0, UPDATE_REQUEST)) return false; - return startOVRotatorSessions(w, h, hw_format, orientation, UPDATE_REQUEST); + return startOVRotatorSessions(ovBufInfo, orientation, UPDATE_REQUEST); } bool OverlayControlChannel::startControlChannel(int w, int h, @@ -806,10 +794,14 @@ bool OverlayControlChannel::startControlChannel(int w, int h, return false; int orientation = mNoRot ? 0: 1; - if (!setOverlayInformation(w, h, hw_format, flags, orientation, zorder, ignoreFB, NEW_REQUEST)) + overlay_buffer_info ovBufInfo; + ovBufInfo.width = w; + ovBufInfo.height = h; + ovBufInfo.format = hw_format; + if (!setOverlayInformation(ovBufInfo, flags, orientation, zorder, ignoreFB, NEW_REQUEST)) return false; - return startOVRotatorSessions(w, h, hw_format, orientation, NEW_REQUEST); + return startOVRotatorSessions(ovBufInfo, orientation, NEW_REQUEST); } bool OverlayControlChannel::closeControlChannel() { diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index fbc6c60..a4bff39 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -90,6 +90,14 @@ enum { #define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present" /* -------------------------- 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 { @@ -130,10 +138,10 @@ class OverlayControlChannel { mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; bool openDevices(int fbnum = -1); - bool setOverlayInformation(int w, int h, int format, + bool setOverlayInformation(const overlay_buffer_info& info, int flags, int orientation, int zorder = 0, bool ignoreFB = false, int requestType = NEW_REQUEST); - bool startOVRotatorSessions(int w, int h, int format, int orientation, int requestType); + bool startOVRotatorSessions(const overlay_buffer_info& info, int orientation, int requestType); void swapOVRotWidthHeight(); public: @@ -147,6 +155,7 @@ public: 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; @@ -160,7 +169,7 @@ public: int orientation, bool ignoreFB); bool getAspectRatioPosition(int w, int h, overlay_rect *rect); bool getPositionS3D(int channel, int format, overlay_rect *rect); - bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation); + bool updateOverlaySource(const overlay_buffer_info& info, int orientation); bool getFormat() const { return mFormat; } }; @@ -212,11 +221,10 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; unsigned int mS3DFormat; - int mWidth; - int mHeight; //Actual cropped source width and height of overlay int mCroppedSrcWidth; int mCroppedSrcHeight; + overlay_buffer_info mOVBufferInfo; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -224,7 +232,7 @@ public: Overlay(); ~Overlay(); - bool startChannel(int w, int h, int format, int fbnum, bool norot = false, + 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); @@ -240,24 +248,25 @@ public: int getFBHeight(int channel = 0) const; bool getOrientation(int& orientation, int channel = 0) const; bool queueBuffer(buffer_handle_t buffer); - bool setSource(uint32_t w, uint32_t h, int format, - int orientation, bool hdmiConnected, + 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; } int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); } - bool updateOverlaySource(uint32_t w, uint32_t h, int format, int orientation); + bool updateOverlaySource(const overlay_buffer_info& info, int orientation); private: - bool startChannelHDMI(int w, int h, int format, bool norot); - bool startChannelS3D(int w, int h, int format, bool norot); + bool startChannelHDMI(const overlay_buffer_info& info, bool norot); + bool startChannelS3D(const overlay_buffer_info& info, bool norot); bool setPositionS3D(int x, int y, uint32_t w, uint32_t h); bool setParameterS3D(int param, int value); 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); int hasHDMIStatusChanged(); + int getColorFormat(int format) { return COLOR_FORMAT(format); } + int getS3DFormat(int format); }; struct overlay_shared_data { diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp index 5066681..f15ef55 100644 --- a/liboverlay/overlayLibUI.cpp +++ b/liboverlay/overlayLibUI.cpp @@ -299,7 +299,7 @@ status_t OVHelper::getOVInfo(mdp_overlay& ovInfo) { } status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo, - int numBuffers) { + int size, int numBuffers) { status_t ret = ALREADY_EXISTS; if (mSessionID == NO_INIT && mFD == NO_INIT) { mNumBuffers = numBuffers; @@ -322,7 +322,7 @@ status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo, return NO_INIT; } - mSize = get_size(rotInfo.src.format, rotInfo.src.width, rotInfo.src.height); + mSize = size; mPmemAddr = (void *) mmap(NULL, mSize* mNumBuffers, PROT_READ | PROT_WRITE, MAP_SHARED, mPmemFD, 0); if (mPmemAddr == MAP_FAILED) { @@ -379,14 +379,14 @@ status_t OverlayUI::closeChannel() { return NO_ERROR; } -status_t OverlayUI::setSource(int w, int h, int format, int orientation, +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(format); - int colorFormat = COLOR_FORMAT(format); - format = get_mdp_format(colorFormat); + int format3D = FORMAT_3D(info.format); + int colorFormat = COLOR_FORMAT(info.format); + int format = get_mdp_format(colorFormat); if (format3D || !isRGBType(format)) return ret; @@ -399,7 +399,7 @@ status_t OverlayUI::setSource(int w, int h, int format, int orientation, if (mobjOVHelper.getOVInfo(ov) == NO_ERROR) { if (mOrientation == orientation && mFBNum == fbnum && - checkOVState(w, h, format, orientation, zorder, ov)) + checkOVState(info.width, info.height, format, orientation, zorder, ov)) return NO_ERROR; else mChannelState = PENDING_CLOSE; @@ -412,7 +412,7 @@ status_t OverlayUI::setSource(int w, int h, int format, int orientation, mOrientation = orientation; mdp_overlay ovInfo; msm_rotator_img_info rotInfo; - setupOvRotInfo(w, h, format, orientation, ovInfo, rotInfo); + setupOvRotInfo(info.width, info.height, format, orientation, ovInfo, rotInfo); int flags = 0; if (ignoreFB) @@ -431,19 +431,20 @@ status_t OverlayUI::setSource(int w, int h, int format, int orientation, if (zorder != NO_INIT) ovInfo.z_order = zorder; - ret = startChannel(fbnum, ovInfo, rotInfo); + ret = startChannel(fbnum, ovInfo, rotInfo, info.size); return ret; } status_t OverlayUI::startChannel(int fbnum, mdp_overlay& ovInfo, - msm_rotator_img_info& rotInfo) { + 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); + if (ret == NO_ERROR && mOrientation) { + ret = mobjRotator.startRotSession(rotInfo, size); + } if (ret == NO_ERROR) { mChannelState = UP; diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h index bf749fa..a044df6 100644 --- a/liboverlay/overlayLibUI.h +++ b/liboverlay/overlayLibUI.h @@ -107,7 +107,8 @@ class Rotator { public: explicit Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1) { }; ~Rotator() { closeRotSession(); } - status_t startRotSession(msm_rotator_img_info& rotInfo, int numBuffers = max_num_buffers); + 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); }; @@ -128,14 +129,14 @@ class OverlayUI { OverlayUI& operator=(const OverlayUI& objOverlay); status_t startChannel(int fbnum, mdp_overlay& ovInfo, - msm_rotator_img_info& rotInfo); + 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(int w, int h, int format, int orientation, + 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) { From 7e2db6e3d075c55e00a03209d54c28634f35223c Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 28 Jun 2011 11:58:56 -0700 Subject: [PATCH 396/435] liboverlay: Add YV12 support Add support in the overlay for the YV12 color format. (cherry picked from commit 0f9a27cc39b6d4202b54059bc7c64eea9efcf3f1) Change-Id: I4b57eb383ca8f728243bd7e397696932e26c8889 --- libgralloc-qsd8k/gpu.cpp | 2 +- liboverlay/overlayLib.cpp | 11 ++++++++++- liboverlay/overlayLib.h | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index b4e00ca..a4234ab 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -259,7 +259,7 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorF *colorFormat = inputFormat; if (inputFormat == HAL_PIXEL_FORMAT_YV12) { - *bufferType = BUFFER_TYPE_UI; // There is no overlay support for this format yet. + *bufferType = BUFFER_TYPE_VIDEO; } else if (inputFormat & S3D_FORMAT_MASK) { // S3D format *colorFormat = COLOR_FORMAT(inputFormat); diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 90fa9bf..cd2d43c 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -42,6 +42,8 @@ int overlay::get_mdp_format(int format) { return MDP_Y_CBCR_H2V2; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return MDP_Y_CRCB_H2V2_TILE; + case HAL_PIXEL_FORMAT_YV12: + return MDP_Y_CR_CB_H2V2; } return -1; } @@ -320,6 +322,11 @@ int Overlay::hasHDMIStatusChanged() { } int Overlay::getS3DFormat(int format) { + // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add + // an explicit check for the format + if (format == HAL_PIXEL_FORMAT_YV12) { + return 0; + } int format3D = FORMAT_3D(format); int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format @@ -773,7 +780,9 @@ bool OverlayControlChannel::startControlChannel(int w, int h, int hw_format; int flags = 0; int colorFormat = format; - if (format & INTERLACE_MASK) { + // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add + // an explicit check for the format + if ((format != HAL_PIXEL_FORMAT_YV12) && (format & INTERLACE_MASK)) { flags |= MDP_DEINTERLACE; // Get the actual format diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index a4bff39..d4709c0 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -265,7 +265,8 @@ private: 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); int hasHDMIStatusChanged(); - int getColorFormat(int format) { return COLOR_FORMAT(format); } + int getColorFormat(int format) { return (format == HAL_PIXEL_FORMAT_YV12) ? + format : COLOR_FORMAT(format); } int getS3DFormat(int format); }; From 3ae7f5272625cad07f98d1a92aa67d7d054e927f Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 28 Jun 2011 13:35:14 -0700 Subject: [PATCH 397/435] libgralloc-qsd8k: Support for additional gralloc usage flags. Add support for the GRALLOC_USAGE_EXTERNAL_DISP and the GRALLOC_USAGE_PROTECTED usage bits. If any of the two usage bits are set, we need to send the buffers to the overlay. Since we send the buffers to the overlay, we need to allocate these buffers from the PMEM region. (cherry picked from commit 195345cd63f0e19cfee4cf055587d5fffe76d0ef) Change-Id: I64116b9be07c8ddadbd5a132ef21b19e5326737b --- libgralloc-qsd8k/gpu.cpp | 9 ++++++++- libgralloc-qsd8k/pmemalloc.cpp | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index a4234ab..d0d4fa4 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -182,7 +182,8 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } #endif - if ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) || (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL)) { + if ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) || (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) + || (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; } @@ -341,6 +342,12 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, 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); diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index 126004d..fa5fc4b 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -277,6 +277,15 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, device = DEVICE_PMEM_ADSP; } else if (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) { 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; From a9181ba3035df77a1ddebe170d2aa7bd2d453b77 Mon Sep 17 00:00:00 2001 From: Chetan Kalyan Date: Mon, 6 Jun 2011 15:35:35 -0700 Subject: [PATCH 398/435] OverlayLib: Set format to non-tiled if rotated Rotator outputs non-tiled formats. Hence, if there is rotation, tiled format needs to be set to non-tiled and aligned properly. Change-Id: I88335ad49c2f7446aa5fa71db80f6051c02bb5ff CRs-fixed: 290428 --- liboverlay/overlayLib.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index cd2d43c..7cd6c62 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -838,18 +838,28 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format = cFormat & INTERLACE_MASK ? (cFormat ^ HAL_PIXEL_FORMAT_INTERLACE) : cFormat; format = get_mdp_format(format); - if ((orientation == mOrientation) - && ((orientation == OVERLAY_TRANSFORM_ROT_90) - || (orientation == OVERLAY_TRANSFORM_ROT_270))) { + if (orientation == mOrientation && orientation != 0){ + //set format to non-tiled and align w, h to 64-bit and 32-bit respectively. if (format == MDP_Y_CRCB_H2V2_TILE) { format = MDP_Y_CRCB_H2V2; w = (((w-1)/64 +1)*64); h = (((h-1)/32 +1)*32); } - int tmp = w; - w = h; - h = tmp; + switch(orientation){ + case (HAL_TRANSFORM_ROT_90 | HAL_TRANSFORM_FLIP_H): + case (HAL_TRANSFORM_ROT_90 | HAL_TRANSFORM_FLIP_V): + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_270: + { + int tmp = w; + w = h; + h = tmp; + } + default: + break; + } } + if (w == mOVInfo.src.width && h == mOVInfo.src.height && format == mOVInfo.src.format && orientation == mOrientation) { mdp_overlay ov; From ea1c22ccde5b665c00dc245b3582cced71084fc9 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 12 Jul 2011 11:41:19 -0700 Subject: [PATCH 399/435] liboverlay: Reset rotation information during updates When updating the overlay source information, reset the rotation information as this would be set during the setParameter call. Also ensure that the HDMI doesn't have any orientation set. Change-Id: I7a8ae96f27046deeed32f968061cc524d57cbfa3 --- liboverlay/overlayLib.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 7cd6c62..25dd23f 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -285,10 +285,12 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati return true; } + // Disable rotation for the HDMI channel + int orient[2] = {orientation, 0}; // Set the overlay source info for (int i = 0; i < NUM_CHANNELS; i++) { if (objOvCtrlChannel[i].isChannelUP()) { - ret = objOvCtrlChannel[i].updateOverlaySource(info, orientation); + ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i]); if (!ret) { LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i); return false; @@ -682,6 +684,7 @@ bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& inf if (h > mFBHeight) mOVInfo.dst_rect.h = mFBHeight; + mOVInfo.user_data[0] = 0; if (requestType == NEW_REQUEST) { mOVInfo.id = MSMFB_NEW_REQUEST; mOVInfo.z_order = zorder; @@ -725,9 +728,9 @@ bool OverlayControlChannel::startOVRotatorSessions( mRotInfo.dst_y = 0; mRotInfo.src_rect.x = 0; mRotInfo.src_rect.y = 0; + mRotInfo.rotations = 0; if (requestType == NEW_REQUEST) { - mRotInfo.rotations = 0; mRotInfo.enable = 0; if(mUIChannel) mRotInfo.enable = 1; From ae67b6bd336ef5277c97acdb20216d8862989393 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Tue, 12 Jul 2011 17:41:10 -0700 Subject: [PATCH 400/435] Put HDMI code under compile time flag Put HDMI code in HWC under compile time flag. This prevents crashes in use cases like HDMI used as primary. If not done, non-existing code in gralloc is called in that use case. Change-Id: Ic7e792acf0c35eb12f04a74405619385d7288991 --- libhwcomposer/Android.mk | 3 +++ libhwcomposer/hwcomposer.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 632190b..5f23f61 100755 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -16,5 +16,8 @@ LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k 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 include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index f1b32a5..557f566 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -127,6 +127,7 @@ static void dump_layer(hwc_layer_t const* l) { } static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { +#if defined HDMI_DUAL_DISPLAY hwc_context_t* ctx = (hwc_context_t*)(dev); private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); @@ -148,10 +149,11 @@ static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { fbDev->videoOverlayStarted(fbDev, false); } } +#endif } static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { - +#if defined HDMI_DUAL_DISPLAY private_hwc_module_t* hwcModule = reinterpret_cast( ctx->device.common.module); overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; @@ -180,6 +182,7 @@ static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { ovLibObject->closeChannel(); fbDev->videoOverlayStarted(fbDev, false); } +#endif return 0; } From d74d6633746470095387bfd3ec9138ae9a33d6c0 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 5 Jul 2011 15:48:18 -0700 Subject: [PATCH 401/435] libgralloc-qsd8k: Fallback to ashmem in case of pmem failure Add a fallback mechanism to allocate memory from ashmem if pmem allocation fails. Do not fallback in the following cases: - MDP composition is being used. - Client has explicitly requested that the memory be allocated from pmem. - Buffer will not be sent to the overlay. Change-Id: Ic690af48f81914cb4c9a102cb386356797451141 --- libgralloc-qsd8k/gpu.cpp | 54 ++++++++++++++++++++++++++++++--- libgralloc-qsd8k/gpu.h | 2 ++ libgralloc-qsd8k/gralloc_priv.h | 8 +++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index d0d4fa4..cca91b1 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -20,6 +20,8 @@ #include +#include + #include "gr.h" #include "gpu.h" @@ -37,6 +39,28 @@ gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, // Zero out the alloc_device_t memset(static_cast(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; @@ -181,6 +205,17 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* if (usage & GRALLOC_USAGE_HW_2D) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } +#else + // Enable use of PMEM only when MDP composition is used (and other conditions apply). + // Else fall back on using ASHMEM + if ((get_composition_type() == MDP_COMPOSITION) && + ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; + } + + if (usage & GRALLOC_USAGE_PRIVATE_PMEM) { + flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; + } #endif if ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) || (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) || (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) { @@ -218,11 +253,18 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format); if (err < 0) { - if (((usage & GRALLOC_USAGE_HW_MASK) == 0) && + // Pmem allocation failed. Try falling back to ashmem iff we are: + // a. not using MDP composition + // b. not allocating memory for a buffer to be used by overlays + // c. The client has not explicitly requested a PMEM buffer + if ((get_composition_type() != MDP_COMPOSITION) && + (bufferType != BUFFER_TYPE_VIDEO) && + ((usage & GRALLOC_USAGE_PRIVATE_PMEM) == 0) && ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { // 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)); @@ -230,10 +272,12 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* } } else { try_ashmem: - fd = deps.ashmem_create_region("gralloc-buffer", size); - if (fd < 0) { - LOGE("couldn't create ashmem (%s)", strerror(errno)); - err = -errno; + 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"); } } diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h index dc0f96c..3ef57d3 100755 --- a/libgralloc-qsd8k/gpu.h +++ b/libgralloc-qsd8k/gpu.h @@ -68,12 +68,14 @@ class gpu_context_t : public alloc_device_t { 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: Deps& deps; PmemAllocator& pmemAllocator; PmemAllocator& pmemAdspAllocator; + int compositionType; int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, int* pOffset, int* pFd); void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType); diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 6804c41..c6780ef 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -39,6 +39,14 @@ enum { /* gralloc usage bit indicating a pmem_adsp allocation should be used */ GRALLOC_USAGE_PRIVATE_PMEM_ADSP = GRALLOC_USAGE_PRIVATE_0, GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL = GRALLOC_USAGE_PRIVATE_1, + GRALLOC_USAGE_PRIVATE_PMEM = GRALLOC_USAGE_PRIVATE_2, +}; + +enum { + GPU_COMPOSITION, + C2D_COMPOSITION, + MDP_COMPOSITION, + CPU_COMPOSITION, }; /* numbers of max buffers for page flipping */ From f979fa8589723413ffadfc9d410cfd2a49e9e0ee Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Fri, 29 Jul 2011 17:51:41 +0530 Subject: [PATCH 403/435] copybit: Set vertical padding Change-Id: I86f3fe29c577b06487aedd9f9569075a22c146fc CRs-fixed: 284384 --- libcopybit/copybit.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 767b3ee..6f6fca5 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -156,7 +156,8 @@ static void set_rects(struct copybit_context_t *dev, const struct copybit_rect_t *dst, const struct copybit_rect_t *src, const struct copybit_rect_t *scissor, - uint32_t padding) { + uint32_t horiz_padding, + uint32_t vert_padding) { struct copybit_rect_t clip; intersect(&clip, scissor, dst); @@ -183,19 +184,20 @@ static void set_rects(struct copybit_context_t *dev, } 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) - padding; + 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); + 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); + 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) - padding; + e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding; } } } @@ -398,7 +400,7 @@ static int stretch_copybit( 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->padding); + 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; From 3de087d0bb571bd55da3e6783aafc233c02cc520 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Fri, 29 Jul 2011 09:42:07 +0530 Subject: [PATCH 404/435] gralloc: Clean pmem caches after memset Change-Id: If403dde70863e0d6ea221f2a105b86bdec134261 --- libgralloc-qsd8k/gralloc.cpp | 8 ++++++++ libgralloc-qsd8k/pmemalloc.cpp | 2 ++ libgralloc-qsd8k/pmemalloc.h | 1 + 3 files changed, 11 insertions(+) diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp index ab574a7..bfade0a 100755 --- a/libgralloc-qsd8k/gralloc.cpp +++ b/libgralloc-qsd8k/gralloc.cpp @@ -108,6 +108,14 @@ class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation); } + 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; } diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index fa5fc4b..f7f9059 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -181,6 +181,8 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, } else { LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); memset((char*)base + offset, 0, size); + //Clean cache before flushing to ensure pmem is properly flushed + deps.cleanPmem(fd, (unsigned long) base, offset, size); #ifdef HOST cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); #endif diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h index c64d9be..2a1c6fd 100755 --- a/libgralloc-qsd8k/pmemalloc.h +++ b/libgralloc-qsd8k/pmemalloc.h @@ -69,6 +69,7 @@ class PmemUserspaceAllocator: public PmemAllocator { virtual int connectPmem(int fd, int master_fd) = 0; virtual int mapPmem(int fd, int offset, size_t size) = 0; virtual int unmapPmem(int fd, int offset, size_t size) = 0; + virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) = 0; // C99 virtual int getErrno() = 0; From f75b90721f488a89f23f61e510e57bd688e630ed Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 1 Aug 2011 12:09:22 -0700 Subject: [PATCH 405/435] libgralloc-qsd8k: Check PMEM_ADSP flag Check the PMEM_ADSP flag during the terminateBuffer and gralloc_unmap operations. CRs-fixed: 296807, 298849, 296817 Change-Id: Ia97aca71935ca3c921f53fc88f5b4f918d7434c0 --- libgralloc-qsd8k/mapper.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index d32fc28..883c10b 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -179,8 +179,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 +189,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); } } @@ -283,7 +285,8 @@ 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) { + if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) { struct pmem_addr pmem_addr; pmem_addr.vaddr = hnd->base; pmem_addr.offset = hnd->offset; From 61390825ec148eae2de4cbcfc08d7115b2a8e38a Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 29 Jul 2011 10:59:33 -0700 Subject: [PATCH 406/435] libhwcomposer: Move the skip composition logic to a separate API Create a new function to check if we need to skip the composition during overlay operations. Reset the previous compCount variable if there is no video layer present. Change-Id: Ibf570805114440f117f0fb98b5f2d53c1780ec84 CRs-fixed: 298014 --- libhwcomposer/hwcomposer.cpp | 38 +++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 557f566..63f6aec 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -272,6 +272,36 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { return 0; } +bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayerCount, + int numLayersNotUpdating) +{ + if (!ctx) { + LOGE("canSkipComposition invalid context"); + return false; + } + + bool compCountChanged = false; + if (yuvBufferCount == 1) { + if (currentLayerCount != ctx->previousLayerCount) { + compCountChanged = true; + ctx->previousLayerCount = currentLayerCount; + } + + if (!compCountChanged) { + if ((currentLayerCount == 1) || + ((currentLayerCount-1) == numLayersNotUpdating)) { + // We either have only one overlay layer or we have + // all the non-UI layers not updating. In this case + // we can skip the composition of the UI layers. + return true; + } + } + } else { + ctx->previousLayerCount = -1; + } + return false; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -335,13 +365,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } - bool compCountChanged = false; - if (list->numHwLayers != ctx->previousLayerCount) { - compCountChanged = true; - ctx->previousLayerCount = list->numHwLayers; - } - if ((yuvBufferCount == 1) && ((list->numHwLayers-1) == numLayersNotUpdating) - && !compCountChanged) { + if (canSkipComposition(ctx, yuvBufferCount, list->numHwLayers, numLayersNotUpdating)) { list->flags |= HWC_SKIP_COMPOSITION; } else { list->flags &= ~HWC_SKIP_COMPOSITION; From 0f0ea079831a393d86f92681381f4aecd2000942 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Fri, 29 Jul 2011 12:02:27 -0700 Subject: [PATCH 407/435] liboverlay: Check if the destination values have changed in setPosition In setPosition, make an ioctl call only when there is a change in the destination values. CRs-fixed: 296400 Change-Id: I9b059e226bf6f6cfd04fb563ac765e2583415157 --- liboverlay/overlayLib.cpp | 53 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 25dd23f..a8375c0 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -890,41 +890,40 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { - int width = w, height = h; if (!isChannelUP() || (x < 0) || (y < 0) || ((x + w) > mFBWidth) || ((y + h) > mFBHeight)) { reportError("setPosition failed"); return false; } + if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y || + w != mOVInfo.dst_rect.w || h != mOVInfo.dst_rect.h ) { + mdp_overlay ov; + ov.id = mOVInfo.id; + if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { + reportError("setPosition, overlay GET failed"); + return false; + } - mdp_overlay ov; - ov.id = mOVInfo.id; - if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { - reportError("setPosition, overlay GET failed"); - return false; + /* Scaling of upto a max of 8 times supported */ + if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){ + w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w; + x = (mFBWidth - w) / 2; + } + if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) { + h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h; + y = (mFBHeight - h) / 2; + } + ov.dst_rect.x = x; + ov.dst_rect.y = y; + ov.dst_rect.w = w; + ov.dst_rect.h = h; + if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { + reportError("setPosition, Overlay SET failed"); + return false; + } + mOVInfo = ov; } - - /* Scaling of upto a max of 8 times supported */ - if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){ - w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w; - x = (mFBWidth - w) / 2; - } - if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) { - h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h; - y = (mFBHeight - h) / 2; - } - ov.dst_rect.x = x; - ov.dst_rect.y = y; - ov.dst_rect.w = w; - ov.dst_rect.h = h; - - if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { - reportError("setPosition, Overlay SET failed"); - return false; - } - mOVInfo = ov; - return true; } From bfe4f06ee4616925e6e7b00e4554271ed89315b4 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Wed, 13 Jul 2011 22:32:48 -0700 Subject: [PATCH 408/435] libhwcomposer: Add support for dynamic composition switching This change adds support in HWC to switch between c2d and gpu composition dynamically. Change-Id: I52effdc3722034cbb0e859e66334ca4769f0d5c6 --- libhwcomposer/hwcomposer.cpp | 71 +++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 63f6aec..90e176a 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -49,7 +49,8 @@ enum { COMPOSITION_TYPE_GPU = 0, COMPOSITION_TYPE_MDP = 0x1, COMPOSITION_TYPE_C2D = 0x2, - COMPOSITION_TYPE_CPU = 0x4 + COMPOSITION_TYPE_CPU = 0x4, + COMPOSITION_TYPE_DYN = 0x8 }; enum HWCCompositionType { @@ -302,6 +303,65 @@ bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayer return false; } +static bool isFullScreenUpdate(const framebuffer_device_t* fbDev, const hwc_layer_list_t* list) { + + if(!fbDev) { + LOGE("ERROR: %s : fb device is invalid",__func__); + return false; + } + + int fb_w = fbDev->width; + int fb_h = fbDev->height; + + /* + * We have full screen condition when + * 1. We have 1 layer to compose + * a. layers dest rect equals display resolution. + * 2. We have 2 layers to compose + * a. Sum of their dest rects equals display resolution. + */ + + if(list->numHwLayers == 1) + { + hwc_rect_t rect = list->hwLayers[0].displayFrame; + + int w = rect.right - rect.left; + int h = rect.bottom - rect.top; + + int transform = list->hwLayers[0].transform; + + if(transform == (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) + return ((fb_w == h) && (fb_h == w)); + else + return ((fb_h == h) && (fb_w == w)); + } + + if(list->numHwLayers == 2) { + + hwc_rect_t rect_1 = list->hwLayers[0].displayFrame; + hwc_rect_t rect_2 = list->hwLayers[1].displayFrame; + + int transform_1 = list->hwLayers[0].transform; + int transform_2 = list->hwLayers[1].transform; + + int w1 = rect_1.right - rect_1.left; + int h1 = rect_1.bottom - rect_1.top; + int w2 = rect_2.right - rect_2.left; + int h2 = rect_2.bottom - rect_2.top; + + if(transform_1 == transform_2) { + if(transform_1 == (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) { + if((fb_w == (w1 + w2)) && (fb_h == h1) && (fb_h == h2)) + return true; + } else { + if((fb_w == w1) && (fb_w == w2) && (fb_h == (h1 + h2))) + return true; + } + } + } + return false; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -313,7 +373,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); - if(!hwcModule) { LOGE("hwc_prepare null module "); return -1; @@ -322,7 +381,11 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { int yuvBufferCount = 0; int layerType = 0; int numLayersNotUpdating = 0; + bool fullscreen = false; + if (list) { + fullscreen = isFullScreenUpdate(hwcModule->fbDevice, list); + for (size_t i=0 ; inumHwLayers; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && @@ -360,6 +423,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { layerType |= HWC_ORIG_RESOLUTION; } else if (hnd && (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) { list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + } else if ((hwcModule->compositionType == COMPOSITION_TYPE_DYN) && fullscreen) { + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; } else { list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; } @@ -623,6 +688,8 @@ static int hwc_module_initialize(struct private_hwc_module_t* hwcModule) hwcModule->compositionType = COMPOSITION_TYPE_MDP; } else if ((strncmp(property, "c2d", 3)) == 0) { hwcModule->compositionType = COMPOSITION_TYPE_C2D; + } else if ((strncmp(property, "dyn", 3)) == 0) { + hwcModule->compositionType = COMPOSITION_TYPE_DYN; } else { hwcModule->compositionType = COMPOSITION_TYPE_GPU; } From e8ded1637454bdcdad81627912bccebd98863711 Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 28 Jul 2011 11:48:38 -0700 Subject: [PATCH 409/435] libgralloc-qsd8k: Invalidate the ashmem cache Invalidate the ashmem cache after allocating an ashmem buffer Change-Id: Id38a4776a80a9b1d8be7fe6bf00f8b187a3278f6 --- libgralloc-qsd8k/gpu.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index cca91b1..dd410b2 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -21,6 +21,9 @@ #include #include +#ifdef HOST +#include +#endif #include "gr.h" #include "gpu.h" @@ -178,6 +181,11 @@ int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** *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; } From 6e3e6e0300b2aad56bfeaa5115d827421f9bd095 Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Wed, 27 Apr 2011 18:49:05 -0700 Subject: [PATCH 410/435] liboverlay: Use aligned width/height for source The source buffers, width/height is aligned. Use aligned width/height for the source buffer. CRs-fixed: 285831 Change-Id: I4c367a03fea833674e03fcab5a38217f9f8c5e05 --- liboverlay/overlayLibUI.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp index f15ef55..5e184fc 100644 --- a/liboverlay/overlayLibUI.cpp +++ b/liboverlay/overlayLibUI.cpp @@ -17,6 +17,7 @@ #include "overlayLibUI.h" #include "gralloc_priv.h" +#define LOG_TAG "OverlayUI" namespace { /* helper functions */ @@ -34,7 +35,9 @@ bool checkOVState(int w, int h, int format, int orientation, break; } - bool displayAttrsCheck = ((w == ov.src.width) && (h == ov.src.height) && + 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); @@ -67,8 +70,10 @@ void setupOvRotInfo(int w, int h, int format, int orientation, memset(&ovInfo, 0, sizeof(ovInfo)); memset(&rotInfo, 0, sizeof(rotInfo)); ovInfo.id = MSMFB_NEW_REQUEST; - ovInfo.src.width = w; - ovInfo.src.height = h; + 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; @@ -76,14 +81,12 @@ void setupOvRotInfo(int w, int h, int format, int orientation, ovInfo.transp_mask = 0xffffffff; rotInfo.src.format = format; rotInfo.dst.format = format; - w = (w + 31) & ~31; - h = (h + 31) & ~31; - rotInfo.src.width = w; - rotInfo.src.height = h; - rotInfo.src_rect.w = w; - rotInfo.src_rect.h = h; - rotInfo.dst.width = w; - rotInfo.dst.height = h; + 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; int flip = 0; From 370a5212cef42a16fb34aa75a661e3c8b8834bbe Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Mon, 15 Aug 2011 17:46:50 -0700 Subject: [PATCH 411/435] hwcomposer: Inform gralloc about video before prepareOverlay prepareOverlay will setup the channels for video playback, so inform gralloc to close UI channels before they are setup. Change-Id: I757a8fd79661eb66ccbe2ac1475e48740bbf1733 CRs-fixed: 298102 --- libhwcomposer/hwcomposer.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 90e176a..0dde148 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -169,14 +169,10 @@ static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { return -1; } - if ((layerType & HWC_STOP_UI_MIRRORING_MASK) && - (OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus())) { + if (layerType & HWC_STOP_UI_MIRRORING_MASK) { // Inform the gralloc to stop UI mirroring fbDev->videoOverlayStarted(fbDev, true); - } - - if ((OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) && - !(layerType & HWC_STOP_UI_MIRRORING_MASK)) { + } else { // Video mirroring is going on, and we do not have any layers to // mirror directly. Close the current video channel and inform the // gralloc to start UI mirroring @@ -399,6 +395,12 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } + if (list->flags & HWC_GEOMETRY_CHANGED) { + layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; + // Inform the gralloc of the current HDMI status + hwc_updateOverlayStatus(ctx, layerType); + } + for (size_t i=0 ; inumHwLayers ; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; // If there is a single Fullscreen layer, we can bypass it - TBD @@ -435,12 +437,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } else { list->flags &= ~HWC_SKIP_COMPOSITION; } - - if (list->flags & HWC_GEOMETRY_CHANGED) { - layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; - // Inform the gralloc of the current HDMI status - hwc_updateOverlayStatus(ctx, layerType); - } } return 0; From 4fc65b100d4fa72d5d4e163f3e31cd590c7395f4 Mon Sep 17 00:00:00 2001 From: Chetan Kalyan Date: Wed, 17 Aug 2011 22:03:40 -0700 Subject: [PATCH 412/435] Overlay: Add debug logs to overlay In case of failure, print out the values of the failed overlay structure, to allow easy debugging. Change-Id: I3e480b8eecc66b54f357b29d02064a751c9ebbfa --- liboverlay/overlayLib.cpp | 69 ++++++++++++++++++++++++++++++++++++++- liboverlay/overlayLib.h | 6 ++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index a8375c0..0dfa814 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -19,6 +19,7 @@ #include "gralloc_priv.h" #define INTERLACE_MASK 0x80 +#define DEBUG_OVERLAY true /* Helper functions */ static inline size_t ALIGN(size_t x, size_t align) { return (x + align-1) & ~(align-1); @@ -85,6 +86,63 @@ static void reportError(const char* message) { LOGE( "%s", message); } +void overlay::dump(mdp_overlay& mOVInfo) { + if (!DEBUG_OVERLAY) + return; + LOGE("mOVInfo:"); + LOGE("src: width %d height %d format %s user_data[0] %d", mOVInfo.src.width, + mOVInfo.src.height, getFormatString(mOVInfo.src.format), + mOVInfo.user_data[0]); + LOGE("src_rect: x %d y %d w %d h %d", mOVInfo.src_rect.x, + mOVInfo.src_rect.y, mOVInfo.src_rect.w, mOVInfo.src_rect.h); + LOGE("dst_rect: x %d y %d w %d h %d", mOVInfo.dst_rect.x, + mOVInfo.dst_rect.y, mOVInfo.dst_rect.w, mOVInfo.dst_rect.h); + LOGE("z_order %d is_fg %d alpha %d transp_mask %d flags %x id %d", + mOVInfo.z_order, mOVInfo.is_fg, mOVInfo.alpha, mOVInfo.transp_mask, + mOVInfo.flags, mOVInfo.id); +} + +void overlay::dump(msm_rotator_img_info& mRotInfo) { + if (!DEBUG_OVERLAY) + return; + LOGE("mRotInfo:"); + LOGE("session_id %d dst_x %d dst_y %d rotations %d enable %d", + mRotInfo.session_id, mRotInfo.dst_x, mRotInfo.dst_y, + mRotInfo.rotations, mRotInfo.enable); + LOGE("src: width %d height %d format %s", mRotInfo.src.width, + mRotInfo.src.height, getFormatString(mRotInfo.src.format)); + LOGE("dst: width %d height %d format %s", mRotInfo.dst.width, + mRotInfo.dst.height, getFormatString(mRotInfo.src.format)); + LOGE("src_rect: x %d y %d w %d h %d", mRotInfo.src_rect.x, + mRotInfo.src_rect.y, mRotInfo.src_rect.w, mRotInfo.src_rect.h); +} + +const char* overlay::getFormatString(int format){ + static const char* formats[] = { + "MDP_RGB_565", + "MDP_XRGB_8888", + "MDP_Y_CBCR_H2V2", + "MDP_ARGB_8888", + "MDP_RGB_888", + "MDP_Y_CRCB_H2V2", + "MDP_YCRYCB_H2V1", + "MDP_Y_CRCB_H2V1", + "MDP_Y_CBCR_H2V1", + "MDP_RGBA_8888", + "MDP_BGRA_8888", + "MDP_RGBX_8888", + "MDP_Y_CRCB_H2V2_TILE", + "MDP_Y_CBCR_H2V2_TILE", + "MDP_Y_CR_CB_H2V2", + "MDP_Y_CB_CR_H2V2", + "MDP_IMGTYPE_LIMIT", + "MDP_BGR_565", + "MDP_FB_FORMAT", + "MDP_IMGTYPE_LIMIT2" + }; + return formats[format]; +} + using namespace overlay; bool overlay::isHDMIConnected () { @@ -741,12 +799,14 @@ bool OverlayControlChannel::startOVRotatorSessions( int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); if (result) { reportError("Rotator session failed"); + dump(mRotInfo); ret = false; } } if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { reportError("startOVRotatorSessions, Overlay set failed"); + dump(mOVInfo); ret = false; } @@ -878,8 +938,11 @@ bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; if (flags != mOVInfo.flags) { - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + LOGE("setSource, OVERLAY_SET failed"); + dump(mOVInfo); return false; + } } return true; @@ -894,6 +957,8 @@ bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { (x < 0) || (y < 0) || ((x + w) > mFBWidth) || ((y + h) > mFBHeight)) { reportError("setPosition failed"); + LOGW("x %d y %d (x+w) %d (y+h) %d FBWidth %d FBHeight %d", x, y, x+w, y+h, + mFBWidth,mFBHeight); return false; } if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y || @@ -920,6 +985,7 @@ bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { ov.dst_rect.h = h; if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { reportError("setPosition, Overlay SET failed"); + dump(ov); return false; } mOVInfo = ov; @@ -1081,6 +1147,7 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { reportError("setParameter, overlay set failed"); + dump(mOVInfo); return false; } break; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index d4709c0..c359c97 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -117,6 +117,12 @@ int get_mdp_format(int format); int get_size(int format, int w, int h); int get_mdp_orientation(int rotation, int flip); +/* 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; From d7add45e8e6049c34ad91cd598f2236b3af3bf89 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Fri, 26 Aug 2011 18:16:21 -0700 Subject: [PATCH 413/435] Fix dynamic composition on framebuffer rotation This change fixes a bug in detecting fullscreen condition for dynamic composition. Change-Id: Ieadaf970061badc1d2f876560c1118fccf3a420a --- libhwcomposer/hwcomposer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 0dde148..49ca41c 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -326,7 +326,7 @@ static bool isFullScreenUpdate(const framebuffer_device_t* fbDev, const hwc_laye int transform = list->hwLayers[0].transform; - if(transform == (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) + if(transform & (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) return ((fb_w == h) && (fb_h == w)); else return ((fb_h == h) && (fb_w == w)); @@ -346,7 +346,7 @@ static bool isFullScreenUpdate(const framebuffer_device_t* fbDev, const hwc_laye int h2 = rect_2.bottom - rect_2.top; if(transform_1 == transform_2) { - if(transform_1 == (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) { + if(transform_1 & (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) { if((fb_w == (w1 + w2)) && (fb_h == h1) && (fb_h == h2)) return true; } else { From 48f7bb38a79175987fe5cc2f7d576469708b4364 Mon Sep 17 00:00:00 2001 From: Kinjal Bhavsar Date: Fri, 11 Feb 2011 18:05:39 -0800 Subject: [PATCH 414/435] liboverlay: Add support for 3D panel Detect and use 3D panel for 3D content. Use the virtual framebuffer for 3D panel. Set position for overlay channels accordingly. Use 3D ioctl for line interleaving. Add state machine for Overlay. Change-Id: I28dc7ed99aed7ca2c53c93722c44279d9c7de9fc Conflicts: liboverlay/overlayLib.cpp --- liboverlay/overlay.cpp | 2061 +++++++++++++++++------------------ liboverlay/overlayLib.cpp | 481 +++++--- liboverlay/overlayLib.h | 23 +- liboverlay/overlayState.cpp | 1109 +++++++++++++++++++ 4 files changed, 2467 insertions(+), 1207 deletions(-) create mode 100644 liboverlay/overlayState.cpp diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 9f9075f..aa2828b 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -31,88 +31,177 @@ using android::Mutex; #define EVEN_OUT(x) if (x & 0x0001) {x--;} #define SHARED_MEMORY_REGION_NAME "overlay_shared_memory" + +#define OVERLAY_HDMI_ENABLE 8 + /*****************************************************************************/ + using namespace overlay; struct overlay_control_context_t { - struct overlay_control_device_t device; - void *sharedMemBase; - unsigned int format3D; //input and output 3D format, zero means no 3D - unsigned int state; - unsigned int orientation; - overlay_rect posPanel; + struct overlay_control_device_t device; + void *sharedMemBase; + unsigned int format3D; //input and output 3D format, zero means no 3D + unsigned int state; + unsigned int orientation; + overlay_rect posPanel; }; struct overlay_data_context_t { - struct overlay_data_device_t device; - OverlayDataChannel* pobjDataChannel[2]; - unsigned int format3D; - unsigned int state; - bool setCrop; - overlay_rect cropRect; - int srcFD; //store the FD as it will needed for fb1 - int size; //size of the overlay created - void *sharedMemBase; + struct overlay_data_device_t device; + OverlayDataChannel* pobjDataChannel[2]; + unsigned int format3D; + unsigned int state; + bool setCrop; + overlay_rect cropRect; + int srcFD; //store the FD as it will needed for fb1 + int size; //size of the overlay created + void *sharedMemBase; }; +/////////////////////////////////////////////////////////////////////////////////// + +/* Overlay State func FIXME move to a separate module */ +class overlay_object; +int setParameterHandleState(overlay_control_context_t *ctx, + overlay_object *obj, + int param, int value); +int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot, + overlay_object* overlay, int fd); +int setPositionHandleState(overlay_control_context_t *ctx, + overlay_object *obj, overlay_rect& rect, + int x, int y, uint32_t w, uint32_t h); +int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +/* queue buffer */ +int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + + +int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +/////////////////////////////////////////////////////////////////////////////////// + + static int overlay_device_open(const struct hw_module_t* module, const char* name, - struct hw_device_t** device); + struct hw_device_t** device); static struct hw_module_methods_t overlay_module_methods = { - open: overlay_device_open +open: overlay_device_open }; struct private_overlay_module_t { - overlay_module_t base; - Mutex *pobjMutex; + overlay_module_t base; + Mutex *pobjMutex; }; struct private_overlay_module_t HAL_MODULE_INFO_SYM = { - base: { - common: { - tag: HARDWARE_MODULE_TAG, - version_major: 1, - version_minor: 0, - id: OVERLAY_HARDWARE_MODULE_ID, - name: "QCT MSM OVERLAY module", - author: "QuIC, Inc.", - methods: &overlay_module_methods, - } - }, - pobjMutex: NULL, +base: { +common: { +tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: OVERLAY_HARDWARE_MODULE_ID, + name: "QCT MSM OVERLAY module", + author: "QuIC, Inc.", + methods: &overlay_module_methods, + } + }, +pobjMutex: NULL, }; struct handle_t : public native_handle { - int sharedMemoryFd; - int ovid[2]; - int rotid[2]; - int size; - int w; - int h; - int format; - unsigned int format3D; - OverlayControlChannel *pobjControlChannel[2]; + int sharedMemoryFd; + int ovid[2]; + int rotid[2]; + int size; + int w; + int h; + int format; + unsigned int format3D; + OverlayControlChannel *pobjControlChannel[2]; }; static int handle_get_ovId(const overlay_handle_t overlay, int index = 0) { - return static_cast(overlay)->ovid[index]; + return static_cast(overlay)->ovid[index]; } static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) { - return static_cast(overlay)->rotid[index]; + return static_cast(overlay)->rotid[index]; } static int handle_get_size(const overlay_handle_t overlay) { - return static_cast(overlay)->size; + return static_cast(overlay)->size; +} + +static int handle_get_width(const overlay_handle_t overlay) { + return static_cast(overlay)->w; +} + +static int handle_get_height(const overlay_handle_t overlay) { + return static_cast(overlay)->h; } static int handle_get_shared_fd(const overlay_handle_t overlay) { - return static_cast(overlay)->sharedMemoryFd; + return static_cast(overlay)->sharedMemoryFd; } static int handle_get_format3D(const overlay_handle_t overlay) { - return static_cast(overlay)->format3D; + return static_cast(overlay)->format3D; } /* @@ -122,1083 +211,987 @@ static int handle_get_format3D(const overlay_handle_t overlay) { * HAL modules (for instance video decode modules). */ class overlay_object : public overlay_t { - handle_t mHandle; + 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)->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)->mHandle); + } -public: - overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) { - this->overlay_t::getHandleRef = getHandleRef; - mHandle.version = sizeof(native_handle); - mHandle.sharedMemoryFd = fd; - mHandle.numFds = 1; - mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4; - mHandle.ovid[0] = -1; - mHandle.ovid[1] = -1; - mHandle.rotid[0] = -1; - mHandle.rotid[1] = -1; - mHandle.size = -1; - mHandle.w = w; - mHandle.h = h; - mHandle.format = format; - mHandle.format3D = format3D; - mHandle.pobjControlChannel[0] = 0; - mHandle.pobjControlChannel[1] = 0; - } + public: + overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) { + this->overlay_t::getHandleRef = getHandleRef; + this->overlay_t::w = w; + this->overlay_t::h = h; + mHandle.version = sizeof(native_handle); + mHandle.sharedMemoryFd = fd; + mHandle.numFds = 1; + mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4; + mHandle.ovid[0] = -1; + mHandle.ovid[1] = -1; + mHandle.rotid[0] = -1; + mHandle.rotid[1] = -1; + mHandle.size = -1; + mHandle.w = w; + mHandle.h = h; + mHandle.format = format; + mHandle.format3D = format3D; + mHandle.pobjControlChannel[0] = 0; + mHandle.pobjControlChannel[1] = 0; + } - ~overlay_object() { - destroy_overlay(); - } + ~overlay_object() { + destroy_overlay(); + } - int getHwOvId(int index = 0) { return mHandle.ovid[index]; } - int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } - int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} + int getHwOvId(int index = 0) { return mHandle.ovid[index]; } + int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } + int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} - bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { - int index = fbnum; - if (mHandle.format3D) - index = zorder; - if (!mHandle.pobjControlChannel[index]) - mHandle.pobjControlChannel[index] = new OverlayControlChannel(); - else { - mHandle.pobjControlChannel[index]->closeControlChannel(); - mHandle.pobjControlChannel[index] = new OverlayControlChannel(); - } - bool ret = mHandle.pobjControlChannel[index]->startControlChannel( - mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, - mHandle.format3D, zorder, true); - if (ret) { - if (!(mHandle.pobjControlChannel[index]-> - getOvSessionID(mHandle.ovid[index]) && - mHandle.pobjControlChannel[index]-> - getRotSessionID(mHandle.rotid[index]) && - mHandle.pobjControlChannel[index]-> - getSize(mHandle.size))) - ret = false; - } + bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { + int index = fbnum; + if (mHandle.format3D) + index = zorder; + if (!mHandle.pobjControlChannel[index]) + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); + else { + mHandle.pobjControlChannel[index]->closeControlChannel(); + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); + } + bool ret = mHandle.pobjControlChannel[index]->startControlChannel( + mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, + mHandle.format3D, zorder, true); + if (ret) { + if (!(mHandle.pobjControlChannel[index]-> + getOvSessionID(mHandle.ovid[index]) && + mHandle.pobjControlChannel[index]-> + getRotSessionID(mHandle.rotid[index]) && + mHandle.pobjControlChannel[index]-> + getSize(mHandle.size))) + ret = false; + } - if (!ret) { - closeControlChannel(index); - } + if (!ret) { + closeControlChannel(index); + } - return ret; - } + return ret; + } - bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->setPosition( - x, y, w, h); - } + bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->setPosition( + x, y, w, h); + } - bool getAspectRatioPosition(overlay_rect *rect, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, - mHandle.h, rect); - } + bool getAspectRatioPosition(overlay_rect *rect, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, + mHandle.h, rect); + } - bool setParameter(int param, int value, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->setParameter( - param, value); - } + bool setParameter(int param, int value, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->setParameter( + param, value); + } - bool closeControlChannel(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return true; - bool ret = mHandle.pobjControlChannel[channel]-> - closeControlChannel(); - delete mHandle.pobjControlChannel[channel]; - mHandle.pobjControlChannel[channel] = 0; - return ret; - } + bool closeControlChannel(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return true; + bool ret = mHandle.pobjControlChannel[channel]-> + closeControlChannel(); + delete mHandle.pobjControlChannel[channel]; + mHandle.pobjControlChannel[channel] = 0; + return ret; + } - bool getPositionS3D(overlay_rect *rect, int channel) { - if (!mHandle.pobjControlChannel[channel]) { - LOGE("%s:Failed got channel %d", __func__, channel); - return false; - } + bool getPositionS3D(overlay_rect *rect, int channel, bool useVFB = false) { + if (!mHandle.pobjControlChannel[channel]) { + LOGE("%s:Failed got channel %d", __func__, channel); + return false; + } + int format = useVFB ? HAL_3D_OUT_SIDE_BY_SIDE_MASK : mHandle.format3D; + return mHandle.pobjControlChannel[channel]->getPositionS3D( + channel, format, rect); + } - return mHandle.pobjControlChannel[channel]->getPositionS3D( - channel, mHandle.format3D, rect); - } + bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getPosition( + *x, *y, *w, *h); + } - bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getPosition( - *x, *y, *w, *h); - } + bool getOrientation(int *orientation, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getOrientation( + *orientation); + } - bool getOrientation(int *orientation, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getOrientation( - *orientation); - } + void destroy_overlay() { + close(mHandle.sharedMemoryFd); + closeControlChannel(VG1_PIPE); + closeControlChannel(VG0_PIPE); + if(mHandle.format3D) { + send3DInfoPacket (0); + enableBarrier(0); + } + } - void destroy_overlay() { - close(mHandle.sharedMemoryFd); - closeControlChannel(0); - closeControlChannel(1); - send3DInfoPacket (0); - } + int getFBWidth(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getFBWidth(); + } - int getFBWidth(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getFBWidth(); - } + int getFBHeight(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getFBHeight(); + } - int getFBHeight(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getFBHeight(); - } + inline void setFormat3D(unsigned int format3D) { + mHandle.format3D = format3D; + } - inline void setFormat3D(unsigned int format3D) { - mHandle.format3D = format3D; - } + inline bool useVirtualFB(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->useVirtualFB(); + } }; // **************************************************************************** // Control module // **************************************************************************** - static int overlay_get(struct overlay_control_device_t *dev, int name) { - int result = -1; - switch (name) { - case OVERLAY_MINIFICATION_LIMIT: - result = HW_OVERLAY_MINIFICATION_LIMIT; - break; - case OVERLAY_MAGNIFICATION_LIMIT: - result = HW_OVERLAY_MAGNIFICATION_LIMIT; - break; - case OVERLAY_SCALING_FRAC_BITS: - result = 32; - 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 int overlay_get(struct overlay_control_device_t *dev, int name) { + int result = -1; + switch (name) { + case OVERLAY_MINIFICATION_LIMIT: + result = HW_OVERLAY_MINIFICATION_LIMIT; + break; + case OVERLAY_MAGNIFICATION_LIMIT: + result = HW_OVERLAY_MAGNIFICATION_LIMIT; + break; + case OVERLAY_SCALING_FRAC_BITS: + result = 32; + 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 void error_cleanup_control(overlay_control_context_t *ctx, overlay_object *overlay, int fd, int index) { - LOGE("Failed to start control channel %d", index); - for (int i = 0; i < index; i++) - overlay->closeControlChannel(i); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); - ctx->sharedMemBase = MAP_FAILED; - } - if(fd > 0) - close(fd); - delete overlay; - } +static void error_cleanup_control(overlay_control_context_t *ctx, overlay_object *overlay, int fd, int index) { + LOGE("Failed to start control channel %d", index); + for (int i = 0; i < index; i++) + overlay->closeControlChannel(i); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + delete overlay; +} - static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, - uint32_t w, uint32_t h, int32_t format) { - overlay_object *overlay = NULL; - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); +static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, + uint32_t w, uint32_t h, int32_t format) { + overlay_object *overlay = NULL; + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - // Open shared memory to store shared data - int size = sizeof(overlay_shared_data); - void *base; - int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, - size); - if(fd < 0) { - LOGE("%s: create shared memory failed", __func__); - return NULL; - } - if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) { - LOGE("ashmem_set_prot_region(fd=%d, failed (%s)", - fd, strerror(-errno)); - close(fd); - fd = -1; - return NULL; - } else { - base = mmap(0, size, PROT_READ | PROT_WRITE, - MAP_SHARED|MAP_POPULATE, fd, 0); - if (base == MAP_FAILED) { - LOGE("alloc mmap(fd=%d, size=%d) failed (%s)", - fd, size, strerror(-errno)); - close(fd); - fd = -1; - return NULL; - } - } + // Open shared memory to store shared data + int size = sizeof(overlay_shared_data); + void *base; + int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, + size); + if(fd < 0) { + LOGE("%s: create shared memory failed", __func__); + return NULL; + } + if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) { + LOGE("ashmem_set_prot_region(fd=%d, failed (%s)", + fd, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } else { + base = mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED|MAP_POPULATE, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d) failed (%s)", + fd, size, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } + } - // Separate the color format from the 3D format. - // If there is 3D content; the effective format passed by the client is: - // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat - unsigned int format3D = FORMAT_3D(format); - format = COLOR_FORMAT(format); - int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format - int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format - format3D = fIn3D | fOut3D; - // Use the same in/out format if not mentioned - if (!fIn3D) { - format3D |= fOut3D << SHIFT_3D; //Set the input format - } - if(!fOut3D) { - switch (fIn3D) { - case HAL_3D_IN_SIDE_BY_SIDE_L_R: - case HAL_3D_IN_SIDE_BY_SIDE_R_L: - // For all side by side formats, set the output - // format as Side-by-Side i.e 0x1 - format3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_3D; - break; - default: - format3D |= fIn3D >> SHIFT_3D; //Set the output format - break; - } - } - unsigned int curState = overlay::getOverlayConfig(format3D); - if (curState == OV_3D_VIDEO_2D_PANEL || curState == OV_3D_VIDEO_2D_TV) { - LOGI("3D content on 2D display: set the output format as monoscopic"); - format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; - } - LOGD("createOverlay: creating overlay with format3D: 0x%x, curState: %d", format3D, curState); - ctx->sharedMemBase = base; - ctx->format3D = format3D; - ctx->state = curState; - memset(ctx->sharedMemBase, 0, size); + // Separate the color format from the 3D format. + // If there is 3D content; the effective format passed by the client is: + // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + unsigned int format3D = FORMAT_3D(format); + format = COLOR_FORMAT(format); + int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format + int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format + format3D = fIn3D | fOut3D; + // Use the same in/out format if not mentioned + if (!fIn3D) { + format3D |= fOut3D << SHIFT_3D; //Set the input format + } + if(!fOut3D) { + switch (fIn3D) { + case HAL_3D_IN_SIDE_BY_SIDE_L_R: + case HAL_3D_IN_SIDE_BY_SIDE_R_L: + // For all side by side formats, set the output + // format as Side-by-Side i.e 0x1 + format3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_3D; + break; + default: + format3D |= fIn3D >> SHIFT_3D; //Set the output format + break; + } + } + unsigned int curState = overlay::getOverlayConfig(format3D); + if (curState == OV_3D_VIDEO_2D_PANEL || curState == OV_3D_VIDEO_2D_TV) { + LOGI("3D content on 2D display: set the output format as monoscopic"); + format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + LOGW("createOverlay: creating overlay with format3D: 0x%x, curState: %d", format3D, curState); + ctx->sharedMemBase = base; + ctx->format3D = format3D; + ctx->state = curState; + memset(ctx->sharedMemBase, 0, size); - /* number of buffer is not being used as overlay buffers are coming from client */ - overlay = new overlay_object(w, h, format, fd, format3D); - if (overlay == NULL) { - LOGE("%s: can't create overlay object!", __FUNCTION__); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; - } - if(fd > 0) - close(fd); - return NULL; - } - bool noRot; + /* number of buffer is not being used as overlay buffers are coming from client */ + overlay = new overlay_object(w, h, format, fd, format3D); + if (overlay == NULL) { + LOGE("%s: can't create overlay object!", __FUNCTION__); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + return NULL; + } + bool noRot; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + noRot = true; #endif - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot)) { - error_cleanup_control(ctx, overlay, fd, FRAMEBUFFER_0); - return NULL; - } - break; - case OV_2D_VIDEO_ON_TV: - case OV_3D_VIDEO_2D_TV: - if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, VG0_PIPE)) { - error_cleanup_control(ctx, overlay, fd, VG0_PIPE); - return NULL; - } - if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { - error_cleanup_control(ctx, overlay, fd, VG1_PIPE); - return NULL; - } - break; - case OV_3D_VIDEO_3D_TV: - for (int i=0; istartControlChannel(FRAMEBUFFER_1, true, i)) { - error_cleanup_control(ctx, overlay, fd, i); - return NULL; - } - } - break; - default: - break; - } - overlay_shared_data* data = static_cast(ctx->sharedMemBase); - data->state = ctx->state; - for (int i=0; iovid[i] = overlay->getHwOvId(i); - data->rotid[i] = overlay->getRotSessionId(i); - } - return overlay; - } + if(-1 == createOverlayHandleState(ctx, noRot, overlay, fd)) + return 0;// NULL + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->state = ctx->state; + for (int i=0; iovid[i] = overlay->getHwOvId(i); + data->rotid[i] = overlay->getRotSessionId(i); + } + return overlay; +} - static void overlay_destroyOverlay(struct overlay_control_device_t *dev, - overlay_t* overlay) - { - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object * obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); - ctx->sharedMemBase = MAP_FAILED; - } - obj->destroy_overlay(); - delete overlay; - } +static void overlay_destroyOverlay(struct overlay_control_device_t *dev, + overlay_t* overlay) +{ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + // ~overlay_object calls destroy_overlay + delete obj; +} - 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) */ - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object * obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool ret; - overlay_rect rect; - // saving the position for the disconnection event - ctx->posPanel.x = x; - ctx->posPanel.y = y; - ctx->posPanel.w = w; - ctx->posPanel.h = h; +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) */ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + bool ret; + overlay_rect rect; + // saving the position for the disconnection event + ctx->posPanel.x = x; + ctx->posPanel.y = y; + ctx->posPanel.w = w; + ctx->posPanel.h = h; - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { - LOGE("%s:Failed for channel 0", __func__); - return -1; - } - break; - case OV_2D_VIDEO_ON_TV: - if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { - LOGE("%s:Failed for channel 0", __func__); - return -1; - } - obj->getAspectRatioPosition(&rect, VG1_PIPE); - if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { - LOGE("%s:Failed for channel 1", __func__); - return -1; - } - break; - case OV_3D_VIDEO_2D_TV: - case OV_3D_VIDEO_3D_TV: - for (int i = 0; i < NUM_CHANNELS; i++) { - if (!obj->getPositionS3D(&rect, i)) - ret = obj->setPosition(x, y, w, h, i); - else - ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i); - if (!ret) { - LOGE("%s:Failed for channel %d", __func__, i); - return -1; - } - } - break; - default: - break; - } - return 0; - } + if(-1 == setPositionHandleState(ctx, obj, rect, x, y, w, h)) + return -1; - static int overlay_commit(struct overlay_control_device_t *dev, - overlay_t* overlay) - { - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object *obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); + return 0; +} - Mutex::Autolock objLock(m->pobjMutex); - if (obj && (obj->getSharedMemoryFD() > 0) && - (ctx->sharedMemBase != MAP_FAILED)) { - overlay_shared_data data; - data.readyToQueue = 1; - memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data)); - } - return 0; - } +static int overlay_commit(struct overlay_control_device_t *dev, + overlay_t* overlay) +{ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); - static int overlay_getPosition(struct overlay_control_device_t *dev, - overlay_t* overlay, - int* x, int* y, uint32_t* w, uint32_t* h) { + Mutex::Autolock objLock(m->pobjMutex); + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->isControlSetup = true; + } + return 0; +} - /* get this overlay's position */ - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - overlay_object * obj = static_cast(overlay); - return obj->getPosition(x, y, w, h, 0) ? 0 : -1; - } -#if 0 - static bool overlay_configPipes(overlay_control_context_t *ctx, - overlay_object *obj, int enable, - unsigned int curState) { - bool noRot = true; - overlay_rect rect; +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 */ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + overlay_object * obj = static_cast(overlay); + return obj->getPosition(x, y, w, h, 0) ? 0 : -1; +} + +static bool overlay_configPipes(overlay_control_context_t *ctx, + overlay_object *obj, int enable, + unsigned int newState) { + bool noRot = true; + overlay_rect rect; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + noRot = true; #endif - if(enable) { - if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || - (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_2D_TV) ) { - LOGI("2D TV connected, Open a new control channel for TV."); - //Start a new channel for mirroring on HDMI - if (!obj->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { - obj->closeControlChannel(FRAMEBUFFER_1); - return false; - } - if (ctx->format3D) - obj->getPositionS3D(&rect, FRAMEBUFFER_1); - else - obj->getAspectRatioPosition(&rect, FRAMEBUFFER_1); - if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, FRAMEBUFFER_1)) { - LOGE("%s:Failed to set position for framebuffer 1", __func__); - return false; - } - } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_3D_TV) ) { - LOGI("3D TV connected, close old ctl channel and open two ctl channels for 3DTV."); - //close the channel 0 as it is configured for panel - obj->closeControlChannel(FRAMEBUFFER_0); - //update the output from monoscopic to stereoscopic - ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; - obj->setFormat3D(ctx->format3D); - LOGI("Control: new S3D format : 0x%x", ctx->format3D); - //now open both the channels - for (int i = 0; i < NUM_CHANNELS; i++) { - if (!obj->startControlChannel(FRAMEBUFFER_1, true, i)) { - LOGE("%s:Failed to open control channel for pipe %d", __func__, i); - return false; - } - obj->getPositionS3D(&rect, i); - if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { - LOGE("%s: failed for channel %d", __func__, i); - return false; - } - } - } - } else { - if ( (ctx->state == OV_2D_VIDEO_ON_TV) || - (ctx->state == OV_3D_VIDEO_2D_TV && curState == OV_3D_VIDEO_2D_PANEL) ) { - LOGI("2D TV disconnected, close the control channel."); - obj->closeControlChannel(VG1_PIPE); - } else if (ctx->state == OV_3D_VIDEO_3D_TV && curState == OV_3D_VIDEO_2D_PANEL) { - LOGI("3D TV disconnected, close the control channels & open one for panel."); - // Close both the pipes' control channel - obj->closeControlChannel(VG0_PIPE); - obj->closeControlChannel(VG1_PIPE); - //update the format3D as monoscopic - ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; - obj->setFormat3D(ctx->format3D); - LOGI("Control: New format3D: 0x%x", ctx->format3D); - //now open the channel 0 - if (!obj->startControlChannel(FRAMEBUFFER_0, noRot)) { - LOGE("%s:Failed to open control channel for pipe 0", __func__); - return false; - } - if(!obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, ctx->posPanel.w, ctx->posPanel.h, FRAMEBUFFER_0)) { - LOGE("%s:Failed to set position for framebuffer 0", __func__); - return false; - } - if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, VG0_PIPE)) { - LOGE("%s: Failed to set orienatation for channel 0", __func__); - return -1; - } - } - } - //update the context's state - ctx->state = curState; - return true; - } -#endif - static int overlay_setParameter(struct overlay_control_device_t *dev, - overlay_t* overlay, int param, int value) { + switch (ctx->state) + { + case OV_2D_VIDEO_ON_PANEL: + if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_2D_VIDEO_ON_TV: + if(-1 == configPipes_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + default: + LOGE("Unknown state in configPipes"); + abort(); + } + //update the context's state + ctx->state = newState; + return true; +} - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object *obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); +static int overlay_setParameter(struct overlay_control_device_t *dev, + overlay_t* overlay, int param, int value) { - if (obj && (obj->getSharedMemoryFD() > 0) && - (ctx->sharedMemBase != MAP_FAILED)) { - overlay_shared_data* data = static_cast(ctx->sharedMemBase); - data->readyToQueue = 0; -#if 0 - /* SF will inform Overlay HAL the HDMI cable connection. - This avoids polling on the system property hw.hdmiON */ - if(param == OVERLAY_HDMI_ENABLE) { - unsigned int curState = getOverlayConfig(ctx->format3D); - if(ctx->state != curState) { - LOGI("Overlay Configured for : %d Current state: %d", ctx->state, curState); - if(!overlay_configPipes(ctx, obj, value, curState)) { - LOGE("In overlay_setParameter: reconfiguring of Overlay failed !!"); - return -1; - } - else { - data->state = ctx->state; - for (int i=0; iovid[i] = obj->getHwOvId(i); - data->rotid[i] = obj->getRotSessionId(i); - } - } - } - } -#endif - } -// if(param != OVERLAY_HDMI_ENABLE) - { - //Save the panel orientation - if (param == OVERLAY_TRANSFORM) - ctx->orientation = value; - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - if(!obj->setParameter(param, value, VG0_PIPE)) { - LOGE("%s: Failed for channel 0", __func__); - return -1; - } - break; - case OV_2D_VIDEO_ON_TV: - case OV_3D_VIDEO_2D_TV: - case OV_3D_VIDEO_3D_TV: - for (int i=0; isetParameter(param, value, i)) { - LOGE("%s: Failed for channel %d", __func__, i); - return -1; - } - } - break; - default: - break; - } - } - return 0; - } + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - 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; - } + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->isControlSetup = false; + /* SF will inform Overlay HAL the HDMI cable connection. + This avoids polling on the system property hw.hdmiON */ + if(param == OVERLAY_HDMI_ENABLE) { + unsigned int curState = getOverlayConfig(ctx->format3D, false, value); + if(ctx->state != curState) { + LOGI("Overlay Configured for : %d Current state: %d", ctx->state, curState); + if(!overlay_configPipes(ctx, obj, value, curState)) { + LOGE("In overlay_setParameter: reconfiguring of Overlay failed !!"); + return -1; + } + else { + data->state = ctx->state; + for (int i=0; iovid[i] = obj->getHwOvId(i); + data->rotid[i] = obj->getRotSessionId(i); + } + } + } + } + } + if(param != OVERLAY_HDMI_ENABLE) { + //Save the panel orientation + if (param == OVERLAY_TRANSFORM) { + ctx->orientation = value; + if(ctx->state == OV_3D_VIDEO_3D_PANEL) { + int barrier = 0; + switch(ctx->orientation) { + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_270: + barrier = BARRIER_LANDSCAPE; + break; + default: + barrier = BARRIER_PORTRAIT; + break; + } + if(!enableBarrier(barrier)) + LOGE("%s:failed to enable barriers for 3D video", __func__); + } + } + if (-1 == setParameterHandleState(ctx, obj, param, value)) + return -1; + } + return 0; +} + +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 // **************************************************************************** - static void error_cleanup_data(struct overlay_data_context_t* ctx, int index) - { - LOGE("Couldn't start data channel %d", index); - for (int i = 0; ipobjDataChannel[i]; - ctx->pobjDataChannel[i] = NULL; - } - } +static void error_cleanup_data(struct overlay_data_context_t* ctx, int index) +{ + LOGE("Couldn't start data channel %d", index); + for (int i = 0; ipobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } +} - 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 - * - */ +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 + * + */ - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - int ovid = handle_get_ovId(handle); - int rotid = handle_get_rotId(handle); - int size = handle_get_size(handle); - int sharedFd = handle_get_shared_fd(handle); - unsigned int format3D = handle_get_format3D(handle); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool noRot = true; + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + int ovid = handle_get_ovId(handle); + int rotid = handle_get_rotId(handle); + int size = handle_get_size(handle); + int sharedFd = handle_get_shared_fd(handle); + unsigned int format3D = handle_get_format3D(handle); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + bool noRot = true; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + noRot = true; #endif - //default: set crop info to src size. - ctx->cropRect.x = 0; - ctx->cropRect.y = 0; - //ctx->cropRect.w = handle_get_width(handle); - //ctx->cropRect.h = handle_get_height(handle); - ctx->sharedMemBase = MAP_FAILED; - ctx->format3D = format3D; + //default: set crop info to src size. + ctx->cropRect.x = 0; + ctx->cropRect.y = 0; + ctx->cropRect.w = handle_get_width(handle); + ctx->cropRect.h = handle_get_height(handle); - if(sharedFd > 0) { - void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, - MAP_SHARED|MAP_POPULATE, sharedFd, 0); - if(base == MAP_FAILED) { - LOGE("%s: map region failed %d", __func__, -errno); - return -1; - } - ctx->sharedMemBase = base; - } else { - LOGE("Received invalid shared memory fd"); - return -1; - } - overlay_shared_data* data = static_cast - (ctx->sharedMemBase); - if (data == NULL){ - LOGE("%s:Shared data is NULL!!", __func__); - return -1; - } - ctx->state = data->state; - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) { - error_cleanup_data(ctx, VG0_PIPE); - return -1; - } - //setting the crop value - if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( - ctx->cropRect.x,ctx->cropRect.y, - ctx->cropRect.w,ctx->cropRect.h)) { - LOGE("%s:failed to crop pipe 0", __func__); - } - break; - case OV_2D_VIDEO_ON_TV: - case OV_3D_VIDEO_2D_TV: - for (int i = 0; i < NUM_CHANNELS; i++) { - ovid = handle_get_ovId(handle, i); - rotid = handle_get_rotId(handle, i); - ctx->pobjDataChannel[i] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, true)) { - error_cleanup_data(ctx, i); - return -1; - } - //setting the crop value - if(!ctx->pobjDataChannel[i]->setCrop( - ctx->cropRect.x,ctx->cropRect.y, - ctx->cropRect.w,ctx->cropRect.h)) { - LOGE("%s:failed to crop pipe %d", __func__, i); - } - } - break; - case OV_3D_VIDEO_3D_TV: - overlay_rect rect; - for (int i = 0; i < NUM_CHANNELS; i++) { - ovid = handle_get_ovId(handle, i); - rotid = handle_get_rotId(handle, i); - ctx->pobjDataChannel[i] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_1, true)) { - error_cleanup_data(ctx, i); - return -1; - } - ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); - if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { - LOGE("%s: Failed to crop channel %d", __func__, i); - //return -1; - } - } - if(!send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D)) - LOGI("%s:Error setting the 3D mode for TV", __func__); - break; - default: - break; - } - return 0; - } + ctx->sharedMemBase = MAP_FAILED; + ctx->format3D = format3D; + //Store the size, needed for HDMI mirroring + ctx->size = size; - 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. - */ + if(sharedFd > 0) { + void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, + MAP_SHARED|MAP_POPULATE, sharedFd, 0); + if(base == MAP_FAILED) { + LOGE("%s: map region failed %d", __func__, -errno); + return -1; + } + ctx->sharedMemBase = base; + } else { + LOGE("Received invalid shared memory fd"); + return -1; + } + overlay_shared_data* data = static_cast + (ctx->sharedMemBase); + if (data == NULL){ + LOGE("%s:Shared data is NULL!!", __func__); + return -1; + } + ctx->state = data->state; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); + return -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (FRAMEBUFFER_1 == i) + noRot = true; + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + } + break; + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + } + if(!send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D)) + LOGI("%s:Error setting the 3D mode for TV", __func__); + break; + default: + break; + } + return 0; +} - /* no internal overlay buffer to dequeue */ - LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); +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 0; - } + /* no internal overlay buffer to dequeue */ + LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); - 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. */ - struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool noRot = true; + return 0; +} + +//Called with Mutex::Autolock objLock(m->pobjMutex); already held +int overlay_queueBufferCheckStateChange(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + /* Mark this buffer for posting and recycle or free overlay_buffer_t. */ + struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; + overlay_shared_data* data = 0; + if(ctx->sharedMemBase != MAP_FAILED) { + data = static_cast(ctx->sharedMemBase); + if(0 == data){ + LOGE("ctx->sharedMemBase is NULL"); + return false; + } + } + else{ + LOGE("ctx->sharedMemBase == MAP_FAILED"); + return false; + } + + bool noRot = true; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + noRot = true; #endif - // Check if readyToQueue is enabled. - overlay_shared_data data; - if(ctx->sharedMemBase != MAP_FAILED) - memcpy(&data, ctx->sharedMemBase, sizeof(data)); - else - return false; - if(!data.readyToQueue) { - LOGE("Overlay is not ready to queue buffers"); - return -1; - } -#if 0 - if(data->state != ctx->state) { - LOGI("Data: State has changed from %d to %d", ctx->state, data->state); - if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || - (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_2D_TV) ) { - LOGI("2D TV connected, Open a new data channel for TV."); - //Start a new channel for mirroring on HDMI - ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel( - data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size, - FRAMEBUFFER_1, true)) { - delete ctx->pobjDataChannel[VG1_PIPE]; - ctx->pobjDataChannel[VG1_PIPE] = NULL; - return -1; - } - //setting the crop value - if(ctx->format3D) { - overlay_rect rect; - ctx->pobjDataChannel[VG1_PIPE]->getCropS3D(&ctx->cropRect, VG1_PIPE, ctx->format3D, &rect); - if (!ctx->pobjDataChannel[VG1_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { - LOGE("%s: Failed to crop pipe 1", __func__); - } - } else { - if(!ctx->pobjDataChannel[VG1_PIPE]->setCrop( - ctx->cropRect.x,ctx->cropRect.y, - ctx->cropRect.w,ctx->cropRect.h)) { - LOGE("%s:failed to crop pipe 1", __func__); - } - } - //setting the srcFD - if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { - LOGE("%s: Failed to set fd for pipe 1", __func__); - return -1; - } - } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_3D_TV) ) { - LOGI("3D TV connected, close data channel and open both data channels for 3DTV."); - //close the channel 0 as it is configured for panel - ctx->pobjDataChannel[VG0_PIPE]->closeDataChannel(); - delete ctx->pobjDataChannel[VG0_PIPE]; - ctx->pobjDataChannel[VG0_PIPE] = NULL; - //update the output from monoscopic to stereoscopic - ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; - LOGI("Data: New S3D format : 0x%x", ctx->format3D); - //now open both the channels - overlay_rect rect; - for (int i = 0; i < NUM_CHANNELS; i++) { - ctx->pobjDataChannel[i] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[i]->startDataChannel( - data->ovid[i], data->rotid[i], ctx->size, - FRAMEBUFFER_1, true)) { - error_cleanup_data(ctx, i); - return -1; - } - ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); - if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { - LOGE("%s: Failed to crop pipe %d", __func__, i); - return -1; - } - if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { - LOGE("%s: Failed to set fd for pipe %d", __func__, i); - return -1; - } - } - send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); - } else if( (ctx->state == OV_2D_VIDEO_ON_TV) || - (ctx->state == OV_3D_VIDEO_2D_TV && data->state == OV_3D_VIDEO_2D_PANEL) ) { - LOGI("2D TV disconnected, close the data channel for TV."); - ctx->pobjDataChannel[VG1_PIPE]->closeDataChannel(); - delete ctx->pobjDataChannel[VG1_PIPE]; - ctx->pobjDataChannel[VG1_PIPE] = NULL; - } else if (ctx->state == OV_3D_VIDEO_3D_TV && data->state == OV_3D_VIDEO_2D_PANEL) { - LOGI("3D TV disconnected, close the data channels for 3DTV and open one for panel."); - // Close both the pipes' data channel - for (int i = 0; i < NUM_CHANNELS; i++) { - ctx->pobjDataChannel[i]->closeDataChannel(); - delete ctx->pobjDataChannel[i]; - ctx->pobjDataChannel[i] = NULL; - } - send3DInfoPacket(0); - //update the format3D as monoscopic - ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; - //now open the channel 0 - ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel( - data->ovid[VG0_PIPE], data->rotid[VG0_PIPE], ctx->size, - FRAMEBUFFER_0, noRot)) { - error_cleanup_data(ctx, VG0_PIPE); - return -1; - } - overlay_rect rect; - ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); - //setting the crop value - if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( rect.x, rect.y,rect.w, rect.h)) { - LOGE("%s:failed to crop pipe 0", __func__); - } - //setting the srcFD - if (!ctx->pobjDataChannel[VG0_PIPE]->setFd(ctx->srcFD)) { - LOGE("%s: Failed set fd for pipe 0", __func__); - return -1; - } - } - //update the context's state - ctx->state = data->state; - } -#endif - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - if (ctx->setCrop) { - if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(ctx->cropRect.x, ctx->cropRect.y, ctx->cropRect.w, ctx->cropRect.h)) { - LOGE("%s: failed for pipe 0", __func__); - } - ctx->setCrop = false; - } - if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { - LOGE("%s: failed for VG pipe 0", __func__); - return -1; - } - break; - case OV_3D_VIDEO_2D_PANEL: - if (ctx->setCrop) { - overlay_rect rect; - ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); - if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { - LOGE("%s: failed for pipe 0", __func__); - } - ctx->setCrop = false; - } - if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { - LOGE("%s: failed for VG pipe 0", __func__); - return -1; - } - break; - case OV_2D_VIDEO_ON_TV: - case OV_3D_VIDEO_2D_TV: - case OV_3D_VIDEO_3D_TV: - for (int i=0; ipobjDataChannel[i]->queueBuffer((uint32_t) buffer)) { - LOGE("%s: failed for VG pipe %d", __func__, i); - return -1; - } - } - break; - default: - break; - } + unsigned int newState = data->state; - return -1; - } + switch (ctx->state) + { + case OV_2D_VIDEO_ON_PANEL: + if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_TV: + if(-1 == queueBuffer_OV_2D_VIDEO_ON_TV(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV(ctx, data, + newState, + noRot)) + return -1; + break; + default: + LOGE("Unknown state in configPipes"); + abort(); + } + //update the context's state + ctx->state = newState; + return 0; +} - int overlay_setFd(struct overlay_data_device_t *dev, int fd) - { - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - Mutex::Autolock objLock(m->pobjMutex); - ctx->srcFD = fd; - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - if(!ctx->pobjDataChannel[VG0_PIPE]->setFd(fd)) { - LOGE("%s: failed for VG pipe 0", __func__); - return -1; - } - break; - case OV_2D_VIDEO_ON_TV: - case OV_3D_VIDEO_2D_TV: - case OV_3D_VIDEO_3D_TV: - for (int i=0; ipobjDataChannel[i]->setFd(fd)) { - LOGE("%s: failed for pipe %d", __func__, i); - return -1; - } - } - break; - default: - break; - } - return 0; - } +int overlay_queueBuffer(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, - uint32_t y, uint32_t w, uint32_t h) - { - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - Mutex::Autolock objLock(m->pobjMutex); - overlay_rect rect; - ctx->cropRect.x = x; - ctx->cropRect.y = y; - ctx->cropRect.w = w; - ctx->cropRect.h = h; - switch (ctx->state) { - case OV_2D_VIDEO_ON_PANEL: - case OV_3D_VIDEO_2D_PANEL: - ctx->setCrop = true; - break; - case OV_2D_VIDEO_ON_TV: - for (int i=0; ipobjDataChannel[i]->setCrop(x, y, w, h)) { - LOGE("%s: failed for pipe %d", __func__, i); - return -1; - } - } - break; - case OV_3D_VIDEO_2D_TV: - case OV_3D_VIDEO_3D_TV: - for (int i=0; ipobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); - if(!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { - LOGE("%s: failed for pipe %d", __func__, i); - return -1; - } - } - break; - default: - break; - } - return 0; - } + // Check if control channel is setup. + overlay_shared_data* data = NULL; + if(ctx->sharedMemBase != MAP_FAILED) { + data = static_cast(ctx->sharedMemBase); + if(data == NULL) + return false; + } + else + return false; - void *overlay_getBufferAddress(struct overlay_data_device_t *dev, - overlay_buffer_t buffer) - { - /* overlay buffers are coming from client */ - return( NULL ); - } + if(false == data->isControlSetup) { + LOGE("Overlay Control Channel is not fully setup yet"); + return -1; + } - int overlay_getBufferCount(struct overlay_data_device_t *dev) - { - return 0; - } + // check any state-changing related events + if(-1 == overlay_queueBufferCheckStateChange(dev, buffer)){ + return -1; + } + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + if (ctx->setCrop) { + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(ctx->cropRect.x, ctx->cropRect.y, ctx->cropRect.w, ctx->cropRect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); + return -1; + } + break; + case OV_3D_VIDEO_2D_PANEL: + if (ctx->setCrop) { + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); + return -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; + } + return 0; +} + +int overlay_setFd(struct overlay_data_device_t *dev, int fd) +{ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + Mutex::Autolock objLock(m->pobjMutex); + ctx->srcFD = fd; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!ctx->pobjDataChannel[VG0_PIPE]->setFd(fd)) { + LOGE("%s: failed for VG pipe 0", __func__); + return -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->setFd(fd)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; + } + return 0; +} + +static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, + uint32_t y, uint32_t w, uint32_t h) +{ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + //Yield processor until control channel is fully set up i.e commit happens. + while(false == data->isControlSetup) { + sched_yield(); + } + Mutex::Autolock objLock(m->pobjMutex); + overlay_rect rect; + ctx->cropRect.x = x; + ctx->cropRect.y = y; + ctx->cropRect.w = w; + ctx->cropRect.h = h; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->setCrop = true; + break; + case OV_2D_VIDEO_ON_TV: + for (int i=0; ipobjDataChannel[i]->setCrop(x, y, w, h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; + } + return 0; +} + +void *overlay_getBufferAddress(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + /* overlay buffers are coming from client */ + return( NULL ); +} + +int overlay_getBufferCount(struct overlay_data_device_t *dev) +{ + return 0; +} - 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). - */ +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). + */ - if (ctx->pobjDataChannel[0]) { - ctx->pobjDataChannel[0]->closeDataChannel(); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - } + if (ctx->pobjDataChannel[0]) { + ctx->pobjDataChannel[0]->closeDataChannel(); + delete ctx->pobjDataChannel[0]; + ctx->pobjDataChannel[0] = 0; + } - if (ctx->pobjDataChannel[1]) { - ctx->pobjDataChannel[1]->closeDataChannel(); - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; - } + if (ctx->pobjDataChannel[1]) { + ctx->pobjDataChannel[1]->closeDataChannel(); + delete ctx->pobjDataChannel[1]; + ctx->pobjDataChannel[1] = 0; + } - if(ctx->sharedMemBase != MAP_FAILED) { - munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); - ctx->sharedMemBase = MAP_FAILED; - } + if(ctx->sharedMemBase != MAP_FAILED) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } - free(ctx); - } - return 0; - } + 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; +static int overlay_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = -EINVAL; - private_overlay_module_t* m = reinterpret_cast - (const_cast(module)); - if (!m->pobjMutex) - m->pobjMutex = new Mutex(); + private_overlay_module_t* m = reinterpret_cast + (const_cast(module)); + if (!m->pobjMutex) + m->pobjMutex = new Mutex(); - if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { - struct overlay_control_context_t *dev; - dev = (overlay_control_context_t*)malloc(sizeof(*dev)); + if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { + struct overlay_control_context_t *dev; + dev = (overlay_control_context_t*)malloc(sizeof(*dev)); - if (!dev) - return status; + if (!dev) + return status; - /* initialize our state here */ - memset(dev, 0, 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(module); - dev->device.common.close = overlay_control_close; + /* 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 = 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; - dev->device.commit = overlay_commit; + 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; + dev->device.commit = overlay_commit; - *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)); + *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)); - if (!dev) - return status; + if (!dev) + return status; - /* initialize our state here */ - memset(dev, 0, 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(module); - dev->device.common.close = overlay_data_close; + /* 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 = overlay_data_close; - dev->device.initialize = overlay_initialize; - dev->device.setCrop = overlay_setCrop; - dev->device.dequeueBuffer = overlay_dequeueBuffer; - dev->device.queueBuffer = overlay_queueBuffer; - dev->device.setFd = overlay_setFd; - dev->device.getBufferAddress = overlay_getBufferAddress; - dev->device.getBufferCount = overlay_getBufferCount; + dev->device.initialize = overlay_initialize; + dev->device.setCrop = overlay_setCrop; + dev->device.dequeueBuffer = overlay_dequeueBuffer; + dev->device.queueBuffer = overlay_queueBuffer; + dev->device.setFd = overlay_setFd; + dev->device.getBufferAddress = overlay_getBufferAddress; + dev->device.getBufferCount = overlay_getBufferCount; - *device = &dev->device.common; - status = 0; - } - return status; - } + *device = &dev->device.common; + status = 0; + } + return status; +} + +#include "overlayState.cpp" diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 0dfa814..7a97063 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -163,6 +163,32 @@ bool overlay::is3DTV() { return (is3DTV == '0') ? false : true; } +bool overlay::isPanel3D() { + int fd = open("/dev/graphics/fb0", O_RDWR, 0); + if (fd < 0) { + reportError("Can't open framebuffer 0"); + return false; + } + fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + reportError("FBIOGET_FSCREENINFO on fb0 failed"); + close(fd); + fd = -1; + return false; + } + close(fd); + return (FB_TYPE_3D_PANEL == finfo.type) ? true : false; +} + +bool overlay::usePanel3D() { + if(!isPanel3D()) + return false; + char value[PROPERTY_VALUE_MAX]; + property_get("persist.user.panel3D", value, "0"); + int usePanel3D = atoi(value); + return usePanel3D ? true : false; +} + bool overlay::send3DInfoPacket (unsigned int format3D) { FILE *fp = fopen(FORMAT_3D_FILE, "wb"); if (fp) { @@ -171,28 +197,45 @@ bool overlay::send3DInfoPacket (unsigned int format3D) { fp = NULL; return true; } - LOGE("%s:no sysfs entry for setting 3d mode!", __func__); + LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__); return false; } -unsigned int overlay::getOverlayConfig (unsigned int format3D) { - bool isTV3D = false, isHDMI = false; +bool overlay::enableBarrier (unsigned int orientation) { + FILE *fp = fopen(BARRIER_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", orientation); + fclose(fp); + fp = NULL; + return true; + } + LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__); + return false; +} + +unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll, + bool isHDMI) { + bool isTV3D = false; unsigned int curState = 0; - isHDMI = overlay::isHDMIConnected(); + if (poll) + isHDMI = isHDMIConnected(); if (isHDMI) { - LOGD("%s: HDMI connected... checking the TV type", __func__); - isTV3D = overlay::is3DTV(); + LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__); if (format3D) { - if (isTV3D) + if (is3DTV()) curState = OV_3D_VIDEO_3D_TV; else curState = OV_3D_VIDEO_2D_TV; } else curState = OV_2D_VIDEO_ON_TV; } else { - LOGD("%s: HDMI not connected...", __func__); - if(format3D) - curState = OV_3D_VIDEO_2D_PANEL; + LOGD("%s: HDMI not connected...", __FUNCTION__); + if(format3D) { + if (usePanel3D()) + curState = OV_3D_VIDEO_3D_PANEL; + else + curState = OV_3D_VIDEO_2D_PANEL; + } else curState = OV_2D_VIDEO_ON_PANEL; } @@ -201,7 +244,7 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), mS3DFormat(0), mCroppedSrcWidth(0), - mCroppedSrcHeight(0) { + mCroppedSrcHeight(0), mState(-1) { mOVBufferInfo.width = mOVBufferInfo.height = 0; mOVBufferInfo.format = mOVBufferInfo.size = 0; } @@ -228,6 +271,9 @@ bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum, mCroppedSrcHeight = info.height; if (format3D) zorder = channel; + if (mState == -1) + mState = OV_UI_MIRROR_TV; + mChannelUP = objOvCtrlChannel[channel].startControlChannel(info.width, info.height, format, fbnum, norot, uichannel, @@ -241,39 +287,16 @@ bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum, norot, uichannel, num_buffers); } -bool Overlay::startChannelHDMI(const overlay_buffer_info& info, bool norot) { - - bool ret = startChannel(info, FRAMEBUFFER_0, norot); - if(ret) { - ret = startChannel(info, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); - } - return ret; -} - -bool Overlay::startChannelS3D(const overlay_buffer_info& info, bool norot) { - bool ret = false; - // Start both the channels for the S3D content - if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) - ret = startChannel(info, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); - else - ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); - if (ret) { - ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); - } - if (!ret) { - closeChannel(); - } else if (!(mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK)) - ret = overlay::send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D); - return ret; -} - bool Overlay::closeChannel() { if (!mChannelUP) return true; if(mS3DFormat) { - overlay::send3DInfoPacket(0); + if (mHDMIConnected) + overlay::send3DInfoPacket(0); + else if (mState == OV_3D_VIDEO_3D_PANEL) + enableBarrier(0); } for (int i = 0; i < NUM_CHANNELS; i++) { objOvCtrlChannel[i].closeControlChannel(); @@ -285,6 +308,7 @@ bool Overlay::closeChannel() { mOVBufferInfo.height = 0; mOVBufferInfo.format = 0; mOVBufferInfo.size = 0; + mState = -1; return true; } @@ -297,40 +321,58 @@ bool Overlay::getOrientation(int& orientation, int channel) const { } bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { - if(mHDMIConnected) { - if(mS3DFormat) { - return setPositionS3D(x, y, w, h); - } else { - overlay_rect rect; + bool ret = false; + overlay_rect rect; + switch (mState) { + case OV_UI_MIRROR_TV: + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + return setChannelPosition(x, y, w, h, VG0_PIPE); + break; + case OV_2D_VIDEO_ON_TV: objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth, mCroppedSrcHeight, &rect); setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE); - } + return setChannelPosition(x, y, w, h, VG0_PIPE); + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!objOvCtrlChannel[i].useVirtualFB()) { + LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i); + return false; + } + objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect); + if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s: failed for channel %d", __FUNCTION__, i); + return false; + } + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); + if (!ret) + ret = setChannelPosition(x, y, w, h, i); + else + ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s: failed for channel %d", __FUNCTION__, i); + return ret; + } + } + break; + default: + LOGE("%s:Unknown state %d", __FUNCTION__, mState); + break; } - return setChannelPosition(x, y, w, h, VG0_PIPE); + return true; } bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) { return objOvCtrlChannel[channel].setPosition(x, y, w, h); } -bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { - bool ret = false; - for (int i = 0; i < NUM_CHANNELS; i++) { - overlay_rect rect; - ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); - if (!ret) - ret = setChannelPosition(x, y, w, h, i); - else - ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i); - if (!ret) { - LOGE("%s: failed for channel %d", __func__, i); - return ret; - } - } - return ret; -} - bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation) { if (hasHDMIStatusChanged()) { return setSource(info, orientation, mHDMIConnected); @@ -343,8 +385,19 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati return true; } - // Disable rotation for the HDMI channel + // Disable rotation for the HDMI channels int orient[2] = {orientation, 0}; + switch(mState) { + case OV_3D_VIDEO_3D_PANEL: + orient[1] = orientation; + break; + case OV_3D_VIDEO_3D_TV: + orient[0] = 0; + break; + default: + break; + } + // Set the overlay source info for (int i = 0; i < NUM_CHANNELS; i++) { if (objOvCtrlChannel[i].isChannelUP()) { @@ -405,80 +458,116 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, // Separate the color format from the 3D format. // If there is 3D content; the effective format passed by the client is: // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + int newState = mState; + bool stateChange = false, ret = true; unsigned int format3D = getS3DFormat(info.format); int colorFormat = getColorFormat(info.format); - - if (format3D) { - bool isTV3D = false; - if (hdmiConnected) - isTV3D = overlay::is3DTV(); - if (!isTV3D) { - LOGD("Set the output format as monoscopic"); - format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; - } - } - int stateChanged = 0; - int hw_format = get_mdp_format(colorFormat); - int s3dChanged =0, hdmiChanged = 0; - - if (format3D != mS3DFormat) - s3dChanged = 0x10; - - stateChanged = s3dChanged|hasHDMIStatusChanged(); - if (stateChanged || !objOvCtrlChannel[0].setSource(info.width, info.height, colorFormat, orientation, ignoreFB)) { + newState = getOverlayConfig (format3D, false, hdmiConnected); + stateChange = (mState == newState) ? false : true; + // Check if the orientation of the primary channel changed + if (mState != OV_3D_VIDEO_3D_TV) + if (mChannelUP) + ret = objOvCtrlChannel[0].setSource(info.width, info.height, + colorFormat, orientation, ignoreFB); + if (stateChange || !ret) { closeChannel(); + mHDMIConnected = hdmiConnected; + mState = newState; mS3DFormat = format3D; - - mOVBufferInfo = info; - if (mHDMIConnected) { - if (mS3DFormat) { - // Start both the VG pipes - return startChannelS3D(info, !orientation); - } else { - return startChannelHDMI(info, !orientation); - } - } else { - return startChannel(info, 0, !orientation, - false, 0, VG0_PIPE, ignoreFB, num_buffers); + if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) { + LOGI("3D content on 2D display: set the output format as monoscopic"); + mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + bool noRot = !orientation; + switch(mState) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + return startChannel(info, FRAMEBUFFER_0, noRot, false, + mS3DFormat, VG0_PIPE, ignoreFB, num_buffers); + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; ioffset; const int fd = hnd->fd; - bool ret = true; - - if (mHDMIConnected) { - // Queue the buffer on VG1 pipe - ret = queueBuffer(fd, offset, VG1_PIPE); + switch (mState) { + case OV_UI_MIRROR_TV: + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!queueBuffer(fd, offset, VG0_PIPE)) { + LOGE("%s:failed for channel 0", __FUNCTION__); + return false; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; i> 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 + #define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" #define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present" +#define BARRIER_FILE "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier" /* -------------------------- end 3D defines ----------------------------------------*/ // Struct to hold the buffer info: geometry and size @@ -101,7 +106,8 @@ struct overlay_buffer_info { namespace overlay { enum { - OV_2D_VIDEO_ON_PANEL = 0, + 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, @@ -110,8 +116,12 @@ enum { }; bool isHDMIConnected(); bool is3DTV(); +bool isPanel3D(); +bool usePanel3D(); bool send3DInfoPacket(unsigned int format3D); -unsigned int getOverlayConfig (unsigned int format3D); +bool enableBarrier(unsigned int orientation); +unsigned int getOverlayConfig (unsigned int format3D, bool poll = true, + bool isHDMI = false); int get_mdp_format(int format); int get_size(int format, int w, int h); @@ -143,6 +153,7 @@ class OverlayControlChannel { bool mUIChannel; mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; + msmfb_overlay_3d m3DOVInfo; bool openDevices(int fbnum = -1); bool setOverlayInformation(const overlay_buffer_info& info, int flags, int orientation, int zorder = 0, bool ignoreFB = false, @@ -177,6 +188,7 @@ public: bool getPositionS3D(int channel, int format, overlay_rect *rect); bool updateOverlaySource(const overlay_buffer_info& info, int orientation); bool getFormat() const { return mFormat; } + bool useVirtualFB (); }; class OverlayDataChannel { @@ -231,6 +243,7 @@ class Overlay { int mCroppedSrcWidth; int mCroppedSrcHeight; overlay_buffer_info mOVBufferInfo; + int mState; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -263,10 +276,6 @@ public: bool updateOverlaySource(const overlay_buffer_info& info, int orientation); private: - bool startChannelHDMI(const overlay_buffer_info& info, bool norot); - bool startChannelS3D(const overlay_buffer_info& info, bool norot); - bool setPositionS3D(int x, int y, uint32_t w, uint32_t h); - bool setParameterS3D(int param, int value); 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); @@ -277,7 +286,7 @@ private: }; struct overlay_shared_data { - int readyToQueue; + volatile bool isControlSetup; unsigned int state; int rotid[2]; int ovid[2]; diff --git a/liboverlay/overlayState.cpp b/liboverlay/overlayState.cpp new file mode 100644 index 0000000..f4398d4 --- /dev/null +++ b/liboverlay/overlayState.cpp @@ -0,0 +1,1109 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2009 - 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. + */ + +int setParameterHandleState(overlay_control_context_t *ctx, + overlay_object *obj, + int param, int value) +{ + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setParameter(param, value, VG0_PIPE)) { + LOGE("%s: Failed for channel 0", __func__); + return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; isetParameter(param, value, i)) { + LOGE("%s: Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + LOGE("Unknown state in setParameter"); + abort(); + break; + } + return 0; +} + +int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot, + overlay_object* overlay, int fd) +{ + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot)) { + error_cleanup_control(ctx, overlay, fd, FRAMEBUFFER_0); + return -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; istartControlChannel(FRAMEBUFFER_0, noRot, i)) { + error_cleanup_control(ctx, overlay, fd, i); + return -1; + } + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, VG0_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG0_PIPE); + return -1; + } + if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG1_PIPE); + return -1; + } + break; + case OV_3D_VIDEO_3D_TV: + for (int i=0; istartControlChannel(FRAMEBUFFER_1, true, i)) { + error_cleanup_control(ctx, overlay, fd, i); + return -1; + } + } + break; + default: + break; + } + return 0; +} + +int setPositionHandleState(overlay_control_context_t *ctx, + overlay_object *obj, overlay_rect& rect, + int x, int y, uint32_t w, uint32_t h) +{ + int ret = 0; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); + return -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->useVirtualFB(i)) { + LOGE("can't use the virtual fb for line interleaving!"); + } + obj->getPositionS3D(&rect, i, true); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + } + break; + case OV_2D_VIDEO_ON_TV: + obj->getAspectRatioPosition(&rect, VG1_PIPE); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { + LOGE("%s:Failed for channel 1", __func__); + } + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); + return -1; + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->getPositionS3D(&rect, i)) + ret = obj->setPosition(x, y, w, h, i); + else + ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + break; + } + return ret; +} + +//////////////////////// configPipes /////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// + +bool TV2Dconn(overlay_control_context_t *ctx, + overlay_object *obj, bool noRot, + overlay_rect& rect) +{ + LOGI("2D TV connected, Open a new control channel for TV."); + //Start a new channel for mirroring on HDMI + if (!obj->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + obj->closeControlChannel(VG1_PIPE); + return false; + } + if (ctx->format3D) + obj->getPositionS3D(&rect, FRAMEBUFFER_1); + else + obj->getAspectRatioPosition(&rect, FRAMEBUFFER_1); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, FRAMEBUFFER_1)) { + LOGE("%s:Failed to set position for framebuffer 1", __func__); + return false; + } + return true; +} + +bool TV3Dconn(overlay_control_context_t *ctx, + overlay_object *obj, bool noRot, + overlay_rect& rect) +{ + LOGI("3D TV connected, close old ctl channel and open two ctl channels for 3DTV."); + //close the channel 0 as it is configured for panel + obj->closeControlChannel(VG0_PIPE); + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->startControlChannel(FRAMEBUFFER_1, true, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + obj->getPositionS3D(&rect, i); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s: failed for channel %d", __func__, i); + return false; + } + } + return true; +} + +bool TV3DSetup(overlay_control_context_t *ctx, overlay_object *obj, int i, + int fbnum, overlay_rect& rect) +{ + bool noRot = fbnum ? true : false; + if (!obj->startControlChannel(fbnum, noRot, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + bool ret=true; + if (!obj->getPositionS3D(&rect, i)) + ret = obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, + ctx->posPanel.w, ctx->posPanel.h, i); + else + ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i); + if(!ret) { + LOGE("%s: failed for channel %d", __func__, i); + return false; + } + return true; +} + +int configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + if(!TV2Dconn(ctx, obj, noRot, rect)) + return -1; + return 0; + } + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; +} + +int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + // same as OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV + return configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + if(!TV3Dconn(ctx, obj, noRot, rect)) + return -1; + return 0; + } + // HDMI disconnected + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(!enable){ // HDMI disconnect + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; + } + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_PIPE); + //disable the panel barriers + enableBarrier(0); + //now open both the channels + //update the output from stereoscopic to monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + int fbnum = 0; + bool ret = true; + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + fbnum = i; + if(!TV3DSetup(ctx, obj, i, fbnum, rect)) + return -1; + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(!enable){ // HDMI disconnect + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; + } + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_PIPE); + //disable the panel barrier + enableBarrier(0); + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + if(!TV3DSetup(ctx, obj, i, FRAMEBUFFER_1, rect)) + return -1; + } + return 0; +} + + +///// HDMI Disconnect //// +int configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + LOGI("2D TV disconnected, close the control channel."); + obj->closeControlChannel(VG1_PIPE); + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + // same as OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL + return configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + LOGI("3D TV disconnected, close the control channels & open one for panel."); + // Close both the pipes' control channel + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_PIPE); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + obj->setFormat3D(ctx->format3D); + LOGI("Control: New format3D: 0x%x", ctx->format3D); + //now open the channel 0 + if (!obj->startControlChannel(FRAMEBUFFER_0, noRot)) { + LOGE("%s:Failed to open control channel for pipe 0", __func__); + return false; + } + if(!obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, + ctx->posPanel.w, ctx->posPanel.h, FRAMEBUFFER_0)) { + LOGE("%s:Failed to set position for framebuffer 0", __func__); + return false; + } + if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, VG0_PIPE)) { + LOGE("%s: Failed to set orientation for channel 0", __func__); + return -1; + } + return 0; +} + +int TVto3DPanel(overlay_control_context_t *ctx, overlay_object *obj, + bool noRot, overlay_rect& rect) +{ + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->startControlChannel(FRAMEBUFFER_0, noRot, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + if (!obj->useVirtualFB(i)) { + LOGE("can't use the virtual fb for line interleaving!"); + } + obj->getPositionS3D(&rect, i); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, i)) { + LOGE("%s: Failed to set orientation for channel 0", __func__); + return -1; + } + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) { // HDMI connect + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + // disconnect TV + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + return TVto3DPanel(ctx, obj, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) { // HDMI connect + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + + // disconnect TV + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + return TVto3DPanel(ctx, obj, noRot, rect); +} + + +//// On Panel //// + +int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("ctl: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState); + abort(); + return -1; + break; + case OV_2D_VIDEO_ON_TV: + LOGI("TV connected: open a new VG control channel"); + if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + break; + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +/// OV on TV //// + +int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + if(-1 == configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_3D_VIDEO_2D_TV: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + + +//////////////////////////////////// Queue Buffer /////////////////////////////////// + +///////////////////////// Helper func /////////////////////////////// + +int queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + LOGI("2D TV connected, Open a new data channel for TV."); + //Start a new channel for mirroring on HDMI + ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel( + data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size, + FRAMEBUFFER_1, true)) { + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + return -1; + } + if(!ctx->pobjDataChannel[VG1_PIPE]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe 1", __func__); + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe 1", __func__); + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + LOGI("2D TV connected, Open a new data channel for TV."); + //Start a new channel for mirroring on HDMI + ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel( + data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size, + FRAMEBUFFER_1, true)) { + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + return -1; + } + overlay_rect rect; + ctx->pobjDataChannel[VG1_PIPE]->getCropS3D(&ctx->cropRect, VG1_PIPE, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[VG1_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe 1", __func__); + return -1; + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe 1", __func__); + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + //close the channel 0 as it is configured for panel + ctx->pobjDataChannel[VG0_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG0_PIPE]; + ctx->pobjDataChannel[VG0_PIPE] = NULL; + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + LOGI("Data: New S3D format : 0x%x", ctx->format3D); + //now open both the channels + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, + FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe %d", __func__, i); + return -1; + } + if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe %d", __func__, i); + return -1; + } + } + send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); + return 0; +} +int queueBuffer_3D_to_2D_TV_common(overlay_data_context_t *ctx, + overlay_shared_data* data, + overlay_rect& rect, + int i, int fbnum) +{ + bool noRot = fbnum ? true : false; + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, fbnum, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe %d", __func__, i); + return -1; + } + if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe %d", __func__, i); + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + //now open both the channels + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + int fbnum = i; + //update the output from stereoscopic to monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + LOGI("Data: New S3D format : 0x%x", ctx->format3D); + if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum)) + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + //now open both the channels + overlay_rect rect; + int fbnum = 1; + for (int i = 0; i < NUM_CHANNELS; i++) { + if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum)) + return -1; + } + send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); + return 0; +} + +void queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx) +{ + LOGI("2D TV disconnected, close the data channel for TV."); + ctx->pobjDataChannel[VG1_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; +} + +void queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx) +{ + // same as queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL + queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx); +} + +int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, bool noRot) +{ + LOGI("3D TV disconnected, close the data channels for 3DTV and open one for panel."); + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + send3DInfoPacket(0); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + //now open the channel 0 + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel( + data->ovid[VG0_PIPE], data->rotid[VG0_PIPE], ctx->size, + FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); + return -1; + } + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, + ctx->format3D, &rect); + //setting the crop value + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( rect.x, rect.y,rect.w, rect.h)) { + LOGE("%s:failed to crop pipe 0", __func__); + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG0_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed set fd for pipe 0", __func__); + return -1; + } + return 0; +} + +void queueBuffer_3D_Panel_common_pre(overlay_data_context_t *ctx) +{ + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + send3DInfoPacket(0); +} + + +int queueBuffer_3D_Panel_common_post(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, + ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe %d", __func__, i); + return -1; + } + if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe %d", __func__, i); + return -1; + } + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + queueBuffer_3D_Panel_common_pre(ctx); + + if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot)) + return -1; + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + queueBuffer_3D_Panel_common_pre(ctx); + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | + ctx->format3D >> SHIFT_3D; + if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot)) + return -1; + + return 0; +} + +////////////////// Queue buffer state machine handling ///////////////////// + +int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + // nothing to do here + break; + case OV_2D_VIDEO_ON_TV: + LOGI("TV connected, open a new data channel"); + if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("data: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_2D_PANEL: + // nothing to do here + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_3D_PANEL: + // nothing to do here + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data)) + return -1; + break; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_2D_VIDEO_ON_TV: + // nothing to see here + break; + case OV_2D_VIDEO_ON_PANEL: + queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx); + break; + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_2D_TV: + // nothing to see here + break; + case OV_3D_VIDEO_2D_PANEL: + queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx); + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_3D_TV: + // nothing to see here + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + + +///////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// + From 28bb235bc39be5d1cd9f0881f999cba7444f887d Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 1 Sep 2011 18:08:34 -0700 Subject: [PATCH 415/435] libgralloc-qsd8k: Use correct vaddr for clean/invalidate pmem regions CRs-fixed: 304740 Change-Id: Id72bb9ae874a56be89aec79d23e8d2e79856409d --- libgralloc-qsd8k/mapper.cpp | 4 ++-- libgralloc-qsd8k/pmemalloc.cpp | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index 883c10b..cdd9bbc 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -297,8 +297,8 @@ int gralloc_unlock(gralloc_module_t const* module, err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL); } - LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n", - hnd, hnd->offset, hnd->size); + 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; } diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index f7f9059..e9c5247 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -182,7 +182,10 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size); memset((char*)base + offset, 0, size); //Clean cache before flushing to ensure pmem is properly flushed - deps.cleanPmem(fd, (unsigned long) base, offset, size); + err = deps.cleanPmem(fd, (unsigned long) base + offset, offset, size); + if (err < 0) { + LOGE("cleanPmem failed: (%s)", strerror(deps.getErrno())); + } #ifdef HOST cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); #endif From 98fc1499dbbe417ed91e72951ded6bbf20f586d3 Mon Sep 17 00:00:00 2001 From: Harshad Bhutada Date: Tue, 23 Aug 2011 17:47:08 +0530 Subject: [PATCH 416/435] ligralloc-qsd8k: Add debug feature to display FPS Change-Id: I0fe7e31f6301d5abca3a81dcd4112ffa2ec937df --- libgralloc-qsd8k/Android.mk | 4 +- libgralloc-qsd8k/framebuffer.cpp | 142 ++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 3 deletions(-) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index be1b23c..28c6a0c 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -19,7 +19,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM +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 @@ -32,7 +32,7 @@ LOCAL_SRC_FILES := \ pmemalloc.cpp LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) -LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT))) LOCAL_CFLAGS += -DTARGET_MSM7x27 diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index b8454ad..60e1e55 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,36 @@ static inline size_t ALIGN(size_t x, size_t align) { char framebufferStateName[] = {'S', 'R', 'A'}; +#ifdef DEBUG_CALC_FPS + +#define MAX_FPS_CALC_PERIOD_IN_FRAMES 128 +#define MAX_FRAMARRIVAL_STEPS 50 +#define MAX_DEBUG_FPS_LEVEL 2 + +struct debug_fps_metadata_t { + /* indicates how many frames do we wait till we calculate FPS */ + unsigned int period; + /* current frame, will go upto period, and then reset */ + unsigned int curr_frame; + /* frame will arrive at a multiple of 16666 us at the display. + This indicates how many steps to consider for our calculations. + For example, if framearrival_steps = 10, then the frame that arrived + after 166660 us or more will be ignored. + */ + unsigned int framearrival_steps; + /* ignorethresh_us = framearrival_steps * 16666 */ + nsecs_t ignorethresh_us; + /* used to calculate the actual frame arrival step, the times might not be + accurate + */ + unsigned int margin_us; + /* actual data storage */ + nsecs_t framearrivals[MAX_FPS_CALC_PERIOD_IN_FRAMES]; + nsecs_t accum_framearrivals[MAX_FRAMARRIVAL_STEPS]; +}; + +#endif + /*****************************************************************************/ enum { @@ -98,6 +129,12 @@ struct fb_context_t { }; static int neworientation; + +#ifdef DEBUG_CALC_FPS +static debug_fps_metadata_t debug_fps_metadata; +static unsigned int debug_fps_level = 0; +#endif + /*****************************************************************************/ static void @@ -133,6 +170,92 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev, return 0; } +#ifdef DEBUG_CALC_FPS + +static void populate_debug_fps_metadata(void) +{ + char prop[PROPERTY_VALUE_MAX]; + + property_get("debug.gr.calcfps.period", prop, "10"); + debug_fps_metadata.period = atoi(prop); + + /* default ignorethresh_us: 500 milli seconds */ + property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000"); + debug_fps_metadata.ignorethresh_us = atoi(prop); + + debug_fps_metadata.framearrival_steps = + (debug_fps_metadata.ignorethresh_us / 16666); + + if (debug_fps_metadata.framearrival_steps > MAX_FRAMARRIVAL_STEPS) { + debug_fps_metadata.framearrival_steps = MAX_FRAMARRIVAL_STEPS; + debug_fps_metadata.ignorethresh_us = + debug_fps_metadata.framearrival_steps * 16666; + } + + /* 2ms margin of error for the gettimeofday */ + debug_fps_metadata.margin_us = 2000; + + for (int i = 0; i < MAX_FRAMARRIVAL_STEPS; i++) + debug_fps_metadata.accum_framearrivals[i] = 0; + + LOGE("period: %d", debug_fps_metadata.period); + LOGE("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us); +} + +static void calc_fps(nsecs_t currtime_us) +{ + static nsecs_t oldtime_us = 0; + + nsecs_t diff = currtime_us - oldtime_us; + + oldtime_us = currtime_us; + + if (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; + } + } + + 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; + + if (currstep < debug_fps_metadata.framearrival_steps) { + debug_fps_metadata.accum_framearrivals[currstep-1]++; + } + } +} + +#endif // DEBUG_CALC_FPS + static void *disp_loop(void *ptr) { struct qbuf_t nxtBuf; @@ -171,6 +294,10 @@ static void *disp_loop(void *ptr) LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed"); } +#ifdef DEBUG_CALC_FPS + if (debug_fps_level > 0) calc_fps(ns2us(systemTime())); +#endif + if (cur_buf == -1) { int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers); pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock)); @@ -674,7 +801,7 @@ int mapFrameBufferLocked(struct private_module_t* module) if (numberOfBuffers > NUM_FRAMEBUFFERS_MAX) numberOfBuffers = NUM_FRAMEBUFFERS_MAX; - LOGD("We support %d buffers", numberOfBuffers); + LOGE("We support %d buffers", numberOfBuffers); info.yres_virtual = info.yres * numberOfBuffers; @@ -769,6 +896,19 @@ int mapFrameBufferLocked(struct private_module_t* module) module->swapInterval = 1; #endif +#ifdef DEBUG_CALC_FPS + char prop[PROPERTY_VALUE_MAX]; + property_get("debug.gr.calcfps", prop, "0"); + debug_fps_level = atoi(prop); + if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) { + LOGW("out of range value for debug.gr.calcfps, using 0"); + debug_fps_level = 0; + } + + LOGE("DEBUG_CALC_FPS: %d", debug_fps_level); + populate_debug_fps_metadata(); +#endif + module->currentIdx = -1; pthread_cond_init(&(module->qpost), NULL); pthread_mutex_init(&(module->qlock), NULL); From 49008be4a3a4b34967505443ba5f0dcb62008880 Mon Sep 17 00:00:00 2001 From: Omprakash Dhyade Date: Sun, 18 Sep 2011 17:35:45 -0700 Subject: [PATCH 417/435] hardware/msm7k: libgralloc-qsd8k: Remove wait in fb_post and lockBuffer implementation Since fb_post and dequeueBuffer may be called from different threads, it might happen that both wait for available buffer causig both threads to go in sleep. To solve this problem we add lockBuffer implementation and remove waits from fb_post and dequeueBuffer. This will also be consistent with native window implementation. Change-Id: Id5e6e2feac5153156fabd9266b0c1cd5a5681514 --- libgralloc-qsd8k/framebuffer.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 60e1e55..29c1c8a 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -609,26 +609,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); @@ -679,7 +664,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( dev->common.module); @@ -1010,7 +995,7 @@ 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; From 34aead9cf1170e1cbc997373b83a49ec9f802871 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Wed, 10 Aug 2011 11:08:16 -0700 Subject: [PATCH 418/435] Composition Bypass: Bypass composition if we have 2 visible layers. Bypass composition if we have 2 visible layers. However, this feature is not used if: 1) Video playback is on 2) Rotation involved 3) App launch animation 4) HDMI connected Set property debug.compbypass.enable=1 in build.prop to enable this feature. Change-Id: I4c0fa2aa1999c06c51f2b9a58641203316896e53 --- libhwcomposer/Android.mk | 4 +- libhwcomposer/hwcomposer.cpp | 339 ++++++++++++++++++++++++++++++----- 2 files changed, 299 insertions(+), 44 deletions(-) diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 5f23f61..1ed1396 100755 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -19,5 +19,7 @@ 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 include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 49ca41c..401766f 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ enum HWCCompositionType { enum HWCPrivateFlags { HWC_USE_ORIGINAL_RESOLUTION = HWC_FLAGS_PRIVATE_0, // This layer is to be drawn using overlays HWC_DO_NOT_USE_OVERLAY = HWC_FLAGS_PRIVATE_1, // Do not use overlays to draw this layer + HWC_COMP_BYPASS = HWC_FLAGS_PRIVATE_3, // Layer "might" use or have used bypass }; enum HWCLayerType{ @@ -71,10 +73,32 @@ enum HWCLayerType{ HWC_STOP_UI_MIRRORING_MASK = 0xF }; +#ifdef COMPOSITION_BYPASS +enum BypassState { + BYPASS_ON, + BYPASS_OFF, + BYPASS_OFF_PENDING, +}; + +enum { + MAX_BYPASS_LAYERS = 2, + ANIM_FRAME_COUNT = 30, +}; +#endif + struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ overlay::Overlay* mOverlayLibObject; +#ifdef COMPOSITION_BYPASS + overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS]; + int animCount; + BypassState bypassState; +#endif +#if defined HDMI_DUAL_DISPLAY + bool mHDMIEnabled; + bool pendingHDMI; +#endif int previousLayerCount; }; @@ -92,6 +116,7 @@ struct private_hwc_module_t { copybit_device_t *copybitEngine; framebuffer_device_t *fbDevice; int compositionType; + bool isBypassEnabled; //from build.prop debug.compbypass.enable }; struct private_hwc_module_t HAL_MODULE_INFO_SYM = { @@ -110,6 +135,7 @@ struct private_hwc_module_t HAL_MODULE_INFO_SYM = { copybitEngine: NULL, fbDevice: NULL, compositionType: 0, + isBypassEnabled: false, }; /*****************************************************************************/ @@ -127,32 +153,6 @@ static void dump_layer(hwc_layer_t const* l) { l->displayFrame.bottom); } -static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { -#if defined HDMI_DUAL_DISPLAY - hwc_context_t* ctx = (hwc_context_t*)(dev); - private_hwc_module_t* hwcModule = reinterpret_cast( - dev->common.module); - framebuffer_device_t *fbDev = hwcModule->fbDevice; - if (fbDev) { - fbDev->enableHDMIOutput(fbDev, enable); - } - - if(ctx && ctx->mOverlayLibObject) { - overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - ovLibObject->setHDMIStatus(enable); - - if (!enable) { - // Close the overlay channels if HDMI is disconnected - ovLibObject->closeChannel(); - // Inform the gralloc that video mirroring is stopped - framebuffer_device_t *fbDev = hwcModule->fbDevice; - if (fbDev) - fbDev->videoOverlayStarted(fbDev, false); - } - } -#endif -} - static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { #if defined HDMI_DUAL_DISPLAY private_hwc_module_t* hwcModule = reinterpret_cast( @@ -242,6 +242,15 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { return -1; } + ovLibObject->getOrientation(orientation); + if (orientation != layer->transform) + ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); + if (!ret) { + LOGE("prepareOverlay setParameter failed transform %x", + layer->transform); + return -1; + } + if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { framebuffer_device_t* fbDev = hwcModule->fbDevice; ret = ovLibObject->setPosition(0, 0, @@ -256,15 +265,6 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { LOGE("prepareOverlay setPosition failed"); return -1; } - - ovLibObject->getOrientation(orientation); - if (orientation != layer->transform) - ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); - if (!ret) { - LOGE("prepareOverlay setParameter failed transform %x", - layer->transform); - return -1; - } } return 0; } @@ -358,6 +358,194 @@ static bool isFullScreenUpdate(const framebuffer_device_t* fbDev, const hwc_laye return false; } +#ifdef COMPOSITION_BYPASS +/* + * Configures pipe(s) for composition bypass + */ +static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer, int index, + int lastLayerIndex) { + if (ctx && ctx->mOvUI[index]) { + private_hwc_module_t* hwcModule = reinterpret_cast< + private_hwc_module_t*>(ctx->device.common.module); + if (!hwcModule) { + LOGE("prepareBypass null module "); + return -1; + } + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + LOGE("prepareBypass handle null"); + return -1; + } + if(hnd->width > hwcModule->fbDevice->width || + hnd->height > hwcModule->fbDevice->height) { + ctx->animCount = ANIM_FRAME_COUNT; + return -1; + } + overlay::OverlayUI *ovUI = ctx->mOvUI[index]; + int ret = 0; + int orientation = layer->transform; + overlay_buffer_info info; + info.width = hnd->width; + info.height = hnd->height; + info.format = hnd->format; + info.size = hnd->size; + const bool useVGPipe = true; + //only last layer should wait for vsync + const bool waitForVsync = (index == lastLayerIndex); + const int fbnum = 0; + //Just to differentiate zorders for different layers + const int zorder = index; + ret = ovUI->setSource(info, orientation, useVGPipe, waitForVsync, + fbnum, zorder); + if (ret) { + LOGE("prepareBypass setSource failed"); + return -1; + } + hwc_rect_t displayFrame = layer->displayFrame; + ret = ovUI->setPosition(displayFrame.left, displayFrame.top, + (displayFrame.right - displayFrame.left), + (displayFrame.bottom - displayFrame.top)); + if (ret) { + LOGE("prepareBypass setPosition failed"); + return -1; + } + } + return 0; +} + +static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer, + int index) { + if (ctx && ctx->mOvUI[index]) { + overlay::OverlayUI *ovUI = ctx->mOvUI[index]; + int ret = 0; + private_handle_t *hnd = (private_handle_t *)layer->handle; + ret = ovUI->queueBuffer(hnd); + if (ret) { + LOGE("drawLayerUsingBypass queueBuffer failed"); + return -1; + } + } + return 0; +} + +/* + * Checks if doing comp. bypass is possible. If video is not on and there + * are 2 layers then its doable. + */ +inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount, + const int numLayers) { + hwc_context_t* ctx = (hwc_context_t*)(dev); + private_hwc_module_t* hwcModule = reinterpret_cast( + dev->common.module); + //Check if enabled in build.prop + if(hwcModule->isBypassEnabled == false) { + return false; + } + //Disable bypass during animation + if(UNLIKELY(ctx->animCount)) { + --(ctx->animCount); + return false; + } +#if defined HDMI_DUAL_DISPLAY + //Disable bypass when HDMI is enabled + if(ctx->mHDMIEnabled || ctx->pendingHDMI) { + return false; + } +#endif + return (yuvCount == 0) && (numLayers == MAX_BYPASS_LAYERS); +} + +/* + * Bypass is not efficient if area is greater than 1280x720 + * AND rotation is necessary, since the rotator consumes + * time greater than 1 Vsync and is sequential. + */ +inline static bool isBypassEfficient(const framebuffer_device_t* fbDev, + const hwc_layer_list_t* list, hwc_context_t* ctx) { + bool rotationNeeded = false; + for(int i = 0; i < list->numHwLayers; ++i) { + if(list->hwLayers[i].transform) { + rotationNeeded = true; + break; + } + } + return !(rotationNeeded); +} + +bool setupBypass(hwc_context_t* ctx, hwc_layer_list_t* list) { + for (int index = 0 ; index < list->numHwLayers; index++) { + if(prepareBypass(ctx, &(list->hwLayers[index]), index, + list->numHwLayers - 1) != 0) { + return false; + } + } + return true; +} + +void setBypassLayerFlags(hwc_context_t* ctx, hwc_layer_list_t* list) { + for (int index = 0 ; index < list->numHwLayers; index++) { + list->hwLayers[index].flags = HWC_COMP_BYPASS; + list->hwLayers[index].compositionType = HWC_USE_OVERLAY; + #ifdef DEBUG + LOGE("%s: layer = %d", __FUNCTION__, index); + #endif + } +} + +void unsetBypassLayerFlags(hwc_layer_list_t* list) { + for (int index = 0 ; index < list->numHwLayers; index++) { + if(list->hwLayers[index].flags == HWC_COMP_BYPASS) { + list->hwLayers[index].flags = 0; + } + } +} + +void closeBypass(hwc_context_t* ctx) { + for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { + ctx->mOvUI[index]->closeChannel(); + #ifdef DEBUG + LOGE("%s", __FUNCTION__); + #endif + } +} +#endif //COMPOSITION_BYPASS + + +static void handleHDMIStateChange(hwc_composer_device_t *dev) { +#if defined HDMI_DUAL_DISPLAY + hwc_context_t* ctx = (hwc_context_t*)(dev); + private_hwc_module_t* hwcModule = reinterpret_cast( + dev->common.module); + framebuffer_device_t *fbDev = hwcModule->fbDevice; + if (fbDev) { + fbDev->enableHDMIOutput(fbDev, ctx->mHDMIEnabled); + } + + if(ctx && ctx->mOverlayLibObject) { + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + ovLibObject->setHDMIStatus(ctx->mHDMIEnabled); + if (!(ctx->mHDMIEnabled)) { + // Close the overlay channels if HDMI is disconnected + ovLibObject->closeChannel(); + } + } +#endif +} + + +/* Just mark flags and do stuff after eglSwapBuffers */ +static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { +#if defined HDMI_DUAL_DISPLAY + hwc_context_t* ctx = (hwc_context_t*)(dev); + ctx->mHDMIEnabled = enable; + if(enable) { //On connect, allow bypass to draw once to FB + ctx->pendingHDMI = true; + } else { //On disconnect, close immediately (there will be no bypass) + handleHDMIStateChange(dev); + } +#endif +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -423,20 +611,42 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; layerType |= HWC_ORIG_RESOLUTION; - } else if (hnd && (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) { + } else if (hnd && (hwcModule->compositionType & + (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) { list->hwLayers[i].compositionType = HWC_USE_COPYBIT; - } else if ((hwcModule->compositionType == COMPOSITION_TYPE_DYN) && fullscreen) { + } else if ((hwcModule->compositionType == COMPOSITION_TYPE_DYN) + && fullscreen) { list->hwLayers[i].compositionType = HWC_USE_COPYBIT; } else { list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; } } - if (canSkipComposition(ctx, yuvBufferCount, list->numHwLayers, numLayersNotUpdating)) { + if (canSkipComposition(ctx, yuvBufferCount, list->numHwLayers, + numLayersNotUpdating)) { list->flags |= HWC_SKIP_COMPOSITION; } else { list->flags &= ~HWC_SKIP_COMPOSITION; } + +#ifdef COMPOSITION_BYPASS + //Check if bypass is feasible + if(isBypassDoable(dev, yuvBufferCount, list->numHwLayers) && + isBypassEfficient(hwcModule->fbDevice, list, ctx)) { + //Setup bypass + if(setupBypass(ctx, list)) { + //Overwrite layer flags only if setup succeeds. + setBypassLayerFlags(ctx, list); + list->flags |= HWC_SKIP_COMPOSITION; + ctx->bypassState = BYPASS_ON; + } + } else { + unsetBypassLayerFlags(list); + if(ctx->bypassState == BYPASS_ON) { + ctx->bypassState = BYPASS_OFF_PENDING; + } + } +#endif } return 0; @@ -598,8 +808,11 @@ static int hwc_set(hwc_composer_device_t *dev, for (size_t i=0; inumHwLayers; i++) { if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; - } - if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { +#ifdef COMPOSITION_BYPASS + } else if (list->hwLayers[i].flags == HWC_COMP_BYPASS) { + drawLayerUsingBypass(ctx, &(list->hwLayers[i]), i); +#endif + } else if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) { drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); } else if (list->flags & HWC_SKIP_COMPOSITION) { break; @@ -615,6 +828,18 @@ static int hwc_set(hwc_composer_device_t *dev, return HWC_EGL_ERROR; } } +#ifdef COMPOSITION_BYPASS + if(ctx->bypassState == BYPASS_OFF_PENDING) { + closeBypass(ctx); + ctx->bypassState = BYPASS_OFF; + } +#endif +#if defined HDMI_DUAL_DISPLAY + if(ctx->pendingHDMI) { + handleHDMIStateChange(dev); + ctx->pendingHDMI = false; + } +#endif return 0; } @@ -647,6 +872,11 @@ static int hwc_device_close(struct hw_device_t *dev) if (ctx) { delete ctx->mOverlayLibObject; ctx->mOverlayLibObject = NULL; +#ifdef COMPOSITION_BYPASS + for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { + delete ctx->mOvUI[i]; + } +#endif free(ctx); } return 0; @@ -697,6 +927,13 @@ static int hwc_module_initialize(struct private_hwc_module_t* hwcModule) hwcModule->compositionType = COMPOSITION_TYPE_CPU; } + //Check if composition bypass is enabled + if(property_get("debug.compbypass.enable", property, NULL) > 0) { + if(atoi(property) == 1) { + hwcModule->isBypassEnabled = true; + } + } + return 0; } @@ -716,10 +953,26 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, /* initialize our state here */ memset(dev, 0, sizeof(*dev)); if(hwcModule->overlayEngine) { - dev->mOverlayLibObject = new overlay::Overlay(); - } else + dev->mOverlayLibObject = new overlay::Overlay(); +#ifdef COMPOSITION_BYPASS + for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { + dev->mOvUI[i] = new overlay::OverlayUI(); + } + dev->animCount = 0; + dev->bypassState = BYPASS_OFF; +#endif + } else { dev->mOverlayLibObject = NULL; - +#ifdef COMPOSITION_BYPASS + for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { + dev->mOvUI[i] = NULL; + } +#endif + } +#if defined HDMI_DUAL_DISPLAY + dev->mHDMIEnabled = false; + dev->pendingHDMI = false; +#endif /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; From 8da83f0059683464f8ca978aff31bbe0b64b856d Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 22 Sep 2011 15:58:27 -0700 Subject: [PATCH 419/435] liboverlay: Use even crop values The overlay hardware requires the values to be even. Calculate the ROI to ensure that the crop rectangle is correct after making the parameters even. CRs-fixed: 302916 Change-Id: I7316a65efe2b72c5392a3d2adbb95070662dced9 --- liboverlay/overlayLib.cpp | 23 +++++++++++++++++++++++ liboverlay/overlayLib.h | 1 + 2 files changed, 24 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 7a97063..186ea97 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -81,6 +81,26 @@ int overlay::get_mdp_orientation(int rotation, int flip) { return -1; } +// This function normalizes the crop values to be all even +void overlay::normalize_crop(uint32_t& xy, uint32_t& wh) { + + if (xy & 0x0001) { + // x or y is odd, increment it's value + xy += 1; + // Since we've incremented x(y), we need to decrement + // w(h) accordingly + if (wh & 0x0001) { + // w or h is odd, decrement it by 1, to make it even + EVEN_OUT(wh); + } else { + // w(h) is already even, hence we decrement by 2 + wh -=2; + } + } else { + EVEN_OUT(wh); + } +} + #define LOG_TAG "OverlayLIB" static void reportError(const char* message) { LOGE( "%s", message); @@ -1673,6 +1693,9 @@ bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) (ov.src_rect.h == h)) return true; + normalize_crop(x, w); + normalize_crop(y, h); + ov.src_rect.x = x; ov.src_rect.y = y; ov.src_rect.w = w; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index aeee828..87a697c 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -126,6 +126,7 @@ unsigned int getOverlayConfig (unsigned int format3D, bool poll = true, int get_mdp_format(int format); int get_size(int format, int w, int h); int get_mdp_orientation(int rotation, int flip); +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 */ From f105d784dae787ee54fe50952b1c9d63a6f3987e Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 26 Sep 2011 12:59:51 -0700 Subject: [PATCH 420/435] Set correct parameters in the gralloc handle Set the aligned width and height in the gralloc handle. Change-Id: I9cb2d9b681bb022bec2fa7cbe495974865f92a54 CRs-fixed: 306991 --- libgralloc-qsd8k/gpu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index dd410b2..af36fee 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -404,7 +404,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(size, usage, pHandle); } else { - err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, w, h); + err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, alignedw, alignedh); } if (err < 0) { From 8afdc162ea8f5ef8a241a6bd988345b90633d6fa Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Fri, 16 Sep 2011 14:30:10 -0700 Subject: [PATCH 421/435] Upgrades to the updateOverlay functionality. Update the overlay when we have a channel up. Previously, we did updates only when the width and height changed. Now, we always update the overlay when the channel is open, and not close the channel to update parameters such as orientation change, flags etc. Change-Id: I0b2ef8b19bd860d5361c391e040ff497f1023ae3 --- libhwcomposer/hwcomposer.cpp | 46 ++---- liboverlay/overlayLib.cpp | 293 ++++++++++++++++++----------------- liboverlay/overlayLib.h | 19 ++- liboverlay/overlayLibUI.cpp | 5 +- 4 files changed, 169 insertions(+), 194 deletions(-) mode change 100644 => 100755 liboverlay/overlayLib.cpp mode change 100644 => 100755 liboverlay/overlayLib.h diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 401766f..e371ab8 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -198,39 +198,24 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { private_handle_t *hnd = (private_handle_t *)layer->handle; overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - int orientation = 0; overlay_buffer_info info; info.width = hnd->width; info.height = hnd->height; info.format = hnd->format; info.size = hnd->size; - if (OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) - ovLibObject->getOrientation(orientation); - - if ((OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus()) - || (layer->transform != orientation) || - (hnd->flags & private_handle_t::PRIV_FLAGS_FORMAT_CHANGED)) { - // Overlay channel is not started, or we have an orientation change - // or there is a format change, call setSource to open the overlay - // if necessary - ret = ovLibObject->setSource(info, layer->transform, + ret = ovLibObject->setSource(info, layer->transform, (ovLibObject->getHDMIStatus()?true:false), false); - if (!ret) { - LOGE("prepareOverlay setSource failed"); - return -1; - } - // Reset this flag so that we don't keep opening and closing channels - // unnecessarily - hnd->flags &= ~private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; - } else { - // The overlay goemetry may have changed, we only need to update the - // overlay - ret = ovLibObject->updateOverlaySource(info, layer->transform); - if (!ret) { - LOGE("prepareOverlay updateOverlaySource failed"); - return -1; - } + if (!ret) { + LOGE("prepareOverlay setSource failed"); + return -1; + } + + ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); + if (!ret) { + LOGE("prepareOverlay setParameter failed transform %x", + layer->transform); + return -1; } hwc_rect_t sourceCrop = layer->sourceCrop; @@ -242,15 +227,6 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { return -1; } - ovLibObject->getOrientation(orientation); - if (orientation != layer->transform) - ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform); - if (!ret) { - LOGE("prepareOverlay setParameter failed transform %x", - layer->transform); - return -1; - } - if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) { framebuffer_device_t* fbDev = hwcModule->fbDevice; ret = ovLibObject->setPosition(0, 0, diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp old mode 100644 new mode 100755 index 186ea97..7d098f0 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -45,38 +45,42 @@ int overlay::get_mdp_format(int format) { return MDP_Y_CRCB_H2V2_TILE; case HAL_PIXEL_FORMAT_YV12: return MDP_Y_CR_CB_H2V2; + default: + LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format); + return -1; } return -1; } -int overlay::get_mdp_orientation(int rotation, int flip) { - switch(flip) { - case HAL_TRANSFORM_FLIP_V: - switch(rotation) { - case 0: return MDP_FLIP_UD; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_LR); - default: return -1; - break; - } - break; - case HAL_TRANSFORM_FLIP_H: - switch(rotation) { - case 0: return MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_90: return (MDP_ROT_90 | MDP_FLIP_UD); - default: return -1; - break; - } - break; - default: - switch(rotation) { - case 0: return MDP_ROT_NOP; +int overlay::get_mdp_orientation(int value) { + switch(value) { + case 0: return 0; + case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD; + case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR; case HAL_TRANSFORM_ROT_90: return MDP_ROT_90; + case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V: + return MDP_ROT_90|MDP_FLIP_LR; + case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H: + return MDP_ROT_90|MDP_FLIP_UD; case HAL_TRANSFORM_ROT_180: return MDP_ROT_180; case HAL_TRANSFORM_ROT_270: return MDP_ROT_270; - default: return -1; - break; - } - break; + default: + LOGE("%s: invalid rotation value (value = 0x%x", + __FUNCTION__, value); + return -1; + } + return -1; +} + +// Rotator - input to output mapping +int overlay::get_rot_output_format(int format) { + switch (format) { + case MDP_Y_CRCB_H2V2_TILE: + return MDP_Y_CRCB_H2V2; + case MDP_Y_CB_CR_H2V2: + return MDP_Y_CBCR_H2V2; + default: + return format; } return -1; } @@ -233,6 +237,12 @@ bool overlay::enableBarrier (unsigned int orientation) { return false; } +int overlay::getColorFormat(int format) +{ + return (format == HAL_PIXEL_FORMAT_YV12) ? + format : COLOR_FORMAT(format); +} + unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll, bool isHDMI) { bool isTV3D = false; @@ -393,20 +403,44 @@ bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int chann return objOvCtrlChannel[channel].setPosition(x, y, w, h); } -bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation) { - if (hasHDMIStatusChanged()) { - return setSource(info, orientation, mHDMIConnected); +bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation, + bool waitForVsync) { + bool ret = false; + int currentFlags = 0; + if (objOvCtrlChannel[0].isChannelUP()) { + currentFlags = objOvCtrlChannel[0].getOverlayFlags(); } - bool ret = false; + bool needUpdateFlags = false; + if (waitForVsync) { + if (currentFlags & MDP_OV_PLAY_NOWAIT) { + needUpdateFlags = true; + } + } else { + if (!(currentFlags & MDP_OV_PLAY_NOWAIT)) { + needUpdateFlags = true; + } + } + + bool geometryChanged = true; if (info.width == mOVBufferInfo.width && - info.height == mOVBufferInfo.height) { + info.height == mOVBufferInfo.height && + info.format == mOVBufferInfo.format) { + geometryChanged = false; + } + + if ((false == needUpdateFlags) && (false == geometryChanged)) { objOvDataChannel[0].updateDataChannel(0, 0); return true; } // Disable rotation for the HDMI channels - int orient[2] = {orientation, 0}; + int orientHdmi = 0; + int orient[2] = {true, orientHdmi}; + // enable waitForVsync on HDMI + bool waitForHDMI = true; + bool wait[2] = {waitForVsync, waitForHDMI}; + switch(mState) { case OV_3D_VIDEO_3D_PANEL: orient[1] = orientation; @@ -418,10 +452,19 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati break; } + int numChannelsToUpdate = NUM_CHANNELS; + if (!geometryChanged) { + // Only update the primary channel - we only need to update the + // wait/no-wait flags + if (objOvCtrlChannel[0].isChannelUP()) { + return objOvCtrlChannel[0].updateWaitForVsyncFlags(waitForVsync); + } + } + // Set the overlay source info for (int i = 0; i < NUM_CHANNELS; i++) { if (objOvCtrlChannel[i].isChannelUP()) { - ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i]); + ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], wait[i]); if (!ret) { LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i); return false; @@ -438,22 +481,6 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati return ret; } -int Overlay::hasHDMIStatusChanged() { - int hdmiChanged = 0; - if (mHDMIConnected) { - // If HDMI is connected and both channels are not up, set the status - if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) { - hdmiChanged = 0x1; - } - } else { - // HDMI is disconnected and both channels are up, set the status - if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) { - hdmiChanged = 0x1; - } - } - return hdmiChanged; -} - int Overlay::getS3DFormat(int format) { // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add // an explicit check for the format @@ -474,22 +501,20 @@ int Overlay::getS3DFormat(int format) { } bool Overlay::setSource(const overlay_buffer_info& info, int orientation, - bool hdmiConnected, bool ignoreFB, int num_buffers) { + bool hdmiConnected, bool waitForVsync, int num_buffers) { // Separate the color format from the 3D format. // If there is 3D content; the effective format passed by the client is: // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat int newState = mState; - bool stateChange = false, ret = true; + bool stateChange = false, ret = false; unsigned int format3D = getS3DFormat(info.format); int colorFormat = getColorFormat(info.format); - newState = getOverlayConfig (format3D, false, hdmiConnected); - stateChange = (mState == newState) ? false : true; - // Check if the orientation of the primary channel changed - if (mState != OV_3D_VIDEO_3D_TV) - if (mChannelUP) - ret = objOvCtrlChannel[0].setSource(info.width, info.height, - colorFormat, orientation, ignoreFB); - if (stateChange || !ret) { + if (-1 == mState) { + newState = getOverlayConfig (format3D, false, hdmiConnected); + stateChange = (mState == newState) ? false : true; + } + + if (stateChange) { closeChannel(); mHDMIConnected = hdmiConnected; mState = newState; @@ -498,17 +523,18 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, LOGI("3D content on 2D display: set the output format as monoscopic"); mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; } - bool noRot = !orientation; + // We always enable the rotator for the primary. + bool noRot = false; switch(mState) { case OV_2D_VIDEO_ON_PANEL: case OV_3D_VIDEO_2D_PANEL: return startChannel(info, FRAMEBUFFER_0, noRot, false, - mS3DFormat, VG0_PIPE, ignoreFB, num_buffers); + mS3DFormat, VG0_PIPE, waitForVsync, num_buffers); break; case OV_3D_VIDEO_3D_PANEL: for (int i=0; i mFBWidth) mOVInfo.dst_rect.w = mFBWidth; if (h > mFBHeight) @@ -900,9 +935,12 @@ bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& inf mOVInfo.alpha = 0xff; mOVInfo.transp_mask = 0xffffffff; mOVInfo.flags = flags; - if (!ignoreFB) - mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; } + if (!ignoreFB) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + else + mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; + return true; } @@ -930,9 +968,8 @@ bool OverlayControlChannel::startOVRotatorSessions( mRotInfo.dst.width = (((w-1)/64 +1)*64); mRotInfo.dst.height = (((h-1)/32 +1)*32); mRotInfo.dst.format = MDP_Y_CRCB_H2V2; - } else { - mRotInfo.dst.format = format; } + mRotInfo.dst.format = get_rot_output_format(format); mRotInfo.dst_x = 0; mRotInfo.dst_y = 0; mRotInfo.src_rect.x = 0; @@ -963,19 +1000,22 @@ bool OverlayControlChannel::startOVRotatorSessions( if (!ret) closeControlChannel(); - + else + mIsChannelUpdated = true; return ret; } bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info, - int orientation) + int orientation, bool waitForVsync) { - int hw_format = get_mdp_format(COLOR_FORMAT(info.format)); + int colorFormat = getColorFormat(info.format); + int hw_format = get_mdp_format(colorFormat); overlay_buffer_info ovBufInfo; ovBufInfo.width = info.width; ovBufInfo.height = info.height; ovBufInfo.format = hw_format; - if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, 0, UPDATE_REQUEST)) + + if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, waitForVsync, UPDATE_REQUEST)) return false; return startOVRotatorSessions(ovBufInfo, orientation, UPDATE_REQUEST); @@ -1053,59 +1093,18 @@ bool OverlayControlChannel::closeControlChannel() { return true; } -bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, - int cFormat, int orientation, bool ignoreFB) { - int format = cFormat & INTERLACE_MASK ? - (cFormat ^ HAL_PIXEL_FORMAT_INTERLACE) : cFormat; - format = get_mdp_format(format); - if (orientation == mOrientation && orientation != 0){ - //set format to non-tiled and align w, h to 64-bit and 32-bit respectively. - if (format == MDP_Y_CRCB_H2V2_TILE) { - format = MDP_Y_CRCB_H2V2; - w = (((w-1)/64 +1)*64); - h = (((h-1)/32 +1)*32); - } - switch(orientation){ - case (HAL_TRANSFORM_ROT_90 | HAL_TRANSFORM_FLIP_H): - case (HAL_TRANSFORM_ROT_90 | HAL_TRANSFORM_FLIP_V): - case HAL_TRANSFORM_ROT_90: - case HAL_TRANSFORM_ROT_270: - { - int tmp = w; - w = h; - h = tmp; - } - default: - break; - } +bool OverlayControlChannel::updateWaitForVsyncFlags(bool waitForVsync) { + if (!waitForVsync) + mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; + else + mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; + + if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { + LOGE("%s: OVERLAY_SET failed", __FUNCTION__); + dump(mOVInfo); + return false; } - - if (w == mOVInfo.src.width && h == mOVInfo.src.height - && format == mOVInfo.src.format && orientation == mOrientation) { - mdp_overlay ov; - ov.id = mOVInfo.id; - if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) - return false; - mOVInfo = ov; - int flags = mOVInfo.flags; - - if (!ignoreFB) - mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; - else - mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT; - - if (flags != mOVInfo.flags) { - if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) { - LOGE("setSource, OVERLAY_SET failed"); - dump(mOVInfo); - return false; - } - } - - return true; - } - mOrientation = orientation; - return false; + return true; } bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { @@ -1177,8 +1176,10 @@ bool OverlayControlChannel::useVirtualFB() { } bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { - if (!isChannelUP()) + if (!isChannelUP()) { + LOGE("%s: channel is not up", __FUNCTION__); return false; + } mdp_overlay ov = mOVInfo; if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { @@ -1186,6 +1187,13 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { return false; } mOVInfo = ov; + if (!mIsChannelUpdated && (OVERLAY_TRANSFORM == param)) { + int orientation = get_mdp_orientation(value); + if (orientation == mOVInfo.user_data[0]) { + return true; + } + } + mIsChannelUpdated = false; switch (param) { case OVERLAY_DITHER: @@ -1197,7 +1205,6 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { return true; int rot = value; - int flip = 0; switch(rot) { case 0: @@ -1218,8 +1225,6 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); } - rot = 0; - flip = value & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; } case HAL_TRANSFORM_ROT_90: @@ -1239,8 +1244,6 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { mOVInfo.src_rect.y = tmp; swapOVRotWidthHeight(); } - rot = HAL_TRANSFORM_ROT_90; - flip = value & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; } case HAL_TRANSFORM_ROT_180: @@ -1280,7 +1283,7 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { } default: return false; } - int mdp_rotation = get_mdp_orientation(rot, flip); + int mdp_rotation = get_mdp_orientation(rot); if (mdp_rotation == -1) return false; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h old mode 100644 new mode 100755 index 87a697c..e711a2a --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -122,10 +122,11 @@ 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_mdp_orientation(int rotation, int flip); +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 @@ -155,6 +156,7 @@ class OverlayControlChannel { 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, @@ -183,13 +185,13 @@ public: int getFBHeight() const { return mFBHeight; } int getFormat3D() const { return mFormat3D; } bool getOrientation(int& orientation) const; - bool setSource(uint32_t w, uint32_t h, int format, - int orientation, bool ignoreFB); + 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 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 { @@ -272,17 +274,14 @@ public: 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; } + void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; } int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); } - bool updateOverlaySource(const overlay_buffer_info& info, int orientation); 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); - int hasHDMIStatusChanged(); - int getColorFormat(int format) { return (format == HAL_PIXEL_FORMAT_YV12) ? - format : COLOR_FORMAT(format); } + bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync); int getS3DFormat(int format); }; diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp index 5e184fc..ccd97c0 100644 --- a/liboverlay/overlayLibUI.cpp +++ b/liboverlay/overlayLibUI.cpp @@ -89,13 +89,11 @@ void setupOvRotInfo(int w, int h, int format, int orientation, rotInfo.dst.height = srch; int rot = orientation; - int flip = 0; switch(rot) { case 0: case HAL_TRANSFORM_FLIP_H: case HAL_TRANSFORM_FLIP_V: rot = 0; - flip = orientation & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; case HAL_TRANSFORM_ROT_90: case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H): @@ -106,7 +104,6 @@ void setupOvRotInfo(int w, int h, int format, int orientation, ovInfo.src_rect.y = tmp; swapOVRotWidthHeight(rotInfo, ovInfo); rot = HAL_TRANSFORM_ROT_90; - flip = orientation & (HAL_TRANSFORM_FLIP_H|HAL_TRANSFORM_FLIP_V); break; } case HAL_TRANSFORM_ROT_180: @@ -123,7 +120,7 @@ void setupOvRotInfo(int w, int h, int format, int orientation, break; } - int mdp_rotation = overlay::get_mdp_orientation(rot, flip); + int mdp_rotation = overlay::get_mdp_orientation(rot); if (mdp_rotation < 0) mdp_rotation = 0; ovInfo.user_data[0] = mdp_rotation; From 376ed9acd904d5b34863407ccf88416334cd225e Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Mon, 19 Sep 2011 16:40:19 -0700 Subject: [PATCH 422/435] Enable overlay NOWAIT when there is UI update. When composing UI along with video, enable the overlay NOWAIT option. If there is no UI during overlay playback, use the WAIT flag. Change-Id: Idc538e4412c790fc295a3aff1d1f23a6e4767fce --- libhwcomposer/hwcomposer.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index e371ab8..9199c99 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -186,7 +186,7 @@ static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { /* * Configures mdp pipes */ -static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { +static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const bool waitForVsync) { int ret = 0; if (LIKELY(ctx && ctx->mOverlayLibObject)) { private_hwc_module_t* hwcModule = @@ -205,7 +205,7 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) { info.size = hnd->size; ret = ovLibObject->setSource(info, layer->transform, - (ovLibObject->getHDMIStatus()?true:false), false); + (ovLibObject->getHDMIStatus()?true:false), waitForVsync); if (!ret) { LOGE("prepareOverlay setSource failed"); return -1; @@ -559,6 +559,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } + bool skipComposition = canSkipComposition(ctx, yuvBufferCount, + list->numHwLayers, numLayersNotUpdating); if (list->flags & HWC_GEOMETRY_CHANGED) { layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; // Inform the gralloc of the current HDMI status @@ -570,18 +572,19 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { - if(prepareOverlay(ctx, &(list->hwLayers[i])) == 0) { + bool waitForVsync = skipComposition ? true:false; + if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) { //Fail safe path: If drawing with overlay fails, //Use C2D if available. list->hwLayers[i].compositionType = HWC_USE_COPYBIT; - yuvBufferCount = 0; + skipComposition = false; } else { //If C2D is not enabled fall back to GPU. list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; - yuvBufferCount = 0; + skipComposition = false; } } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; @@ -598,8 +601,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { } } - if (canSkipComposition(ctx, yuvBufferCount, list->numHwLayers, - numLayersNotUpdating)) { + if (skipComposition) { list->flags |= HWC_SKIP_COMPOSITION; } else { list->flags &= ~HWC_SKIP_COMPOSITION; @@ -768,7 +770,6 @@ static int hwc_set(hwc_composer_device_t *dev, hwc_surface_t sur, hwc_layer_list_t* list) { - hwc_context_t* ctx = (hwc_context_t*)(dev); if(!ctx || !list) { LOGE("hwc_set invalid context or list"); @@ -781,6 +782,7 @@ static int hwc_set(hwc_composer_device_t *dev, LOGE("hwc_set null module "); return -1; } + for (size_t i=0; inumHwLayers; i++) { if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; From 38fa4f72ffdffa5f7522209f6d5e3f7c37b723ec Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Thu, 22 Sep 2011 14:14:22 -0700 Subject: [PATCH 423/435] libhwcomposer: Close overlay channels in HWC set Close overlay channels in the next HWC set phase. This allows the framebuffer to be composed prior to the closing of channels. CRs-fixed: 305070 Change-Id: I8719381136c20c0febbd4f7bf5b935b92f6508ec --- libhwcomposer/hwcomposer.cpp | 177 +++++++++++++++++++++++++++-------- 1 file changed, 140 insertions(+), 37 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 9199c99..844f690 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -55,9 +55,9 @@ enum { }; enum HWCCompositionType { - HWC_USE_GPU, // This layer is to be handled by Surfaceflinger - HWC_USE_OVERLAY, // This layer is to be handled by the overlay - HWC_USE_COPYBIT // This layer is to be handled by copybit + HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by Surfaceflinger + HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay + HWC_USE_COPYBIT // This layer is to be handled by copybit }; enum HWCPrivateFlags { @@ -86,6 +86,12 @@ enum { }; #endif +enum eHWCOverlayStatus { + HWC_OVERLAY_OPEN, + HWC_OVERLAY_PREPARE_TO_CLOSE, + HWC_OVERLAY_CLOSED +}; + struct hwc_context_t { hwc_composer_device_t device; /* our private state goes below here */ @@ -100,6 +106,7 @@ struct hwc_context_t { bool pendingHDMI; #endif int previousLayerCount; + eHWCOverlayStatus hwcOverlayStatus; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -153,33 +160,64 @@ static void dump_layer(hwc_layer_t const* l) { l->displayFrame.bottom); } -static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) { +static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) { #if defined HDMI_DUAL_DISPLAY private_hwc_module_t* hwcModule = reinterpret_cast( ctx->device.common.module); - overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; - if(!hwcModule || !ovLibObject) { - LOGE("hwc_set_hdmi_status invalid params"); + if(!hwcModule) { + LOGE("%s: invalid params", __FUNCTION__); return -1; } framebuffer_device_t *fbDev = hwcModule->fbDevice; if (!fbDev) { - LOGE("hwc_set_hdmi_status fbDev is NULL"); + LOGE("%s: fbDev is NULL", __FUNCTION__); return -1; } - if (layerType & HWC_STOP_UI_MIRRORING_MASK) { - // Inform the gralloc to stop UI mirroring - fbDev->videoOverlayStarted(fbDev, true); - } else { + // Inform the gralloc to stop or start UI mirroring + fbDev->videoOverlayStarted(fbDev, enable); +#endif + return 0; +} + +static void setHWCOverlayStatus(hwc_context_t *ctx, bool isVideoPresent) { + + switch (ctx->hwcOverlayStatus) { + case HWC_OVERLAY_OPEN: + ctx->hwcOverlayStatus = + isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_PREPARE_TO_CLOSE; + break; + case HWC_OVERLAY_PREPARE_TO_CLOSE: + ctx->hwcOverlayStatus = + isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED; + break; + case HWC_OVERLAY_CLOSED: + ctx->hwcOverlayStatus = + isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED; + break; + default: + LOGE("%s: Invalid hwcOverlayStatus (status =%d)", __FUNCTION__, + ctx->hwcOverlayStatus); + break; + } +} + +static int hwc_closeOverlayChannels(hwc_context_t* ctx) { + overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; + if(!ovLibObject) { + LOGE("%s: invalid params", __FUNCTION__); + return -1; + } + + if (HWC_OVERLAY_PREPARE_TO_CLOSE == ctx->hwcOverlayStatus) { // Video mirroring is going on, and we do not have any layers to // mirror directly. Close the current video channel and inform the // gralloc to start UI mirroring ovLibObject->closeChannel(); - fbDev->videoOverlayStarted(fbDev, false); + // Inform the gralloc that video overlay has stopped. + setVideoOverlayStatusInGralloc(ctx, false); } -#endif return 0; } @@ -522,6 +560,62 @@ static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) { #endif } +static bool isValidDestination(const framebuffer_device_t* fbDev, const hwc_rect_t& rect) +{ + if (!fbDev) { + LOGE("%s: fbDev is null", __FUNCTION__); + return false; + } + + int dest_width = (rect.right - rect.left); + int dest_height = (rect.bottom - rect.top); + + if (rect.left < 0 || rect.right < 0 || rect.top < 0 || rect.bottom < 0 + || dest_width <= 0 || dest_height <= 0) { + LOGE("%s: destination: left=%d right=%d top=%d bottom=%d width=%d" + "height=%d", __FUNCTION__, rect.left, rect.right, rect.top, + rect.bottom, dest_width, dest_height); + return false; + } + + if ((rect.left+dest_width) > fbDev->width || (rect.top+dest_height) > fbDev->height) { + LOGE("%s: destination out of bound params", __FUNCTION__); + return false; + } + + return true; +} + +static int getYUVBufferCount (const hwc_layer_list_t* list) { + int yuvBufferCount = 0; + if (list) { + for (size_t i=0 ; inumHwLayers; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && + !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) { + yuvBufferCount++; + if (yuvBufferCount > 1) { + break; + } + } + } + } + return yuvBufferCount; +} + +static int getLayersNotUpdatingCount(const hwc_layer_list_t* list) { + int numLayersNotUpdating = 0; + if (list) { + for (size_t i=0 ; inumHwLayers; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + if (hnd && (hnd->bufferType != BUFFER_TYPE_VIDEO) && + list->hwLayers[i].flags & HWC_LAYER_NOT_UPDATING) + numLayersNotUpdating++; + } + } + return numLayersNotUpdating; +} + static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -545,39 +639,42 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { if (list) { fullscreen = isFullScreenUpdate(hwcModule->fbDevice, list); + yuvBufferCount = getYUVBufferCount(list); - for (size_t i=0 ; inumHwLayers; i++) { - private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; - if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && - !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) { - yuvBufferCount++; - if (yuvBufferCount > 1) { - break; - } - } else if (list->hwLayers[i].flags & HWC_LAYER_NOT_UPDATING) { - numLayersNotUpdating++; - } + bool skipComposition = false; + if (yuvBufferCount == 1) { + numLayersNotUpdating = getLayersNotUpdatingCount(list); + skipComposition = canSkipComposition(ctx, yuvBufferCount, + list->numHwLayers, numLayersNotUpdating); } - bool skipComposition = canSkipComposition(ctx, yuvBufferCount, - list->numHwLayers, numLayersNotUpdating); if (list->flags & HWC_GEOMETRY_CHANGED) { - layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0; - // Inform the gralloc of the current HDMI status - hwc_updateOverlayStatus(ctx, layerType); + if (yuvBufferCount == 1) { + // Inform the gralloc of the current video overlay status + setVideoOverlayStatusInGralloc(ctx, true); + } } for (size_t i=0 ; inumHwLayers ; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn + if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { + continue; + } if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { bool waitForVsync = skipComposition ? true:false; - if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) { + if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) { + list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + skipComposition = false; + } else if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; + // We've opened the channel. Set the state to open. + ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN; } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) { //Fail safe path: If drawing with overlay fails, + //Use C2D if available. list->hwLayers[i].compositionType = HWC_USE_COPYBIT; skipComposition = false; @@ -783,6 +880,7 @@ static int hwc_set(hwc_composer_device_t *dev, return -1; } + int ret = 0; for (size_t i=0; inumHwLayers; i++) { if (list->hwLayers[i].flags == HWC_SKIP_LAYER) { continue; @@ -803,7 +901,7 @@ static int hwc_set(hwc_composer_device_t *dev, if (!(list->flags & HWC_SKIP_COMPOSITION)) { EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); if (!sucess) { - return HWC_EGL_ERROR; + ret = HWC_EGL_ERROR; } } #ifdef COMPOSITION_BYPASS @@ -818,7 +916,11 @@ static int hwc_set(hwc_composer_device_t *dev, ctx->pendingHDMI = false; } #endif - return 0; + + hwc_closeOverlayChannels(ctx); + int yuvBufferCount = getYUVBufferCount(list); + setHWCOverlayStatus(ctx, yuvBufferCount); + return ret; } static int hwc_device_close(struct hw_device_t *dev) @@ -930,11 +1032,11 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, /* initialize our state here */ memset(dev, 0, sizeof(*dev)); - if(hwcModule->overlayEngine) { - dev->mOverlayLibObject = new overlay::Overlay(); + if(hwcModule->overlayEngine) { + dev->mOverlayLibObject = new overlay::Overlay(); #ifdef COMPOSITION_BYPASS for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { - dev->mOvUI[i] = new overlay::OverlayUI(); + dev->mOvUI[i] = new overlay::OverlayUI(); } dev->animCount = 0; dev->bypassState = BYPASS_OFF; @@ -943,7 +1045,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->mOverlayLibObject = NULL; #ifdef COMPOSITION_BYPASS for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { - dev->mOvUI[i] = NULL; + dev->mOvUI[i] = NULL; } #endif } @@ -951,6 +1053,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, dev->mHDMIEnabled = false; dev->pendingHDMI = false; #endif + dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED; /* initialize the procs */ dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 0; From f3353ad3283e8bfd3ffc176b1cb5456bb5691e2e Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Thu, 13 Oct 2011 14:32:49 -0700 Subject: [PATCH 424/435] Bypass: Fix source dimensions Since the RGB buffer could be 32 aligned, use actual source dimensions. Change-Id: Ice615e34a304c864cbe8fef044e14e9f835f9359 --- libhwcomposer/hwcomposer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index 844f690..1b55fdb 100755 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -390,8 +390,9 @@ static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer, int index, LOGE("prepareBypass handle null"); return -1; } - if(hnd->width > hwcModule->fbDevice->width || - hnd->height > hwcModule->fbDevice->height) { + hwc_rect_t sourceCrop = layer->sourceCrop; + if((sourceCrop.right - sourceCrop.left) > hwcModule->fbDevice->width || + (sourceCrop.bottom - sourceCrop.top) > hwcModule->fbDevice->height) { ctx->animCount = ANIM_FRAME_COUNT; return -1; } @@ -399,8 +400,8 @@ static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer, int index, int ret = 0; int orientation = layer->transform; overlay_buffer_info info; - info.width = hnd->width; - info.height = hnd->height; + info.width = sourceCrop.right - sourceCrop.left; + info.height = sourceCrop.bottom - sourceCrop.top; info.format = hnd->format; info.size = hnd->size; const bool useVGPipe = true; @@ -415,6 +416,7 @@ static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer, int index, LOGE("prepareBypass setSource failed"); return -1; } + hwc_rect_t displayFrame = layer->displayFrame; ret = ovUI->setPosition(displayFrame.left, displayFrame.top, (displayFrame.right - displayFrame.left), From 802829be05b3497a20a715168b3cf5fdba28182d Mon Sep 17 00:00:00 2001 From: Rajulu Ponnada Date: Wed, 12 Oct 2011 20:10:12 -0700 Subject: [PATCH 425/435] hardware/msm7k/libgralloc-qsd8k - framebuffer.cpp fps calaculation for a time interval Change-Id: I11ee7973e192e5cc3cf5086b865632eec46eaf8c --- libgralloc-qsd8k/framebuffer.cpp | 114 +++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp index 29c1c8a..dc51e08 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc-qsd8k/framebuffer.cpp @@ -86,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 */ @@ -176,9 +190,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); @@ -202,6 +228,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; @@ -210,41 +271,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; @@ -252,6 +287,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 From 6eb041de80bc4832b0b1d1cafb82ff5b2f32b295 Mon Sep 17 00:00:00 2001 From: Kinjal Bhavsar Date: Fri, 14 Oct 2011 18:03:04 -0700 Subject: [PATCH 426/435] msm7k: Detect display type and mark layers Mark layers for convert to S3D when playing S3D content on a 3DTV. Change-Id: I355a73753682134b8ec5544a03d55ae40793e897 --- libhwcomposer/Android.mk | 3 ++ libhwcomposer/hwcomposer.cpp | 51 +++++++++++++++++++++++++++++++ liboverlay/Android.mk | 3 ++ liboverlay/overlayLib.cpp | 58 ++++++++++++++++++++++++++---------- liboverlay/overlayLib.h | 6 ++++ 5 files changed, 106 insertions(+), 15 deletions(-) mode change 100755 => 100644 libhwcomposer/Android.mk mode change 100755 => 100644 libhwcomposer/hwcomposer.cpp mode change 100755 => 100644 liboverlay/overlayLib.cpp mode change 100755 => 100644 liboverlay/overlayLib.h diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk old mode 100755 new mode 100644 index 1ed1396..df25be9 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -22,4 +22,7 @@ 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) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp old mode 100755 new mode 100644 index 1b55fdb..f55dba8 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -605,6 +605,46 @@ static int getYUVBufferCount (const hwc_layer_list_t* list) { return yuvBufferCount; } +static int getS3DVideoFormat (const hwc_layer_list_t* list) { + int s3dFormat = 0; + if (list) { + for (size_t i=0; inumHwLayers; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO)) + s3dFormat = FORMAT_3D_INPUT(hnd->format); + if (s3dFormat) + break; + } + } + return s3dFormat; +} + +static bool isS3DCompositionRequired() { +#ifdef HDMI_AS_PRIMARY + return overlay::is3DTV(); +#endif + return false; +} + +static void markUILayerForS3DComposition (hwc_layer_t &layer, int s3dVideoFormat) { +#ifdef HDMI_AS_PRIMARY + layer.compositionType = HWC_FRAMEBUFFER; + switch(s3dVideoFormat) { + case HAL_3D_IN_SIDE_BY_SIDE_L_R: + case HAL_3D_IN_SIDE_BY_SIDE_R_L: + layer.hints |= HWC_HINT_DRAW_S3D_SIDE_BY_SIDE; + break; + case HAL_3D_IN_TOP_BOTTOM: + layer.hints |= HWC_HINT_DRAW_S3D_TOP_BOTTOM; + break; + default: + LOGE("%s: Unknown S3D input format 0x%x", __FUNCTION__, s3dVideoFormat); + break; + } +#endif + return; +} + static int getLayersNotUpdatingCount(const hwc_layer_list_t* list) { int numLayersNotUpdating = 0; if (list) { @@ -636,6 +676,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { int yuvBufferCount = 0; int layerType = 0; + bool isS3DCompositionNeeded = false; + int s3dVideoFormat = 0; int numLayersNotUpdating = 0; bool fullscreen = false; @@ -648,6 +690,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { numLayersNotUpdating = getLayersNotUpdatingCount(list); skipComposition = canSkipComposition(ctx, yuvBufferCount, list->numHwLayers, numLayersNotUpdating); + s3dVideoFormat = getS3DVideoFormat(list); + if (s3dVideoFormat) + isS3DCompositionNeeded = isS3DCompositionRequired(); } if (list->flags & HWC_GEOMETRY_CHANGED) { @@ -662,6 +707,10 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { // If there is a single Fullscreen layer, we can bypass it - TBD // If there is only one video/camera buffer, we can bypass itn if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { + // During the animaton UI layers are marked as SKIP + // need to still mark the layer for S3D composition + if (isS3DCompositionNeeded) + markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat); continue; } if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { @@ -685,6 +734,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; skipComposition = false; } + } else if (isS3DCompositionNeeded) { + markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat); } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) { list->hwLayers[i].compositionType = HWC_USE_OVERLAY; list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index d271fb5..a257de2 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -27,6 +27,9 @@ LOCAL_SRC_FILES := \ overlayLib.cpp \ overlayLibUI.cpp \ LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\" +ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true) +LOCAL_CFLAGS += -DHDMI_AS_PRIMARY +endif LOCAL_MODULE := liboverlay include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp old mode 100755 new mode 100644 index 7d098f0..b111c86 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -25,6 +25,14 @@ static inline size_t ALIGN(size_t x, size_t align) { return (x + align-1) & ~(align-1); } +using namespace overlay; + +#ifdef HDMI_AS_PRIMARY +bool Overlay::sHDMIAsPrimary = true; +#else +bool Overlay::sHDMIAsPrimary = false; +#endif + int overlay::get_mdp_format(int format) { switch (format) { case HAL_PIXEL_FORMAT_RGBA_8888 : @@ -167,8 +175,6 @@ const char* overlay::getFormatString(int format){ return formats[format]; } -using namespace overlay; - bool overlay::isHDMIConnected () { char value[PROPERTY_VALUE_MAX]; property_get("hw.hdmiON", value, "0"); @@ -183,7 +189,7 @@ bool overlay::is3DTV() { fread(&is3DTV, 1, 1, fp); fclose(fp); } - LOGI("3DTV EDID flag: %d", is3DTV); + LOGI("3DTV EDID flag: %c", is3DTV); return (is3DTV == '0') ? false : true; } @@ -205,6 +211,9 @@ bool overlay::isPanel3D() { } bool overlay::usePanel3D() { + if (Overlay::sHDMIAsPrimary) + return is3DTV(); + if(!isPanel3D()) return false; char value[PROPERTY_VALUE_MAX]; @@ -325,8 +334,12 @@ bool Overlay::closeChannel() { if(mS3DFormat) { if (mHDMIConnected) overlay::send3DInfoPacket(0); - else if (mState == OV_3D_VIDEO_3D_PANEL) - enableBarrier(0); + else if (mState == OV_3D_VIDEO_3D_PANEL) { + if (sHDMIAsPrimary) + overlay::send3DInfoPacket(0); + else + enableBarrier(0); + } } for (int i = 0; i < NUM_CHANNELS; i++) { objOvCtrlChannel[i].closeControlChannel(); @@ -367,11 +380,15 @@ bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { break; case OV_3D_VIDEO_3D_PANEL: for (int i = 0; i < NUM_CHANNELS; i++) { - if (!objOvCtrlChannel[i].useVirtualFB()) { - LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i); - return false; + if (sHDMIAsPrimary) + objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); + else { + if (!objOvCtrlChannel[i].useVirtualFB()) { + LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i); + return false; + } + objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect); } - objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect); if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) { LOGE("%s: failed for channel %d", __FUNCTION__, i); return false; @@ -429,6 +446,9 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati geometryChanged = false; } + if (sHDMIAsPrimary) + needUpdateFlags = false; + if ((false == needUpdateFlags) && (false == geometryChanged)) { objOvDataChannel[0].updateDataChannel(0, 0); return true; @@ -436,14 +456,16 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati // Disable rotation for the HDMI channels int orientHdmi = 0; - int orient[2] = {true, orientHdmi}; + int orientPrimary = sHDMIAsPrimary ? 0 : orientation; + int orient[2] = {orientPrimary, orientHdmi}; // enable waitForVsync on HDMI bool waitForHDMI = true; - bool wait[2] = {waitForVsync, waitForHDMI}; + bool waitForPrimary = sHDMIAsPrimary ? true : waitForVsync; + bool waitCond[2] = {waitForPrimary, waitForHDMI}; switch(mState) { case OV_3D_VIDEO_3D_PANEL: - orient[1] = orientation; + orient[1] = sHDMIAsPrimary ? 0 : orientation; break; case OV_3D_VIDEO_3D_TV: orient[0] = 0; @@ -464,7 +486,7 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati // Set the overlay source info for (int i = 0; i < NUM_CHANNELS; i++) { if (objOvCtrlChannel[i].isChannelUP()) { - ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], wait[i]); + ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], waitCond[i]); if (!ret) { LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i); return false; @@ -525,6 +547,7 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, } // We always enable the rotator for the primary. bool noRot = false; + bool uiChannel = false; switch(mState) { case OV_2D_VIDEO_ON_PANEL: case OV_3D_VIDEO_2D_PANEL: @@ -532,8 +555,13 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, mS3DFormat, VG0_PIPE, waitForVsync, num_buffers); break; case OV_3D_VIDEO_3D_PANEL: + if (sHDMIAsPrimary) { + noRot = true; + waitForVsync = true; + send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D); + } for (int i=0; i Date: Wed, 2 Nov 2011 13:49:15 -0700 Subject: [PATCH 427/435] Multi layer composition bypass Allow 1 or 2 non overlapping layers to use composition bypass. This is an enhancement to the previous approach which uses bypass strictly for 2 layers. Change-Id: I879903db44cb1fddbe3e428ffa77eb67e95e0886 --- libhwcomposer/hwcomposer.cpp | 44 +++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp index f55dba8..034d74d 100644 --- a/libhwcomposer/hwcomposer.cpp +++ b/libhwcomposer/hwcomposer.cpp @@ -160,6 +160,14 @@ static void dump_layer(hwc_layer_t const* l) { l->displayFrame.bottom); } +static inline int min(const int& a, const int& b) { + return (a < b) ? a : b; +} + +static inline int max(const int& a, const int& b) { + return (a > b) ? a : b; +} + static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) { #if defined HDMI_DUAL_DISPLAY private_hwc_module_t* hwcModule = reinterpret_cast( @@ -444,12 +452,42 @@ static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer, return 0; } +/* Checks if 2 layers intersect */ +static bool isIntersect(const hwc_rect_t& one, const hwc_rect_t& two) { + hwc_rect_t result; + result.left = max(one.left, two.left); + result.top = max(one.top, two.top); + result.right = min(one.right, two.right); + result.bottom = min(one.bottom, two.bottom); + const int width = result.right - result.left; + const int height = result.bottom - result.top; + const bool isEmpty = width <= 0 || height <= 0; + return !isEmpty; +} + +/* Check if layers are disjoint */ +static bool isDisjoint(const hwc_layer_list_t* list) { + //Validate supported layer range + if(list->numHwLayers <= 0 || list->numHwLayers > MAX_BYPASS_LAYERS) { + return false; + } + for(int i = 0; i < (list->numHwLayers) - 1; i++) { + for(int j = i + 1; j < list->numHwLayers; j++) { + if(isIntersect(list->hwLayers[i].displayFrame, + list->hwLayers[j].displayFrame)) { + return false; + } + } + } + return true; +} + /* * Checks if doing comp. bypass is possible. If video is not on and there * are 2 layers then its doable. */ inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount, - const int numLayers) { + const hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); private_hwc_module_t* hwcModule = reinterpret_cast( dev->common.module); @@ -468,7 +506,7 @@ inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount return false; } #endif - return (yuvCount == 0) && (numLayers == MAX_BYPASS_LAYERS); + return (yuvCount == 0) && isDisjoint(list); } /* @@ -759,7 +797,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { #ifdef COMPOSITION_BYPASS //Check if bypass is feasible - if(isBypassDoable(dev, yuvBufferCount, list->numHwLayers) && + if(isBypassDoable(dev, yuvBufferCount, list) && isBypassEfficient(hwcModule->fbDevice, list, ctx)) { //Setup bypass if(setupBypass(ctx, list)) { From 0856a1cf2f285109e8bc618dcfc18a101b987512 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Wed, 2 Nov 2011 18:29:14 -0700 Subject: [PATCH 428/435] gralloc: header change for ION support Change-Id: Ibbb81034c1c4cbc6ddc79719c7d47ded97bd816e --- libgralloc-qsd8k/gpu.cpp | 10 +++++----- libgralloc-qsd8k/gralloc_priv.h | 18 ++++++++++++------ libgralloc-qsd8k/mapper.cpp | 1 - libgralloc-qsd8k/pmemalloc.cpp | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp index af36fee..cabcda9 100755 --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc-qsd8k/gpu.cpp @@ -80,7 +80,7 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, private_module_t* m = reinterpret_cast(common.module); // we don't support allocations with both the FB and PMEM_ADSP flags - if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { + if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) { return -EINVAL; } @@ -221,11 +221,11 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } - if (usage & GRALLOC_USAGE_PRIVATE_PMEM) { + if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; } #endif - if ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) || (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) + if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) || (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) { flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; @@ -267,8 +267,8 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* // c. The client has not explicitly requested a PMEM buffer if ((get_composition_type() != MDP_COMPOSITION) && (bufferType != BUFFER_TYPE_VIDEO) && - ((usage & GRALLOC_USAGE_PRIVATE_PMEM) == 0) && - ((usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) == 0)) { + ((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) && + ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0)) { // the caller didn't request PMEM, so we can try something else flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; err = 0; diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index c6780ef..8037812 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -36,10 +36,15 @@ using namespace overlay; #endif enum { - /* gralloc usage bit indicating a pmem_adsp allocation should be used */ - GRALLOC_USAGE_PRIVATE_PMEM_ADSP = GRALLOC_USAGE_PRIVATE_0, - GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL = GRALLOC_USAGE_PRIVATE_1, - GRALLOC_USAGE_PRIVATE_PMEM = GRALLOC_USAGE_PRIVATE_2, + /* 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, }; enum { @@ -262,9 +267,10 @@ struct private_handle_t { PRIV_FLAGS_FRAMEBUFFER = 0x00000001, PRIV_FLAGS_USES_PMEM = 0x00000002, PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004, - PRIV_FLAGS_NEEDS_FLUSH = 0x00000008, + PRIV_FLAGS_USES_ION = 0x00000008, PRIV_FLAGS_USES_ASHMEM = 0x00000010, - PRIV_FLAGS_FORMAT_CHANGED = 0x00000020, + PRIV_FLAGS_NEEDS_FLUSH = 0x00000020, + PRIV_FLAGS_DO_NOT_FLUSH = 0x00000040, }; enum { diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp index cdd9bbc..0e495be 100755 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc-qsd8k/mapper.cpp @@ -374,7 +374,6 @@ int gralloc_perform(struct gralloc_module_t const* module, hnd->height = h; if (hnd->format != f) { hnd->format = f; - hnd->flags |= private_handle_t::PRIV_FLAGS_FORMAT_CHANGED; } break; } diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp index e9c5247..fce2d87 100755 --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc-qsd8k/pmemalloc.cpp @@ -278,9 +278,9 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, int openFlags = get_open_flags(usage); const char *device; - if (usage & GRALLOC_USAGE_PRIVATE_PMEM_ADSP) { + if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) { device = DEVICE_PMEM_ADSP; - } else if (usage & GRALLOC_USAGE_PRIVATE_PMEM_SMIPOOL) { + } else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) { device = DEVICE_PMEM_SMIPOOL; } else if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) { From 724b65132054708e44f57f41eb8ab2a99db8e29e Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Fri, 11 Nov 2011 13:57:26 -0800 Subject: [PATCH 429/435] overlay: Add FB flag for UI mirroring When the source for rotator is the framebuffer, the FB flag needs to be set to identify the type of memory to be used. Change-Id: I4fc6112832ad42eb7092be5243653b9baf8a241a --- liboverlay/overlayLib.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index b111c86..fd7eab9 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -1489,6 +1489,9 @@ bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int r } } } + // Set this flag if source memory is fb + if(uiChannel) + mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB; mOvDataRot.data.memory_id = mPmemFD; mRotData.dst.memory_id = mPmemFD; From 7ab3fc97e08170cc49468008a7a20d174b081d3c Mon Sep 17 00:00:00 2001 From: Chetan Kalyan Date: Thu, 13 Oct 2011 15:37:16 -0700 Subject: [PATCH 430/435] Overlay: Change MDP format for YV12 buffers Android uses different alignments for YV12 buffers. Hence, introduce a new format (MDP_Y_CR_CB_GH2V2) for such buffers. Change-Id: I50ba8baf2696252fce513e455d94bfde460b0e51 CRs-fixed: 302752 --- liboverlay/overlayLib.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index fd7eab9..1f599a2 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -52,7 +52,7 @@ int overlay::get_mdp_format(int format) { case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return MDP_Y_CRCB_H2V2_TILE; case HAL_PIXEL_FORMAT_YV12: - return MDP_Y_CR_CB_H2V2; + return MDP_Y_CR_CB_GH2V2; default: LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format); return -1; @@ -86,6 +86,7 @@ int overlay::get_rot_output_format(int format) { case MDP_Y_CRCB_H2V2_TILE: return MDP_Y_CRCB_H2V2; case MDP_Y_CB_CR_H2V2: + case MDP_Y_CR_CB_GH2V2: return MDP_Y_CBCR_H2V2; default: return format; @@ -166,7 +167,10 @@ const char* overlay::getFormatString(int format){ "MDP_Y_CRCB_H2V2_TILE", "MDP_Y_CBCR_H2V2_TILE", "MDP_Y_CR_CB_H2V2", + "MDP_Y_CR_CB_GH2V2", "MDP_Y_CB_CR_H2V2", + "MDP_Y_CRCB_H1V1", + "MDP_Y_CBCR_H1V1", "MDP_IMGTYPE_LIMIT", "MDP_BGR_565", "MDP_FB_FORMAT", From b2f68b619061af18e214769720d3715ccc4d9591 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 14 Nov 2011 14:43:46 -0800 Subject: [PATCH 431/435] copybit: Check for invalid handle Change-Id: I3b0bcb3b464aaa15994add3b2f8d6feea3becc68 --- libcopybit/copybit_c2d.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 63493d7..88f59de 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -307,6 +307,11 @@ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image return -EINVAL; } + if(handle == NULL) { + LOGE("%s: invalid handle", __func__); + return -EINVAL; + } + if (handle->gpuaddr == 0) { handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); if(!handle->gpuaddr) { From e8525339bcca0b88077d46fa1ec260448045bed8 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Fri, 11 Nov 2011 17:59:42 -0800 Subject: [PATCH 432/435] hardware/msm7k: When ION is enabled use the new gralloc Change-Id: Id0644da2aa4d55bed7c6c41a2c6e58e860475274 --- libgralloc-qsd8k/Android.mk | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk index 28c6a0c..1157e9f 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc-qsd8k/Android.mk @@ -11,7 +11,7 @@ # 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. - +ifneq ($(TARGET_USES_ION),true) LOCAL_PATH := $(call my-dir) # HAL module implemenation, not prelinked and stored in @@ -21,7 +21,8 @@ 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_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \ + hardware/qcom/display/libgralloc LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr LOCAL_SRC_FILES := \ allocator.cpp \ @@ -62,3 +63,4 @@ LOCAL_MODULE := libgralloc_qsd8k_host LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\" include $(BUILD_HOST_STATIC_LIBRARY) endif +endif From 049cef0c8c72e7023739100c180043bd993d8e3f Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 14 Nov 2011 14:44:34 -0800 Subject: [PATCH 433/435] C2D HAL: Enable ION Change-Id: Ibfd124d620bab018bc89dd37e4471270c93aa58d --- libcopybit/copybit_c2d.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 88f59de..0995345 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -208,10 +208,17 @@ static uint32 c2d_get_gpuaddr(int device_fd, struct private_handle_t *handle) param.offset = handle->offset; param.hostptr = handle->base; - if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM|private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) + if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) param.memtype = KGSL_USER_MEM_TYPE_PMEM; - else + else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) param.memtype = KGSL_USER_MEM_TYPE_ASHMEM; + else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION) + param.memtype = KGSL_USER_MEM_TYPE_ION; + else { + LOGE("Invalid handle flags: 0x%x", handle->flags); + return 0; + } if (!ioctl(device_fd, IOCTL_KGSL_MAP_USER_MEM, (void *)¶m, sizeof(param))) { return param.gpuaddr; From b4684bce38db3ad03ab3f52ce5177246408b7f3f Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 14 Nov 2011 14:32:10 -0800 Subject: [PATCH 434/435] overlay: Enable ION for rotator Change-Id: I08f1cd0f8d49812ba8723a137913e386365c946a --- liboverlay/Android.mk | 12 +++++++--- liboverlay/overlayLib.cpp | 48 +++++++++++++++++++++++++++++++++++-- liboverlay/overlayLib.h | 5 ++++ liboverlay/overlayLibUI.cpp | 32 +++++++++++++++++++++++++ liboverlay/overlayLibUI.h | 9 ++++++- 5 files changed, 100 insertions(+), 6 deletions(-) diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index a257de2..0f3512c 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -19,14 +19,20 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -LOCAL_SHARED_LIBRARIES := liblog libcutils +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/msm7k/libgralloc-qsd8k +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 @@ -41,7 +47,7 @@ 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/msm7k/libgralloc-qsd8k +LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc LOCAL_SRC_FILES := overlay.cpp LOCAL_MODULE := overlay.default include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 1f599a2..f0db551 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -26,6 +26,10 @@ static inline size_t ALIGN(size_t x, size_t align) { } using namespace overlay; +using android::sp; +using gralloc::IMemAlloc; +using gralloc::IonController; +using gralloc::alloc_data; #ifdef HDMI_AS_PRIMARY bool Overlay::sHDMIAsPrimary = true; @@ -1406,7 +1410,11 @@ bool OverlayControlChannel::getSize(int& size) const { } OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1), - mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(0) { + mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(0) +{ +#ifdef USE_ION + mAlloc = gralloc::IAllocController::getInstance(); +#endif } OverlayDataChannel::~OverlayDataChannel() { @@ -1462,6 +1470,30 @@ bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int r { mPmemAddr = MAP_FAILED; +#ifdef USE_ION + alloc_data data; + data.base = 0; + data.fd = -1; + data.offset = 0; + data.size = mPmemOffset * num_buffers; + data.align = getpagesize(); + data.uncached = true; + + int err = mAlloc->allocate(data, GRALLOC_USAGE_PRIVATE_ADSP_HEAP| + GRALLOC_USAGE_PRIVATE_SMI_HEAP, 0); + if(err) { + reportError("Cant allocate from ION"); + close(mFD); + mFD = -1; + close(mRotFD); + mRotFD = -1; + return false; + } + mPmemFD = data.fd; + mPmemAddr = data.base; + mBufferType = data.allocType; +#else + if((requestType == NEW_REQUEST) && !uiChannel) { mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC); if(mPmemFD >= 0) @@ -1493,6 +1525,7 @@ bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int r } } } +#endif // Set this flag if source memory is fb if(uiChannel) mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB; @@ -1537,8 +1570,13 @@ bool OverlayDataChannel::closeDataChannel() { return true; if (!mNoRot && mRotFD > 0) { +#ifdef USE_ION + sp memalloc = mAlloc->getAllocator(mBufferType); + memalloc->free_buffer(mPmemAddr, mPmemOffset * mNumBuffers, 0, mPmemFD); +#else munmap(mPmemAddr, mPmemOffset * mNumBuffers); - + close(mPmemFD); +#endif close(mPmemFD); mPmemFD = -1; close(mRotFD); @@ -1591,8 +1629,14 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { // Unmap the old PMEM memory after the queueBuffer has returned if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) { +#ifdef USE_ION + sp memalloc = mAlloc->getAllocator(mBufferType); + memalloc->free_buffer(oldPmemAddr, oldPmemOffset * mNumBuffers, 0, oldPmemFD); +#else munmap(oldPmemAddr, oldPmemOffset * mNumBuffers); close(oldPmemFD); +#endif + oldPmemFD = -1; } return result; diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 1402037..0ad92ce 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -40,6 +40,9 @@ #include #include #include +#include +#include +#include #define HW_OVERLAY_MAGNIFICATION_LIMIT 8 #define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT @@ -215,6 +218,8 @@ class OverlayDataChannel { int mCurrentItem; int mNumBuffers; int mUpdateDataChannel; + android::sp mAlloc; + int mBufferType; bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2); bool mapRotatorMemory(int num_buffers, bool uiChannel, int requestType); diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp index ccd97c0..dd19cd9 100644 --- a/liboverlay/overlayLibUI.cpp +++ b/liboverlay/overlayLibUI.cpp @@ -19,6 +19,10 @@ #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, @@ -315,6 +319,27 @@ status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo, 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) { @@ -329,6 +354,7 @@ status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo, closeRotSession(); return NO_INIT; } +#endif mCurrentItem = 0; for (int i = 0; i < mNumBuffers; i++) @@ -343,8 +369,14 @@ status_t Rotator::closeRotSession() { if (mSessionID != NO_INIT && mFD != NO_INIT) { ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID); close(mFD); +#ifdef USE_ION + sp 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; diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h index a044df6..2cb1ffe 100644 --- a/liboverlay/overlayLibUI.h +++ b/liboverlay/overlayLibUI.h @@ -101,11 +101,18 @@ class Rotator { int mCurrentItem; int mNumBuffers; int mSize; + android::sp mAlloc; + int mBufferType; Rotator(const Rotator& objROtator); Rotator& operator=(const Rotator& objRotator); public: - explicit Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1) { }; + 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); From dd6a62c9dd0f2ef485f0c1bd2269c5ad5dcac1a8 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Mon, 14 Nov 2011 14:58:33 -0800 Subject: [PATCH 435/435] hwc: Change Android.mk to point to new display gralloc Change-Id: Ie7c08fb55339c2c7b7bf2c28576291a5a1e1d809 --- libhwcomposer/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index df25be9..ffc30bd 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -5,14 +5,14 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware liboverlay +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/msm7k/libgralloc-qsd8k +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