copybit.cpp revision c9410082453abfb6eaaf43e6c97e04711d0751c0
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18#define LOG_TAG "copybit" 19 20#include <cutils/log.h> 21 22#include <linux/msm_mdp.h> 23#include <linux/fb.h> 24 25#include <stdint.h> 26#include <string.h> 27#include <unistd.h> 28#include <errno.h> 29#include <fcntl.h> 30 31#include <sys/ioctl.h> 32#include <sys/types.h> 33#include <sys/mman.h> 34 35#include <hardware/copybit.h> 36 37#include "gralloc_priv.h" 38 39/******************************************************************************/ 40 41#if defined(COPYBIT_MSM7K) 42#define MAX_SCALE_FACTOR (4) 43#elif defined(COPYBIT_QSD8K) 44#define MAX_SCALE_FACTOR (8) 45#else 46#error "Unsupported MDP version" 47#endif 48 49/******************************************************************************/ 50 51/** State information for each device instance */ 52struct copybit_context_t { 53 struct copybit_device_t device; 54 int mFD; 55 uint8_t mAlpha; 56 uint8_t mFlags; 57}; 58 59/** 60 * Common hardware methods 61 */ 62 63static int open_copybit(const struct hw_module_t* module, const char* name, 64 struct hw_device_t** device); 65 66static struct hw_module_methods_t copybit_module_methods = { 67 open: open_copybit 68}; 69 70/* 71 * The COPYBIT Module 72 */ 73struct copybit_module_t HAL_MODULE_INFO_SYM = { 74 common: { 75 tag: HARDWARE_MODULE_TAG, 76 version_major: 1, 77 version_minor: 0, 78 id: COPYBIT_HARDWARE_MODULE_ID, 79 name: "QCT MSM7K COPYBIT Module", 80 author: "Google, Inc.", 81 methods: ©bit_module_methods 82 } 83}; 84 85/******************************************************************************/ 86 87/** min of int a, b */ 88static inline int min(int a, int b) { 89 return (a<b) ? a : b; 90} 91 92/** max of int a, b */ 93static inline int max(int a, int b) { 94 return (a>b) ? a : b; 95} 96 97/** scale each parameter by mul/div. Assume div isn't 0 */ 98static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) { 99 if (mul != div) { 100 *a = (mul * *a) / div; 101 *b = (mul * *b) / div; 102 } 103} 104 105/** Determine the intersection of lhs & rhs store in out */ 106static void intersect(struct copybit_rect_t *out, 107 const struct copybit_rect_t *lhs, 108 const struct copybit_rect_t *rhs) { 109 out->l = max(lhs->l, rhs->l); 110 out->t = max(lhs->t, rhs->t); 111 out->r = min(lhs->r, rhs->r); 112 out->b = min(lhs->b, rhs->b); 113} 114 115/** convert COPYBIT_FORMAT to MDP format */ 116static int get_format(int format) { 117 switch (format) { 118 case COPYBIT_FORMAT_RGB_565: return MDP_RGB_565; 119 case COPYBIT_FORMAT_RGBX_8888: return MDP_RGBX_8888; 120 case COPYBIT_FORMAT_RGB_888: return MDP_RGB_888; 121 case COPYBIT_FORMAT_RGBA_8888: return MDP_RGBA_8888; 122 case COPYBIT_FORMAT_BGRA_8888: return MDP_BGRA_8888; 123 case COPYBIT_FORMAT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1; 124 case COPYBIT_FORMAT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2; 125 } 126 return -1; 127} 128 129/** convert from copybit image to mdp image structure */ 130static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) 131{ 132 private_handle_t* hnd = (private_handle_t*)rhs->handle; 133 img->width = rhs->w; 134 img->height = rhs->h; 135 img->format = get_format(rhs->format); 136 img->offset = hnd->offset; 137#if defined(COPYBIT_MSM7K) 138 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { 139 img->memory_id = hnd->gpu_fd; 140 if (img->format == MDP_RGBA_8888) { 141 // msm7201A GPU only supports BGRA_8888 destinations 142 img->format = MDP_BGRA_8888; 143 } 144 } else { 145 img->memory_id = hnd->fd; 146 } 147#else 148 img->memory_id = hnd->fd; 149#endif 150} 151/** setup rectangles */ 152static void set_rects(struct copybit_context_t *dev, 153 struct mdp_blit_req *e, 154 const struct copybit_rect_t *dst, 155 const struct copybit_rect_t *src, 156 const struct copybit_rect_t *scissor) { 157 struct copybit_rect_t clip; 158 intersect(&clip, scissor, dst); 159 160 e->dst_rect.x = clip.l; 161 e->dst_rect.y = clip.t; 162 e->dst_rect.w = clip.r - clip.l; 163 e->dst_rect.h = clip.b - clip.t; 164 165 uint32_t W, H; 166 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) { 167 e->src_rect.x = (clip.t - dst->t) + src->t; 168 e->src_rect.y = (dst->r - clip.r) + src->l; 169 e->src_rect.w = (clip.b - clip.t); 170 e->src_rect.h = (clip.r - clip.l); 171 W = dst->b - dst->t; 172 H = dst->r - dst->l; 173 } else { 174 e->src_rect.x = (clip.l - dst->l) + src->l; 175 e->src_rect.y = (clip.t - dst->t) + src->t; 176 e->src_rect.w = (clip.r - clip.l); 177 e->src_rect.h = (clip.b - clip.t); 178 W = dst->r - dst->l; 179 H = dst->b - dst->t; 180 } 181 MULDIV(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W); 182 MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H); 183 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) { 184 e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h); 185 } 186 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) { 187 e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w); 188 } 189} 190 191/** setup mdp request */ 192static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) { 193 req->alpha = dev->mAlpha; 194 req->transp_mask = MDP_TRANSP_NOP; 195 req->flags = dev->mFlags; 196} 197 198/** copy the bits */ 199static int msm_copybit(struct copybit_context_t *dev, void const *list) 200{ 201 int err = ioctl(dev->mFD, MSMFB_BLIT, 202 (struct mdp_blit_req_list const*)list); 203 LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno)); 204 if (err == 0) 205 return 0; 206 else 207 return -errno; 208} 209 210/*****************************************************************************/ 211 212/** Set a parameter to value */ 213static int set_parameter_copybit( 214 struct copybit_device_t *dev, 215 int name, 216 int value) 217{ 218 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 219 int status = 0; 220 if (ctx) { 221 switch(name) { 222 case COPYBIT_ROTATION_DEG: 223 switch (value) { 224 case 0: 225 ctx->mFlags &= ~0x7; 226 break; 227 case 90: 228 ctx->mFlags &= ~0x7; 229 ctx->mFlags |= MDP_ROT_90; 230 break; 231 case 180: 232 ctx->mFlags &= ~0x7; 233 ctx->mFlags |= MDP_ROT_180; 234 break; 235 case 270: 236 ctx->mFlags &= ~0x7; 237 ctx->mFlags |= MDP_ROT_270; 238 break; 239 default: 240 LOGE("Invalid value for COPYBIT_ROTATION_DEG"); 241 status = -EINVAL; 242 break; 243 } 244 break; 245 case COPYBIT_PLANE_ALPHA: 246 if (value < 0) value = 0; 247 if (value >= 256) value = 255; 248 ctx->mAlpha = value; 249 break; 250 case COPYBIT_DITHER: 251 if (value == COPYBIT_ENABLE) { 252 ctx->mFlags |= MDP_DITHER; 253 } else if (value == COPYBIT_DISABLE) { 254 ctx->mFlags &= ~MDP_DITHER; 255 } 256 break; 257 case COPYBIT_BLUR: 258 if (value == COPYBIT_ENABLE) { 259 ctx->mFlags |= MDP_BLUR; 260 } else if (value == COPYBIT_DISABLE) { 261 ctx->mFlags &= ~MDP_BLUR; 262 } 263 break; 264 case COPYBIT_TRANSFORM: 265 ctx->mFlags &= ~0x7; 266 ctx->mFlags |= value & 0x7; 267 break; 268 default: 269 status = -EINVAL; 270 break; 271 } 272 } else { 273 status = -EINVAL; 274 } 275 return status; 276} 277 278/** Get a static info value */ 279static int get(struct copybit_device_t *dev, int name) 280{ 281 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 282 int value; 283 if (ctx) { 284 switch(name) { 285 case COPYBIT_MINIFICATION_LIMIT: 286 value = MAX_SCALE_FACTOR; 287 break; 288 case COPYBIT_MAGNIFICATION_LIMIT: 289 value = MAX_SCALE_FACTOR; 290 break; 291 case COPYBIT_SCALING_FRAC_BITS: 292 value = 32; 293 break; 294 case COPYBIT_ROTATION_STEP_DEG: 295 value = 90; 296 break; 297 default: 298 value = -EINVAL; 299 } 300 } else { 301 value = -EINVAL; 302 } 303 return value; 304} 305 306/** do a stretch blit type operation */ 307static int stretch_copybit( 308 struct copybit_device_t *dev, 309 struct copybit_image_t const *dst, 310 struct copybit_image_t const *src, 311 struct copybit_rect_t const *dst_rect, 312 struct copybit_rect_t const *src_rect, 313 struct copybit_region_t const *region) 314{ 315 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 316 int status = 0; 317 if (ctx) { 318 struct { 319 uint32_t count; 320 struct mdp_blit_req req[12]; 321 } list; 322 323 if (ctx->mAlpha < 255) { 324 switch (src->format) { 325 // we don't support plane alpha with RGBA formats 326 case COPYBIT_FORMAT_RGBA_8888: 327 case COPYBIT_FORMAT_BGRA_8888: 328 case COPYBIT_FORMAT_RGBA_5551: 329 case COPYBIT_FORMAT_RGBA_4444: 330 return -EINVAL; 331 } 332 } 333 334 const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]); 335 const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h }; 336 struct copybit_rect_t clip; 337 list.count = 0; 338 status = 0; 339 while ((status == 0) && region->next(region, &clip)) { 340 intersect(&clip, &bounds, &clip); 341 set_infos(ctx, &list.req[list.count]); 342 set_image(&list.req[list.count].dst, dst); 343 set_image(&list.req[list.count].src, src); 344 set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip); 345 if (++list.count == maxCount) { 346 status = msm_copybit(ctx, &list); 347 list.count = 0; 348 } 349 } 350 if ((status == 0) && list.count) { 351 status = msm_copybit(ctx, &list); 352 } 353 } else { 354 status = -EINVAL; 355 } 356 return status; 357} 358 359/** Perform a blit type operation */ 360static int blit_copybit( 361 struct copybit_device_t *dev, 362 struct copybit_image_t const *dst, 363 struct copybit_image_t const *src, 364 struct copybit_region_t const *region) 365{ 366 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h }; 367 struct copybit_rect_t sr = { 0, 0, src->w, src->h }; 368 return stretch_copybit(dev, dst, src, &dr, &sr, region); 369} 370 371/*****************************************************************************/ 372 373/** Close the copybit device */ 374static int close_copybit(struct hw_device_t *dev) 375{ 376 struct copybit_context_t* ctx = (struct copybit_context_t*)dev; 377 if (ctx) { 378 close(ctx->mFD); 379 free(ctx); 380 } 381 return 0; 382} 383 384/** Open a new instance of a copybit device using name */ 385static int open_copybit(const struct hw_module_t* module, const char* name, 386 struct hw_device_t** device) 387{ 388 int status = -EINVAL; 389 copybit_context_t *ctx; 390 ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t)); 391 memset(ctx, 0, sizeof(*ctx)); 392 393 ctx->device.common.tag = HARDWARE_DEVICE_TAG; 394 ctx->device.common.version = 1; 395 ctx->device.common.module = const_cast<hw_module_t*>(module); 396 ctx->device.common.close = close_copybit; 397 ctx->device.set_parameter = set_parameter_copybit; 398 ctx->device.get = get; 399 ctx->device.blit = blit_copybit; 400 ctx->device.stretch = stretch_copybit; 401 ctx->mAlpha = MDP_ALPHA_NOP; 402 ctx->mFlags = 0; 403 ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0); 404 405 if (ctx->mFD < 0) { 406 status = errno; 407 LOGE("Error opening frame buffer errno=%d (%s)", 408 status, strerror(status)); 409 status = -status; 410 } else { 411 struct fb_fix_screeninfo finfo; 412 if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) { 413 if (strcmp(finfo.id, "msmfb") == 0) { 414 /* Success */ 415 status = 0; 416 } else { 417 LOGE("Error not msm frame buffer"); 418 status = -EINVAL; 419 } 420 } else { 421 LOGE("Error executing ioctl for screen info"); 422 status = -errno; 423 } 424 } 425 426 if (status == 0) { 427 *device = &ctx->device.common; 428 } else { 429 close_copybit(&ctx->device.common); 430 } 431 return status; 432} 433