• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /******************************************************************************/
38 
39 /** State information for each device instance */
40 struct copybit_context_t {
41     struct copybit_device_t device;
42     int     mFD;
43     uint8_t mAlpha;
44     uint8_t mFlags;
45 };
46 
47 /**
48  * Common hardware methods
49  */
50 
51 static int open_copybit(const struct hw_module_t* module, const char* name,
52         struct hw_device_t** device);
53 
54 static struct hw_module_methods_t copybit_module_methods = {
55     .open =  open_copybit
56 };
57 
58 /*
59  * The COPYBIT Module
60  */
61 const struct copybit_module_t HAL_MODULE_INFO_SYM = {
62     .common = {
63         .tag = HARDWARE_MODULE_TAG,
64         .version_major = 1,
65         .version_minor = 0,
66         .id = COPYBIT_HARDWARE_MODULE_ID,
67         .name = "QCT MSM7K COPYBIT Module",
68         .author = "Google, Inc.",
69         .methods = &copybit_module_methods,
70     }
71 };
72 
73 /******************************************************************************/
74 
75 /** min of int a, b */
min(int a,int b)76 static inline int min(int a, int b) {
77     return (a<b) ? a : b;
78 }
79 
80 /** max of int a, b */
max(int a,int b)81 static inline int max(int a, int b) {
82     return (a>b) ? a : b;
83 }
84 
85 /** scale each parameter by mul/div. Assume div isn't 0 */
MULDIV(uint32_t * a,uint32_t * b,int mul,int div)86 static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
87     if (mul != div) {
88         *a = (mul * *a) / div;
89         *b = (mul * *b) / div;
90     }
91 }
92 
93 /** Determine the intersection of lhs & rhs store in out */
intersect(struct copybit_rect_t * out,const struct copybit_rect_t * lhs,const struct copybit_rect_t * rhs)94 static void intersect(struct copybit_rect_t *out,
95                       const struct copybit_rect_t *lhs,
96                       const struct copybit_rect_t *rhs) {
97     out->l = max(lhs->l, rhs->l);
98     out->t = max(lhs->t, rhs->t);
99     out->r = min(lhs->r, rhs->r);
100     out->b = min(lhs->b, rhs->b);
101 }
102 
103 /** convert COPYBIT_FORMAT to MDP format */
get_format(int format)104 static int get_format(int format) {
105     switch (format) {
106     case COPYBIT_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
107     case COPYBIT_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
108     case COPYBIT_FORMAT_RGB_565:       return MDP_RGB_565;
109     case COPYBIT_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
110     case COPYBIT_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
111     }
112     return -1;
113 }
114 
115 /** convert from copybit image to mdp image structure */
set_image(struct mdp_img * img,const struct copybit_image_t * rhs)116 static void set_image(struct mdp_img *img,
117                       const struct copybit_image_t *rhs) {
118     img->width      = rhs->w;
119     img->height     = rhs->h;
120     img->format     = get_format(rhs->format);
121     img->offset     = rhs->offset;
122     img->memory_id  = rhs->fd;
123 }
124 
125 /** setup rectangles */
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)126 static void set_rects(struct copybit_context_t *dev,
127                       struct mdp_blit_req *e,
128                       const struct copybit_rect_t *dst,
129                       const struct copybit_rect_t *src,
130                       const struct copybit_rect_t *scissor) {
131     struct copybit_rect_t clip;
132     intersect(&clip, scissor, dst);
133 
134     e->dst_rect.x  = clip.l;
135     e->dst_rect.y  = clip.t;
136     e->dst_rect.w  = clip.r - clip.l;
137     e->dst_rect.h  = clip.b - clip.t;
138 
139     uint32_t W, H;
140     if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
141         e->src_rect.x = (clip.t - dst->t) + src->t;
142         e->src_rect.y = (dst->r - clip.r) + src->l;
143         e->src_rect.w = (clip.b - clip.t);
144         e->src_rect.h = (clip.r - clip.l);
145         W = dst->b - dst->t;
146         H = dst->r - dst->l;
147     } else {
148         e->src_rect.x  = (clip.l - dst->l) + src->l;
149         e->src_rect.y  = (clip.t - dst->t) + src->t;
150         e->src_rect.w  = (clip.r - clip.l);
151         e->src_rect.h  = (clip.b - clip.t);
152         W = dst->r - dst->l;
153         H = dst->b - dst->t;
154     }
155     MULDIV(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W);
156     MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H);
157     if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
158         e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h);
159     }
160     if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
161         e->src_rect.x = e->src.width  - (e->src_rect.x + e->src_rect.w);
162     }
163 }
164 
165 /** setup mdp request */
set_infos(struct copybit_context_t * dev,struct mdp_blit_req * req)166 static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) {
167     req->alpha = dev->mAlpha;
168     req->transp_mask = MDP_TRANSP_NOP;
169     req->flags = dev->mFlags;
170 }
171 
172 /** copy the bits */
msm_copybit(struct copybit_context_t * dev,void const * list)173 static int msm_copybit(struct copybit_context_t *dev, void const *list)
174 {
175     int err = ioctl(dev->mFD, MSMFB_BLIT,
176                     (struct mdp_blit_req_list const*)list);
177     LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
178     if (err == 0)
179         return 0;
180     else
181         return -errno;
182 }
183 
184 /*****************************************************************************/
185 
186 /** Set a parameter to value */
set_parameter_copybit(struct copybit_device_t * dev,int name,int value)187 static int set_parameter_copybit(
188         struct copybit_device_t *dev,
189         int name,
190         int value)
191 {
192     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
193     int status = 0;
194     if (ctx) {
195         switch(name) {
196         case COPYBIT_ROTATION_DEG:
197             switch (value) {
198             case 0:
199                 ctx->mFlags &= ~0x7;
200                 break;
201             case 90:
202                 ctx->mFlags &= ~0x7;
203                 ctx->mFlags |= MDP_ROT_90;
204                 break;
205             case 180:
206                 ctx->mFlags &= ~0x7;
207                 ctx->mFlags |= MDP_ROT_180;
208                 break;
209             case 270:
210                 ctx->mFlags &= ~0x7;
211                 ctx->mFlags |= MDP_ROT_270;
212                 break;
213             default:
214                 LOGE("Invalid value for COPYBIT_ROTATION_DEG");
215                 status = -EINVAL;
216                 break;
217             }
218             break;
219         case COPYBIT_PLANE_ALPHA:
220             if (value < 0)      value = 0;
221             if (value >= 256)   value = 255;
222             ctx->mAlpha = value;
223             break;
224         case COPYBIT_DITHER:
225             if (value == COPYBIT_ENABLE) {
226                 ctx->mFlags |= MDP_DITHER;
227             } else if (value == COPYBIT_DISABLE) {
228                 ctx->mFlags &= ~MDP_DITHER;
229             }
230             break;
231         case COPYBIT_BLUR:
232             if (value == COPYBIT_ENABLE) {
233                 ctx->mFlags |= MDP_BLUR;
234             } else if (value == COPYBIT_DISABLE) {
235                 ctx->mFlags &= ~MDP_BLUR;
236             }
237             break;
238         case COPYBIT_TRANSFORM:
239             ctx->mFlags &= ~0x7;
240             ctx->mFlags |= value & 0x7;
241             break;
242         default:
243             status = -EINVAL;
244             break;
245         }
246     } else {
247         status = -EINVAL;
248     }
249     return status;
250 }
251 
252 /** Get a static info value */
get(struct copybit_device_t * dev,int name)253 static int get(struct copybit_device_t *dev, int name)
254 {
255     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
256     int value;
257     if (ctx) {
258         switch(name) {
259         case COPYBIT_MINIFICATION_LIMIT:
260             value = 4;
261             break;
262         case COPYBIT_MAGNIFICATION_LIMIT:
263             value = 4;
264             break;
265         case COPYBIT_SCALING_FRAC_BITS:
266             value = 32;
267             break;
268         case COPYBIT_ROTATION_STEP_DEG:
269             value = 90;
270             break;
271         default:
272             value = -EINVAL;
273         }
274     } else {
275         value = -EINVAL;
276     }
277     return value;
278 }
279 
280 /** do a stretch blit type operation */
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)281 static int stretch_copybit(
282         struct copybit_device_t *dev,
283         struct copybit_image_t const *dst,
284         struct copybit_image_t const *src,
285         struct copybit_rect_t const *dst_rect,
286         struct copybit_rect_t const *src_rect,
287         struct copybit_region_t const *region)
288 {
289     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
290     int status = 0;
291     if (ctx) {
292         struct {
293             uint32_t count;
294             struct mdp_blit_req req[12];
295         } list;
296 
297         if (ctx->mAlpha < 255) {
298             switch (src->format) {
299                 // we don't support plane alpha with RGBA formats
300                 case COPYBIT_FORMAT_RGBA_8888:
301                 case COPYBIT_FORMAT_BGRA_8888:
302                 case COPYBIT_FORMAT_RGBA_5551:
303                 case COPYBIT_FORMAT_RGBA_4444:
304                     return -EINVAL;
305             }
306         }
307 
308         const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
309         const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
310         struct copybit_rect_t clip;
311         list.count = 0;
312         status = 0;
313         while ((status == 0) && region->next(region, &clip)) {
314             intersect(&clip, &bounds, &clip);
315             set_infos(ctx, &list.req[list.count]);
316             set_image(&list.req[list.count].dst, dst);
317             set_image(&list.req[list.count].src, src);
318             set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip);
319             if (++list.count == maxCount) {
320                 status = msm_copybit(ctx, &list);
321                 list.count = 0;
322             }
323         }
324         if ((status == 0) && list.count) {
325             status = msm_copybit(ctx, &list);
326         }
327     } else {
328         status = -EINVAL;
329     }
330     return status;
331 }
332 
333 /** Perform a blit type operation */
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)334 static int blit_copybit(
335         struct copybit_device_t *dev,
336         struct copybit_image_t const *dst,
337         struct copybit_image_t const *src,
338         struct copybit_region_t const *region)
339 {
340     struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
341     struct copybit_rect_t sr = { 0, 0, src->w, src->h };
342     return stretch_copybit(dev, dst, src, &dr, &sr, region);
343 }
344 
345 /*****************************************************************************/
346 
347 /** Close the copybit device */
close_copybit(struct hw_device_t * dev)348 static int close_copybit(struct hw_device_t *dev)
349 {
350     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
351     if (ctx) {
352         close(ctx->mFD);
353         free(ctx);
354     }
355     return 0;
356 }
357 
358 /** Open a new instance of a copybit device using name */
open_copybit(const struct hw_module_t * module,const char * name,struct hw_device_t ** device)359 static int open_copybit(const struct hw_module_t* module, const char* name,
360         struct hw_device_t** device)
361 {
362     int status = -EINVAL;
363     struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t));
364     memset(ctx, 0, sizeof(*ctx));
365 
366     ctx->device.common.tag = HARDWARE_DEVICE_TAG;
367     ctx->device.common.version = 0;
368     ctx->device.common.module = module;
369     ctx->device.common.close = close_copybit;
370     ctx->device.set_parameter = set_parameter_copybit;
371     ctx->device.get = get;
372     ctx->device.blit = blit_copybit;
373     ctx->device.stretch = stretch_copybit;
374     ctx->mAlpha = MDP_ALPHA_NOP;
375     ctx->mFlags = 0;
376     ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
377 
378     if (ctx->mFD < 0) {
379         status = errno;
380         LOGE("Error opening frame buffer errno=%d (%s)",
381              status, strerror(status));
382         status = -status;
383     } else {
384         struct fb_fix_screeninfo finfo;
385         if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
386             if (strcmp(finfo.id, "msmfb") == 0) {
387                 /* Success */
388                 status = 0;
389             } else {
390                 LOGE("Error not msm frame buffer");
391                 status = -EINVAL;
392             }
393         } else {
394             LOGE("Error executing ioctl for screen info");
395             status = -errno;
396         }
397     }
398 
399     if (status == 0) {
400         *device = &ctx->device.common;
401     } else {
402         close_copybit(&ctx->device.common);
403     }
404     return status;
405 }
406