Commit | Line | Data |
---|---|---|
5763fb39 T |
1 | /* |
2 | ** | |
3 | ** Copyright 2009 Samsung Electronics Co, Ltd. | |
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 | ||
20 | #define LOG_NDEBUG 0 | |
21 | #define LOG_TAG "SKIA" | |
22 | #include <utils/Log.h> | |
23 | ||
24 | #include "FimgApi.h" | |
25 | ||
26 | pthread_mutex_t s_g2d_lock = PTHREAD_MUTEX_INITIALIZER; | |
27 | ||
28 | struct blitinfo_table optbl[] = { | |
29 | { (int)BLIT_OP_SOLID_FILL, "FILL" }, | |
30 | { (int)BLIT_OP_CLR, "CLR" }, | |
31 | { (int)BLIT_OP_SRC, "SRC" }, | |
32 | { (int)BLIT_OP_DST, "DST" }, | |
33 | { (int)BLIT_OP_SRC_OVER, "SRC_OVER" }, | |
34 | { (int)BLIT_OP_DST_OVER, "DST_OVER" }, | |
35 | { (int)BLIT_OP_SRC_IN, "SRC_IN" }, | |
36 | { (int)BLIT_OP_DST_IN, "DST_IN" }, | |
37 | { (int)BLIT_OP_SRC_OUT, "SRC_OUT" }, | |
38 | { (int)BLIT_OP_DST_OUT, "DST_OUT" }, | |
39 | { (int)BLIT_OP_SRC_ATOP, "SRC_ATOP" }, | |
40 | { (int)BLIT_OP_DST_ATOP, "DST_ATOP" }, | |
41 | { (int)BLIT_OP_XOR, "XOR" }, | |
42 | { (int)BLIT_OP_ADD, "ADD" }, | |
43 | { (int)BLIT_OP_MULTIPLY, "MULTIPLY" }, | |
44 | { (int)BLIT_OP_SCREEN, "SCREEN" }, | |
45 | { (int)BLIT_OP_DARKEN, "DARKEN" }, | |
46 | { (int)BLIT_OP_LIGHTEN, "LIGHTEN" }, | |
47 | { (int)BLIT_OP_DISJ_SRC_OVER, "DISJ_SRC_OVER" }, | |
48 | { (int)BLIT_OP_DISJ_DST_OVER, "DISJ_DST_OVER" }, | |
49 | { (int)BLIT_OP_DISJ_SRC_IN, "DISJ_SRC_IN" }, | |
50 | { (int)BLIT_OP_DISJ_DST_IN, "DISJ_DST_IN" }, | |
51 | { (int)BLIT_OP_DISJ_SRC_OUT, "DISJ_SRC_OUT" }, | |
52 | { (int)BLIT_OP_DISJ_DST_OUT, "DISJ_DST_OUT" }, | |
53 | { (int)BLIT_OP_DISJ_SRC_ATOP, "DISJ_SRC_ATOP" }, | |
54 | { (int)BLIT_OP_DISJ_DST_ATOP, "DISJ_DST_ATOP" }, | |
55 | { (int)BLIT_OP_DISJ_XOR, "DISJ_XOR" }, | |
56 | { (int)BLIT_OP_CONJ_SRC_OVER, "CONJ_SRC_OVER" }, | |
57 | { (int)BLIT_OP_CONJ_DST_OVER, "CONJ_DST_OVER" }, | |
58 | { (int)BLIT_OP_CONJ_SRC_IN, "CONJ_SRC_IN" }, | |
59 | { (int)BLIT_OP_CONJ_DST_IN, "CONJ_DST_IN" }, | |
60 | { (int)BLIT_OP_CONJ_SRC_OUT, "CONJ_SRC_OUT" }, | |
61 | { (int)BLIT_OP_CONJ_DST_OUT, "CONJ_DST_OUT" }, | |
62 | { (int)BLIT_OP_CONJ_SRC_ATOP, "CONJ_SRC_ATOP" }, | |
63 | { (int)BLIT_OP_CONJ_DST_ATOP, "CONJ_DST_ATOP" }, | |
64 | { (int)BLIT_OP_CONJ_XOR, "CONJ_XOR" }, | |
65 | { (int)BLIT_OP_USER_COEFF, "USER_COEFF" }, | |
66 | { (int)BLIT_OP_END, "" }, | |
67 | }; | |
68 | ||
69 | struct blitinfo_table repeat_tbl[] = { | |
70 | { (int)NO_REPEAT, "NON" }, | |
71 | { (int)REPEAT_NORMAL, "DEFAULT" }, | |
72 | { (int)REPEAT_PAD, "PAD" }, | |
73 | { (int)REPEAT_REFLECT, "REFLECT, MIRROR" }, | |
74 | { (int)REPEAT_CLAMP, "CLAMP" }, | |
75 | }; | |
76 | ||
77 | #ifndef REAL_DEBUG | |
78 | void VOID_FUNC(const char *format, ...) | |
79 | {} | |
80 | #endif | |
81 | ||
82 | FimgApi::FimgApi() | |
83 | { | |
84 | m_flagCreate = false; | |
85 | } | |
86 | ||
87 | FimgApi::~FimgApi() | |
88 | { | |
89 | if (m_flagCreate == true) | |
90 | PRINT("%s::this is not Destroyed fail\n", __func__); | |
91 | } | |
92 | ||
93 | bool FimgApi::Create(void) | |
94 | { | |
95 | bool ret = false; | |
96 | ||
97 | if (t_Lock() == false) { | |
98 | PRINT("%s::t_Lock() fail\n", __func__); | |
99 | goto CREATE_DONE; | |
100 | } | |
101 | ||
102 | if (m_flagCreate == true) { | |
103 | PRINT("%s::Already Created fail\n", __func__); | |
104 | goto CREATE_DONE; | |
105 | } | |
106 | ||
107 | if (t_Create() == false) { | |
108 | PRINT("%s::t_Create() fail\n", __func__); | |
109 | goto CREATE_DONE; | |
110 | } | |
111 | ||
112 | m_flagCreate = true; | |
113 | ||
114 | ret = true; | |
115 | ||
116 | CREATE_DONE : | |
117 | ||
118 | t_UnLock(); | |
119 | ||
120 | return ret; | |
121 | } | |
122 | ||
123 | bool FimgApi::Destroy(void) | |
124 | { | |
125 | bool ret = false; | |
126 | ||
127 | if (t_Lock() == false) { | |
128 | PRINT("%s::t_Lock() fail\n", __func__); | |
129 | goto DESTROY_DONE; | |
130 | } | |
131 | ||
132 | if (m_flagCreate == false) { | |
133 | PRINT("%s::Already Destroyed fail\n", __func__); | |
134 | goto DESTROY_DONE; | |
135 | } | |
136 | ||
137 | if (t_Destroy() == false) { | |
138 | PRINT("%s::t_Destroy() fail\n", __func__); | |
139 | goto DESTROY_DONE; | |
140 | } | |
141 | ||
142 | m_flagCreate = false; | |
143 | ||
144 | ret = true; | |
145 | ||
146 | DESTROY_DONE : | |
147 | ||
148 | t_UnLock(); | |
149 | ||
150 | return ret; | |
151 | } | |
152 | ||
153 | bool FimgApi::Stretch(struct fimg2d_blit *cmd) | |
154 | { | |
155 | bool ret = false; | |
156 | ||
157 | if (t_Lock() == false) { | |
158 | PRINT("%s::t_Lock() fail\n", __func__); | |
159 | goto STRETCH_DONE; | |
160 | } | |
161 | ||
162 | if (m_flagCreate == false) { | |
163 | PRINT("%s::This is not Created fail\n", __func__); | |
164 | goto STRETCH_DONE; | |
165 | } | |
166 | ||
167 | if (t_Stretch(cmd) == false) { | |
168 | goto STRETCH_DONE; | |
169 | } | |
170 | ||
171 | ret = true; | |
172 | ||
173 | STRETCH_DONE : | |
174 | ||
175 | t_UnLock(); | |
176 | ||
177 | return ret; | |
178 | } | |
179 | ||
180 | bool FimgApi::Sync(void) | |
181 | { | |
182 | bool ret = false; | |
183 | ||
184 | if (m_flagCreate == false) { | |
185 | PRINT("%s::This is not Created fail\n", __func__); | |
186 | goto SYNC_DONE; | |
187 | } | |
188 | ||
189 | if (t_Sync() == false) | |
190 | goto SYNC_DONE; | |
191 | ||
192 | ret = true; | |
193 | ||
194 | SYNC_DONE : | |
195 | ||
196 | return ret; | |
197 | } | |
198 | ||
199 | bool FimgApi::t_Create(void) | |
200 | { | |
201 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
202 | return false; | |
203 | } | |
204 | ||
205 | bool FimgApi::t_Destroy(void) | |
206 | { | |
207 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
208 | return false; | |
209 | } | |
210 | ||
211 | bool FimgApi::t_Stretch(struct fimg2d_blit *cmd) | |
212 | { | |
213 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
214 | return false; | |
215 | } | |
216 | ||
217 | bool FimgApi::t_Sync(void) | |
218 | { | |
219 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
220 | return false; | |
221 | } | |
222 | ||
223 | bool FimgApi::t_Lock(void) | |
224 | { | |
225 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
226 | return false; | |
227 | } | |
228 | ||
229 | bool FimgApi::t_UnLock(void) | |
230 | { | |
231 | PRINT("%s::This is empty virtual function fail\n", __func__); | |
232 | return false; | |
233 | } | |
234 | ||
235 | //---------------------------------------------------------------------------// | |
236 | // extern function | |
237 | //---------------------------------------------------------------------------// | |
238 | extern "C" int stretchFimgApi(struct fimg2d_blit *cmd) | |
239 | { | |
240 | pthread_mutex_lock(&s_g2d_lock); | |
241 | ||
242 | FimgApi * fimgApi = createFimgApi(); | |
243 | ||
244 | if (fimgApi == NULL) { | |
245 | PRINT("%s::createFimgApi() fail\n", __func__); | |
246 | pthread_mutex_unlock(&s_g2d_lock); | |
247 | return -1; | |
248 | } | |
249 | ||
250 | if (fimgApi->Stretch(cmd) == false) { | |
251 | if (fimgApi != NULL) | |
252 | destroyFimgApi(fimgApi); | |
253 | ||
254 | pthread_mutex_unlock(&s_g2d_lock); | |
255 | return -1; | |
256 | } | |
257 | ||
258 | if (fimgApi != NULL) | |
259 | destroyFimgApi(fimgApi); | |
260 | ||
261 | pthread_mutex_unlock(&s_g2d_lock); | |
262 | return 0; | |
263 | } | |
264 | ||
265 | extern "C" int stretchFimgApi_fast(struct fimg2d_blit *cmd, unsigned long tmpbuf_addr, int tmpbuf_size) | |
266 | { | |
267 | if (tmpbuf_addr == 0 || tmpbuf_size <= 0) | |
268 | return stretchFimgApi(cmd); | |
269 | ||
270 | /* scaling & rotation only */ | |
271 | if (cmd->param.rotate == ORIGIN || cmd->param.scaling.mode == NO_SCALING) | |
272 | return stretchFimgApi(cmd); | |
273 | ||
274 | /* src & dst only */ | |
275 | if (cmd->src == NULL || cmd->msk != NULL) | |
276 | return stretchFimgApi(cmd); | |
277 | ||
278 | /* a(x)rgb8888 src only */ | |
279 | if (cmd->src->fmt >= CF_RGB_565) | |
280 | return stretchFimgApi(cmd); | |
281 | ||
282 | FimgApi * fimgApi = createFimgApi(); | |
283 | ||
284 | if (fimgApi == NULL) { | |
285 | PRINT("%s::createFimgApi() fail\n", __func__); | |
286 | return -1; | |
287 | } | |
288 | ||
289 | bool is_scaledown, sr_w, sr_h; | |
290 | struct fimg2d_image tmpbuf; | |
291 | struct fimg2d_blit cmd1st, cmd2nd; | |
292 | struct fimg2d_param *p; | |
293 | ||
294 | /* check is_scaledown */ | |
295 | p = &cmd->param; | |
296 | sr_w = p->scaling.src_w - p->scaling.dst_w; | |
297 | sr_h = p->scaling.src_h - p->scaling.dst_h; | |
298 | is_scaledown = (sr_w + sr_h > 0) ? true : false; | |
299 | ||
300 | if (is_scaledown) { | |
301 | /* set temp buffer */ | |
302 | tmpbuf.width = cmd->dst->rect.y2 - cmd->dst->rect.y1; | |
303 | tmpbuf.height = cmd->dst->rect.x2 - cmd->dst->rect.x1; | |
304 | tmpbuf.stride = tmpbuf.width * 4; | |
305 | tmpbuf.order = cmd->src->order; | |
306 | tmpbuf.fmt = cmd->src->fmt; | |
307 | tmpbuf.addr.type = cmd->src->addr.type; | |
308 | tmpbuf.addr.start = tmpbuf_addr; | |
309 | tmpbuf.plane2.type = ADDR_NONE; | |
310 | tmpbuf.rect.x1 = 0; | |
311 | tmpbuf.rect.y1 = 0; | |
312 | tmpbuf.rect.x2 = tmpbuf.width; | |
313 | tmpbuf.rect.y2 = tmpbuf.height; | |
314 | tmpbuf.need_cacheopr = false; | |
315 | ||
316 | /* 1st step : copy with scaling down */ | |
317 | p = &cmd1st.param; | |
318 | memcpy(p, &cmd->param, sizeof(cmd->param)); | |
319 | p->rotate = ORIGIN; | |
320 | p->g_alpha = 0xff; | |
321 | p->dither = false; | |
322 | cmd1st.op = BLIT_OP_SRC; | |
323 | cmd1st.src = cmd->src; | |
324 | cmd1st.dst = &tmpbuf; | |
325 | cmd1st.msk = NULL; | |
326 | cmd1st.tmp = NULL; | |
327 | cmd1st.sync = BLIT_SYNC; | |
328 | cmd1st.seq_no = cmd->seq_no; | |
329 | ||
330 | /* 2nd step : op with rotation */ | |
331 | p = &cmd2nd.param; | |
332 | memcpy(p, &cmd->param, sizeof(cmd->param)); | |
333 | p->scaling.mode = NO_SCALING; | |
334 | cmd2nd.op = cmd->op; | |
335 | cmd2nd.src = &tmpbuf; | |
336 | cmd2nd.dst = cmd->dst; | |
337 | cmd2nd.msk = NULL; | |
338 | cmd2nd.tmp = NULL; | |
339 | cmd2nd.sync = BLIT_SYNC; | |
340 | cmd2nd.seq_no = cmd->seq_no; | |
341 | } else { | |
342 | /* set temp buffer */ | |
343 | tmpbuf.width = cmd->src->rect.y2 - cmd->src->rect.y1; | |
344 | tmpbuf.height = cmd->src->rect.x2 - cmd->src->rect.x1; | |
345 | tmpbuf.stride = tmpbuf.width * 4; | |
346 | tmpbuf.order = cmd->src->order; | |
347 | tmpbuf.fmt = cmd->src->fmt; | |
348 | tmpbuf.addr.type = cmd->src->addr.type; | |
349 | tmpbuf.addr.start = tmpbuf_addr; | |
350 | tmpbuf.plane2.type = ADDR_NONE; | |
351 | tmpbuf.rect.x1 = 0; | |
352 | tmpbuf.rect.y1 = 0; | |
353 | tmpbuf.rect.x2 = tmpbuf.width; | |
354 | tmpbuf.rect.y2 = tmpbuf.height; | |
355 | tmpbuf.need_cacheopr = false; | |
356 | ||
357 | /* 1st step : copy with rotation */ | |
358 | p = &cmd1st.param; | |
359 | memcpy(p, &cmd->param, sizeof(cmd->param)); | |
360 | p->scaling.mode = NO_SCALING; | |
361 | p->g_alpha = 0xff; | |
362 | p->dither = false; | |
363 | cmd1st.op = BLIT_OP_SRC; | |
364 | cmd1st.src = cmd->src; | |
365 | cmd1st.dst = &tmpbuf; | |
366 | cmd1st.msk = NULL; | |
367 | cmd1st.tmp = NULL; | |
368 | cmd1st.sync = BLIT_SYNC; | |
369 | cmd1st.seq_no = cmd->seq_no; | |
370 | ||
371 | /* 2nd step : op with scaling up */ | |
372 | p = &cmd2nd.param; | |
373 | memcpy(p, &cmd->param, sizeof(cmd->param)); | |
374 | p->rotate = ORIGIN; | |
375 | cmd2nd.op = cmd->op; | |
376 | cmd2nd.src = &tmpbuf; | |
377 | cmd2nd.dst = cmd->dst; | |
378 | cmd2nd.msk = NULL; | |
379 | cmd2nd.tmp = NULL; | |
380 | cmd2nd.sync = BLIT_SYNC; | |
381 | cmd2nd.seq_no = cmd->seq_no; | |
382 | } | |
383 | ||
384 | /* 1st step blit */ | |
385 | if (fimgApi->Stretch(&cmd1st) == false) { | |
386 | if (fimgApi != NULL) | |
387 | destroyFimgApi(fimgApi); | |
388 | return -1; | |
389 | } | |
390 | ||
391 | /* 2nd step blit */ | |
392 | if (fimgApi->Stretch(&cmd2nd) == false) { | |
393 | if (fimgApi != NULL) | |
394 | destroyFimgApi(fimgApi); | |
395 | return -1; | |
396 | } | |
397 | ||
398 | if (fimgApi != NULL) | |
399 | destroyFimgApi(fimgApi); | |
400 | ||
401 | return 0; | |
402 | } | |
403 | ||
404 | extern "C" int SyncFimgApi(void) | |
405 | { | |
406 | pthread_mutex_lock(&s_g2d_lock); | |
407 | FimgApi * fimgApi = createFimgApi(); | |
408 | if (fimgApi == NULL) { | |
409 | PRINT("%s::createFimgApi() fail\n", __func__); | |
410 | pthread_mutex_unlock(&s_g2d_lock); | |
411 | return -1; | |
412 | } | |
413 | ||
414 | if (fimgApi->Sync() == false) { | |
415 | if (fimgApi != NULL) | |
416 | destroyFimgApi(fimgApi); | |
417 | ||
418 | pthread_mutex_unlock(&s_g2d_lock); | |
419 | return -1; | |
420 | } | |
421 | ||
422 | if (fimgApi != NULL) | |
423 | destroyFimgApi(fimgApi); | |
424 | ||
425 | pthread_mutex_unlock(&s_g2d_lock); | |
426 | return 0; | |
427 | } | |
428 | ||
429 | void printDataBlit(char *title, const char *called, struct fimg2d_blit *cmd) | |
430 | { | |
431 | SLOGI("%s (From %s)\n", title, called); | |
432 | SLOGI(" sequence_no. = %u\n", cmd->seq_no); | |
433 | SLOGI(" blit_op = %d(%s)\n", cmd->op, optbl[cmd->op].str); | |
434 | SLOGI(" fill_color = %X\n", cmd->param.solid_color); | |
435 | SLOGI(" global_alpha = %u\n", (unsigned int)cmd->param.g_alpha); | |
436 | SLOGI(" PREMULT = %s\n", cmd->param.premult == PREMULTIPLIED ? "PREMULTIPLIED" : "NON-PREMULTIPLIED"); | |
437 | SLOGI(" do_dither = %s\n", cmd->param.dither == true ? "dither" : "no-dither"); | |
438 | SLOGI(" repeat = %d(%s)\n", cmd->param.repeat.mode, | |
439 | repeat_tbl[cmd->param.repeat.mode].str); | |
440 | ||
441 | printDataBlitRotate(cmd->param.rotate); | |
442 | ||
443 | printDataBlitScale(&cmd->param.scaling); | |
444 | ||
445 | printDataBlitImage("SRC", cmd->src); | |
446 | printDataBlitImage("DST", cmd->dst); | |
447 | ||
448 | if (cmd->src != NULL) | |
449 | printDataBlitRect("SRC", &cmd->src->rect); | |
450 | if (cmd->dst != NULL) | |
451 | printDataBlitRect("DST", &cmd->dst->rect); | |
452 | } | |
453 | ||
454 | void printDataBlitImage(const char *title, struct fimg2d_image *image) | |
455 | { | |
456 | if (NULL != image) { | |
457 | SLOGI(" Image_%s\n", title); | |
458 | SLOGI(" addr = %X\n", image->addr.start); | |
459 | SLOGI(" format = %d\n", image->fmt); | |
460 | SLOGI(" size = (%d, %d)\n", image->width, image->height); | |
461 | } else { | |
462 | SLOGI(" Image_%s : NULL\n", title); | |
463 | } | |
464 | } | |
465 | ||
466 | void printDataBlitRect(const char *title, struct fimg2d_rect *rect) | |
467 | { | |
468 | if (NULL != rect) { | |
469 | SLOGI(" RECT_%s\n", title); | |
470 | SLOGI(" (x1, y1) = (%d, %d)\n", rect->x1, rect->y1); | |
471 | SLOGI(" (x2, y2) = (%d, %d)\n", rect->x2, rect->y2); | |
472 | SLOGI(" (width, height) = (%d, %d)\n", rect->x2 - rect->x1, rect->y2 - rect->y1); | |
473 | } else | |
474 | SLOGI(" RECT_%s : NULL\n", title); | |
475 | } | |
476 | ||
477 | void printDataBlitRotate(int rotate) | |
478 | { | |
479 | SLOGI(" ROTATE : %d\n", rotate); | |
480 | } | |
481 | ||
482 | void printDataBlitScale(struct fimg2d_scale *scaling) | |
483 | { | |
484 | SLOGI(" SCALING\n"); | |
485 | if (scaling->mode != 0) { | |
486 | SLOGI(" scale_mode : %s\n", (scaling->mode == 1 ? "SCALING_NEAREST" : "SCALING_BILINEAR")); | |
487 | SLOGI(" src : (src_w, src_h) = (%d, %d)\n", scaling->src_w, scaling->src_h); | |
488 | SLOGI(" dst : (dst_w, dst_h) = (%d, %d)\n", scaling->dst_w, scaling->dst_h); | |
489 | SLOGI(" scaling_factor : (scale_w, scale_y) = (%3.2f, %3.2f)\n", | |
490 | (double)scaling->dst_w / scaling->src_w, (double)scaling->dst_h / scaling->src_h); | |
491 | } else { | |
492 | SLOGI(" scale_mode : NO_SCALING\n"); | |
493 | } | |
494 | } |