blob: 29bf61e22a9dafd6048ff2200cf1f8e90b9e05f3 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * Copyright (c) 2010-2012, 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#define LOG_TAG "copybit_c2d"
19
20#include <cutils/log.h>
21
22#include <stdint.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
26#include <fcntl.h>
27
28#include <sys/ioctl.h>
29#include <sys/types.h>
30#include <sys/mman.h>
31
32#include <linux/msm_kgsl.h>
33
34#include <EGL/eglplatform.h>
35#include <cutils/native_handle.h>
36#include <cutils/ashmem.h>
37#include <linux/ashmem.h>
38#include <gralloc_priv.h>
39
40#include <copybit.h>
41#include <alloc_controller.h>
42#include <memalloc.h>
43
44#include "c2d2.h"
45#include "software_converter.h"
46
47#include <dlfcn.h>
48
49using gralloc::IMemAlloc;
50using gralloc::IonController;
51using gralloc::alloc_data;
Naseer Ahmed29a26812012-06-14 00:56:20 -070052
53C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
54 uint32 surface_bits,
55 C2D_SURFACE_TYPE surface_type,
56 void *surface_definition );
57
58C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
59 uint32 surface_bits,
60 C2D_SURFACE_TYPE surface_type,
61 void *surface_definition );
62
63C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
64 C2D_SURFACE_TYPE surface_type,
65 void *surface_definition,
66 int32 x, int32 y );
67
68C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
69 uint32 target_config, C2D_RECT *target_scissor,
70 uint32 target_mask_id, uint32 target_color_key,
71 C2D_OBJECT *objects_list, uint32 num_objects );
72
73C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
74
75C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
76
77C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
78
79C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
80
81C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
82
83C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
84
85/******************************************************************************/
86
87#if defined(COPYBIT_Z180)
88#define MAX_SCALE_FACTOR (4096)
89#define MAX_DIMENSION (4096)
90#else
91#error "Unsupported HW version"
92#endif
93
94#define NUM_SURFACES 3
95
96enum {
97 RGB_SURFACE,
98 YUV_SURFACE_2_PLANES,
99 YUV_SURFACE_3_PLANES
100};
101
102enum eConversionType {
103 CONVERT_TO_ANDROID_FORMAT,
104 CONVERT_TO_C2D_FORMAT
105};
106
107enum eC2DFlags {
108 FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
109 FLAGS_YUV_DESTINATION = 1<<1
110};
111
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700112static gralloc::IAllocController* sAlloc = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700113/******************************************************************************/
114
115/** State information for each device instance */
116struct copybit_context_t {
117 struct copybit_device_t device;
118 unsigned int src[NUM_SURFACES]; /* src surfaces */
119 unsigned int dst[NUM_SURFACES]; /* dst surfaces */
120 unsigned int trg_transform; /* target transform */
121 C2D_OBJECT blitState;
122 void *libc2d2;
123 alloc_data temp_src_buffer;
124 alloc_data temp_dst_buffer;
125 int fb_width;
126 int fb_height;
127 bool isPremultipliedAlpha;
128};
129
130struct blitlist{
131 uint32_t count;
132 C2D_OBJECT blitObjects[12];
133};
134
135struct bufferInfo {
136 int width;
137 int height;
138 int format;
139};
140
141struct yuvPlaneInfo {
142 int yStride; //luma stride
143 int plane1_stride;
144 int plane2_stride;
145 int plane1_offset;
146 int plane2_offset;
147};
148
149/**
150 * Common hardware methods
151 */
152
153static int open_copybit(const struct hw_module_t* module, const char* name,
154 struct hw_device_t** device);
155
156static struct hw_module_methods_t copybit_module_methods = {
157open: open_copybit
158};
159
160/*
161 * The COPYBIT Module
162 */
163struct copybit_module_t HAL_MODULE_INFO_SYM = {
164common: {
165tag: HARDWARE_MODULE_TAG,
166 version_major: 1,
167 version_minor: 0,
168 id: COPYBIT_HARDWARE_MODULE_ID,
169 name: "QCT COPYBIT C2D 2.0 Module",
170 author: "Qualcomm",
171 methods: &copybit_module_methods
172 }
173};
174
175
176/* convert COPYBIT_FORMAT to C2D format */
177static int get_format(int format) {
178 switch (format) {
179 case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
180 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
181 C2D_FORMAT_SWAP_RB |
182 C2D_FORMAT_DISABLE_ALPHA;
183 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
184 C2D_FORMAT_SWAP_RB;
185 case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
186 case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA;
187 case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA;
188 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
189 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
190 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
191 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
192 C2D_FORMAT_MACROTILED;
193 default: ALOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL;
194 }
195 return -EINVAL;
196}
197
198/* Get the C2D formats needed for conversion to YUV */
199static int get_c2d_format_for_yuv_destination(int halFormat) {
200 switch (halFormat) {
201 // We do not swap the RB when the target is YUV
202 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
203 C2D_FORMAT_DISABLE_ALPHA;
204 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
205 // The U and V need to be interchanged when the target is YUV
206 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
207 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
208 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
209 default: return get_format(halFormat);
210 }
211 return -EINVAL;
212}
213
214/* ------------------------------------------------------------------- *//*!
215 * \internal
216 * \brief Get the bpp for a particular color format
217 * \param color format
218 * \return bits per pixel
219 *//* ------------------------------------------------------------------- */
220int c2diGetBpp(int32 colorformat)
221{
222
223 int c2dBpp = 0;
224
225 switch(colorformat&0xFF)
226 {
227 case C2D_COLOR_FORMAT_4444_RGBA:
228 case C2D_COLOR_FORMAT_4444_ARGB:
229 case C2D_COLOR_FORMAT_1555_ARGB:
230 case C2D_COLOR_FORMAT_565_RGB:
231 case C2D_COLOR_FORMAT_5551_RGBA:
232 c2dBpp = 16;
233 break;
234 case C2D_COLOR_FORMAT_8888_RGBA:
235 case C2D_COLOR_FORMAT_8888_ARGB:
236 c2dBpp = 32;
237 break;
238 case C2D_COLOR_FORMAT_8_L:
239 case C2D_COLOR_FORMAT_8_A:
240 c2dBpp = 8;
241 break;
242 case C2D_COLOR_FORMAT_4_A:
243 c2dBpp = 4;
244 break;
245 case C2D_COLOR_FORMAT_1:
246 c2dBpp = 1;
247 break;
248 default:
249 ALOGE("%s ERROR", __func__);
250 break;
251 }
252 return c2dBpp;
253}
254
255static uint32 c2d_get_gpuaddr( struct private_handle_t *handle)
256{
257 uint32 memtype, *gpuaddr;
258 C2D_STATUS rc;
259
260 if(!handle)
261 return 0;
262
263 if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
264 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
265 memtype = KGSL_USER_MEM_TYPE_PMEM;
266 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
267 memtype = KGSL_USER_MEM_TYPE_ASHMEM;
268 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
269 memtype = KGSL_USER_MEM_TYPE_ION;
270 else {
271 ALOGE("Invalid handle flags: 0x%x", handle->flags);
272 return 0;
273 }
274
275 rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, handle->offset, memtype, (void**)&gpuaddr);
276 if (rc == C2D_STATUS_OK) {
277 return (uint32) gpuaddr;
278 }
279 return 0;
280}
281
282static int is_supported_rgb_format(int format)
283{
284 switch(format) {
285 case HAL_PIXEL_FORMAT_RGBA_8888:
286 case HAL_PIXEL_FORMAT_RGBX_8888:
287 case HAL_PIXEL_FORMAT_RGB_565:
288 case HAL_PIXEL_FORMAT_BGRA_8888:
289 case HAL_PIXEL_FORMAT_RGBA_5551:
290 case HAL_PIXEL_FORMAT_RGBA_4444: {
291 return COPYBIT_SUCCESS;
292 }
293 default:
294 return COPYBIT_FAILURE;
295 }
296}
297
298static int get_num_planes(int format)
299{
300 switch(format) {
301 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
302 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
303 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
304 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
305 return 2;
306 }
307 case HAL_PIXEL_FORMAT_YV12: {
308 return 3;
309 }
310 default:
311 return COPYBIT_FAILURE;
312 }
313}
314
315static int is_supported_yuv_format(int format)
316{
317 switch(format) {
318 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
319 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
320 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
321 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
322 return COPYBIT_SUCCESS;
323 }
324 default:
325 return COPYBIT_FAILURE;
326 }
327}
328
329static int is_valid_destination_format(int format)
330{
331 if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
332 // C2D does not support NV12Tile as a destination format.
333 return COPYBIT_FAILURE;
334 }
335 return COPYBIT_SUCCESS;
336}
337
338static int calculate_yuv_offset_and_stride(const bufferInfo& info,
339 yuvPlaneInfo& yuvInfo)
340{
341 int width = info.width;
342 int height = info.height;
343 int format = info.format;
344
345 int aligned_height = 0;
346 int aligned_width = 0, size = 0;
347
348 switch (format) {
349 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
350 /* NV12 Tile buffers have their luma height aligned to 32bytes and width
351 * aligned to 128 bytes. The chroma offset starts at an 8K boundary
352 */
353 aligned_height = ALIGN(height, 32);
354 aligned_width = ALIGN(width, 128);
355 size = aligned_width * aligned_height;
356 yuvInfo.plane1_offset = ALIGN(size,8192);
357 yuvInfo.yStride = aligned_width;
358 yuvInfo.plane1_stride = aligned_width;
359 break;
360 }
361 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
362 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
363 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
364 aligned_width = ALIGN(width, 32);
365 yuvInfo.yStride = aligned_width;
366 yuvInfo.plane1_stride = aligned_width;
367 if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
368 // The encoder requires a 2K aligned chroma offset
369 yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
370 } else
371 yuvInfo.plane1_offset = aligned_width * height;
372
373 break;
374 }
375 default: {
376 return COPYBIT_FAILURE;
377 }
378 }
379 return COPYBIT_SUCCESS;
380}
381
382/** create C2D surface from copybit image */
383static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs,
384 int *cformat, uint32_t *mapped, const eC2DFlags flags)
385{
386 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
387 C2D_SURFACE_TYPE surfaceType;
388 int status = COPYBIT_SUCCESS;
389
390 if (flags & FLAGS_YUV_DESTINATION) {
391 *cformat = get_c2d_format_for_yuv_destination(rhs->format);
392 } else {
393 *cformat = get_format(rhs->format);
394 }
395
396 if(*cformat == -EINVAL) {
397 ALOGE("%s: invalid format", __FUNCTION__);
398 return -EINVAL;
399 }
400
401 if(handle == NULL) {
402 ALOGE("%s: invalid handle", __func__);
403 return -EINVAL;
404 }
405
406 if (handle->gpuaddr == 0) {
407 handle->gpuaddr = c2d_get_gpuaddr(handle);
408 if(!handle->gpuaddr) {
409 ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
410 return COPYBIT_FAILURE;
411 }
412 *mapped = 1;
413 }
414
415 /* create C2D surface */
416 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
417 /* RGB */
418 C2D_RGB_SURFACE_DEF surfaceDef;
419
420 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
421
422 surfaceDef.phys = (void*) handle->gpuaddr;
423 surfaceDef.buffer = (void*) (handle->base);
424
425 surfaceDef.format = *cformat |
426 ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
427 surfaceDef.width = rhs->w;
428 surfaceDef.height = rhs->h;
429 int aligned_width = ALIGN(surfaceDef.width,32);
430 surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
431
432 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
433 ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
434 goto error;
435 status = COPYBIT_FAILURE;
436 }
437 } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
438 C2D_YUV_SURFACE_DEF surfaceDef;
439 memset(&surfaceDef, 0, sizeof(surfaceDef));
440 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
441 surfaceDef.format = *cformat;
442
443 bufferInfo info;
444 info.width = rhs->w;
445 info.height = rhs->h;
446 info.format = rhs->format;
447
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700448 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700449 status = calculate_yuv_offset_and_stride(info, yuvInfo);
450 if(status != COPYBIT_SUCCESS) {
451 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
452 goto error;
453 }
454
455 surfaceDef.width = rhs->w;
456 surfaceDef.height = rhs->h;
457 surfaceDef.plane0 = (void*) (handle->base);
458 surfaceDef.phys0 = (void*) (handle->gpuaddr);
459 surfaceDef.stride0 = yuvInfo.yStride;
460
461 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
462 surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
463 surfaceDef.stride1 = yuvInfo.plane1_stride;
464 if (3 == get_num_planes(rhs->format)) {
465 surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
466 surfaceDef.phys2 = (void*) (handle->gpuaddr + yuvInfo.plane2_offset);
467 surfaceDef.stride2 = yuvInfo.plane2_stride;
468 }
469
470 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
471 &surfaceDef)) {
472 ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
473 goto error;
474 status = COPYBIT_FAILURE;
475 }
476 } else {
477 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
478 goto error;
479 status = COPYBIT_FAILURE;
480 }
481
482 return status;
483
484error:
485 if(*mapped == 1) {
486 LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
487 handle->gpuaddr = 0;
488 *mapped = 0;
489 }
490 return status;
491}
492
493static int set_src_image( uint32 *surfaceId, const struct copybit_image_t *rhs,
494 int *cformat, uint32 *mapped)
495{
496 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
497 *cformat = get_format(rhs->format);
498 C2D_SURFACE_TYPE surfaceType;
499 uint32 gpuaddr = (uint32)handle->gpuaddr;
500 int status = COPYBIT_SUCCESS;
501
502 if (handle->gpuaddr == 0)
503 {
504 handle->gpuaddr = c2d_get_gpuaddr( handle);
505 if(!handle->gpuaddr)
506 return COPYBIT_FAILURE;
507
508 *mapped = 1;
509 }
510
511 /* create C2D surface */
512 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
513 /* RGB */
514 C2D_RGB_SURFACE_DEF surfaceDef;
515 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
516
517 surfaceDef.phys = (void*) handle->gpuaddr;
518 surfaceDef.buffer = (void*) (handle->base);
519 surfaceDef.buffer = (void*) (handle->base + handle->offset);
520
521 surfaceDef.format = get_format(rhs->format);
522 surfaceDef.width = rhs->w;
523 surfaceDef.height = rhs->h;
524 surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
525
526 if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) {
527 ALOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__);
528 status = COPYBIT_FAILURE;
529 goto error;
530 }
531 } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
532 /* YUV */
533 C2D_YUV_SURFACE_DEF surfaceDef;
534 int offset = 0;
535 int yStride = 0;
536 int uvStride = 0;
537 memset(&surfaceDef, 0, sizeof(surfaceDef));
538
539 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
540 surfaceDef.format = get_format(rhs->format);
541 bufferInfo info;
542 info.width = rhs->w;
543 info.height = rhs->h;
544 info.format = rhs->format;
545
546 yuvPlaneInfo yuvInfo;
547 status = calculate_yuv_offset_and_stride(info, yuvInfo);
548 if(status != COPYBIT_SUCCESS) {
549 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
550 goto error;
551 }
552
553 surfaceDef.width = rhs->w;
554 surfaceDef.height = rhs->h;
555 surfaceDef.plane0 = (void*) (handle->base);
556 surfaceDef.phys0 = (void*) handle->gpuaddr;
557 surfaceDef.stride0 = yuvInfo.yStride;
558
559 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
560 surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
561 surfaceDef.stride1 = yuvInfo.plane1_stride;
562
563 if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType,
564 (void*)&surfaceDef)) {
565 ALOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__);
566 status = COPYBIT_FAILURE;
567 goto error;
568 }
569 } else {
570 ALOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format);
571 status = COPYBIT_FAILURE;
572 }
573
574 return COPYBIT_SUCCESS;
575
576error:
577 if(*mapped == 1) {
578 LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
579 handle->gpuaddr = 0;
580 *mapped = 0;
581 }
582 return status;
583}
584
585void unset_image( uint32 surfaceId, const struct copybit_image_t *rhs,
586 uint32 mmapped)
587{
588 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
589
590 if (mmapped && handle->gpuaddr) {
591 // Unmap this gpuaddr
592 LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
593 handle->gpuaddr = 0;
594 }
595}
596
597static int blit_to_target( uint32 surfaceId, const struct copybit_image_t *rhs)
598{
599 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
600 uint32 cformat = get_format(rhs->format);
601 C2D_SURFACE_TYPE surfaceType;
602 uint32 memoryMapped = 0;
603 int status = COPYBIT_SUCCESS;
604
605 if (!handle->gpuaddr) {
606 handle->gpuaddr = c2d_get_gpuaddr(handle);
607 if(!handle->gpuaddr)
608 return COPYBIT_FAILURE;
609
610 memoryMapped = 1;
611 }
612
613 /* create C2D surface */
614
615 if(cformat) {
616 /* RGB */
617 C2D_RGB_SURFACE_DEF surfaceDef;
618 memset(&surfaceDef, 0, sizeof(surfaceDef));
619
620 surfaceDef.buffer = (void*) handle->base;
621 surfaceDef.phys = (void*) handle->gpuaddr;
622
623 surfaceType = C2D_SURFACE_RGB_HOST;
624 surfaceDef.format = get_format(rhs->format);
625 surfaceDef.width = rhs->w;
626 surfaceDef.height = rhs->h;
627 surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
628
629 if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) {
630 ALOGE("%s: LINK_c2dReadSurface ERROR", __func__);
631 status = COPYBIT_FAILURE;
632 goto done;
633 }
634 }
635 else {
636 /* YUV */
637 /* TODO */
638 }
639
640done:
641 if (memoryMapped) {
642 LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
643 handle->gpuaddr = 0;
644 }
645 return status;
646}
647
648/** setup rectangles */
649static void set_rects(struct copybit_context_t *ctx,
650 C2D_OBJECT *c2dObject,
651 const struct copybit_rect_t *dst,
652 const struct copybit_rect_t *src,
653 const struct copybit_rect_t *scissor)
654{
655 // Set the target rect.
656 if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
657 (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
658 /* target rotation is 270 */
659 c2dObject->target_rect.x = (dst->t)<<16;
660 c2dObject->target_rect.y = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
661 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
662 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
663 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
664 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
665 c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
666 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
667 c2dObject->target_rect.y = (dst->l)<<16;
668 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
669 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
670 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
671 c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
672 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
673 c2dObject->target_rect.x = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
674 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
675 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
676 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
677 } else {
678 c2dObject->target_rect.x = (dst->l)<<16;
679 c2dObject->target_rect.y = (dst->t)<<16;
680 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
681 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
682 }
683 c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
684
685 // Set the source rect
686 c2dObject->source_rect.x = (src->l)<<16;
687 c2dObject->source_rect.y = (src->t)<<16;
688 c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
689 c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
690 c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
691
692 // Set the scissor rect
693 c2dObject->scissor_rect.x = scissor->l;
694 c2dObject->scissor_rect.y = scissor->t;
695 c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
696 c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
697 c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
698}
699
700/** copy the bits */
701static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target)
702{
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700703 unsigned int objects;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700704
705 for(objects = 0; objects < list->count; objects++) {
706 list->blitObjects[objects].next = &(list->blitObjects[objects+1]);
707 }
708
709 if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects,
710 list->count)) {
711 ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
712 return COPYBIT_FAILURE;
713 }
714
715 return COPYBIT_SUCCESS;
716}
717
718/*****************************************************************************/
719
720/** Set a parameter to value */
721static int set_parameter_copybit(
722 struct copybit_device_t *dev,
723 int name,
724 int value)
725{
726 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
727 if (!ctx) {
728 ALOGE("%s: null context", __FUNCTION__);
729 return -EINVAL;
730 }
731
732 switch(name) {
733 case COPYBIT_ROTATION_DEG:
734 ctx->blitState.rotation = value<<16;
735 /* SRC rotation */
736 if(!value)
737 ctx->blitState.config_mask &=~C2D_ROTATE_BIT;;
738 break;
739 case COPYBIT_PLANE_ALPHA:
740 if (value < 0) value = 0;
741 if (value >= 256) value = 255;
742
743 ctx->blitState.global_alpha = value;
744
745 if(ctx->blitState.global_alpha<255)
746 ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT;
747 else
748 ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT;
749 break;
750 case COPYBIT_DITHER:
751 /* TODO */
752 break;
753 case COPYBIT_BLUR:
754 /* TODO */
755 break;
756 case COPYBIT_TRANSFORM:
757 ctx->blitState.config_mask &=~C2D_ROTATE_BIT;
758 ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT;
759 ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT;
760 ctx->trg_transform = C2D_TARGET_ROTATE_0;
761
762 if((value&0x7) == COPYBIT_TRANSFORM_ROT_180)
763 ctx->trg_transform = C2D_TARGET_ROTATE_180;
764 else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270)
765 ctx->trg_transform = C2D_TARGET_ROTATE_90;
766 else {
767 if(value&COPYBIT_TRANSFORM_FLIP_H)
768 ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
769 if(value&COPYBIT_TRANSFORM_FLIP_V)
770 ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
771 if(value&COPYBIT_TRANSFORM_ROT_90)
772 ctx->trg_transform = C2D_TARGET_ROTATE_270;
773 }
774 break;
775 case COPYBIT_PREMULTIPLIED_ALPHA:
776 (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true :
777 ctx->isPremultipliedAlpha = false;
778 break;
779 case COPYBIT_FRAMEBUFFER_WIDTH:
780 ctx->fb_width = value;
781 break;
782 case COPYBIT_FRAMEBUFFER_HEIGHT:
783 ctx->fb_height = value;
784 break;
785 default:
786 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
787 return -EINVAL;
788 break;
789 }
790
791 return COPYBIT_SUCCESS;
792}
793
794/** Get a static info value */
795static int get(struct copybit_device_t *dev, int name)
796{
797 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
798 int value;
799
800 if (!ctx) {
801 ALOGE("%s: null context error", __FUNCTION__);
802 return -EINVAL;
803 }
804
805 switch(name) {
806 case COPYBIT_MINIFICATION_LIMIT:
807 value = MAX_SCALE_FACTOR;
808 break;
809 case COPYBIT_MAGNIFICATION_LIMIT:
810 value = MAX_SCALE_FACTOR;
811 break;
812 case COPYBIT_SCALING_FRAC_BITS:
813 value = 32;
814 break;
815 case COPYBIT_ROTATION_STEP_DEG:
816 value = 1;
817 break;
818 default:
819 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
820 value = -EINVAL;
821 }
822 return value;
823}
824
825static int is_alpha(int cformat)
826{
827 int alpha = 0;
828 switch (cformat & 0xFF) {
829 case C2D_COLOR_FORMAT_8888_ARGB:
830 case C2D_COLOR_FORMAT_8888_RGBA:
831 case C2D_COLOR_FORMAT_5551_RGBA:
832 case C2D_COLOR_FORMAT_4444_ARGB:
833 alpha = 1;
834 break;
835 default:
836 alpha = 0;
837 break;
838 }
839
840 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
841 alpha = 0;
842
843 return alpha;
844}
845
846/* Function to check if we need a temporary buffer for the blit.
847 * This would happen if the requested destination stride and the
848 * C2D stride do not match. We ignore RGB buffers, since their
849 * stride is always aligned to 32.
850 */
851static bool need_temp_buffer(struct copybit_image_t const *img)
852{
853 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
854 return false;
855
856 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
857
858 // The width parameter in the handle contains the aligned_w. We check if we
859 // need to convert based on this param. YUV formats have bpp=1, so checking
860 // if the requested stride is aligned should suffice.
861 if (0 == (handle->width)%32) {
862 return false;
863 }
864
865 return true;
866}
867
868/* Function to extract the information from the copybit image and set the corresponding
869 * values in the bufferInfo struct.
870 */
871static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
872{
873 info.width = img->w;
874 info.height = img->h;
875 info.format = img->format;
876}
877
878/* Function to get the required size for a particular format, inorder for C2D to perform
879 * the blit operation.
880 */
881static size_t get_size(const bufferInfo& info)
882{
883 size_t size = 0;
884 int w = info.width;
885 int h = info.height;
886 int aligned_w = ALIGN(w, 32);
887 switch(info.format) {
888 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
889 {
890 // Chroma for this format is aligned to 2K.
891 size = ALIGN((aligned_w*h), 2048) +
892 ALIGN(w/2, 32) * h/2 *2;
893 size = ALIGN(size, 4096);
894 } break;
895 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
896 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
897 {
898 size = aligned_w*h +
899 ALIGN(w/2, 32) * h/2 *2;
900 size = ALIGN(size, 4096);
901 } break;
902 default: break;
903 }
904 return size;
905}
906
907/* Function to allocate memory for the temporary buffer. This memory is
908 * allocated from Ashmem. It is the caller's responsibility to free this
909 * memory.
910 */
911static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
912{
913 ALOGD("%s E", __FUNCTION__);
914 // Alloc memory from system heap
915 data.base = 0;
916 data.fd = -1;
917 data.offset = 0;
918 data.size = get_size(info);
919 data.align = getpagesize();
920 data.uncached = true;
921 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
922
923 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700924 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -0700925 }
926
927 if (sAlloc == 0) {
928 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
929 return COPYBIT_FAILURE;
930 }
931
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700932 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700933 if (0 != err) {
934 ALOGE("%s: allocate failed", __FUNCTION__);
935 return COPYBIT_FAILURE;
936 }
937
938 ALOGD("%s X", __FUNCTION__);
939 return err;
940}
941
942/* Function to free the temporary allocated memory.*/
943static void free_temp_buffer(alloc_data &data)
944{
945 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700946 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700947 memalloc->free_buffer(data.base, data.size, 0, data.fd);
948 }
949}
950
951/* Function to perform the software color conversion. Convert the
952 * C2D compatible format to the Android compatible format
953 */
954static int copy_image(private_handle_t *src_handle,
955 struct copybit_image_t const *rhs,
956 eConversionType conversionType)
957{
958 if (src_handle->fd == -1) {
959 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
960 return COPYBIT_FAILURE;
961 }
962
963 // Copy the info.
964 int ret = COPYBIT_SUCCESS;
965 switch(rhs->format) {
966 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
967 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
968 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
969 {
970 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
971 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
972 } else {
973 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
974 }
975
976 } break;
977 default: {
978 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
979 ret = COPYBIT_FAILURE;
980 } break;
981 }
982 return ret;
983}
984
985static void delete_handle(private_handle_t *handle)
986{
987 if (handle) {
988 delete handle;
989 handle = 0;
990 }
991}
992/** do a stretch blit type operation */
993static int stretch_copybit_internal(
994 struct copybit_device_t *dev,
995 struct copybit_image_t const *dst,
996 struct copybit_image_t const *src,
997 struct copybit_rect_t const *dst_rect,
998 struct copybit_rect_t const *src_rect,
999 struct copybit_region_t const *region,
1000 bool enableBlend)
1001{
1002 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1003 int status = COPYBIT_SUCCESS;
1004 uint32 maxCount;
1005 uint32 src_mapped = 0, trg_mapped = 0;
1006 blitlist list;
1007 C2D_OBJECT *req;
1008 memset(&list, 0, sizeof(list));
1009 int cformat;
1010 c2d_ts_handle timestamp;
1011 uint32 src_surface_index = 0, dst_surface_index = 0;
1012
1013 if (!ctx) {
1014 ALOGE("%s: null context error", __FUNCTION__);
1015 return -EINVAL;
1016 }
1017
1018 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1019 ALOGE("%s: src dimension error", __FUNCTION__);
1020 return -EINVAL;
1021 }
1022
1023 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
1024 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, dst->h);
1025 return -EINVAL;
1026 }
1027
1028 maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
1029
1030 struct copybit_rect_t clip;
1031 list.count = 0;
1032
1033 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
1034 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format);
1035 return COPYBIT_FAILURE;
1036 }
1037
1038 bool isYUVDestination = false;
1039 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
1040 dst_surface_index = RGB_SURFACE;
1041 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
1042 isYUVDestination = true;
1043 int num_planes = get_num_planes(dst->format);
1044 if (num_planes == 2) {
1045 dst_surface_index = YUV_SURFACE_2_PLANES;
1046 } else if (num_planes == 3) {
1047 dst_surface_index = YUV_SURFACE_3_PLANES;
1048 } else {
1049 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1050 __FUNCTION__, dst->format);
1051 return COPYBIT_FAILURE;
1052 }
1053 } else {
1054 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format);
1055 return COPYBIT_FAILURE;
1056 }
1057
1058 copybit_image_t dst_image;
1059 dst_image.w = dst->w;
1060 dst_image.h = dst->h;
1061 dst_image.format = dst->format;
1062 dst_image.handle = dst->handle;
1063 // Check if we need a temp. copy for the destination. We'd need this the destination
1064 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1065 // aligned to 32.
1066 bool needTempDestination = need_temp_buffer(dst);
1067 bufferInfo dst_info;
1068 populate_buffer_info(dst, dst_info);
1069 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1070 dst_info.width, dst_info.height);
1071 if (dst_hnd == NULL) {
1072 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1073 return COPYBIT_FAILURE;
1074 }
1075 if (needTempDestination) {
1076 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1077 free_temp_buffer(ctx->temp_dst_buffer);
1078 // Create a temp buffer and set that as the destination.
1079 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1080 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1081 delete_handle(dst_hnd);
1082 return COPYBIT_FAILURE;
1083 }
1084 }
1085 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1086 dst_hnd->size = ctx->temp_dst_buffer.size;
1087 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
1088 dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
1089 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1090 dst_hnd->gpuaddr = 0;
1091 dst_image.handle = dst_hnd;
1092 }
1093
1094 int flags = 0;
1095 flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1096 flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0;
1097
1098 status = set_image( ctx->dst[dst_surface_index], &dst_image,
1099 &cformat, &trg_mapped, (eC2DFlags)flags);
1100 if(status) {
1101 ALOGE("%s: dst: set_image error", __FUNCTION__);
1102 delete_handle(dst_hnd);
1103 return COPYBIT_FAILURE;
1104 }
1105
1106 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
1107 src_surface_index = RGB_SURFACE;
1108 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1109 int num_planes = get_num_planes(src->format);
1110 if (num_planes == 2) {
1111 src_surface_index = YUV_SURFACE_2_PLANES;
1112 } else if (num_planes == 3) {
1113 src_surface_index = YUV_SURFACE_3_PLANES;
1114 } else {
1115 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1116 __FUNCTION__, src->format);
1117 delete_handle(dst_hnd);
1118 return -EINVAL;
1119 }
1120 } else {
1121 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format);
1122 delete_handle(dst_hnd);
1123 return -EINVAL;
1124 }
1125
1126 copybit_image_t src_image;
1127 src_image.w = src->w;
1128 src_image.h = src->h;
1129 src_image.format = src->format;
1130 src_image.handle = src->handle;
1131
1132 bool needTempSource = need_temp_buffer(src);
1133 bufferInfo src_info;
1134 populate_buffer_info(src, src_info);
1135 private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
1136 src_info.width, src_info.height);
1137 if (NULL == src_hnd) {
1138 ALOGE("%s: src_hnd is null", __FUNCTION__);
1139 delete_handle(dst_hnd);
1140 return COPYBIT_FAILURE;
1141 }
1142 if (needTempSource) {
1143 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1144 free_temp_buffer(ctx->temp_src_buffer);
1145 // Create a temp buffer and set that as the destination.
1146 if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) {
1147 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1148 delete_handle(dst_hnd);
1149 delete_handle(src_hnd);
1150 return COPYBIT_FAILURE;
1151 }
1152 }
1153 src_hnd->fd = ctx->temp_src_buffer.fd;
1154 src_hnd->size = ctx->temp_src_buffer.size;
1155 src_hnd->flags = ctx->temp_src_buffer.allocType;
1156 src_hnd->base = (int)(ctx->temp_src_buffer.base);
1157 src_hnd->offset = ctx->temp_src_buffer.offset;
1158 src_hnd->gpuaddr = 0;
1159 src_image.handle = src_hnd;
1160
1161 // Copy the source.
1162 copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT);
1163
1164 // Flush the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001165 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001166 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
1167 src_hnd->offset, src_hnd->fd)) {
1168 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1169 delete_handle(dst_hnd);
1170 delete_handle(src_hnd);
1171 return COPYBIT_FAILURE;
1172 }
1173 }
1174
1175 status = set_image( ctx->src[src_surface_index], &src_image,
1176 &cformat, &src_mapped, (eC2DFlags)flags);
1177 if(status) {
1178 ALOGE("%s: set_src_image error", __FUNCTION__);
1179 delete_handle(dst_hnd);
1180 delete_handle(src_hnd);
1181 return COPYBIT_FAILURE;
1182 }
1183
1184 if (enableBlend) {
1185 if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1186 ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1187 if(!(ctx->blitState.global_alpha)) {
1188 // src alpha is zero
1189 unset_image( ctx->src[src_surface_index],
1190 &src_image, src_mapped);
1191 unset_image( ctx->dst[dst_surface_index],
1192 &dst_image, trg_mapped);
1193 delete_handle(dst_hnd);
1194 delete_handle(src_hnd);
1195 return status;
1196 }
1197 } else {
1198 if(is_alpha(cformat))
1199 ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1200 else
1201 ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
1202 }
1203 } else {
1204 ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
1205 }
1206
1207 ctx->blitState.surface_id = ctx->src[src_surface_index];
1208
1209 while ((status == 0) && region->next(region, &clip)) {
1210 req = &(list.blitObjects[list.count]);
1211 memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
1212
1213 set_rects(ctx, req, dst_rect, src_rect, &clip);
1214
1215 if (++list.count == maxCount) {
1216 status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
1217 list.count = 0;
1218 }
1219 }
1220 if ((status == 0) && list.count) {
1221 status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
1222 }
1223
1224 if(LINK_c2dFinish(ctx->dst[dst_surface_index])) {
1225 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
1226 }
1227
1228 unset_image( ctx->src[src_surface_index], &src_image,
1229 src_mapped);
1230 unset_image( ctx->dst[dst_surface_index], &dst_image,
1231 trg_mapped);
1232 if (needTempDestination) {
1233 // copy the temp. destination without the alignment to the actual destination.
1234 copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1235 // Invalidate the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001236 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001237 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
1238 dst_hnd->offset, dst_hnd->fd);
1239 }
1240 delete_handle(dst_hnd);
1241 delete_handle(src_hnd);
1242 ctx->isPremultipliedAlpha = false;
1243 ctx->fb_width = 0;
1244 ctx->fb_height = 0;
1245 return status;
1246}
1247
1248static int stretch_copybit(
1249 struct copybit_device_t *dev,
1250 struct copybit_image_t const *dst,
1251 struct copybit_image_t const *src,
1252 struct copybit_rect_t const *dst_rect,
1253 struct copybit_rect_t const *src_rect,
1254 struct copybit_region_t const *region)
1255{
1256 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1257 bool needsBlending = (ctx->blitState.global_alpha != 0);
1258 return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
1259 region, needsBlending);
1260}
1261
1262/** Perform a blit type operation */
1263static int blit_copybit(
1264 struct copybit_device_t *dev,
1265 struct copybit_image_t const *dst,
1266 struct copybit_image_t const *src,
1267 struct copybit_region_t const *region)
1268{
1269 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
1270 struct copybit_rect_t sr = { 0, 0, src->w, src->h };
1271 return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1272}
1273
1274/*****************************************************************************/
1275
1276/** Close the copybit device */
1277static int close_copybit(struct hw_device_t *dev)
1278{
1279 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1280 if (ctx) {
1281 for(int i = 0; i <NUM_SURFACES; i++) {
1282 LINK_c2dDestroySurface(ctx->dst[i]);
1283 LINK_c2dDestroySurface(ctx->src[i]);
1284 }
1285
1286 if (ctx->libc2d2) {
1287 ::dlclose(ctx->libc2d2);
1288 ALOGV("dlclose(libc2d2)");
1289 }
1290
1291 free_temp_buffer(ctx->temp_src_buffer);
1292 free_temp_buffer(ctx->temp_dst_buffer);
1293 free(ctx);
1294 }
1295
1296 return 0;
1297}
1298
1299/** Open a new instance of a copybit device using name */
1300static int open_copybit(const struct hw_module_t* module, const char* name,
1301 struct hw_device_t** device)
1302{
1303 int status = COPYBIT_SUCCESS;
1304 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1305 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1306 struct copybit_context_t *ctx;
1307 char fbName[64];
1308
1309 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1310 if(!ctx) {
1311 ALOGE("%s: malloc failed", __FUNCTION__);
1312 return COPYBIT_FAILURE;
1313 }
1314
1315 /* initialize drawstate */
1316 memset(ctx, 0, sizeof(*ctx));
1317
1318 for (int i=0; i< NUM_SURFACES; i++) {
1319 ctx->dst[i] = -1;
1320 ctx->src[i] = -1;
1321 }
1322
1323 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1324 if (!ctx->libc2d2) {
1325 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
1326 goto error;
1327 }
1328 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1329 "c2dCreateSurface");
1330 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1331 "c2dUpdateSurface");
1332 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1333 "c2dReadSurface");
1334 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1335 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1336 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1337 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1338 "c2dWaitTimestamp");
1339 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1340 "c2dDestroySurface");
1341 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1342 "c2dMapAddr");
1343 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1344 "c2dUnMapAddr");
1345
1346 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
1347 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
1348 || !LINK_c2dDestroySurface) {
1349 ALOGE("%s: dlsym ERROR", __FUNCTION__);
1350 goto error;
1351 }
1352
1353 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1354 ctx->device.common.version = 1;
1355 ctx->device.common.module = (hw_module_t*)(module);
1356 ctx->device.common.close = close_copybit;
1357 ctx->device.set_parameter = set_parameter_copybit;
1358 ctx->device.get = get;
1359 ctx->device.blit = blit_copybit;
1360 ctx->device.stretch = stretch_copybit;
1361 ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
1362 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1363
1364 /* Create RGB Surface */
1365 surfDefinition.buffer = (void*)0xdddddddd;
1366 surfDefinition.phys = (void*)0xdddddddd;
1367 surfDefinition.stride = 1 * 4;
1368 surfDefinition.width = 1;
1369 surfDefinition.height = 1;
1370 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1371 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1372 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1373 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) {
1374 ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__);
1375 ctx->dst[RGB_SURFACE] = -1;
1376 goto error;
1377 }
1378
1379
1380 if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1381 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1382 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) {
1383 ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__);
1384 ctx->src[RGB_SURFACE] = -1;
1385 goto error;
1386 }
1387
1388 /* Create YUV source surface */
1389 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
1390
1391 yuvSurfaceDef.width = 4;
1392 yuvSurfaceDef.height = 4;
1393 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1394 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1395 yuvSurfaceDef.stride0 = 4;
1396
1397 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1398 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1399 yuvSurfaceDef.stride1 = 4;
1400
1401 if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),
1402 C2D_TARGET | C2D_SOURCE,
1403 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1404 &yuvSurfaceDef)) {
1405 ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
1406 ctx->src[YUV_SURFACE_2_PLANES] = -1;
1407 goto error;
1408 }
1409
1410 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1411 C2D_TARGET | C2D_SOURCE,
1412 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1413 &yuvSurfaceDef)) {
1414 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
1415 ctx->dst[YUV_SURFACE_2_PLANES] = -1;
1416 goto error;
1417 }
1418
1419 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1420 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1421 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1422 yuvSurfaceDef.stride2 = 4;
1423
1424 if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),
1425 C2D_TARGET | C2D_SOURCE,
1426 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1427 &yuvSurfaceDef)) {
1428 ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
1429 ctx->src[YUV_SURFACE_3_PLANES] = -1;
1430 goto error;
1431 }
1432
1433 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1434 C2D_TARGET | C2D_SOURCE,
1435 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1436 &yuvSurfaceDef)) {
1437 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
1438 ctx->dst[YUV_SURFACE_3_PLANES] = -1;
1439 goto error;
1440 }
1441
1442 ctx->temp_src_buffer.fd = -1;
1443 ctx->temp_src_buffer.base = 0;
1444 ctx->temp_src_buffer.size = 0;
1445
1446 ctx->temp_dst_buffer.fd = -1;
1447 ctx->temp_dst_buffer.base = 0;
1448 ctx->temp_dst_buffer.size = 0;
1449
1450 ctx->fb_width = 0;
1451 ctx->fb_height = 0;
1452 ctx->isPremultipliedAlpha = false;
1453
1454 *device = &ctx->device.common;
1455 return status;
1456
1457error:
1458 for (int i = 0; i<NUM_SURFACES; i++) {
1459 if (-1 != (ctx->src[i])) {
1460 LINK_c2dDestroySurface(ctx->src[i]);
1461 ctx->src[i] = -1;
1462 }
1463 if (-1 != (ctx->dst[i])) {
1464 LINK_c2dDestroySurface(ctx->dst[i]);
1465 ctx->dst[i] = -1;
1466 }
1467 }
1468 if (ctx->libc2d2)
1469 ::dlclose(ctx->libc2d2);
1470 if (ctx)
1471 free(ctx);
1472 status = COPYBIT_FAILURE;
1473 *device = NULL;
1474
1475 return status;
1476}