blob: 365be5f3d4c5fd796323994195840bb80313e018 [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;
Naseer Ahmed45a99602012-07-31 19:15:24 -0700128 bool mBlitToFB;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700129};
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
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700449 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700450 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{
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700704 unsigned int objects;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700705
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;
Naseer Ahmed45a99602012-07-31 19:15:24 -0700786 case COPYBIT_BLIT_TO_FRAMEBUFFER:
787 if (COPYBIT_ENABLE == value) {
788 ctx->mBlitToFB = value;
789 } else if (COPYBIT_DISABLE == value) {
790 ctx->mBlitToFB = value;
791 } else {
792 ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
793 __FUNCTION__, value);
794 }
795 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700796 default:
797 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
798 return -EINVAL;
799 break;
800 }
801
802 return COPYBIT_SUCCESS;
803}
804
805/** Get a static info value */
806static int get(struct copybit_device_t *dev, int name)
807{
808 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
809 int value;
810
811 if (!ctx) {
812 ALOGE("%s: null context error", __FUNCTION__);
813 return -EINVAL;
814 }
815
816 switch(name) {
817 case COPYBIT_MINIFICATION_LIMIT:
818 value = MAX_SCALE_FACTOR;
819 break;
820 case COPYBIT_MAGNIFICATION_LIMIT:
821 value = MAX_SCALE_FACTOR;
822 break;
823 case COPYBIT_SCALING_FRAC_BITS:
824 value = 32;
825 break;
826 case COPYBIT_ROTATION_STEP_DEG:
827 value = 1;
828 break;
829 default:
830 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
831 value = -EINVAL;
832 }
833 return value;
834}
835
836static int is_alpha(int cformat)
837{
838 int alpha = 0;
839 switch (cformat & 0xFF) {
840 case C2D_COLOR_FORMAT_8888_ARGB:
841 case C2D_COLOR_FORMAT_8888_RGBA:
842 case C2D_COLOR_FORMAT_5551_RGBA:
843 case C2D_COLOR_FORMAT_4444_ARGB:
844 alpha = 1;
845 break;
846 default:
847 alpha = 0;
848 break;
849 }
850
851 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
852 alpha = 0;
853
854 return alpha;
855}
856
857/* Function to check if we need a temporary buffer for the blit.
858 * This would happen if the requested destination stride and the
859 * C2D stride do not match. We ignore RGB buffers, since their
860 * stride is always aligned to 32.
861 */
862static bool need_temp_buffer(struct copybit_image_t const *img)
863{
864 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
865 return false;
866
867 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
868
869 // The width parameter in the handle contains the aligned_w. We check if we
870 // need to convert based on this param. YUV formats have bpp=1, so checking
871 // if the requested stride is aligned should suffice.
872 if (0 == (handle->width)%32) {
873 return false;
874 }
875
876 return true;
877}
878
879/* Function to extract the information from the copybit image and set the corresponding
880 * values in the bufferInfo struct.
881 */
882static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
883{
884 info.width = img->w;
885 info.height = img->h;
886 info.format = img->format;
887}
888
889/* Function to get the required size for a particular format, inorder for C2D to perform
890 * the blit operation.
891 */
892static size_t get_size(const bufferInfo& info)
893{
894 size_t size = 0;
895 int w = info.width;
896 int h = info.height;
897 int aligned_w = ALIGN(w, 32);
898 switch(info.format) {
899 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
900 {
901 // Chroma for this format is aligned to 2K.
902 size = ALIGN((aligned_w*h), 2048) +
903 ALIGN(w/2, 32) * h/2 *2;
904 size = ALIGN(size, 4096);
905 } break;
906 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
907 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
908 {
909 size = aligned_w*h +
910 ALIGN(w/2, 32) * h/2 *2;
911 size = ALIGN(size, 4096);
912 } break;
913 default: break;
914 }
915 return size;
916}
917
918/* Function to allocate memory for the temporary buffer. This memory is
919 * allocated from Ashmem. It is the caller's responsibility to free this
920 * memory.
921 */
922static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
923{
924 ALOGD("%s E", __FUNCTION__);
925 // Alloc memory from system heap
926 data.base = 0;
927 data.fd = -1;
928 data.offset = 0;
929 data.size = get_size(info);
930 data.align = getpagesize();
931 data.uncached = true;
932 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
933
934 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700935 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -0700936 }
937
938 if (sAlloc == 0) {
939 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
940 return COPYBIT_FAILURE;
941 }
942
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700943 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700944 if (0 != err) {
945 ALOGE("%s: allocate failed", __FUNCTION__);
946 return COPYBIT_FAILURE;
947 }
948
949 ALOGD("%s X", __FUNCTION__);
950 return err;
951}
952
953/* Function to free the temporary allocated memory.*/
954static void free_temp_buffer(alloc_data &data)
955{
956 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700957 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700958 memalloc->free_buffer(data.base, data.size, 0, data.fd);
959 }
960}
961
962/* Function to perform the software color conversion. Convert the
963 * C2D compatible format to the Android compatible format
964 */
965static int copy_image(private_handle_t *src_handle,
966 struct copybit_image_t const *rhs,
967 eConversionType conversionType)
968{
969 if (src_handle->fd == -1) {
970 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
971 return COPYBIT_FAILURE;
972 }
973
974 // Copy the info.
975 int ret = COPYBIT_SUCCESS;
976 switch(rhs->format) {
977 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
978 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
979 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
980 {
981 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
982 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
983 } else {
984 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
985 }
986
987 } break;
988 default: {
989 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
990 ret = COPYBIT_FAILURE;
991 } break;
992 }
993 return ret;
994}
995
996static void delete_handle(private_handle_t *handle)
997{
998 if (handle) {
999 delete handle;
1000 handle = 0;
1001 }
1002}
1003/** do a stretch blit type operation */
1004static int stretch_copybit_internal(
1005 struct copybit_device_t *dev,
1006 struct copybit_image_t const *dst,
1007 struct copybit_image_t const *src,
1008 struct copybit_rect_t const *dst_rect,
1009 struct copybit_rect_t const *src_rect,
1010 struct copybit_region_t const *region,
1011 bool enableBlend)
1012{
1013 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1014 int status = COPYBIT_SUCCESS;
1015 uint32 maxCount;
1016 uint32 src_mapped = 0, trg_mapped = 0;
1017 blitlist list;
1018 C2D_OBJECT *req;
1019 memset(&list, 0, sizeof(list));
1020 int cformat;
1021 c2d_ts_handle timestamp;
1022 uint32 src_surface_index = 0, dst_surface_index = 0;
1023
1024 if (!ctx) {
1025 ALOGE("%s: null context error", __FUNCTION__);
1026 return -EINVAL;
1027 }
1028
1029 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1030 ALOGE("%s: src dimension error", __FUNCTION__);
1031 return -EINVAL;
1032 }
1033
1034 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
1035 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, dst->h);
1036 return -EINVAL;
1037 }
1038
1039 maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
1040
1041 struct copybit_rect_t clip;
1042 list.count = 0;
1043
1044 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
1045 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format);
1046 return COPYBIT_FAILURE;
1047 }
1048
1049 bool isYUVDestination = false;
1050 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
1051 dst_surface_index = RGB_SURFACE;
1052 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
1053 isYUVDestination = true;
1054 int num_planes = get_num_planes(dst->format);
1055 if (num_planes == 2) {
1056 dst_surface_index = YUV_SURFACE_2_PLANES;
1057 } else if (num_planes == 3) {
1058 dst_surface_index = YUV_SURFACE_3_PLANES;
1059 } else {
1060 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1061 __FUNCTION__, dst->format);
1062 return COPYBIT_FAILURE;
1063 }
1064 } else {
1065 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format);
1066 return COPYBIT_FAILURE;
1067 }
1068
1069 copybit_image_t dst_image;
1070 dst_image.w = dst->w;
1071 dst_image.h = dst->h;
1072 dst_image.format = dst->format;
1073 dst_image.handle = dst->handle;
1074 // Check if we need a temp. copy for the destination. We'd need this the destination
1075 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1076 // aligned to 32.
1077 bool needTempDestination = need_temp_buffer(dst);
1078 bufferInfo dst_info;
1079 populate_buffer_info(dst, dst_info);
1080 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1081 dst_info.width, dst_info.height);
1082 if (dst_hnd == NULL) {
1083 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1084 return COPYBIT_FAILURE;
1085 }
1086 if (needTempDestination) {
1087 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1088 free_temp_buffer(ctx->temp_dst_buffer);
1089 // Create a temp buffer and set that as the destination.
1090 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1091 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1092 delete_handle(dst_hnd);
1093 return COPYBIT_FAILURE;
1094 }
1095 }
1096 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1097 dst_hnd->size = ctx->temp_dst_buffer.size;
1098 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
1099 dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
1100 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1101 dst_hnd->gpuaddr = 0;
1102 dst_image.handle = dst_hnd;
1103 }
1104
1105 int flags = 0;
1106 flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1107 flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0;
1108
1109 status = set_image( ctx->dst[dst_surface_index], &dst_image,
1110 &cformat, &trg_mapped, (eC2DFlags)flags);
1111 if(status) {
1112 ALOGE("%s: dst: set_image error", __FUNCTION__);
1113 delete_handle(dst_hnd);
1114 return COPYBIT_FAILURE;
1115 }
1116
1117 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
1118 src_surface_index = RGB_SURFACE;
1119 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1120 int num_planes = get_num_planes(src->format);
1121 if (num_planes == 2) {
1122 src_surface_index = YUV_SURFACE_2_PLANES;
1123 } else if (num_planes == 3) {
1124 src_surface_index = YUV_SURFACE_3_PLANES;
1125 } else {
1126 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1127 __FUNCTION__, src->format);
1128 delete_handle(dst_hnd);
1129 return -EINVAL;
1130 }
1131 } else {
1132 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format);
1133 delete_handle(dst_hnd);
1134 return -EINVAL;
1135 }
1136
1137 copybit_image_t src_image;
1138 src_image.w = src->w;
1139 src_image.h = src->h;
1140 src_image.format = src->format;
1141 src_image.handle = src->handle;
1142
1143 bool needTempSource = need_temp_buffer(src);
1144 bufferInfo src_info;
1145 populate_buffer_info(src, src_info);
1146 private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
1147 src_info.width, src_info.height);
1148 if (NULL == src_hnd) {
1149 ALOGE("%s: src_hnd is null", __FUNCTION__);
1150 delete_handle(dst_hnd);
1151 return COPYBIT_FAILURE;
1152 }
1153 if (needTempSource) {
1154 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1155 free_temp_buffer(ctx->temp_src_buffer);
1156 // Create a temp buffer and set that as the destination.
1157 if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) {
1158 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1159 delete_handle(dst_hnd);
1160 delete_handle(src_hnd);
1161 return COPYBIT_FAILURE;
1162 }
1163 }
1164 src_hnd->fd = ctx->temp_src_buffer.fd;
1165 src_hnd->size = ctx->temp_src_buffer.size;
1166 src_hnd->flags = ctx->temp_src_buffer.allocType;
1167 src_hnd->base = (int)(ctx->temp_src_buffer.base);
1168 src_hnd->offset = ctx->temp_src_buffer.offset;
1169 src_hnd->gpuaddr = 0;
1170 src_image.handle = src_hnd;
1171
1172 // Copy the source.
1173 copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT);
1174
1175 // Flush the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001176 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001177 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
1178 src_hnd->offset, src_hnd->fd)) {
1179 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1180 delete_handle(dst_hnd);
1181 delete_handle(src_hnd);
1182 return COPYBIT_FAILURE;
1183 }
1184 }
1185
1186 status = set_image( ctx->src[src_surface_index], &src_image,
1187 &cformat, &src_mapped, (eC2DFlags)flags);
1188 if(status) {
1189 ALOGE("%s: set_src_image error", __FUNCTION__);
1190 delete_handle(dst_hnd);
1191 delete_handle(src_hnd);
1192 return COPYBIT_FAILURE;
1193 }
1194
1195 if (enableBlend) {
1196 if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1197 ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1198 if(!(ctx->blitState.global_alpha)) {
1199 // src alpha is zero
1200 unset_image( ctx->src[src_surface_index],
1201 &src_image, src_mapped);
1202 unset_image( ctx->dst[dst_surface_index],
1203 &dst_image, trg_mapped);
1204 delete_handle(dst_hnd);
1205 delete_handle(src_hnd);
1206 return status;
1207 }
1208 } else {
1209 if(is_alpha(cformat))
1210 ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1211 else
1212 ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
1213 }
1214 } else {
1215 ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
1216 }
1217
1218 ctx->blitState.surface_id = ctx->src[src_surface_index];
1219
1220 while ((status == 0) && region->next(region, &clip)) {
1221 req = &(list.blitObjects[list.count]);
1222 memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
1223
1224 set_rects(ctx, req, dst_rect, src_rect, &clip);
1225
1226 if (++list.count == maxCount) {
1227 status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
1228 list.count = 0;
1229 }
1230 }
1231 if ((status == 0) && list.count) {
1232 status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
1233 }
1234
1235 if(LINK_c2dFinish(ctx->dst[dst_surface_index])) {
1236 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
1237 }
1238
1239 unset_image( ctx->src[src_surface_index], &src_image,
1240 src_mapped);
1241 unset_image( ctx->dst[dst_surface_index], &dst_image,
1242 trg_mapped);
1243 if (needTempDestination) {
1244 // copy the temp. destination without the alignment to the actual destination.
1245 copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1246 // Invalidate the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001247 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001248 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
1249 dst_hnd->offset, dst_hnd->fd);
1250 }
1251 delete_handle(dst_hnd);
1252 delete_handle(src_hnd);
1253 ctx->isPremultipliedAlpha = false;
1254 ctx->fb_width = 0;
1255 ctx->fb_height = 0;
1256 return status;
1257}
1258
1259static int stretch_copybit(
1260 struct copybit_device_t *dev,
1261 struct copybit_image_t const *dst,
1262 struct copybit_image_t const *src,
1263 struct copybit_rect_t const *dst_rect,
1264 struct copybit_rect_t const *src_rect,
1265 struct copybit_region_t const *region)
1266{
1267 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1268 bool needsBlending = (ctx->blitState.global_alpha != 0);
1269 return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
1270 region, needsBlending);
1271}
1272
1273/** Perform a blit type operation */
1274static int blit_copybit(
1275 struct copybit_device_t *dev,
1276 struct copybit_image_t const *dst,
1277 struct copybit_image_t const *src,
1278 struct copybit_region_t const *region)
1279{
1280 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
1281 struct copybit_rect_t sr = { 0, 0, src->w, src->h };
1282 return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1283}
1284
1285/*****************************************************************************/
1286
1287/** Close the copybit device */
1288static int close_copybit(struct hw_device_t *dev)
1289{
1290 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1291 if (ctx) {
1292 for(int i = 0; i <NUM_SURFACES; i++) {
1293 LINK_c2dDestroySurface(ctx->dst[i]);
1294 LINK_c2dDestroySurface(ctx->src[i]);
1295 }
1296
1297 if (ctx->libc2d2) {
1298 ::dlclose(ctx->libc2d2);
1299 ALOGV("dlclose(libc2d2)");
1300 }
1301
1302 free_temp_buffer(ctx->temp_src_buffer);
1303 free_temp_buffer(ctx->temp_dst_buffer);
1304 free(ctx);
1305 }
1306
1307 return 0;
1308}
1309
1310/** Open a new instance of a copybit device using name */
1311static int open_copybit(const struct hw_module_t* module, const char* name,
1312 struct hw_device_t** device)
1313{
1314 int status = COPYBIT_SUCCESS;
1315 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1316 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1317 struct copybit_context_t *ctx;
1318 char fbName[64];
1319
1320 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1321 if(!ctx) {
1322 ALOGE("%s: malloc failed", __FUNCTION__);
1323 return COPYBIT_FAILURE;
1324 }
1325
1326 /* initialize drawstate */
1327 memset(ctx, 0, sizeof(*ctx));
1328
1329 for (int i=0; i< NUM_SURFACES; i++) {
1330 ctx->dst[i] = -1;
1331 ctx->src[i] = -1;
1332 }
1333
1334 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1335 if (!ctx->libc2d2) {
1336 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
1337 goto error;
1338 }
1339 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1340 "c2dCreateSurface");
1341 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1342 "c2dUpdateSurface");
1343 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1344 "c2dReadSurface");
1345 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1346 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1347 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1348 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1349 "c2dWaitTimestamp");
1350 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1351 "c2dDestroySurface");
1352 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1353 "c2dMapAddr");
1354 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1355 "c2dUnMapAddr");
1356
1357 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
1358 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
1359 || !LINK_c2dDestroySurface) {
1360 ALOGE("%s: dlsym ERROR", __FUNCTION__);
1361 goto error;
1362 }
1363
1364 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1365 ctx->device.common.version = 1;
1366 ctx->device.common.module = (hw_module_t*)(module);
1367 ctx->device.common.close = close_copybit;
1368 ctx->device.set_parameter = set_parameter_copybit;
1369 ctx->device.get = get;
1370 ctx->device.blit = blit_copybit;
1371 ctx->device.stretch = stretch_copybit;
1372 ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
1373 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1374
1375 /* Create RGB Surface */
1376 surfDefinition.buffer = (void*)0xdddddddd;
1377 surfDefinition.phys = (void*)0xdddddddd;
1378 surfDefinition.stride = 1 * 4;
1379 surfDefinition.width = 1;
1380 surfDefinition.height = 1;
1381 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1382 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1383 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1384 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) {
1385 ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__);
1386 ctx->dst[RGB_SURFACE] = -1;
1387 goto error;
1388 }
1389
1390
1391 if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1392 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1393 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) {
1394 ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__);
1395 ctx->src[RGB_SURFACE] = -1;
1396 goto error;
1397 }
1398
1399 /* Create YUV source surface */
1400 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
1401
1402 yuvSurfaceDef.width = 4;
1403 yuvSurfaceDef.height = 4;
1404 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1405 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1406 yuvSurfaceDef.stride0 = 4;
1407
1408 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1409 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1410 yuvSurfaceDef.stride1 = 4;
1411
1412 if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),
1413 C2D_TARGET | C2D_SOURCE,
1414 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1415 &yuvSurfaceDef)) {
1416 ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
1417 ctx->src[YUV_SURFACE_2_PLANES] = -1;
1418 goto error;
1419 }
1420
1421 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1422 C2D_TARGET | C2D_SOURCE,
1423 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1424 &yuvSurfaceDef)) {
1425 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
1426 ctx->dst[YUV_SURFACE_2_PLANES] = -1;
1427 goto error;
1428 }
1429
1430 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1431 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1432 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1433 yuvSurfaceDef.stride2 = 4;
1434
1435 if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),
1436 C2D_TARGET | C2D_SOURCE,
1437 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1438 &yuvSurfaceDef)) {
1439 ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
1440 ctx->src[YUV_SURFACE_3_PLANES] = -1;
1441 goto error;
1442 }
1443
1444 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1445 C2D_TARGET | C2D_SOURCE,
1446 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
1447 &yuvSurfaceDef)) {
1448 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
1449 ctx->dst[YUV_SURFACE_3_PLANES] = -1;
1450 goto error;
1451 }
1452
1453 ctx->temp_src_buffer.fd = -1;
1454 ctx->temp_src_buffer.base = 0;
1455 ctx->temp_src_buffer.size = 0;
1456
1457 ctx->temp_dst_buffer.fd = -1;
1458 ctx->temp_dst_buffer.base = 0;
1459 ctx->temp_dst_buffer.size = 0;
1460
1461 ctx->fb_width = 0;
1462 ctx->fb_height = 0;
1463 ctx->isPremultipliedAlpha = false;
1464
1465 *device = &ctx->device.common;
1466 return status;
1467
1468error:
1469 for (int i = 0; i<NUM_SURFACES; i++) {
1470 if (-1 != (ctx->src[i])) {
1471 LINK_c2dDestroySurface(ctx->src[i]);
1472 ctx->src[i] = -1;
1473 }
1474 if (-1 != (ctx->dst[i])) {
1475 LINK_c2dDestroySurface(ctx->dst[i]);
1476 ctx->dst[i] = -1;
1477 }
1478 }
1479 if (ctx->libc2d2)
1480 ::dlclose(ctx->libc2d2);
1481 if (ctx)
1482 free(ctx);
1483 status = COPYBIT_FAILURE;
1484 *device = NULL;
1485
1486 return status;
1487}