blob: c1862420c3bf283723f9707f3cf910dbe40e8d09 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08003 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
Naseer Ahmed29a26812012-06-14 00:56:20 -07007 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
Naseer Ahmed29a26812012-06-14 00:56:20 -070020#include <cutils/log.h>
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -080021#include <sys/resource.h>
22#include <sys/prctl.h>
Naseer Ahmed29a26812012-06-14 00:56:20 -070023
24#include <stdint.h>
25#include <string.h>
26#include <unistd.h>
27#include <errno.h>
28#include <fcntl.h>
29
30#include <sys/ioctl.h>
31#include <sys/types.h>
32#include <sys/mman.h>
33
34#include <linux/msm_kgsl.h>
35
36#include <EGL/eglplatform.h>
37#include <cutils/native_handle.h>
38#include <cutils/ashmem.h>
39#include <linux/ashmem.h>
40#include <gralloc_priv.h>
41
42#include <copybit.h>
43#include <alloc_controller.h>
44#include <memalloc.h>
45
46#include "c2d2.h"
47#include "software_converter.h"
48
49#include <dlfcn.h>
50
51using gralloc::IMemAlloc;
52using gralloc::IonController;
53using gralloc::alloc_data;
Naseer Ahmed29a26812012-06-14 00:56:20 -070054
55C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
56 uint32 surface_bits,
57 C2D_SURFACE_TYPE surface_type,
58 void *surface_definition );
59
60C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
61 uint32 surface_bits,
62 C2D_SURFACE_TYPE surface_type,
63 void *surface_definition );
64
65C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
66 C2D_SURFACE_TYPE surface_type,
67 void *surface_definition,
68 int32 x, int32 y );
69
70C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
71 uint32 target_config, C2D_RECT *target_scissor,
72 uint32 target_mask_id, uint32 target_color_key,
73 C2D_OBJECT *objects_list, uint32 num_objects );
74
75C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
76
77C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
78
79C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
80
81C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
82
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -080083C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len,
84 uint32 offset, uint32 flags, void ** gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -070085
86C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
87
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -080088C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -080089
90/* create a fence fd for the timestamp */
91C2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
92 int32 *fd);
Naseer Ahmed29a26812012-06-14 00:56:20 -070093/******************************************************************************/
94
95#if defined(COPYBIT_Z180)
96#define MAX_SCALE_FACTOR (4096)
97#define MAX_DIMENSION (4096)
98#else
99#error "Unsupported HW version"
100#endif
101
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800102// The following defines can be changed as required i.e. as we encounter
103// complex use cases.
104#define MAX_RGB_SURFACES 8 // Max. RGB layers currently supported per draw
105#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
106#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
107// +1 for the destination surface. We cannot have multiple destination surfaces.
108#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
109#define NUM_SURFACE_TYPES 3 // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
110#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
Naseer Ahmed29a26812012-06-14 00:56:20 -0700111
112enum {
113 RGB_SURFACE,
114 YUV_SURFACE_2_PLANES,
115 YUV_SURFACE_3_PLANES
116};
117
118enum eConversionType {
119 CONVERT_TO_ANDROID_FORMAT,
120 CONVERT_TO_C2D_FORMAT
121};
122
123enum eC2DFlags {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800124 FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
125 FLAGS_YUV_DESTINATION = 1<<1,
126 FLAGS_TEMP_SRC_DST = 1<<2
Naseer Ahmed29a26812012-06-14 00:56:20 -0700127};
128
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700129static gralloc::IAllocController* sAlloc = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700130/******************************************************************************/
131
132/** State information for each device instance */
133struct copybit_context_t {
134 struct copybit_device_t device;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800135 // Templates for the various source surfaces. These templates are created
136 // to avoid the expensive create/destroy C2D Surfaces
137 C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
138 C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
139 C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
140 C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
141 C2D_DRIVER_INFO c2d_driver_info;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700142 void *libc2d2;
143 alloc_data temp_src_buffer;
144 alloc_data temp_dst_buffer;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800145 unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
146 unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
147 int blit_rgb_count; // Total RGB surfaces being blit
148 int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
149 int blit_yuv_3_plane_count; // Total 3 plane YUV surfaces being blit
150 int blit_count; // Total blit objects.
151 unsigned int trg_transform; /* target transform */
Naseer Ahmed29a26812012-06-14 00:56:20 -0700152 int fb_width;
153 int fb_height;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800154 int src_global_alpha;
155 int config_mask;
156 int dst_surface_type;
157 bool is_premultiplied_alpha;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800158 void* time_stamp;
159
160 // used for signaling the wait thread
161 bool wait_timestamp;
162 pthread_t wait_thread_id;
163 bool stop_thread;
164 pthread_mutex_t wait_cleanup_lock;
165 pthread_cond_t wait_cleanup_cond;
166
Naseer Ahmed29a26812012-06-14 00:56:20 -0700167};
168
169struct bufferInfo {
170 int width;
171 int height;
172 int format;
173};
174
175struct yuvPlaneInfo {
176 int yStride; //luma stride
177 int plane1_stride;
178 int plane2_stride;
179 int plane1_offset;
180 int plane2_offset;
181};
182
183/**
184 * Common hardware methods
185 */
186
187static int open_copybit(const struct hw_module_t* module, const char* name,
188 struct hw_device_t** device);
189
190static struct hw_module_methods_t copybit_module_methods = {
191open: open_copybit
192};
193
194/*
195 * The COPYBIT Module
196 */
197struct copybit_module_t HAL_MODULE_INFO_SYM = {
198common: {
199tag: HARDWARE_MODULE_TAG,
200 version_major: 1,
201 version_minor: 0,
202 id: COPYBIT_HARDWARE_MODULE_ID,
203 name: "QCT COPYBIT C2D 2.0 Module",
204 author: "Qualcomm",
205 methods: &copybit_module_methods
206 }
207};
208
209
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800210/* thread function which waits on the timeStamp and cleans up the surfaces */
211static void* c2d_wait_loop(void* ptr) {
212 copybit_context_t* ctx = (copybit_context_t*)(ptr);
213 char thread_name[64] = "copybitWaitThr";
214 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
215 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
216
217 while(ctx->stop_thread == false) {
218 pthread_mutex_lock(&ctx->wait_cleanup_lock);
219 while(ctx->wait_timestamp == false && !ctx->stop_thread) {
220 pthread_cond_wait(&(ctx->wait_cleanup_cond),
221 &(ctx->wait_cleanup_lock));
222 }
223 if(ctx->wait_timestamp) {
224 if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
225 ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
226 }
227 ctx->wait_timestamp = false;
228 // Unmap any mapped addresses.
229 for (int i = 0; i < MAX_SURFACES; i++) {
230 if (ctx->mapped_gpu_addr[i]) {
231 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
232 ctx->mapped_gpu_addr[i] = 0;
233 }
234 }
235 // Reset the counts after the draw.
236 ctx->blit_rgb_count = 0;
237 ctx->blit_yuv_2_plane_count = 0;
238 ctx->blit_yuv_3_plane_count = 0;
239 ctx->blit_count = 0;
240 }
241 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
242 if(ctx->stop_thread)
243 break;
244 }
245 pthread_exit(NULL);
246 return NULL;
247}
248
249
Naseer Ahmed29a26812012-06-14 00:56:20 -0700250/* convert COPYBIT_FORMAT to C2D format */
251static int get_format(int format) {
252 switch (format) {
253 case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
254 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
255 C2D_FORMAT_SWAP_RB |
256 C2D_FORMAT_DISABLE_ALPHA;
257 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
258 C2D_FORMAT_SWAP_RB;
259 case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
260 case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA;
261 case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA;
262 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
263 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
264 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
265 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
266 C2D_FORMAT_MACROTILED;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800267 default: ALOGE("%s: invalid format (0x%x",
268 __FUNCTION__, format);
269 return -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700270 }
271 return -EINVAL;
272}
273
274/* Get the C2D formats needed for conversion to YUV */
275static int get_c2d_format_for_yuv_destination(int halFormat) {
276 switch (halFormat) {
277 // We do not swap the RB when the target is YUV
278 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
279 C2D_FORMAT_DISABLE_ALPHA;
280 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800281 // The U and V need to be interchanged when the target is YUV
Naseer Ahmed29a26812012-06-14 00:56:20 -0700282 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
283 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
284 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
285 default: return get_format(halFormat);
286 }
287 return -EINVAL;
288}
289
290/* ------------------------------------------------------------------- *//*!
291 * \internal
292 * \brief Get the bpp for a particular color format
293 * \param color format
294 * \return bits per pixel
295 *//* ------------------------------------------------------------------- */
296int c2diGetBpp(int32 colorformat)
297{
298
299 int c2dBpp = 0;
300
301 switch(colorformat&0xFF)
302 {
303 case C2D_COLOR_FORMAT_4444_RGBA:
304 case C2D_COLOR_FORMAT_4444_ARGB:
305 case C2D_COLOR_FORMAT_1555_ARGB:
306 case C2D_COLOR_FORMAT_565_RGB:
307 case C2D_COLOR_FORMAT_5551_RGBA:
308 c2dBpp = 16;
309 break;
310 case C2D_COLOR_FORMAT_8888_RGBA:
311 case C2D_COLOR_FORMAT_8888_ARGB:
312 c2dBpp = 32;
313 break;
314 case C2D_COLOR_FORMAT_8_L:
315 case C2D_COLOR_FORMAT_8_A:
316 c2dBpp = 8;
317 break;
318 case C2D_COLOR_FORMAT_4_A:
319 c2dBpp = 4;
320 break;
321 case C2D_COLOR_FORMAT_1:
322 c2dBpp = 1;
323 break;
324 default:
325 ALOGE("%s ERROR", __func__);
326 break;
327 }
328 return c2dBpp;
329}
330
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800331static uint32 c2d_get_gpuaddr(copybit_context_t* ctx, struct private_handle_t *handle,
332 int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700333{
334 uint32 memtype, *gpuaddr;
335 C2D_STATUS rc;
336
337 if(!handle)
338 return 0;
339
340 if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
341 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
342 memtype = KGSL_USER_MEM_TYPE_PMEM;
343 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
344 memtype = KGSL_USER_MEM_TYPE_ASHMEM;
345 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
346 memtype = KGSL_USER_MEM_TYPE_ION;
347 else {
348 ALOGE("Invalid handle flags: 0x%x", handle->flags);
349 return 0;
350 }
351
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800352 rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
353 handle->offset, memtype, (void**)&gpuaddr);
354
Naseer Ahmed29a26812012-06-14 00:56:20 -0700355 if (rc == C2D_STATUS_OK) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800356 // We have mapped the GPU address inside copybit. We need to unmap this
357 // address after the blit. Store this address
358 for (int i = 0; i < MAX_SURFACES; i++) {
359 if (ctx->mapped_gpu_addr[i] == 0) {
360 ctx->mapped_gpu_addr[i] = (uint32) gpuaddr;
361 mapped_idx = i;
362 break;
363 }
364 }
365
Naseer Ahmed29a26812012-06-14 00:56:20 -0700366 return (uint32) gpuaddr;
367 }
368 return 0;
369}
370
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800371static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
372{
373 if (!ctx || (mapped_idx == -1))
374 return;
375
376 if (ctx->mapped_gpu_addr[mapped_idx]) {
377 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
378 ctx->mapped_gpu_addr[mapped_idx] = 0;
379 }
380}
381
Naseer Ahmed29a26812012-06-14 00:56:20 -0700382static int is_supported_rgb_format(int format)
383{
384 switch(format) {
385 case HAL_PIXEL_FORMAT_RGBA_8888:
386 case HAL_PIXEL_FORMAT_RGBX_8888:
387 case HAL_PIXEL_FORMAT_RGB_565:
388 case HAL_PIXEL_FORMAT_BGRA_8888:
389 case HAL_PIXEL_FORMAT_RGBA_5551:
390 case HAL_PIXEL_FORMAT_RGBA_4444: {
391 return COPYBIT_SUCCESS;
392 }
393 default:
394 return COPYBIT_FAILURE;
395 }
396}
397
398static int get_num_planes(int format)
399{
400 switch(format) {
401 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
402 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
403 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
404 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
405 return 2;
406 }
407 case HAL_PIXEL_FORMAT_YV12: {
408 return 3;
409 }
410 default:
411 return COPYBIT_FAILURE;
412 }
413}
414
415static int is_supported_yuv_format(int format)
416{
417 switch(format) {
418 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
419 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
420 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
421 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
422 return COPYBIT_SUCCESS;
423 }
424 default:
425 return COPYBIT_FAILURE;
426 }
427}
428
429static int is_valid_destination_format(int format)
430{
431 if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
432 // C2D does not support NV12Tile as a destination format.
433 return COPYBIT_FAILURE;
434 }
435 return COPYBIT_SUCCESS;
436}
437
438static int calculate_yuv_offset_and_stride(const bufferInfo& info,
439 yuvPlaneInfo& yuvInfo)
440{
441 int width = info.width;
442 int height = info.height;
443 int format = info.format;
444
445 int aligned_height = 0;
446 int aligned_width = 0, size = 0;
447
448 switch (format) {
449 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
450 /* NV12 Tile buffers have their luma height aligned to 32bytes and width
451 * aligned to 128 bytes. The chroma offset starts at an 8K boundary
452 */
453 aligned_height = ALIGN(height, 32);
454 aligned_width = ALIGN(width, 128);
455 size = aligned_width * aligned_height;
456 yuvInfo.plane1_offset = ALIGN(size,8192);
457 yuvInfo.yStride = aligned_width;
458 yuvInfo.plane1_stride = aligned_width;
459 break;
460 }
461 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
462 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
463 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
464 aligned_width = ALIGN(width, 32);
465 yuvInfo.yStride = aligned_width;
466 yuvInfo.plane1_stride = aligned_width;
467 if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
468 // The encoder requires a 2K aligned chroma offset
469 yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
470 } else
471 yuvInfo.plane1_offset = aligned_width * height;
472
473 break;
474 }
475 default: {
476 return COPYBIT_FAILURE;
477 }
478 }
479 return COPYBIT_SUCCESS;
480}
481
482/** create C2D surface from copybit image */
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800483static int set_image(copybit_context_t* ctx, uint32 surfaceId,
484 const struct copybit_image_t *rhs,
485 const eC2DFlags flags, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700486{
487 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
488 C2D_SURFACE_TYPE surfaceType;
489 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800490 uint32 gpuaddr = 0;
491 int c2d_format;
492 mapped_idx = -1;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700493
494 if (flags & FLAGS_YUV_DESTINATION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800495 c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700496 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800497 c2d_format = get_format(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700498 }
499
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800500 if(c2d_format == -EINVAL) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700501 ALOGE("%s: invalid format", __FUNCTION__);
502 return -EINVAL;
503 }
504
505 if(handle == NULL) {
506 ALOGE("%s: invalid handle", __func__);
507 return -EINVAL;
508 }
509
510 if (handle->gpuaddr == 0) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800511 gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
512 if(!gpuaddr) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700513 ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
514 return COPYBIT_FAILURE;
515 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800516 } else {
517 gpuaddr = handle->gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700518 }
519
520 /* create C2D surface */
521 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
522 /* RGB */
523 C2D_RGB_SURFACE_DEF surfaceDef;
524
525 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
526
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800527 surfaceDef.phys = (void*) gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700528 surfaceDef.buffer = (void*) (handle->base);
529
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800530 surfaceDef.format = c2d_format |
Naseer Ahmed29a26812012-06-14 00:56:20 -0700531 ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
532 surfaceDef.width = rhs->w;
533 surfaceDef.height = rhs->h;
534 int aligned_width = ALIGN(surfaceDef.width,32);
535 surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
536
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800537 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
538 &surfaceDef)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700539 ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800540 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700541 status = COPYBIT_FAILURE;
542 }
543 } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
544 C2D_YUV_SURFACE_DEF surfaceDef;
545 memset(&surfaceDef, 0, sizeof(surfaceDef));
546 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800547 surfaceDef.format = c2d_format;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700548
549 bufferInfo info;
550 info.width = rhs->w;
551 info.height = rhs->h;
552 info.format = rhs->format;
553
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700554 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700555 status = calculate_yuv_offset_and_stride(info, yuvInfo);
556 if(status != COPYBIT_SUCCESS) {
557 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800558 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700559 }
560
561 surfaceDef.width = rhs->w;
562 surfaceDef.height = rhs->h;
563 surfaceDef.plane0 = (void*) (handle->base);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800564 surfaceDef.phys0 = (void*) (gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700565 surfaceDef.stride0 = yuvInfo.yStride;
566
567 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800568 surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700569 surfaceDef.stride1 = yuvInfo.plane1_stride;
570 if (3 == get_num_planes(rhs->format)) {
571 surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800572 surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700573 surfaceDef.stride2 = yuvInfo.plane2_stride;
574 }
575
576 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
577 &surfaceDef)) {
578 ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800579 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700580 status = COPYBIT_FAILURE;
581 }
582 } else {
583 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800584 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700585 status = COPYBIT_FAILURE;
586 }
587
588 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700589}
590
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800591/** copy the bits */
592static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700593{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800594 if (ctx->blit_count == 0) {
595 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700596 }
597
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800598 for (int i = 0; i < ctx->blit_count; i++)
599 {
600 ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
601 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800602 ctx->blit_list[ctx->blit_count-1].next = NULL;
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800603 uint32_t target_transform = ctx->trg_transform;
604 if (ctx->c2d_driver_info.capabilities_mask &
605 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
606 // For A3xx - set 0x0 as the transform is set in the config_mask
607 target_transform = 0x0;
608 }
609 if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800610 ctx->blit_count)) {
611 ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
612 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700613 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700614 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700615}
616
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800617
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800618
619static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
620{
621 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
622 int status = COPYBIT_FAILURE;
623 if (!ctx)
624 return COPYBIT_FAILURE;
625 pthread_mutex_lock(&ctx->wait_cleanup_lock);
626 status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
627
628 if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
629 ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
630 // unlock the mutex and return failure
631 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
632 return COPYBIT_FAILURE;
633 }
634 if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
635 fd)) {
636 ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
637 status = COPYBIT_FAILURE;
638 }
639 if(status == COPYBIT_SUCCESS) {
640 //signal the wait_thread
641 ctx->wait_timestamp = true;
642 pthread_cond_signal(&ctx->wait_cleanup_cond);
643 }
644 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
645 return status;
646}
647
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800648static int finish_copybit(struct copybit_device_t *dev)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700649{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800650 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
651 if (!ctx)
652 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700653
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800654 int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700655
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800656 if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
657 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
658 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700659 }
660
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800661 // Unmap any mapped addresses.
662 for (int i = 0; i < MAX_SURFACES; i++) {
663 if (ctx->mapped_gpu_addr[i]) {
664 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
665 ctx->mapped_gpu_addr[i] = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700666 }
667 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700668
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800669 // Reset the counts after the draw.
670 ctx->blit_rgb_count = 0;
671 ctx->blit_yuv_2_plane_count = 0;
672 ctx->blit_yuv_3_plane_count = 0;
673 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700674 return status;
675}
676
677/** setup rectangles */
678static void set_rects(struct copybit_context_t *ctx,
679 C2D_OBJECT *c2dObject,
680 const struct copybit_rect_t *dst,
681 const struct copybit_rect_t *src,
682 const struct copybit_rect_t *scissor)
683{
684 // Set the target rect.
685 if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
686 (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
687 /* target rotation is 270 */
688 c2dObject->target_rect.x = (dst->t)<<16;
689 c2dObject->target_rect.y = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
690 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
691 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
692 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
693 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
694 c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
695 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
696 c2dObject->target_rect.y = (dst->l)<<16;
697 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
698 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
699 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
700 c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
701 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
702 c2dObject->target_rect.x = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
703 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
704 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
705 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
706 } else {
707 c2dObject->target_rect.x = (dst->l)<<16;
708 c2dObject->target_rect.y = (dst->t)<<16;
709 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
710 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
711 }
712 c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
713
714 // Set the source rect
715 c2dObject->source_rect.x = (src->l)<<16;
716 c2dObject->source_rect.y = (src->t)<<16;
717 c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
718 c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
719 c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
720
721 // Set the scissor rect
722 c2dObject->scissor_rect.x = scissor->l;
723 c2dObject->scissor_rect.y = scissor->t;
724 c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
725 c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
726 c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
727}
728
Naseer Ahmed29a26812012-06-14 00:56:20 -0700729/*****************************************************************************/
730
731/** Set a parameter to value */
732static int set_parameter_copybit(
733 struct copybit_device_t *dev,
734 int name,
735 int value)
736{
737 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800738 int status = COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700739 if (!ctx) {
740 ALOGE("%s: null context", __FUNCTION__);
741 return -EINVAL;
742 }
743
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800744 pthread_mutex_lock(&ctx->wait_cleanup_lock);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700745 switch(name) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700746 case COPYBIT_PLANE_ALPHA:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800747 {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700748 if (value < 0) value = 0;
749 if (value >= 256) value = 255;
750
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800751 ctx->src_global_alpha = value;
752 if (value < 255)
753 ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700754 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800755 ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
756 }
757 break;
758 case COPYBIT_BLEND_MODE:
759 {
760 if (value == COPYBIT_BLENDING_NONE) {
761 ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
762 ctx->is_premultiplied_alpha = true;
763 } else if (value == COPYBIT_BLENDING_PREMULT) {
764 ctx->is_premultiplied_alpha = true;
765 } else {
766 ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700767 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800768 }
769 break;
770 case COPYBIT_TRANSFORM:
771 {
772 unsigned int transform = 0;
773 uint32 config_mask = 0;
774 config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
775 if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
776 transform = C2D_TARGET_ROTATE_180;
777 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
778 } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
779 transform = C2D_TARGET_ROTATE_90;
780 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
781 } else if(value == COPYBIT_TRANSFORM_ROT_90) {
782 transform = C2D_TARGET_ROTATE_270;
783 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
784 } else {
785 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
786 if(value & COPYBIT_TRANSFORM_FLIP_H) {
787 config_mask |= C2D_MIRROR_H_BIT;
788 } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
789 config_mask |= C2D_MIRROR_V_BIT;
790 }
791 }
792
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800793 if (ctx->c2d_driver_info.capabilities_mask &
794 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
795 ctx->config_mask |= config_mask;
796 } else {
797 // The transform for this surface does not match the current
798 // target transform. Draw all previous surfaces. This will be
799 // changed once we have a new mechanism to send different
800 // target rotations to c2d.
801 finish_copybit(dev);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800802 }
803 ctx->trg_transform = transform;
804 }
805 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700806 case COPYBIT_FRAMEBUFFER_WIDTH:
807 ctx->fb_width = value;
808 break;
809 case COPYBIT_FRAMEBUFFER_HEIGHT:
810 ctx->fb_height = value;
811 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800812 case COPYBIT_ROTATION_DEG:
813 case COPYBIT_DITHER:
814 case COPYBIT_BLUR:
Naseer Ahmed45a99602012-07-31 19:15:24 -0700815 case COPYBIT_BLIT_TO_FRAMEBUFFER:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800816 // Do nothing
Naseer Ahmed45a99602012-07-31 19:15:24 -0700817 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700818 default:
819 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800820 status = -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700821 break;
822 }
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800823 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
824 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700825}
826
827/** Get a static info value */
828static int get(struct copybit_device_t *dev, int name)
829{
830 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
831 int value;
832
833 if (!ctx) {
834 ALOGE("%s: null context error", __FUNCTION__);
835 return -EINVAL;
836 }
837
838 switch(name) {
839 case COPYBIT_MINIFICATION_LIMIT:
840 value = MAX_SCALE_FACTOR;
841 break;
842 case COPYBIT_MAGNIFICATION_LIMIT:
843 value = MAX_SCALE_FACTOR;
844 break;
845 case COPYBIT_SCALING_FRAC_BITS:
846 value = 32;
847 break;
848 case COPYBIT_ROTATION_STEP_DEG:
849 value = 1;
850 break;
851 default:
852 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
853 value = -EINVAL;
854 }
855 return value;
856}
857
858static int is_alpha(int cformat)
859{
860 int alpha = 0;
861 switch (cformat & 0xFF) {
862 case C2D_COLOR_FORMAT_8888_ARGB:
863 case C2D_COLOR_FORMAT_8888_RGBA:
864 case C2D_COLOR_FORMAT_5551_RGBA:
865 case C2D_COLOR_FORMAT_4444_ARGB:
866 alpha = 1;
867 break;
868 default:
869 alpha = 0;
870 break;
871 }
872
873 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
874 alpha = 0;
875
876 return alpha;
877}
878
879/* Function to check if we need a temporary buffer for the blit.
880 * This would happen if the requested destination stride and the
881 * C2D stride do not match. We ignore RGB buffers, since their
882 * stride is always aligned to 32.
883 */
884static bool need_temp_buffer(struct copybit_image_t const *img)
885{
886 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
887 return false;
888
889 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
890
891 // The width parameter in the handle contains the aligned_w. We check if we
892 // need to convert based on this param. YUV formats have bpp=1, so checking
893 // if the requested stride is aligned should suffice.
894 if (0 == (handle->width)%32) {
895 return false;
896 }
897
898 return true;
899}
900
901/* Function to extract the information from the copybit image and set the corresponding
902 * values in the bufferInfo struct.
903 */
904static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
905{
906 info.width = img->w;
907 info.height = img->h;
908 info.format = img->format;
909}
910
911/* Function to get the required size for a particular format, inorder for C2D to perform
912 * the blit operation.
913 */
914static size_t get_size(const bufferInfo& info)
915{
916 size_t size = 0;
917 int w = info.width;
918 int h = info.height;
919 int aligned_w = ALIGN(w, 32);
920 switch(info.format) {
921 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
922 {
923 // Chroma for this format is aligned to 2K.
924 size = ALIGN((aligned_w*h), 2048) +
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800925 ALIGN(aligned_w/2, 32) * (h/2) *2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700926 size = ALIGN(size, 4096);
927 } break;
928 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
929 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
930 {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800931 size = aligned_w * h +
932 ALIGN(aligned_w/2, 32) * (h/2) * 2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700933 size = ALIGN(size, 4096);
934 } break;
935 default: break;
936 }
937 return size;
938}
939
940/* Function to allocate memory for the temporary buffer. This memory is
941 * allocated from Ashmem. It is the caller's responsibility to free this
942 * memory.
943 */
944static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
945{
946 ALOGD("%s E", __FUNCTION__);
947 // Alloc memory from system heap
948 data.base = 0;
949 data.fd = -1;
950 data.offset = 0;
951 data.size = get_size(info);
952 data.align = getpagesize();
953 data.uncached = true;
954 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
955
956 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700957 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -0700958 }
959
960 if (sAlloc == 0) {
961 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
962 return COPYBIT_FAILURE;
963 }
964
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700965 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700966 if (0 != err) {
967 ALOGE("%s: allocate failed", __FUNCTION__);
968 return COPYBIT_FAILURE;
969 }
970
971 ALOGD("%s X", __FUNCTION__);
972 return err;
973}
974
975/* Function to free the temporary allocated memory.*/
976static void free_temp_buffer(alloc_data &data)
977{
978 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700979 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700980 memalloc->free_buffer(data.base, data.size, 0, data.fd);
981 }
982}
983
984/* Function to perform the software color conversion. Convert the
985 * C2D compatible format to the Android compatible format
986 */
987static int copy_image(private_handle_t *src_handle,
988 struct copybit_image_t const *rhs,
989 eConversionType conversionType)
990{
991 if (src_handle->fd == -1) {
992 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
993 return COPYBIT_FAILURE;
994 }
995
996 // Copy the info.
997 int ret = COPYBIT_SUCCESS;
998 switch(rhs->format) {
999 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1000 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1001 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1002 {
1003 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
1004 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
1005 } else {
1006 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
1007 }
1008
1009 } break;
1010 default: {
1011 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
1012 ret = COPYBIT_FAILURE;
1013 } break;
1014 }
1015 return ret;
1016}
1017
1018static void delete_handle(private_handle_t *handle)
1019{
1020 if (handle) {
1021 delete handle;
1022 handle = 0;
1023 }
1024}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001025
1026static bool need_to_execute_draw(struct copybit_context_t* ctx,
1027 eC2DFlags flags)
1028{
1029 if (flags & FLAGS_TEMP_SRC_DST) {
1030 return true;
1031 }
1032 if (flags & FLAGS_YUV_DESTINATION) {
1033 return true;
1034 }
1035 return false;
1036}
1037
Naseer Ahmed29a26812012-06-14 00:56:20 -07001038/** do a stretch blit type operation */
1039static int stretch_copybit_internal(
1040 struct copybit_device_t *dev,
1041 struct copybit_image_t const *dst,
1042 struct copybit_image_t const *src,
1043 struct copybit_rect_t const *dst_rect,
1044 struct copybit_rect_t const *src_rect,
1045 struct copybit_region_t const *region,
1046 bool enableBlend)
1047{
1048 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1049 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001050 int flags = 0;
1051 int src_surface_type;
1052 int mapped_src_idx = -1, mapped_dst_idx = -1;
1053 C2D_OBJECT_STR src_surface;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001054
1055 if (!ctx) {
1056 ALOGE("%s: null context error", __FUNCTION__);
1057 return -EINVAL;
1058 }
1059
1060 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1061 ALOGE("%s: src dimension error", __FUNCTION__);
1062 return -EINVAL;
1063 }
1064
1065 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001066 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w,
1067 dst->h);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001068 return -EINVAL;
1069 }
1070
Naseer Ahmed29a26812012-06-14 00:56:20 -07001071 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001072 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
1073 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001074 return COPYBIT_FAILURE;
1075 }
1076
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001077 int dst_surface_type;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001078 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001079 dst_surface_type = RGB_SURFACE;
1080 flags |= FLAGS_PREMULTIPLIED_ALPHA;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001081 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001082 int num_planes = get_num_planes(dst->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001083 flags |= FLAGS_YUV_DESTINATION;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001084 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001085 dst_surface_type = YUV_SURFACE_2_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001086 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001087 dst_surface_type = YUV_SURFACE_3_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001088 } else {
1089 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1090 __FUNCTION__, dst->format);
1091 return COPYBIT_FAILURE;
1092 }
1093 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001094 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
1095 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001096 return COPYBIT_FAILURE;
1097 }
1098
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001099 if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
1100 ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1101 ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1102 ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
1103 ctx->dst_surface_type != dst_surface_type) {
1104 // we have reached the max. limits of our internal structures or
1105 // changed the target.
1106 // Draw the remaining surfaces. We need to do the finish here since
1107 // we need to free up the surface templates.
1108 finish_copybit(dev);
1109 }
1110
1111 ctx->dst_surface_type = dst_surface_type;
1112
1113 // Update the destination
Naseer Ahmed29a26812012-06-14 00:56:20 -07001114 copybit_image_t dst_image;
1115 dst_image.w = dst->w;
1116 dst_image.h = dst->h;
1117 dst_image.format = dst->format;
1118 dst_image.handle = dst->handle;
1119 // Check if we need a temp. copy for the destination. We'd need this the destination
1120 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1121 // aligned to 32.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001122 bool need_temp_dst = need_temp_buffer(dst);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001123 bufferInfo dst_info;
1124 populate_buffer_info(dst, dst_info);
1125 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1126 dst_info.width, dst_info.height);
1127 if (dst_hnd == NULL) {
1128 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1129 return COPYBIT_FAILURE;
1130 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001131 if (need_temp_dst) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001132 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1133 free_temp_buffer(ctx->temp_dst_buffer);
1134 // Create a temp buffer and set that as the destination.
1135 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1136 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1137 delete_handle(dst_hnd);
1138 return COPYBIT_FAILURE;
1139 }
1140 }
1141 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1142 dst_hnd->size = ctx->temp_dst_buffer.size;
1143 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
1144 dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
1145 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1146 dst_hnd->gpuaddr = 0;
1147 dst_image.handle = dst_hnd;
1148 }
1149
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001150 status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
1151 (eC2DFlags)flags, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001152 if(status) {
1153 ALOGE("%s: dst: set_image error", __FUNCTION__);
1154 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001155 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001156 return COPYBIT_FAILURE;
1157 }
1158
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001159 // Update the source
1160 flags = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001161 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001162 src_surface_type = RGB_SURFACE;
1163 src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001164 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1165 int num_planes = get_num_planes(src->format);
1166 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001167 src_surface_type = YUV_SURFACE_2_PLANES;
1168 src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001169 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001170 src_surface_type = YUV_SURFACE_3_PLANES;
1171 src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001172 } else {
1173 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1174 __FUNCTION__, src->format);
1175 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001176 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001177 return -EINVAL;
1178 }
1179 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001180 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
1181 src->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001182 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001183 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001184 return -EINVAL;
1185 }
1186
1187 copybit_image_t src_image;
1188 src_image.w = src->w;
1189 src_image.h = src->h;
1190 src_image.format = src->format;
1191 src_image.handle = src->handle;
1192
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001193 bool need_temp_src = need_temp_buffer(src);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001194 bufferInfo src_info;
1195 populate_buffer_info(src, src_info);
1196 private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001197 src_info.width, src_info.height);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001198 if (NULL == src_hnd) {
1199 ALOGE("%s: src_hnd is null", __FUNCTION__);
1200 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001201 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001202 return COPYBIT_FAILURE;
1203 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001204 if (need_temp_src) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001205 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1206 free_temp_buffer(ctx->temp_src_buffer);
1207 // Create a temp buffer and set that as the destination.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001208 if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
1209 ctx->temp_src_buffer)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001210 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1211 delete_handle(dst_hnd);
1212 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001213 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001214 return COPYBIT_FAILURE;
1215 }
1216 }
1217 src_hnd->fd = ctx->temp_src_buffer.fd;
1218 src_hnd->size = ctx->temp_src_buffer.size;
1219 src_hnd->flags = ctx->temp_src_buffer.allocType;
1220 src_hnd->base = (int)(ctx->temp_src_buffer.base);
1221 src_hnd->offset = ctx->temp_src_buffer.offset;
1222 src_hnd->gpuaddr = 0;
1223 src_image.handle = src_hnd;
1224
1225 // Copy the source.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001226 status = copy_image((private_handle_t *)src->handle, &src_image,
1227 CONVERT_TO_C2D_FORMAT);
1228 if (status == COPYBIT_FAILURE) {
1229 ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
1230 delete_handle(dst_hnd);
1231 delete_handle(src_hnd);
1232 unmap_gpuaddr(ctx, mapped_dst_idx);
1233 return status;
1234 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001235
1236 // Flush the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001237 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001238 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
1239 src_hnd->offset, src_hnd->fd)) {
1240 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1241 delete_handle(dst_hnd);
1242 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001243 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001244 return COPYBIT_FAILURE;
1245 }
1246 }
1247
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001248 flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1249 flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
1250 status = set_image(ctx, src_surface.surface_id, &src_image,
1251 (eC2DFlags)flags, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001252 if(status) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001253 ALOGE("%s: set_image (src) error", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001254 delete_handle(dst_hnd);
1255 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001256 unmap_gpuaddr(ctx, mapped_dst_idx);
1257 unmap_gpuaddr(ctx, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001258 return COPYBIT_FAILURE;
1259 }
1260
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001261 src_surface.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT |
1262 ctx->config_mask;
1263 src_surface.global_alpha = ctx->src_global_alpha;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001264 if (enableBlend) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001265 if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1266 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1267 if(!(src_surface.global_alpha)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001268 // src alpha is zero
Naseer Ahmed29a26812012-06-14 00:56:20 -07001269 delete_handle(dst_hnd);
1270 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001271 unmap_gpuaddr(ctx, mapped_dst_idx);
1272 unmap_gpuaddr(ctx, mapped_src_idx);
1273 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001274 }
1275 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001276 int c2d_format = get_format(src->format);
1277 if(is_alpha(c2d_format))
1278 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001279 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001280 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001281 }
1282 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001283 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001284 }
1285
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001286 if (src_surface_type == RGB_SURFACE) {
1287 ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
1288 ctx->blit_rgb_count++;
1289 } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
1290 ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
1291 ctx->blit_yuv_2_plane_count++;
1292 } else {
1293 ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
1294 ctx->blit_yuv_3_plane_count++;
1295 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001296
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001297 struct copybit_rect_t clip;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001298 while ((status == 0) && region->next(region, &clip)) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001299 set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
1300 if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
1301 ALOGW("Reached end of blit count");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001302 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001303 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001304 ctx->blit_list[ctx->blit_count] = src_surface;
1305 ctx->blit_count++;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001306 }
1307
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001308 // Check if we need to perform an early draw-finish.
1309 flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
1310 if (need_to_execute_draw(ctx, (eC2DFlags)flags))
1311 {
1312 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001313 }
1314
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001315 if (need_temp_dst) {
1316 // copy the temp. destination without the alignment to the actual
1317 // destination.
1318 status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1319 if (status == COPYBIT_FAILURE) {
1320 ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
1321 delete_handle(dst_hnd);
1322 delete_handle(src_hnd);
1323 unmap_gpuaddr(ctx, mapped_dst_idx);
1324 unmap_gpuaddr(ctx, mapped_src_idx);
1325 return status;
1326 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001327 // Invalidate the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001328 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001329 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
1330 dst_hnd->offset, dst_hnd->fd);
1331 }
1332 delete_handle(dst_hnd);
1333 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001334
1335 ctx->is_premultiplied_alpha = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001336 ctx->fb_width = 0;
1337 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001338 ctx->config_mask = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001339 return status;
1340}
1341
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001342
Naseer Ahmed29a26812012-06-14 00:56:20 -07001343static int stretch_copybit(
1344 struct copybit_device_t *dev,
1345 struct copybit_image_t const *dst,
1346 struct copybit_image_t const *src,
1347 struct copybit_rect_t const *dst_rect,
1348 struct copybit_rect_t const *src_rect,
1349 struct copybit_region_t const *region)
1350{
1351 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001352 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001353 bool needsBlending = (ctx->src_global_alpha != 0);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001354 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1355 status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001356 region, needsBlending);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001357 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1358 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001359}
1360
1361/** Perform a blit type operation */
1362static int blit_copybit(
1363 struct copybit_device_t *dev,
1364 struct copybit_image_t const *dst,
1365 struct copybit_image_t const *src,
1366 struct copybit_region_t const *region)
1367{
1368 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
1369 struct copybit_rect_t sr = { 0, 0, src->w, src->h };
1370 return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1371}
1372
1373/*****************************************************************************/
1374
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001375static void clean_up(copybit_context_t* ctx)
1376{
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001377 void* ret;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001378 if (!ctx)
1379 return;
1380
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001381 // stop the wait_cleanup_thread
1382 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1383 ctx->stop_thread = true;
1384 // Signal waiting thread
1385 pthread_cond_signal(&ctx->wait_cleanup_cond);
1386 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1387 // waits for the cleanup thread to exit
1388 pthread_join(ctx->wait_thread_id, &ret);
1389 pthread_mutex_destroy(&ctx->wait_cleanup_lock);
1390 pthread_cond_destroy (&ctx->wait_cleanup_cond);
1391
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001392 for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
1393 if (ctx->dst[i])
1394 LINK_c2dDestroySurface(ctx->dst[i]);
1395 }
1396
1397 for (int i = 0; i < MAX_RGB_SURFACES; i++) {
1398 if (ctx->blit_rgb_object[i].surface_id)
1399 LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
1400 }
1401
1402 for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
1403 if (ctx->blit_yuv_2_plane_object[i].surface_id)
1404 LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
1405 }
1406
1407 for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
1408 if (ctx->blit_yuv_3_plane_object[i].surface_id)
1409 LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
1410 }
1411
1412 if (ctx->libc2d2) {
1413 ::dlclose(ctx->libc2d2);
1414 ALOGV("dlclose(libc2d2)");
1415 }
1416
1417 free(ctx);
1418}
1419
Naseer Ahmed29a26812012-06-14 00:56:20 -07001420/** Close the copybit device */
1421static int close_copybit(struct hw_device_t *dev)
1422{
1423 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1424 if (ctx) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001425 free_temp_buffer(ctx->temp_src_buffer);
1426 free_temp_buffer(ctx->temp_dst_buffer);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001427 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001428 clean_up(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001429 return 0;
1430}
1431
1432/** Open a new instance of a copybit device using name */
1433static int open_copybit(const struct hw_module_t* module, const char* name,
1434 struct hw_device_t** device)
1435{
1436 int status = COPYBIT_SUCCESS;
1437 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1438 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1439 struct copybit_context_t *ctx;
1440 char fbName[64];
1441
1442 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1443 if(!ctx) {
1444 ALOGE("%s: malloc failed", __FUNCTION__);
1445 return COPYBIT_FAILURE;
1446 }
1447
1448 /* initialize drawstate */
1449 memset(ctx, 0, sizeof(*ctx));
Naseer Ahmed29a26812012-06-14 00:56:20 -07001450 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1451 if (!ctx->libc2d2) {
1452 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001453 clean_up(ctx);
1454 status = COPYBIT_FAILURE;
1455 *device = NULL;
1456 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001457 }
1458 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1459 "c2dCreateSurface");
1460 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1461 "c2dUpdateSurface");
1462 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1463 "c2dReadSurface");
1464 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1465 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1466 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1467 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1468 "c2dWaitTimestamp");
1469 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1470 "c2dDestroySurface");
1471 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1472 "c2dMapAddr");
1473 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1474 "c2dUnMapAddr");
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001475 *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
1476 "c2dGetDriverCapabilities");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001477 *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
1478 "c2dCreateFenceFD");
Naseer Ahmed29a26812012-06-14 00:56:20 -07001479
1480 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001481 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
1482 !LINK_c2dFinish || !LINK_c2dDestroySurface ||
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001483 !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001484 ALOGE("%s: dlsym ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001485 clean_up(ctx);
1486 status = COPYBIT_FAILURE;
1487 *device = NULL;
1488 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001489 }
1490
1491 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1492 ctx->device.common.version = 1;
1493 ctx->device.common.module = (hw_module_t*)(module);
1494 ctx->device.common.close = close_copybit;
1495 ctx->device.set_parameter = set_parameter_copybit;
1496 ctx->device.get = get;
1497 ctx->device.blit = blit_copybit;
1498 ctx->device.stretch = stretch_copybit;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001499 ctx->device.finish = finish_copybit;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001500 ctx->device.flush_get_fence = flush_get_fence_copybit;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001501
1502 /* Create RGB Surface */
1503 surfDefinition.buffer = (void*)0xdddddddd;
1504 surfDefinition.phys = (void*)0xdddddddd;
1505 surfDefinition.stride = 1 * 4;
1506 surfDefinition.width = 1;
1507 surfDefinition.height = 1;
1508 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1509 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1510 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001511 C2D_SURFACE_WITH_PHYS |
1512 C2D_SURFACE_WITH_PHYS_DUMMY ),
1513 &surfDefinition)) {
1514 ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
1515 ctx->dst[RGB_SURFACE] = 0;
1516 clean_up(ctx);
1517 status = COPYBIT_FAILURE;
1518 *device = NULL;
1519 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001520 }
1521
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001522 unsigned int surface_id = 0;
1523 for (int i = 0; i < MAX_RGB_SURFACES; i++)
1524 {
1525 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001526 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001527 C2D_SURFACE_WITH_PHYS |
1528 C2D_SURFACE_WITH_PHYS_DUMMY ),
1529 &surfDefinition)) {
1530 ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
1531 ctx->blit_rgb_object[i].surface_id = 0;
1532 status = COPYBIT_FAILURE;
1533 break;
1534 } else {
1535 ctx->blit_rgb_object[i].surface_id = surface_id;
1536 ALOGW("%s i = %d surface_id=%d", __FUNCTION__, i,
1537 ctx->blit_rgb_object[i].surface_id);
1538 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001539 }
1540
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001541 if (status == COPYBIT_FAILURE) {
1542 clean_up(ctx);
1543 status = COPYBIT_FAILURE;
1544 *device = NULL;
1545 return status;
1546 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001547
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001548 // Create 2 plane YUV surfaces
1549 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001550 yuvSurfaceDef.width = 4;
1551 yuvSurfaceDef.height = 4;
1552 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1553 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1554 yuvSurfaceDef.stride0 = 4;
1555
1556 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1557 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1558 yuvSurfaceDef.stride1 = 4;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001559 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1560 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001561 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1562 C2D_SURFACE_WITH_PHYS |
1563 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001564 &yuvSurfaceDef)) {
1565 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001566 ctx->dst[YUV_SURFACE_2_PLANES] = 0;
1567 clean_up(ctx);
1568 status = COPYBIT_FAILURE;
1569 *device = NULL;
1570 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001571 }
1572
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001573 for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
1574 {
1575 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1576 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1577 C2D_SURFACE_WITH_PHYS |
1578 C2D_SURFACE_WITH_PHYS_DUMMY ),
1579 &yuvSurfaceDef)) {
1580 ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
1581 ctx->blit_yuv_2_plane_object[i].surface_id = 0;
1582 status = COPYBIT_FAILURE;
1583 break;
1584 } else {
1585 ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
1586 ALOGW("%s: 2 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1587 ctx->blit_yuv_2_plane_object[i].surface_id);
1588 }
1589 }
1590
1591 if (status == COPYBIT_FAILURE) {
1592 clean_up(ctx);
1593 status = COPYBIT_FAILURE;
1594 *device = NULL;
1595 return status;
1596 }
1597
1598 // Create YUV 3 plane surfaces
Naseer Ahmed29a26812012-06-14 00:56:20 -07001599 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1600 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1601 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1602 yuvSurfaceDef.stride2 = 4;
1603
Naseer Ahmed29a26812012-06-14 00:56:20 -07001604 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1605 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001606 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1607 C2D_SURFACE_WITH_PHYS |
1608 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001609 &yuvSurfaceDef)) {
1610 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001611 ctx->dst[YUV_SURFACE_3_PLANES] = 0;
1612 clean_up(ctx);
1613 status = COPYBIT_FAILURE;
1614 *device = NULL;
1615 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001616 }
1617
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001618 for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
1619 {
1620 if (LINK_c2dCreateSurface(&(surface_id),
1621 C2D_TARGET | C2D_SOURCE,
1622 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1623 C2D_SURFACE_WITH_PHYS |
1624 C2D_SURFACE_WITH_PHYS_DUMMY),
1625 &yuvSurfaceDef)) {
1626 ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
1627 ctx->blit_yuv_3_plane_object[i].surface_id = 0;
1628 status = COPYBIT_FAILURE;
1629 break;
1630 } else {
1631 ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
1632 ALOGW("%s: 3 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1633 ctx->blit_yuv_3_plane_object[i].surface_id);
1634 }
1635 }
1636
1637 if (status == COPYBIT_FAILURE) {
1638 clean_up(ctx);
1639 status = COPYBIT_FAILURE;
1640 *device = NULL;
1641 return status;
1642 }
1643
1644 if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
1645 ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
1646 clean_up(ctx);
1647 status = COPYBIT_FAILURE;
1648 *device = NULL;
1649 return status;
1650 }
1651 // Initialize context variables.
1652 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1653
Naseer Ahmed29a26812012-06-14 00:56:20 -07001654 ctx->temp_src_buffer.fd = -1;
1655 ctx->temp_src_buffer.base = 0;
1656 ctx->temp_src_buffer.size = 0;
1657
1658 ctx->temp_dst_buffer.fd = -1;
1659 ctx->temp_dst_buffer.base = 0;
1660 ctx->temp_dst_buffer.size = 0;
1661
1662 ctx->fb_width = 0;
1663 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001664
1665 ctx->blit_rgb_count = 0;
1666 ctx->blit_yuv_2_plane_count = 0;
1667 ctx->blit_yuv_3_plane_count = 0;
1668 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001669
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001670 ctx->wait_timestamp = false;
1671 ctx->stop_thread = false;
1672 pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
1673 pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
1674 /* Start the wait thread */
1675 pthread_attr_t attr;
1676 pthread_attr_init(&attr);
1677 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1678
1679 pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
1680 (void *)ctx);
1681 pthread_attr_destroy(&attr);
1682
Naseer Ahmed29a26812012-06-14 00:56:20 -07001683 *device = &ctx->device.common;
1684 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001685}