blob: 886d12b9f5a9f5c018742a244157c407aada5a42 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2010 - 2011, Code Aurora Forum. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19#define LOG_TAG "copybit"
20
21#include <cutils/log.h>
22
23#include <linux/msm_mdp.h>
24#include <linux/fb.h>
25
26#include <stdint.h>
27#include <string.h>
28#include <unistd.h>
29#include <errno.h>
30#include <fcntl.h>
31
32#include <sys/ioctl.h>
33#include <sys/types.h>
34#include <sys/mman.h>
35
36#include <copybit.h>
37
38#include "gralloc_priv.h"
39#include "software_converter.h"
40
41#define DEBUG_MDP_ERRORS 1
42
43/******************************************************************************/
44
45#if defined(COPYBIT_MSM7K)
46#define MAX_SCALE_FACTOR (4)
47#define MAX_DIMENSION (4096)
48#elif defined(COPYBIT_QSD8K)
49#define MAX_SCALE_FACTOR (8)
50#define MAX_DIMENSION (2048)
51#else
52#error "Unsupported MDP version"
53#endif
54
55/******************************************************************************/
56
57/** State information for each device instance */
58struct copybit_context_t {
59 struct copybit_device_t device;
60 int mFD;
61 uint8_t mAlpha;
62 int mFlags;
63};
64
65/**
66 * Common hardware methods
67 */
68
69static int open_copybit(const struct hw_module_t* module, const char* name,
70 struct hw_device_t** device);
71
72static struct hw_module_methods_t copybit_module_methods = {
73open: open_copybit
74};
75
76/*
77 * The COPYBIT Module
78 */
79struct copybit_module_t HAL_MODULE_INFO_SYM = {
80common: {
81tag: HARDWARE_MODULE_TAG,
82 version_major: 1,
83 version_minor: 0,
84 id: COPYBIT_HARDWARE_MODULE_ID,
85 name: "QCT MSM7K COPYBIT Module",
86 author: "Google, Inc.",
87 methods: &copybit_module_methods
88 }
89};
90
91/******************************************************************************/
92
93/** min of int a, b */
94static inline int min(int a, int b) {
95 return (a<b) ? a : b;
96}
97
98/** max of int a, b */
99static inline int max(int a, int b) {
100 return (a>b) ? a : b;
101}
102
103/** scale each parameter by mul/div. Assume div isn't 0 */
104static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
105 if (mul != div) {
106 *a = (mul * *a) / div;
107 *b = (mul * *b) / div;
108 }
109}
110
111/** Determine the intersection of lhs & rhs store in out */
112static void intersect(struct copybit_rect_t *out,
113 const struct copybit_rect_t *lhs,
114 const struct copybit_rect_t *rhs) {
115 out->l = max(lhs->l, rhs->l);
116 out->t = max(lhs->t, rhs->t);
117 out->r = min(lhs->r, rhs->r);
118 out->b = min(lhs->b, rhs->b);
119}
120
121/** convert COPYBIT_FORMAT to MDP format */
122static int get_format(int format) {
123 switch (format) {
124 case HAL_PIXEL_FORMAT_RGB_565: return MDP_RGB_565;
125 case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888;
126 case HAL_PIXEL_FORMAT_RGB_888: return MDP_RGB_888;
127 case HAL_PIXEL_FORMAT_RGBA_8888: return MDP_RGBA_8888;
128 case HAL_PIXEL_FORMAT_BGRA_8888: return MDP_BGRA_8888;
129 case HAL_PIXEL_FORMAT_YCrCb_422_SP: return MDP_Y_CBCR_H2V1;
130 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return MDP_Y_CBCR_H2V2;
131 case HAL_PIXEL_FORMAT_YCbCr_422_SP: return MDP_Y_CRCB_H2V1;
132 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return MDP_Y_CRCB_H2V2;
133 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
134 }
135 return -1;
136}
137
138/** convert from copybit image to mdp image structure */
139static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs)
140{
141 private_handle_t* hnd = (private_handle_t*)rhs->handle;
142 if(hnd == NULL){
143 ALOGE("copybit: Invalid handle");
144 return;
145 }
146 img->width = rhs->w;
147 img->height = rhs->h;
148 img->format = get_format(rhs->format);
149 img->offset = hnd->offset;
150 img->memory_id = hnd->fd;
151}
152/** setup rectangles */
153static void set_rects(struct copybit_context_t *dev,
154 struct mdp_blit_req *e,
155 const struct copybit_rect_t *dst,
156 const struct copybit_rect_t *src,
157 const struct copybit_rect_t *scissor,
158 uint32_t horiz_padding,
159 uint32_t vert_padding) {
160 struct copybit_rect_t clip;
161 intersect(&clip, scissor, dst);
162
163 e->dst_rect.x = clip.l;
164 e->dst_rect.y = clip.t;
165 e->dst_rect.w = clip.r - clip.l;
166 e->dst_rect.h = clip.b - clip.t;
167
168 uint32_t W, H, delta_x, delta_y;
169 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
170 delta_x = (clip.t - dst->t);
171 delta_y = (dst->r - clip.r);
172 e->src_rect.w = (clip.b - clip.t);
173 e->src_rect.h = (clip.r - clip.l);
174 W = dst->b - dst->t;
175 H = dst->r - dst->l;
176 } else {
177 delta_x = (clip.l - dst->l);
178 delta_y = (clip.t - dst->t);
179 e->src_rect.w = (clip.r - clip.l);
180 e->src_rect.h = (clip.b - clip.t);
181 W = dst->r - dst->l;
182 H = dst->b - dst->t;
183 }
184
185 MULDIV(&delta_x, &e->src_rect.w, src->r - src->l, W);
186 MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H);
187
188 e->src_rect.x = delta_x + src->l;
189 e->src_rect.y = delta_y + src->t;
190
191 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
192 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
193 e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
194 }else{
195 e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
196 }
197 }
198
199 if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
200 if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
201 e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
202 }else{
203 e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
204 }
205 }
206}
207
208/** setup mdp request */
209static void set_infos(struct copybit_context_t *dev,
210 struct mdp_blit_req *req, int flags)
211{
212 req->alpha = dev->mAlpha;
213 req->transp_mask = MDP_TRANSP_NOP;
214 req->flags = dev->mFlags | flags;
215#if defined(COPYBIT_QSD8K)
216 req->flags |= MDP_BLEND_FG_PREMULT;
217#endif
218}
219
220/** copy the bits */
221static int msm_copybit(struct copybit_context_t *dev, void const *list)
222{
223 int err = ioctl(dev->mFD, MSMFB_BLIT,
224 (struct mdp_blit_req_list const*)list);
225 ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
226 if (err == 0) {
227 return 0;
228 } else {
229#if DEBUG_MDP_ERRORS
230 struct mdp_blit_req_list const* l =
231 (struct mdp_blit_req_list const*)list;
232 for (int i=0 ; i<l->count ; i++) {
233 ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
234 " dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
235 " flags=%08lx"
236 ,
237 i,
238 l->req[i].src.width,
239 l->req[i].src.height,
240 l->req[i].src.format,
241 l->req[i].src_rect.x,
242 l->req[i].src_rect.y,
243 l->req[i].src_rect.w,
244 l->req[i].src_rect.h,
245 l->req[i].dst.width,
246 l->req[i].dst.height,
247 l->req[i].dst.format,
248 l->req[i].dst_rect.x,
249 l->req[i].dst_rect.y,
250 l->req[i].dst_rect.w,
251 l->req[i].dst_rect.h,
252 l->req[i].flags
253 );
254 }
255#endif
256 return -errno;
257 }
258}
259
260/*****************************************************************************/
261
262/** Set a parameter to value */
263static int set_parameter_copybit(
264 struct copybit_device_t *dev,
265 int name,
266 int value)
267{
268 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
269 int status = 0;
270 if (ctx) {
271 switch(name) {
272 case COPYBIT_ROTATION_DEG:
273 switch (value) {
274 case 0:
275 ctx->mFlags &= ~0x7;
276 break;
277 case 90:
278 ctx->mFlags &= ~0x7;
279 ctx->mFlags |= MDP_ROT_90;
280 break;
281 case 180:
282 ctx->mFlags &= ~0x7;
283 ctx->mFlags |= MDP_ROT_180;
284 break;
285 case 270:
286 ctx->mFlags &= ~0x7;
287 ctx->mFlags |= MDP_ROT_270;
288 break;
289 default:
290 ALOGE("Invalid value for COPYBIT_ROTATION_DEG");
291 status = -EINVAL;
292 break;
293 }
294 break;
295 case COPYBIT_PLANE_ALPHA:
296 if (value < 0) value = MDP_ALPHA_NOP;
297 if (value >= 256) value = 255;
298 ctx->mAlpha = value;
299 break;
300 case COPYBIT_DITHER:
301 if (value == COPYBIT_ENABLE) {
302 ctx->mFlags |= MDP_DITHER;
303 } else if (value == COPYBIT_DISABLE) {
304 ctx->mFlags &= ~MDP_DITHER;
305 }
306 break;
307 case COPYBIT_BLUR:
308 if (value == COPYBIT_ENABLE) {
309 ctx->mFlags |= MDP_BLUR;
310 } else if (value == COPYBIT_DISABLE) {
311 ctx->mFlags &= ~MDP_BLUR;
312 }
313 break;
314 case COPYBIT_PREMULTIPLIED_ALPHA:
315 if(value == COPYBIT_ENABLE) {
316 ctx->mFlags |= MDP_BLEND_FG_PREMULT;
317 } else if (value == COPYBIT_DISABLE) {
318 ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
319 }
320 break;
321 case COPYBIT_TRANSFORM:
322 ctx->mFlags &= ~0x7;
323 ctx->mFlags |= value & 0x7;
324 break;
325 default:
326 status = -EINVAL;
327 break;
328 }
329 } else {
330 status = -EINVAL;
331 }
332 return status;
333}
334
335/** Get a static info value */
336static int get(struct copybit_device_t *dev, int name)
337{
338 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
339 int value;
340 if (ctx) {
341 switch(name) {
342 case COPYBIT_MINIFICATION_LIMIT:
343 value = MAX_SCALE_FACTOR;
344 break;
345 case COPYBIT_MAGNIFICATION_LIMIT:
346 value = MAX_SCALE_FACTOR;
347 break;
348 case COPYBIT_SCALING_FRAC_BITS:
349 value = 32;
350 break;
351 case COPYBIT_ROTATION_STEP_DEG:
352 value = 90;
353 break;
354 default:
355 value = -EINVAL;
356 }
357 } else {
358 value = -EINVAL;
359 }
360 return value;
361}
362
363/** do a stretch blit type operation */
364static int stretch_copybit(
365 struct copybit_device_t *dev,
366 struct copybit_image_t const *dst,
367 struct copybit_image_t const *src,
368 struct copybit_rect_t const *dst_rect,
369 struct copybit_rect_t const *src_rect,
370 struct copybit_region_t const *region)
371{
372 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
373 int status = 0;
374 private_handle_t *yv12_handle = NULL;
375 if (ctx) {
376 struct {
377 uint32_t count;
378 struct mdp_blit_req req[12];
379 } list;
380
381 if (ctx->mAlpha < 255) {
382 switch (src->format) {
383 // we don't support plane alpha with RGBA formats
384 case HAL_PIXEL_FORMAT_RGBA_8888:
385 case HAL_PIXEL_FORMAT_BGRA_8888:
386 case HAL_PIXEL_FORMAT_RGBA_5551:
387 case HAL_PIXEL_FORMAT_RGBA_4444:
388 ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
389 src->format);
390 return -EINVAL;
391 }
392 }
393
394 if (src_rect->l < 0 || src_rect->r > src->w ||
395 src_rect->t < 0 || src_rect->b > src->h) {
396 // this is always invalid
397 ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
398 __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
399
400 return -EINVAL;
401 }
402
403 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
404 ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h);
405 return -EINVAL;
406 }
407
408 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
409 ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h);
410 return -EINVAL;
411 }
412
413 if(src->format == HAL_PIXEL_FORMAT_YV12) {
414 int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
415 GRALLOC_USAGE_PRIVATE_MM_HEAP;
416 if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
417 src->format, usage)){
418 if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
419 (const_cast<copybit_image_t *>(src))->format =
420 HAL_PIXEL_FORMAT_YCrCb_420_SP;
421 (const_cast<copybit_image_t *>(src))->handle =
422 yv12_handle;
423 (const_cast<copybit_image_t *>(src))->base =
424 (void *)yv12_handle->base;
425 }
426 else{
427 ALOGE("Error copybit conversion from yv12 failed");
428 if(yv12_handle)
429 free_buffer(yv12_handle);
430 return -EINVAL;
431 }
432 }
433 else{
434 ALOGE("Error:unable to allocate memeory for yv12 software conversion");
435 return -EINVAL;
436 }
437 }
438 const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
439 const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
440 struct copybit_rect_t clip;
441 list.count = 0;
442 status = 0;
443 while ((status == 0) && region->next(region, &clip)) {
444 intersect(&clip, &bounds, &clip);
445 mdp_blit_req* req = &list.req[list.count];
446 int flags = 0;
447
448 private_handle_t* src_hnd = (private_handle_t*)src->handle;
449 if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
450 flags |= MDP_BLIT_NON_CACHED;
451 }
452
453 set_infos(ctx, req, flags);
454 set_image(&req->dst, dst);
455 set_image(&req->src, src);
456 set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
457
458 if (req->src_rect.w<=0 || req->src_rect.h<=0)
459 continue;
460
461 if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
462 continue;
463
464 if (++list.count == maxCount) {
465 status = msm_copybit(ctx, &list);
466 list.count = 0;
467 }
468 }
469 if ((status == 0) && list.count) {
470 status = msm_copybit(ctx, &list);
471 }
472 } else {
473 ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
474 status = -EINVAL;
475 }
476 if(yv12_handle)
477 free_buffer(yv12_handle);
478 return status;
479}
480
481/** Perform a blit type operation */
482static int blit_copybit(
483 struct copybit_device_t *dev,
484 struct copybit_image_t const *dst,
485 struct copybit_image_t const *src,
486 struct copybit_region_t const *region)
487{
488 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
489 struct copybit_rect_t sr = { 0, 0, src->w, src->h };
490 return stretch_copybit(dev, dst, src, &dr, &sr, region);
491}
492
493/*****************************************************************************/
494
495/** Close the copybit device */
496static int close_copybit(struct hw_device_t *dev)
497{
498 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
499 if (ctx) {
500 close(ctx->mFD);
501 free(ctx);
502 }
503 return 0;
504}
505
506/** Open a new instance of a copybit device using name */
507static int open_copybit(const struct hw_module_t* module, const char* name,
508 struct hw_device_t** device)
509{
510 int status = -EINVAL;
511 copybit_context_t *ctx;
512 ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
513 memset(ctx, 0, sizeof(*ctx));
514
515 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
516 ctx->device.common.version = 1;
517 ctx->device.common.module = const_cast<hw_module_t*>(module);
518 ctx->device.common.close = close_copybit;
519 ctx->device.set_parameter = set_parameter_copybit;
520 ctx->device.get = get;
521 ctx->device.blit = blit_copybit;
522 ctx->device.stretch = stretch_copybit;
523 ctx->mAlpha = MDP_ALPHA_NOP;
524 ctx->mFlags = 0;
525 ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
526 if (ctx->mFD < 0) {
527 status = errno;
528 ALOGE("Error opening frame buffer errno=%d (%s)",
529 status, strerror(status));
530 status = -status;
531 } else {
532 struct fb_fix_screeninfo finfo;
533 if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
534 if (strncmp(finfo.id, "msmfb", 5) == 0) {
535 /* Success */
536 status = 0;
537 } else {
538 ALOGE("Error not msm frame buffer");
539 status = -EINVAL;
540 }
541 } else {
542 ALOGE("Error executing ioctl for screen info");
543 status = -errno;
544 }
545 }
546
547 if (status == 0) {
548 *device = &ctx->device.common;
549 } else {
550 close_copybit(&ctx->device.common);
551 }
552 return status;
553}