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