blob: 90838b43531a4f00e669671aebf79355ad5d45cd [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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#define LOG_TAG "SurfaceFlinger"
18
19#include <stdint.h>
20#include <string.h>
21#include <unistd.h>
22#include <fcntl.h>
23
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <sys/mman.h>
27
28#include <cutils/log.h>
29
30#include <utils/Errors.h>
31
32#if HAVE_ANDROID_OS
33#include <linux/fb.h>
34#include <linux/msm_mdp.h>
35#endif
36
37#include <ui/BlitHardware.h>
38
39/******************************************************************************/
40
41namespace android {
42class CopybitMSM7K : public copybit_t {
43public:
44 CopybitMSM7K();
45 ~CopybitMSM7K();
46
47 status_t getStatus() const {
48 if (mFD<0) return mFD;
49 return NO_ERROR;
50 }
51
52 status_t setParameter(int name, int value);
53
54 status_t get(int name);
55
56 status_t blit(
57 const copybit_image_t& dst,
58 const copybit_image_t& src,
59 copybit_region_t const* region);
60
61 status_t stretch(
62 const copybit_image_t& dst,
63 const copybit_image_t& src,
64 const copybit_rect_t& dst_rect,
65 const copybit_rect_t& src_rect,
66 copybit_region_t const* region);
67
68#if HAVE_ANDROID_OS
69private:
70 static int copybit_set_parameter(copybit_t* handle, int name, int value);
71 static int copybit_blit( copybit_t* handle,
72 copybit_image_t const* dst, copybit_image_t const* src,
73 copybit_region_t const* region);
74 static int copybit_stretch(copybit_t* handle,
75 copybit_image_t const* dst, copybit_image_t const* src,
76 copybit_rect_t const* dst_rect, copybit_rect_t const* src_rect,
77 copybit_region_t const* region);
78 static int copybit_get(copybit_t* handle, int name);
79
80 int getFormat(int format);
81 void setImage(mdp_img* img, const copybit_image_t& rhs);
82 void setRects(mdp_blit_req* req, const copybit_rect_t& dst,
83 const copybit_rect_t& src, const copybit_rect_t& scissor);
84 void setInfos(mdp_blit_req* req);
85 static void intersect(copybit_rect_t* out,
86 const copybit_rect_t& lhs, const copybit_rect_t& rhs);
87 status_t msm_copybit(void const* list);
88#endif
89 int mFD;
90 uint8_t mAlpha;
91 uint8_t mFlags;
92};
93}; // namespace android
94
95using namespace android;
96
97/******************************************************************************/
98
99struct copybit_t* copybit_init()
100{
101 CopybitMSM7K* engine = new CopybitMSM7K();
102 if (engine->getStatus() != NO_ERROR) {
103 delete engine;
104 engine = 0;
105 }
106 return (struct copybit_t*)engine;
107
108}
109
110int copybit_term(copybit_t* handle)
111{
112 delete static_cast<CopybitMSM7K*>(handle);
113 return NO_ERROR;
114}
115
116namespace android {
117/******************************************************************************/
118
119static inline
120int min(int a, int b) {
121 return (a<b) ? a : b;
122}
123
124static inline
125int max(int a, int b) {
126 return (a>b) ? a : b;
127}
128
129static inline
130void MULDIV(uint32_t& a, uint32_t& b, int mul, int div)
131{
132 if (mul != div) {
133 a = (mul * a) / div;
134 b = (mul * b) / div;
135 }
136}
137
138//-----------------------------------------------------------------------------
139
140#if HAVE_ANDROID_OS
141
142int CopybitMSM7K::copybit_set_parameter(copybit_t* handle, int name, int value)
143{
144 return static_cast<CopybitMSM7K*>(handle)->setParameter(name, value);
145}
146
147int CopybitMSM7K::copybit_get(copybit_t* handle, int name)
148{
149 return static_cast<CopybitMSM7K*>(handle)->get(name);
150}
151
152int CopybitMSM7K::copybit_blit(
153 copybit_t* handle,
154 copybit_image_t const* dst,
155 copybit_image_t const* src,
156 struct copybit_region_t const* region)
157{
158 return static_cast<CopybitMSM7K*>(handle)->blit(*dst, *src, region);
159}
160
161int CopybitMSM7K::copybit_stretch(
162 copybit_t* handle,
163 copybit_image_t const* dst,
164 copybit_image_t const* src,
165 copybit_rect_t const* dst_rect,
166 copybit_rect_t const* src_rect,
167 struct copybit_region_t const* region)
168{
169 return static_cast<CopybitMSM7K*>(handle)->stretch(
170 *dst, *src, *dst_rect, *src_rect, region);
171}
172
173//-----------------------------------------------------------------------------
174
175CopybitMSM7K::CopybitMSM7K()
176 : mFD(-1), mAlpha(MDP_ALPHA_NOP), mFlags(0)
177{
178 int fd = open("/dev/graphics/fb0", O_RDWR, 0);
179 if (fd > 0) {
180 struct fb_fix_screeninfo finfo;
181 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == 0) {
182 if (!strcmp(finfo.id, "msmfb")) {
183 mFD = fd;
184 copybit_t::set_parameter = copybit_set_parameter;
185 copybit_t::get = copybit_get;
186 copybit_t::blit = copybit_blit;
187 copybit_t::stretch = copybit_stretch;
188 }
189 }
190 }
191 if (fd<0 || mFD<0) {
192 if (fd>0) { close(fd); }
193 mFD = -errno;
194 }
195}
196
197CopybitMSM7K::~CopybitMSM7K()
198{
199 if (mFD > 0){
200 close(mFD);
201 }
202}
203
204status_t CopybitMSM7K::setParameter(int name, int value)
205{
206 switch(name) {
207 case COPYBIT_ROTATION_DEG:
208 switch (value) {
209 case 0:
210 mFlags &= ~0x7;
211 break;
212 case 90:
213 mFlags &= ~0x7;
214 mFlags |= MDP_ROT_90;
215 break;
216 case 180:
217 mFlags &= ~0x7;
218 mFlags |= MDP_ROT_180;
219 break;
220 case 270:
221 mFlags &= ~0x7;
222 mFlags |= MDP_ROT_270;
223 break;
224 default:
225 return BAD_VALUE;
226 }
227 break;
228 case COPYBIT_PLANE_ALPHA:
229 if (value < 0) value = 0;
230 if (value >= 256) value = 255;
231 mAlpha = value;
232 break;
233 case COPYBIT_DITHER:
234 if (value == COPYBIT_ENABLE) {
235 mFlags |= MDP_DITHER;
236 } else if (value == COPYBIT_DISABLE) {
237 mFlags &= ~MDP_DITHER;
238 }
239 break;
240 case COPYBIT_TRANSFORM:
241 mFlags &= ~0x7;
242 mFlags |= value & 0x7;
243 break;
244 default:
245 return BAD_VALUE;
246 }
247 return NO_ERROR;
248}
249
250status_t CopybitMSM7K::get(int name)
251{
252 switch(name) {
253 case COPYBIT_MINIFICATION_LIMIT:
254 return 4;
255 case COPYBIT_MAGNIFICATION_LIMIT:
256 return 4;
257 case COPYBIT_SCALING_FRAC_BITS:
258 return 32;
259 case COPYBIT_ROTATION_STEP_DEG:
260 return 90;
261 }
262 return BAD_VALUE;
263}
264
265status_t CopybitMSM7K::blit(
266 const copybit_image_t& dst,
267 const copybit_image_t& src,
268 copybit_region_t const* region)
269{
270
271 copybit_rect_t dr = { 0, 0, dst.w, dst.h };
272 copybit_rect_t sr = { 0, 0, src.w, src.h };
273 return CopybitMSM7K::stretch(dst, src, dr, sr, region);
274}
275
276status_t CopybitMSM7K::stretch(
277 const copybit_image_t& dst,
278 const copybit_image_t& src,
279 const copybit_rect_t& dst_rect,
280 const copybit_rect_t& src_rect,
281 copybit_region_t const* region)
282{
283 struct {
284 uint32_t count;
285 struct mdp_blit_req req[12];
286 } list;
287
288 if (mAlpha<255) {
289 switch (src.format) {
290 // we dont' support plane alpha with RGBA formats
291 case COPYBIT_RGBA_8888:
292 case COPYBIT_RGBA_5551:
293 case COPYBIT_RGBA_4444:
294 return INVALID_OPERATION;
295 }
296 }
297
298 const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
299 const copybit_rect_t bounds = { 0, 0, dst.w, dst.h };
300 copybit_rect_t clip;
301 list.count = 0;
302 int err = 0;
303 while (!err && region->next(region, &clip)) {
304 intersect(&clip, bounds, clip);
305 setInfos(&list.req[list.count]);
306 setImage(&list.req[list.count].dst, dst);
307 setImage(&list.req[list.count].src, src);
308 setRects(&list.req[list.count], dst_rect, src_rect, clip);
309 if (++list.count == maxCount) {
310 err = msm_copybit(&list);
311 list.count = 0;
312 }
313 }
314 if (!err && list.count) {
315 err = msm_copybit(&list);
316 }
317 return err;
318}
319
320status_t CopybitMSM7K::msm_copybit(void const* list)
321{
322 int err = ioctl(mFD, MSMFB_BLIT, static_cast<mdp_blit_req_list const*>(list));
323 LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
324 if (err == 0)
325 return NO_ERROR;
326 return -errno;
327}
328
329int CopybitMSM7K::getFormat(int format)
330{
331 switch (format) {
332 case COPYBIT_RGBA_8888: return MDP_RGBA_8888;
333 case COPYBIT_RGB_565: return MDP_RGB_565;
334 case COPYBIT_YCbCr_422_SP: return MDP_Y_CBCR_H2V1;
335 case COPYBIT_YCbCr_420_SP: return MDP_Y_CBCR_H2V2;
336 }
337 return -1;
338}
339
340void CopybitMSM7K::setInfos(mdp_blit_req* req)
341{
342 req->alpha = mAlpha;
343 req->transp_mask = MDP_TRANSP_NOP;
344 req->flags = mFlags;
345}
346
347void CopybitMSM7K::setImage(mdp_img* img, const copybit_image_t& rhs)
348{
349 img->width = rhs.w;
350 img->height = rhs.h;
351 img->format = getFormat(rhs.format);
352 img->offset = rhs.offset;
353 img->memory_id = rhs.fd;
354}
355
356void CopybitMSM7K::setRects(mdp_blit_req* e,
357 const copybit_rect_t& dst, const copybit_rect_t& src,
358 const copybit_rect_t& scissor)
359{
360 copybit_rect_t clip;
361 intersect(&clip, scissor, dst);
362
363 e->dst_rect.x = clip.l;
364 e->dst_rect.y = clip.t;
365 e->dst_rect.w = clip.r - clip.l;
366 e->dst_rect.h = clip.b - clip.t;
367
368 uint32_t W, H;
369 if (mFlags & COPYBIT_TRANSFORM_ROT_90) {
370 e->src_rect.x = (clip.t - dst.t) + src.t;
371 e->src_rect.y = (dst.r - clip.r) + src.l;
372 e->src_rect.w = (clip.b - clip.t);
373 e->src_rect.h = (clip.r - clip.l);
374 W = dst.b - dst.t;
375 H = dst.r - dst.l;
376 } else {
377 e->src_rect.x = (clip.l - dst.l) + src.l;
378 e->src_rect.y = (clip.t - dst.t) + src.t;
379 e->src_rect.w = (clip.r - clip.l);
380 e->src_rect.h = (clip.b - clip.t);
381 W = dst.r - dst.l;
382 H = dst.b - dst.t;
383 }
384 MULDIV(e->src_rect.x, e->src_rect.w, src.r - src.l, W);
385 MULDIV(e->src_rect.y, e->src_rect.h, src.b - src.t, H);
386 if (mFlags & COPYBIT_TRANSFORM_FLIP_V) {
387 e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h);
388 }
389 if (mFlags & COPYBIT_TRANSFORM_FLIP_H) {
390 e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w);
391 }
392}
393
394void CopybitMSM7K::intersect(copybit_rect_t* out,
395 const copybit_rect_t& lhs, const copybit_rect_t& rhs)
396{
397 out->l = max(lhs.l, rhs.l);
398 out->t = max(lhs.t, rhs.t);
399 out->r = min(lhs.r, rhs.r);
400 out->b = min(lhs.b, rhs.b);
401}
402
403/******************************************************************************/
404#else // HAVE_ANDROID_OS
405
406CopybitMSM7K::CopybitMSM7K()
407 : mFD(-1)
408{
409}
410
411CopybitMSM7K::~CopybitMSM7K()
412{
413}
414
415status_t CopybitMSM7K::setParameter(int name, int value)
416{
417 return NO_INIT;
418}
419
420status_t CopybitMSM7K::get(int name)
421{
422 return BAD_VALUE;
423}
424
425status_t CopybitMSM7K::blit(
426 const copybit_image_t& dst,
427 const copybit_image_t& src,
428 copybit_region_t const* region)
429{
430 return NO_INIT;
431}
432
433status_t CopybitMSM7K::stretch(
434 const copybit_image_t& dst,
435 const copybit_image_t& src,
436 const copybit_rect_t& dst_rect,
437 const copybit_rect_t& src_rect,
438 copybit_region_t const* region)
439{
440 return NO_INIT;
441}
442
443#endif // HAVE_ANDROID_OS
444
445/******************************************************************************/
446}; // namespace android