blob: e172770436575e98f62edfc00dd753a80d2c83e9 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05303 * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08004 *
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
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +053083C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
84 size_t 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 Ahmed183939d2013-03-14 20:44:17 -040093
94C2D_STATUS (*LINK_c2dFillSurface) ( uint32 surface_id, uint32 fill_color,
95 C2D_RECT * fill_rect);
96
Naseer Ahmed29a26812012-06-14 00:56:20 -070097/******************************************************************************/
98
99#if defined(COPYBIT_Z180)
100#define MAX_SCALE_FACTOR (4096)
101#define MAX_DIMENSION (4096)
102#else
103#error "Unsupported HW version"
104#endif
105
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800106// The following defines can be changed as required i.e. as we encounter
107// complex use cases.
Sushil Chauhanb00f59d2013-04-29 18:35:54 -0700108#define MAX_RGB_SURFACES 32 // Max. RGB layers currently supported per draw
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800109#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
110#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
111// +1 for the destination surface. We cannot have multiple destination surfaces.
112#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
113#define NUM_SURFACE_TYPES 3 // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
114#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
Naseer Ahmed29a26812012-06-14 00:56:20 -0700115
116enum {
117 RGB_SURFACE,
118 YUV_SURFACE_2_PLANES,
119 YUV_SURFACE_3_PLANES
120};
121
122enum eConversionType {
123 CONVERT_TO_ANDROID_FORMAT,
124 CONVERT_TO_C2D_FORMAT
125};
126
127enum eC2DFlags {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800128 FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
129 FLAGS_YUV_DESTINATION = 1<<1,
130 FLAGS_TEMP_SRC_DST = 1<<2
Naseer Ahmed29a26812012-06-14 00:56:20 -0700131};
132
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700133static gralloc::IAllocController* sAlloc = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700134/******************************************************************************/
135
136/** State information for each device instance */
137struct copybit_context_t {
138 struct copybit_device_t device;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800139 // Templates for the various source surfaces. These templates are created
140 // to avoid the expensive create/destroy C2D Surfaces
141 C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
142 C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
143 C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
144 C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
145 C2D_DRIVER_INFO c2d_driver_info;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700146 void *libc2d2;
147 alloc_data temp_src_buffer;
148 alloc_data temp_dst_buffer;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800149 unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530150 uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800151 int blit_rgb_count; // Total RGB surfaces being blit
152 int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
153 int blit_yuv_3_plane_count; // Total 3 plane YUV surfaces being blit
154 int blit_count; // Total blit objects.
155 unsigned int trg_transform; /* target transform */
Naseer Ahmed29a26812012-06-14 00:56:20 -0700156 int fb_width;
157 int fb_height;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800158 int src_global_alpha;
159 int config_mask;
160 int dst_surface_type;
161 bool is_premultiplied_alpha;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800162 void* time_stamp;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700163 bool dst_surface_mapped; // Set when dst surface is mapped to GPU addr
164 void* dst_surface_base; // Stores the dst surface addr
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800165
166 // used for signaling the wait thread
167 bool wait_timestamp;
168 pthread_t wait_thread_id;
169 bool stop_thread;
170 pthread_mutex_t wait_cleanup_lock;
171 pthread_cond_t wait_cleanup_cond;
172
Naseer Ahmed29a26812012-06-14 00:56:20 -0700173};
174
175struct bufferInfo {
176 int width;
177 int height;
178 int format;
179};
180
181struct yuvPlaneInfo {
182 int yStride; //luma stride
183 int plane1_stride;
184 int plane2_stride;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530185 size_t plane1_offset;
186 size_t plane2_offset;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700187};
188
189/**
190 * Common hardware methods
191 */
192
193static int open_copybit(const struct hw_module_t* module, const char* name,
194 struct hw_device_t** device);
195
196static struct hw_module_methods_t copybit_module_methods = {
197open: open_copybit
198};
199
200/*
201 * The COPYBIT Module
202 */
203struct copybit_module_t HAL_MODULE_INFO_SYM = {
204common: {
205tag: HARDWARE_MODULE_TAG,
206 version_major: 1,
207 version_minor: 0,
208 id: COPYBIT_HARDWARE_MODULE_ID,
209 name: "QCT COPYBIT C2D 2.0 Module",
210 author: "Qualcomm",
211 methods: &copybit_module_methods
212 }
213};
214
215
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800216/* thread function which waits on the timeStamp and cleans up the surfaces */
217static void* c2d_wait_loop(void* ptr) {
218 copybit_context_t* ctx = (copybit_context_t*)(ptr);
219 char thread_name[64] = "copybitWaitThr";
220 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
221 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
222
223 while(ctx->stop_thread == false) {
224 pthread_mutex_lock(&ctx->wait_cleanup_lock);
225 while(ctx->wait_timestamp == false && !ctx->stop_thread) {
226 pthread_cond_wait(&(ctx->wait_cleanup_cond),
227 &(ctx->wait_cleanup_lock));
228 }
229 if(ctx->wait_timestamp) {
230 if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
231 ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
232 }
233 ctx->wait_timestamp = false;
234 // Unmap any mapped addresses.
235 for (int i = 0; i < MAX_SURFACES; i++) {
236 if (ctx->mapped_gpu_addr[i]) {
237 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
238 ctx->mapped_gpu_addr[i] = 0;
239 }
240 }
241 // Reset the counts after the draw.
242 ctx->blit_rgb_count = 0;
243 ctx->blit_yuv_2_plane_count = 0;
244 ctx->blit_yuv_3_plane_count = 0;
245 ctx->blit_count = 0;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700246 ctx->dst_surface_mapped = false;
247 ctx->dst_surface_base = 0;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800248 }
249 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
250 if(ctx->stop_thread)
251 break;
252 }
253 pthread_exit(NULL);
254 return NULL;
255}
256
257
Naseer Ahmed29a26812012-06-14 00:56:20 -0700258/* convert COPYBIT_FORMAT to C2D format */
259static int get_format(int format) {
260 switch (format) {
261 case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
Sushil Chauhan43755de2014-05-15 11:20:32 -0700262 case HAL_PIXEL_FORMAT_RGB_888: return C2D_COLOR_FORMAT_888_RGB;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700263 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
264 C2D_FORMAT_SWAP_RB |
265 C2D_FORMAT_DISABLE_ALPHA;
266 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
267 C2D_FORMAT_SWAP_RB;
268 case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700269 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
270 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
271 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
272 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
273 C2D_FORMAT_MACROTILED;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800274 default: ALOGE("%s: invalid format (0x%x",
275 __FUNCTION__, format);
276 return -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700277 }
278 return -EINVAL;
279}
280
281/* Get the C2D formats needed for conversion to YUV */
282static int get_c2d_format_for_yuv_destination(int halFormat) {
283 switch (halFormat) {
284 // We do not swap the RB when the target is YUV
285 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
286 C2D_FORMAT_DISABLE_ALPHA;
287 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800288 // The U and V need to be interchanged when the target is YUV
Naseer Ahmed29a26812012-06-14 00:56:20 -0700289 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
290 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
291 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
292 default: return get_format(halFormat);
293 }
294 return -EINVAL;
295}
296
297/* ------------------------------------------------------------------- *//*!
298 * \internal
299 * \brief Get the bpp for a particular color format
300 * \param color format
301 * \return bits per pixel
302 *//* ------------------------------------------------------------------- */
303int c2diGetBpp(int32 colorformat)
304{
305
306 int c2dBpp = 0;
307
308 switch(colorformat&0xFF)
309 {
310 case C2D_COLOR_FORMAT_4444_RGBA:
311 case C2D_COLOR_FORMAT_4444_ARGB:
312 case C2D_COLOR_FORMAT_1555_ARGB:
313 case C2D_COLOR_FORMAT_565_RGB:
314 case C2D_COLOR_FORMAT_5551_RGBA:
315 c2dBpp = 16;
316 break;
317 case C2D_COLOR_FORMAT_8888_RGBA:
318 case C2D_COLOR_FORMAT_8888_ARGB:
319 c2dBpp = 32;
320 break;
Sushil Chauhan43755de2014-05-15 11:20:32 -0700321 case C2D_COLOR_FORMAT_888_RGB:
322 c2dBpp = 24;
323 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700324 case C2D_COLOR_FORMAT_8_L:
325 case C2D_COLOR_FORMAT_8_A:
326 c2dBpp = 8;
327 break;
328 case C2D_COLOR_FORMAT_4_A:
329 c2dBpp = 4;
330 break;
331 case C2D_COLOR_FORMAT_1:
332 c2dBpp = 1;
333 break;
334 default:
335 ALOGE("%s ERROR", __func__);
336 break;
337 }
338 return c2dBpp;
339}
340
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530341static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700342 struct private_handle_t *handle, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700343{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530344 uint32 memtype;
345 size_t *gpuaddr = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700346 C2D_STATUS rc;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700347 int freeindex = 0;
348 bool mapaddr = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700349
350 if(!handle)
351 return 0;
352
353 if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
354 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
355 memtype = KGSL_USER_MEM_TYPE_PMEM;
356 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
357 memtype = KGSL_USER_MEM_TYPE_ASHMEM;
358 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
359 memtype = KGSL_USER_MEM_TYPE_ION;
360 else {
361 ALOGE("Invalid handle flags: 0x%x", handle->flags);
362 return 0;
363 }
364
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700365 // Check for a freeindex in the mapped_gpu_addr list
366 for (freeindex = 0; freeindex < MAX_SURFACES; freeindex++) {
367 if (ctx->mapped_gpu_addr[freeindex] == 0) {
368 // free index is available
369 // map GPU addr and use this as mapped_idx
370 mapaddr = true;
371 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800372 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700373 }
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700374
375 if(mapaddr) {
376 rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
377 handle->offset, memtype, (void**)&gpuaddr);
378
379 if (rc == C2D_STATUS_OK) {
380 // We have mapped the GPU address inside copybit. We need to unmap
381 // this address after the blit. Store this address
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530382 ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700383 mapped_idx = freeindex;
384 }
385 }
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530386 return (size_t)gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700387}
388
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800389static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
390{
391 if (!ctx || (mapped_idx == -1))
392 return;
393
394 if (ctx->mapped_gpu_addr[mapped_idx]) {
395 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
396 ctx->mapped_gpu_addr[mapped_idx] = 0;
397 }
398}
399
Naseer Ahmed29a26812012-06-14 00:56:20 -0700400static int is_supported_rgb_format(int format)
401{
402 switch(format) {
403 case HAL_PIXEL_FORMAT_RGBA_8888:
404 case HAL_PIXEL_FORMAT_RGBX_8888:
Sushil Chauhan43755de2014-05-15 11:20:32 -0700405 case HAL_PIXEL_FORMAT_RGB_888:
Naseer Ahmed29a26812012-06-14 00:56:20 -0700406 case HAL_PIXEL_FORMAT_RGB_565:
Mathias Agopiane4001e72013-09-17 10:37:22 -0700407 case HAL_PIXEL_FORMAT_BGRA_8888: {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700408 return COPYBIT_SUCCESS;
409 }
410 default:
411 return COPYBIT_FAILURE;
412 }
413}
414
415static int get_num_planes(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 2;
423 }
424 case HAL_PIXEL_FORMAT_YV12: {
425 return 3;
426 }
427 default:
428 return COPYBIT_FAILURE;
429 }
430}
431
432static int is_supported_yuv_format(int format)
433{
434 switch(format) {
435 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
436 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
437 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
438 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
439 return COPYBIT_SUCCESS;
440 }
441 default:
442 return COPYBIT_FAILURE;
443 }
444}
445
446static int is_valid_destination_format(int format)
447{
448 if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
449 // C2D does not support NV12Tile as a destination format.
450 return COPYBIT_FAILURE;
451 }
452 return COPYBIT_SUCCESS;
453}
454
455static int calculate_yuv_offset_and_stride(const bufferInfo& info,
456 yuvPlaneInfo& yuvInfo)
457{
458 int width = info.width;
459 int height = info.height;
460 int format = info.format;
461
462 int aligned_height = 0;
463 int aligned_width = 0, size = 0;
464
465 switch (format) {
466 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
467 /* NV12 Tile buffers have their luma height aligned to 32bytes and width
468 * aligned to 128 bytes. The chroma offset starts at an 8K boundary
469 */
470 aligned_height = ALIGN(height, 32);
471 aligned_width = ALIGN(width, 128);
472 size = aligned_width * aligned_height;
473 yuvInfo.plane1_offset = ALIGN(size,8192);
474 yuvInfo.yStride = aligned_width;
475 yuvInfo.plane1_stride = aligned_width;
476 break;
477 }
478 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
479 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
480 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
481 aligned_width = ALIGN(width, 32);
482 yuvInfo.yStride = aligned_width;
483 yuvInfo.plane1_stride = aligned_width;
484 if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
485 // The encoder requires a 2K aligned chroma offset
486 yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
487 } else
488 yuvInfo.plane1_offset = aligned_width * height;
489
490 break;
491 }
492 default: {
493 return COPYBIT_FAILURE;
494 }
495 }
496 return COPYBIT_SUCCESS;
497}
498
499/** create C2D surface from copybit image */
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800500static int set_image(copybit_context_t* ctx, uint32 surfaceId,
501 const struct copybit_image_t *rhs,
502 const eC2DFlags flags, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700503{
504 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
505 C2D_SURFACE_TYPE surfaceType;
506 int status = COPYBIT_SUCCESS;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530507 uintptr_t gpuaddr = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800508 int c2d_format;
509 mapped_idx = -1;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700510
511 if (flags & FLAGS_YUV_DESTINATION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800512 c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700513 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800514 c2d_format = get_format(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700515 }
516
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800517 if(c2d_format == -EINVAL) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700518 ALOGE("%s: invalid format", __FUNCTION__);
519 return -EINVAL;
520 }
521
522 if(handle == NULL) {
523 ALOGE("%s: invalid handle", __func__);
524 return -EINVAL;
525 }
526
527 if (handle->gpuaddr == 0) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800528 gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
529 if(!gpuaddr) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700530 ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
531 return COPYBIT_FAILURE;
532 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800533 } else {
534 gpuaddr = handle->gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700535 }
536
537 /* create C2D surface */
538 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
539 /* RGB */
540 C2D_RGB_SURFACE_DEF surfaceDef;
541
542 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
543
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800544 surfaceDef.phys = (void*) gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700545 surfaceDef.buffer = (void*) (handle->base);
546
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800547 surfaceDef.format = c2d_format |
Naseer Ahmed29a26812012-06-14 00:56:20 -0700548 ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
549 surfaceDef.width = rhs->w;
550 surfaceDef.height = rhs->h;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530551 int aligned_width = ALIGN((int)surfaceDef.width,32);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700552 surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
553
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800554 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
555 &surfaceDef)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700556 ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800557 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700558 status = COPYBIT_FAILURE;
559 }
560 } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
561 C2D_YUV_SURFACE_DEF surfaceDef;
562 memset(&surfaceDef, 0, sizeof(surfaceDef));
563 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800564 surfaceDef.format = c2d_format;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700565
566 bufferInfo info;
567 info.width = rhs->w;
568 info.height = rhs->h;
569 info.format = rhs->format;
570
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700571 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700572 status = calculate_yuv_offset_and_stride(info, yuvInfo);
573 if(status != COPYBIT_SUCCESS) {
574 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800575 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700576 }
577
578 surfaceDef.width = rhs->w;
579 surfaceDef.height = rhs->h;
580 surfaceDef.plane0 = (void*) (handle->base);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800581 surfaceDef.phys0 = (void*) (gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700582 surfaceDef.stride0 = yuvInfo.yStride;
583
584 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800585 surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700586 surfaceDef.stride1 = yuvInfo.plane1_stride;
587 if (3 == get_num_planes(rhs->format)) {
588 surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800589 surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700590 surfaceDef.stride2 = yuvInfo.plane2_stride;
591 }
592
593 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
594 &surfaceDef)) {
595 ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800596 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700597 status = COPYBIT_FAILURE;
598 }
599 } else {
600 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800601 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700602 status = COPYBIT_FAILURE;
603 }
604
605 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700606}
607
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800608/** copy the bits */
609static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700610{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800611 if (ctx->blit_count == 0) {
612 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700613 }
614
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800615 for (int i = 0; i < ctx->blit_count; i++)
616 {
617 ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
618 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800619 ctx->blit_list[ctx->blit_count-1].next = NULL;
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800620 uint32_t target_transform = ctx->trg_transform;
621 if (ctx->c2d_driver_info.capabilities_mask &
622 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
623 // For A3xx - set 0x0 as the transform is set in the config_mask
624 target_transform = 0x0;
625 }
626 if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800627 ctx->blit_count)) {
628 ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
629 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700630 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700631 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700632}
633
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800634
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800635
636static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
637{
638 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
639 int status = COPYBIT_FAILURE;
640 if (!ctx)
641 return COPYBIT_FAILURE;
642 pthread_mutex_lock(&ctx->wait_cleanup_lock);
643 status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
644
645 if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
646 ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
647 // unlock the mutex and return failure
648 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
649 return COPYBIT_FAILURE;
650 }
651 if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
652 fd)) {
653 ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
654 status = COPYBIT_FAILURE;
655 }
656 if(status == COPYBIT_SUCCESS) {
657 //signal the wait_thread
658 ctx->wait_timestamp = true;
659 pthread_cond_signal(&ctx->wait_cleanup_cond);
660 }
661 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
662 return status;
663}
664
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800665static int finish_copybit(struct copybit_device_t *dev)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700666{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800667 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
668 if (!ctx)
669 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700670
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800671 int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700672
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800673 if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
674 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
675 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700676 }
677
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800678 // Unmap any mapped addresses.
679 for (int i = 0; i < MAX_SURFACES; i++) {
680 if (ctx->mapped_gpu_addr[i]) {
681 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
682 ctx->mapped_gpu_addr[i] = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700683 }
684 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700685
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800686 // Reset the counts after the draw.
687 ctx->blit_rgb_count = 0;
688 ctx->blit_yuv_2_plane_count = 0;
689 ctx->blit_yuv_3_plane_count = 0;
690 ctx->blit_count = 0;
Pawan Kumar74d9ea92013-05-03 14:25:49 +0530691 ctx->dst_surface_mapped = false;
692 ctx->dst_surface_base = 0;
693
Naseer Ahmed29a26812012-06-14 00:56:20 -0700694 return status;
695}
696
Naseer Ahmed183939d2013-03-14 20:44:17 -0400697static int clear_copybit(struct copybit_device_t *dev,
698 struct copybit_image_t const *buf,
699 struct copybit_rect_t *rect)
700{
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700701 int ret = COPYBIT_SUCCESS;
Naseer Ahmed183939d2013-03-14 20:44:17 -0400702 int flags = FLAGS_PREMULTIPLIED_ALPHA;
703 int mapped_dst_idx = -1;
704 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
705 C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700706 pthread_mutex_lock(&ctx->wait_cleanup_lock);
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700707 if(!ctx->dst_surface_mapped) {
708 ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
709 (eC2DFlags)flags, mapped_dst_idx);
710 if(ret) {
711 ALOGE("%s: set_image error", __FUNCTION__);
712 unmap_gpuaddr(ctx, mapped_dst_idx);
713 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
714 return COPYBIT_FAILURE;
715 }
716 //clear_copybit is the first call made by HWC for each composition
717 //with the dest surface, hence set dst_surface_mapped.
718 ctx->dst_surface_mapped = true;
719 ctx->dst_surface_base = buf->base;
720 ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
Naseer Ahmed183939d2013-03-14 20:44:17 -0400721 }
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700722 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
Naseer Ahmed183939d2013-03-14 20:44:17 -0400723 return ret;
724}
725
726
Naseer Ahmed29a26812012-06-14 00:56:20 -0700727/** setup rectangles */
728static void set_rects(struct copybit_context_t *ctx,
729 C2D_OBJECT *c2dObject,
730 const struct copybit_rect_t *dst,
731 const struct copybit_rect_t *src,
732 const struct copybit_rect_t *scissor)
733{
734 // Set the target rect.
735 if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
736 (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
737 /* target rotation is 270 */
738 c2dObject->target_rect.x = (dst->t)<<16;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530739 c2dObject->target_rect.y = ctx->fb_width?
740 (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700741 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
742 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
743 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
744 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
745 c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
746 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
747 c2dObject->target_rect.y = (dst->l)<<16;
748 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
749 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
750 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
751 c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
752 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530753 c2dObject->target_rect.x = ctx->fb_width?
754 (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700755 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
756 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
757 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
758 } else {
759 c2dObject->target_rect.x = (dst->l)<<16;
760 c2dObject->target_rect.y = (dst->t)<<16;
761 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
762 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
763 }
764 c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
765
766 // Set the source rect
767 c2dObject->source_rect.x = (src->l)<<16;
768 c2dObject->source_rect.y = (src->t)<<16;
769 c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
770 c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
771 c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
772
773 // Set the scissor rect
774 c2dObject->scissor_rect.x = scissor->l;
775 c2dObject->scissor_rect.y = scissor->t;
776 c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
777 c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
778 c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
779}
780
Naseer Ahmed29a26812012-06-14 00:56:20 -0700781/*****************************************************************************/
782
783/** Set a parameter to value */
784static int set_parameter_copybit(
785 struct copybit_device_t *dev,
786 int name,
787 int value)
788{
789 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800790 int status = COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700791 if (!ctx) {
792 ALOGE("%s: null context", __FUNCTION__);
793 return -EINVAL;
794 }
795
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800796 pthread_mutex_lock(&ctx->wait_cleanup_lock);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700797 switch(name) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700798 case COPYBIT_PLANE_ALPHA:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800799 {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700800 if (value < 0) value = 0;
801 if (value >= 256) value = 255;
802
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800803 ctx->src_global_alpha = value;
804 if (value < 255)
805 ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700806 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800807 ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
808 }
809 break;
810 case COPYBIT_BLEND_MODE:
811 {
812 if (value == COPYBIT_BLENDING_NONE) {
813 ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
814 ctx->is_premultiplied_alpha = true;
815 } else if (value == COPYBIT_BLENDING_PREMULT) {
816 ctx->is_premultiplied_alpha = true;
817 } else {
818 ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700819 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800820 }
821 break;
822 case COPYBIT_TRANSFORM:
823 {
824 unsigned int transform = 0;
825 uint32 config_mask = 0;
826 config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
827 if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
828 transform = C2D_TARGET_ROTATE_180;
829 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
830 } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
831 transform = C2D_TARGET_ROTATE_90;
832 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
833 } else if(value == COPYBIT_TRANSFORM_ROT_90) {
834 transform = C2D_TARGET_ROTATE_270;
835 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
836 } else {
837 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
838 if(value & COPYBIT_TRANSFORM_FLIP_H) {
839 config_mask |= C2D_MIRROR_H_BIT;
840 } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
841 config_mask |= C2D_MIRROR_V_BIT;
842 }
843 }
844
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800845 if (ctx->c2d_driver_info.capabilities_mask &
846 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
847 ctx->config_mask |= config_mask;
848 } else {
849 // The transform for this surface does not match the current
850 // target transform. Draw all previous surfaces. This will be
851 // changed once we have a new mechanism to send different
852 // target rotations to c2d.
853 finish_copybit(dev);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800854 }
855 ctx->trg_transform = transform;
856 }
857 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700858 case COPYBIT_FRAMEBUFFER_WIDTH:
859 ctx->fb_width = value;
860 break;
861 case COPYBIT_FRAMEBUFFER_HEIGHT:
862 ctx->fb_height = value;
863 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800864 case COPYBIT_ROTATION_DEG:
865 case COPYBIT_DITHER:
866 case COPYBIT_BLUR:
Naseer Ahmed45a99602012-07-31 19:15:24 -0700867 case COPYBIT_BLIT_TO_FRAMEBUFFER:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800868 // Do nothing
Naseer Ahmed45a99602012-07-31 19:15:24 -0700869 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700870 default:
871 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800872 status = -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700873 break;
874 }
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800875 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
876 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700877}
878
879/** Get a static info value */
880static int get(struct copybit_device_t *dev, int name)
881{
882 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
883 int value;
884
885 if (!ctx) {
886 ALOGE("%s: null context error", __FUNCTION__);
887 return -EINVAL;
888 }
889
890 switch(name) {
891 case COPYBIT_MINIFICATION_LIMIT:
892 value = MAX_SCALE_FACTOR;
893 break;
894 case COPYBIT_MAGNIFICATION_LIMIT:
895 value = MAX_SCALE_FACTOR;
896 break;
897 case COPYBIT_SCALING_FRAC_BITS:
898 value = 32;
899 break;
900 case COPYBIT_ROTATION_STEP_DEG:
901 value = 1;
902 break;
903 default:
904 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
905 value = -EINVAL;
906 }
907 return value;
908}
909
910static int is_alpha(int cformat)
911{
912 int alpha = 0;
913 switch (cformat & 0xFF) {
914 case C2D_COLOR_FORMAT_8888_ARGB:
915 case C2D_COLOR_FORMAT_8888_RGBA:
916 case C2D_COLOR_FORMAT_5551_RGBA:
917 case C2D_COLOR_FORMAT_4444_ARGB:
918 alpha = 1;
919 break;
920 default:
921 alpha = 0;
922 break;
923 }
924
925 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
926 alpha = 0;
927
928 return alpha;
929}
930
931/* Function to check if we need a temporary buffer for the blit.
932 * This would happen if the requested destination stride and the
933 * C2D stride do not match. We ignore RGB buffers, since their
934 * stride is always aligned to 32.
935 */
936static bool need_temp_buffer(struct copybit_image_t const *img)
937{
938 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
939 return false;
940
941 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
942
943 // The width parameter in the handle contains the aligned_w. We check if we
944 // need to convert based on this param. YUV formats have bpp=1, so checking
945 // if the requested stride is aligned should suffice.
946 if (0 == (handle->width)%32) {
947 return false;
948 }
949
950 return true;
951}
952
953/* Function to extract the information from the copybit image and set the corresponding
954 * values in the bufferInfo struct.
955 */
956static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
957{
958 info.width = img->w;
959 info.height = img->h;
960 info.format = img->format;
961}
962
963/* Function to get the required size for a particular format, inorder for C2D to perform
964 * the blit operation.
965 */
966static size_t get_size(const bufferInfo& info)
967{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530968 int size = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700969 int w = info.width;
970 int h = info.height;
971 int aligned_w = ALIGN(w, 32);
972 switch(info.format) {
973 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
974 {
975 // Chroma for this format is aligned to 2K.
976 size = ALIGN((aligned_w*h), 2048) +
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800977 ALIGN(aligned_w/2, 32) * (h/2) *2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700978 size = ALIGN(size, 4096);
979 } break;
980 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
981 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
982 {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800983 size = aligned_w * h +
984 ALIGN(aligned_w/2, 32) * (h/2) * 2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700985 size = ALIGN(size, 4096);
986 } break;
987 default: break;
988 }
989 return size;
990}
991
992/* Function to allocate memory for the temporary buffer. This memory is
993 * allocated from Ashmem. It is the caller's responsibility to free this
994 * memory.
995 */
996static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
997{
998 ALOGD("%s E", __FUNCTION__);
999 // Alloc memory from system heap
1000 data.base = 0;
1001 data.fd = -1;
1002 data.offset = 0;
1003 data.size = get_size(info);
1004 data.align = getpagesize();
1005 data.uncached = true;
1006 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
1007
1008 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001009 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -07001010 }
1011
1012 if (sAlloc == 0) {
1013 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
1014 return COPYBIT_FAILURE;
1015 }
1016
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001017 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001018 if (0 != err) {
1019 ALOGE("%s: allocate failed", __FUNCTION__);
1020 return COPYBIT_FAILURE;
1021 }
1022
1023 ALOGD("%s X", __FUNCTION__);
1024 return err;
1025}
1026
1027/* Function to free the temporary allocated memory.*/
1028static void free_temp_buffer(alloc_data &data)
1029{
1030 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001031 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001032 memalloc->free_buffer(data.base, data.size, 0, data.fd);
1033 }
1034}
1035
1036/* Function to perform the software color conversion. Convert the
1037 * C2D compatible format to the Android compatible format
1038 */
1039static int copy_image(private_handle_t *src_handle,
1040 struct copybit_image_t const *rhs,
1041 eConversionType conversionType)
1042{
1043 if (src_handle->fd == -1) {
1044 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
1045 return COPYBIT_FAILURE;
1046 }
1047
1048 // Copy the info.
1049 int ret = COPYBIT_SUCCESS;
1050 switch(rhs->format) {
1051 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1052 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1053 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1054 {
1055 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
1056 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
1057 } else {
1058 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
1059 }
1060
1061 } break;
1062 default: {
1063 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
1064 ret = COPYBIT_FAILURE;
1065 } break;
1066 }
1067 return ret;
1068}
1069
1070static void delete_handle(private_handle_t *handle)
1071{
1072 if (handle) {
1073 delete handle;
1074 handle = 0;
1075 }
1076}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001077
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301078static bool need_to_execute_draw(eC2DFlags flags)
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001079{
1080 if (flags & FLAGS_TEMP_SRC_DST) {
1081 return true;
1082 }
1083 if (flags & FLAGS_YUV_DESTINATION) {
1084 return true;
1085 }
1086 return false;
1087}
1088
Naseer Ahmed29a26812012-06-14 00:56:20 -07001089/** do a stretch blit type operation */
1090static int stretch_copybit_internal(
1091 struct copybit_device_t *dev,
1092 struct copybit_image_t const *dst,
1093 struct copybit_image_t const *src,
1094 struct copybit_rect_t const *dst_rect,
1095 struct copybit_rect_t const *src_rect,
1096 struct copybit_region_t const *region,
1097 bool enableBlend)
1098{
1099 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1100 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001101 int flags = 0;
1102 int src_surface_type;
1103 int mapped_src_idx = -1, mapped_dst_idx = -1;
1104 C2D_OBJECT_STR src_surface;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001105
1106 if (!ctx) {
1107 ALOGE("%s: null context error", __FUNCTION__);
1108 return -EINVAL;
1109 }
1110
1111 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1112 ALOGE("%s: src dimension error", __FUNCTION__);
1113 return -EINVAL;
1114 }
1115
1116 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001117 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w,
1118 dst->h);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001119 return -EINVAL;
1120 }
1121
Naseer Ahmed29a26812012-06-14 00:56:20 -07001122 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001123 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
1124 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001125 return COPYBIT_FAILURE;
1126 }
1127
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001128 int dst_surface_type;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001129 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001130 dst_surface_type = RGB_SURFACE;
1131 flags |= FLAGS_PREMULTIPLIED_ALPHA;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001132 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001133 int num_planes = get_num_planes(dst->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001134 flags |= FLAGS_YUV_DESTINATION;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001135 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001136 dst_surface_type = YUV_SURFACE_2_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001137 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001138 dst_surface_type = YUV_SURFACE_3_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001139 } else {
1140 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1141 __FUNCTION__, dst->format);
1142 return COPYBIT_FAILURE;
1143 }
1144 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001145 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
1146 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001147 return COPYBIT_FAILURE;
1148 }
1149
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001150 if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
1151 ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1152 ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1153 ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
1154 ctx->dst_surface_type != dst_surface_type) {
1155 // we have reached the max. limits of our internal structures or
1156 // changed the target.
1157 // Draw the remaining surfaces. We need to do the finish here since
1158 // we need to free up the surface templates.
1159 finish_copybit(dev);
1160 }
1161
1162 ctx->dst_surface_type = dst_surface_type;
1163
1164 // Update the destination
Naseer Ahmed29a26812012-06-14 00:56:20 -07001165 copybit_image_t dst_image;
1166 dst_image.w = dst->w;
1167 dst_image.h = dst->h;
1168 dst_image.format = dst->format;
1169 dst_image.handle = dst->handle;
1170 // Check if we need a temp. copy for the destination. We'd need this the destination
1171 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1172 // aligned to 32.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001173 bool need_temp_dst = need_temp_buffer(dst);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001174 bufferInfo dst_info;
1175 populate_buffer_info(dst, dst_info);
1176 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1177 dst_info.width, dst_info.height);
1178 if (dst_hnd == NULL) {
1179 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1180 return COPYBIT_FAILURE;
1181 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001182 if (need_temp_dst) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001183 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1184 free_temp_buffer(ctx->temp_dst_buffer);
1185 // Create a temp buffer and set that as the destination.
1186 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1187 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1188 delete_handle(dst_hnd);
1189 return COPYBIT_FAILURE;
1190 }
1191 }
1192 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1193 dst_hnd->size = ctx->temp_dst_buffer.size;
1194 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301195 dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001196 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1197 dst_hnd->gpuaddr = 0;
1198 dst_image.handle = dst_hnd;
1199 }
Arun Kumar K.R14031eb2013-04-15 14:26:43 -07001200 if(!ctx->dst_surface_mapped) {
1201 //map the destination surface to GPU address
1202 status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
1203 (eC2DFlags)flags, mapped_dst_idx);
1204 if(status) {
1205 ALOGE("%s: dst: set_image error", __FUNCTION__);
1206 delete_handle(dst_hnd);
1207 unmap_gpuaddr(ctx, mapped_dst_idx);
1208 return COPYBIT_FAILURE;
1209 }
1210 ctx->dst_surface_mapped = true;
1211 ctx->dst_surface_base = dst->base;
1212 } else if(ctx->dst_surface_mapped && ctx->dst_surface_base != dst->base) {
1213 // Destination surface for the operation should be same for multiple
1214 // requests, this check is catch if there is any case when the
1215 // destination changes
1216 ALOGE("%s: a different destination surface!!", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001217 }
1218
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001219 // Update the source
1220 flags = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001221 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001222 src_surface_type = RGB_SURFACE;
1223 src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001224 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1225 int num_planes = get_num_planes(src->format);
1226 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001227 src_surface_type = YUV_SURFACE_2_PLANES;
1228 src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001229 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001230 src_surface_type = YUV_SURFACE_3_PLANES;
1231 src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001232 } else {
1233 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1234 __FUNCTION__, src->format);
1235 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001236 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001237 return -EINVAL;
1238 }
1239 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001240 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
1241 src->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001242 delete_handle(dst_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 -EINVAL;
1245 }
1246
1247 copybit_image_t src_image;
1248 src_image.w = src->w;
1249 src_image.h = src->h;
1250 src_image.format = src->format;
1251 src_image.handle = src->handle;
1252
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001253 bool need_temp_src = need_temp_buffer(src);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001254 bufferInfo src_info;
1255 populate_buffer_info(src, src_info);
1256 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 -08001257 src_info.width, src_info.height);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001258 if (NULL == src_hnd) {
1259 ALOGE("%s: src_hnd is null", __FUNCTION__);
1260 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001261 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001262 return COPYBIT_FAILURE;
1263 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001264 if (need_temp_src) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001265 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1266 free_temp_buffer(ctx->temp_src_buffer);
1267 // Create a temp buffer and set that as the destination.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001268 if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
1269 ctx->temp_src_buffer)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001270 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1271 delete_handle(dst_hnd);
1272 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001273 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001274 return COPYBIT_FAILURE;
1275 }
1276 }
1277 src_hnd->fd = ctx->temp_src_buffer.fd;
1278 src_hnd->size = ctx->temp_src_buffer.size;
1279 src_hnd->flags = ctx->temp_src_buffer.allocType;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301280 src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001281 src_hnd->offset = ctx->temp_src_buffer.offset;
1282 src_hnd->gpuaddr = 0;
1283 src_image.handle = src_hnd;
1284
1285 // Copy the source.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001286 status = copy_image((private_handle_t *)src->handle, &src_image,
1287 CONVERT_TO_C2D_FORMAT);
1288 if (status == COPYBIT_FAILURE) {
1289 ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
1290 delete_handle(dst_hnd);
1291 delete_handle(src_hnd);
1292 unmap_gpuaddr(ctx, mapped_dst_idx);
1293 return status;
1294 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001295
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001296 // Clean the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001297 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001298 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001299 src_hnd->offset, src_hnd->fd,
1300 gralloc::CACHE_CLEAN)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001301 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1302 delete_handle(dst_hnd);
1303 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001304 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001305 return COPYBIT_FAILURE;
1306 }
1307 }
1308
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001309 flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1310 flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
1311 status = set_image(ctx, src_surface.surface_id, &src_image,
1312 (eC2DFlags)flags, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001313 if(status) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001314 ALOGE("%s: set_image (src) error", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001315 delete_handle(dst_hnd);
1316 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001317 unmap_gpuaddr(ctx, mapped_dst_idx);
1318 unmap_gpuaddr(ctx, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001319 return COPYBIT_FAILURE;
1320 }
1321
Arun Kumar K.Re29916b2013-03-20 11:42:53 -07001322 src_surface.config_mask = C2D_NO_ANTIALIASING_BIT | ctx->config_mask;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001323 src_surface.global_alpha = ctx->src_global_alpha;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001324 if (enableBlend) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001325 if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1326 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1327 if(!(src_surface.global_alpha)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001328 // src alpha is zero
Naseer Ahmed29a26812012-06-14 00:56:20 -07001329 delete_handle(dst_hnd);
1330 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001331 unmap_gpuaddr(ctx, mapped_dst_idx);
1332 unmap_gpuaddr(ctx, mapped_src_idx);
1333 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001334 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001335 }
1336 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001337 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001338 }
1339
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001340 if (src_surface_type == RGB_SURFACE) {
1341 ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
1342 ctx->blit_rgb_count++;
1343 } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
1344 ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
1345 ctx->blit_yuv_2_plane_count++;
1346 } else {
1347 ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
1348 ctx->blit_yuv_3_plane_count++;
1349 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001350
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001351 struct copybit_rect_t clip;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001352 while ((status == 0) && region->next(region, &clip)) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001353 set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
1354 if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
1355 ALOGW("Reached end of blit count");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001356 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001357 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001358 ctx->blit_list[ctx->blit_count] = src_surface;
1359 ctx->blit_count++;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001360 }
1361
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001362 // Check if we need to perform an early draw-finish.
1363 flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301364 if (need_to_execute_draw((eC2DFlags)flags))
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001365 {
1366 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001367 }
1368
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001369 if (need_temp_dst) {
1370 // copy the temp. destination without the alignment to the actual
1371 // destination.
1372 status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1373 if (status == COPYBIT_FAILURE) {
1374 ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
1375 delete_handle(dst_hnd);
1376 delete_handle(src_hnd);
1377 unmap_gpuaddr(ctx, mapped_dst_idx);
1378 unmap_gpuaddr(ctx, mapped_src_idx);
1379 return status;
1380 }
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001381 // Clean the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001382 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001383 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001384 dst_hnd->offset, dst_hnd->fd,
1385 gralloc::CACHE_CLEAN);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001386 }
1387 delete_handle(dst_hnd);
1388 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001389
1390 ctx->is_premultiplied_alpha = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001391 ctx->fb_width = 0;
1392 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001393 ctx->config_mask = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001394 return status;
1395}
1396
Terence Hampsonadf47302013-05-23 12:21:02 -04001397static int set_sync_copybit(struct copybit_device_t *dev,
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301398 int /*acquireFenceFd*/)
Terence Hampsonadf47302013-05-23 12:21:02 -04001399{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301400 if(!dev)
1401 return -EINVAL;
1402
Terence Hampsonadf47302013-05-23 12:21:02 -04001403 return 0;
1404}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001405
Naseer Ahmed29a26812012-06-14 00:56:20 -07001406static int stretch_copybit(
1407 struct copybit_device_t *dev,
1408 struct copybit_image_t const *dst,
1409 struct copybit_image_t const *src,
1410 struct copybit_rect_t const *dst_rect,
1411 struct copybit_rect_t const *src_rect,
1412 struct copybit_region_t const *region)
1413{
1414 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001415 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001416 bool needsBlending = (ctx->src_global_alpha != 0);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001417 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1418 status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001419 region, needsBlending);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001420 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1421 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001422}
1423
1424/** Perform a blit type operation */
1425static int blit_copybit(
1426 struct copybit_device_t *dev,
1427 struct copybit_image_t const *dst,
1428 struct copybit_image_t const *src,
1429 struct copybit_region_t const *region)
1430{
Arun Kumar K.R71cfd812013-04-03 11:25:41 -07001431 int status = COPYBIT_SUCCESS;
1432 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Naseer Ahmedbb887bd2013-04-16 14:12:27 -04001433 struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
1434 struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
Arun Kumar K.R71cfd812013-04-03 11:25:41 -07001435 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1436 status = stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1437 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1438 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001439}
1440
Sushil Chauhan943797c2013-10-21 17:35:55 -07001441/** Fill the rect on dst with RGBA color **/
1442static int fill_color(struct copybit_device_t *dev,
1443 struct copybit_image_t const *dst,
1444 struct copybit_rect_t const *rect,
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301445 uint32_t /*color*/)
Sushil Chauhan943797c2013-10-21 17:35:55 -07001446{
1447 // TODO: Implement once c2d driver supports color fill
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301448 if(!dev || !dst || !rect)
1449 return -EINVAL;
1450
Sushil Chauhan943797c2013-10-21 17:35:55 -07001451 return -EINVAL;
1452}
1453
Naseer Ahmed29a26812012-06-14 00:56:20 -07001454/*****************************************************************************/
1455
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001456static void clean_up(copybit_context_t* ctx)
1457{
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001458 void* ret;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001459 if (!ctx)
1460 return;
1461
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001462 // stop the wait_cleanup_thread
1463 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1464 ctx->stop_thread = true;
1465 // Signal waiting thread
1466 pthread_cond_signal(&ctx->wait_cleanup_cond);
1467 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1468 // waits for the cleanup thread to exit
1469 pthread_join(ctx->wait_thread_id, &ret);
1470 pthread_mutex_destroy(&ctx->wait_cleanup_lock);
1471 pthread_cond_destroy (&ctx->wait_cleanup_cond);
1472
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001473 for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
1474 if (ctx->dst[i])
1475 LINK_c2dDestroySurface(ctx->dst[i]);
1476 }
1477
1478 for (int i = 0; i < MAX_RGB_SURFACES; i++) {
1479 if (ctx->blit_rgb_object[i].surface_id)
1480 LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
1481 }
1482
1483 for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
1484 if (ctx->blit_yuv_2_plane_object[i].surface_id)
1485 LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
1486 }
1487
1488 for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
1489 if (ctx->blit_yuv_3_plane_object[i].surface_id)
1490 LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
1491 }
1492
1493 if (ctx->libc2d2) {
1494 ::dlclose(ctx->libc2d2);
1495 ALOGV("dlclose(libc2d2)");
1496 }
1497
1498 free(ctx);
1499}
1500
Naseer Ahmed29a26812012-06-14 00:56:20 -07001501/** Close the copybit device */
1502static int close_copybit(struct hw_device_t *dev)
1503{
1504 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1505 if (ctx) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001506 free_temp_buffer(ctx->temp_src_buffer);
1507 free_temp_buffer(ctx->temp_dst_buffer);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001508 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001509 clean_up(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001510 return 0;
1511}
1512
1513/** Open a new instance of a copybit device using name */
1514static int open_copybit(const struct hw_module_t* module, const char* name,
1515 struct hw_device_t** device)
1516{
1517 int status = COPYBIT_SUCCESS;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301518 if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
1519 return COPYBIT_FAILURE;
1520 }
1521
Naseer Ahmed29a26812012-06-14 00:56:20 -07001522 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1523 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1524 struct copybit_context_t *ctx;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001525
1526 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1527 if(!ctx) {
1528 ALOGE("%s: malloc failed", __FUNCTION__);
1529 return COPYBIT_FAILURE;
1530 }
1531
1532 /* initialize drawstate */
1533 memset(ctx, 0, sizeof(*ctx));
Naseer Ahmed29a26812012-06-14 00:56:20 -07001534 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1535 if (!ctx->libc2d2) {
1536 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001537 clean_up(ctx);
1538 status = COPYBIT_FAILURE;
1539 *device = NULL;
1540 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001541 }
1542 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1543 "c2dCreateSurface");
1544 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1545 "c2dUpdateSurface");
1546 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1547 "c2dReadSurface");
1548 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1549 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1550 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1551 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1552 "c2dWaitTimestamp");
1553 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1554 "c2dDestroySurface");
1555 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1556 "c2dMapAddr");
1557 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1558 "c2dUnMapAddr");
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001559 *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
1560 "c2dGetDriverCapabilities");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001561 *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
1562 "c2dCreateFenceFD");
Naseer Ahmed183939d2013-03-14 20:44:17 -04001563 *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
1564 "c2dFillSurface");
Naseer Ahmed29a26812012-06-14 00:56:20 -07001565
1566 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001567 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
1568 !LINK_c2dFinish || !LINK_c2dDestroySurface ||
Naseer Ahmed183939d2013-03-14 20:44:17 -04001569 !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
1570 !LINK_c2dFillSurface) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001571 ALOGE("%s: dlsym ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001572 clean_up(ctx);
1573 status = COPYBIT_FAILURE;
1574 *device = NULL;
1575 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001576 }
1577
1578 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1579 ctx->device.common.version = 1;
1580 ctx->device.common.module = (hw_module_t*)(module);
1581 ctx->device.common.close = close_copybit;
1582 ctx->device.set_parameter = set_parameter_copybit;
1583 ctx->device.get = get;
1584 ctx->device.blit = blit_copybit;
Terence Hampsonadf47302013-05-23 12:21:02 -04001585 ctx->device.set_sync = set_sync_copybit;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001586 ctx->device.stretch = stretch_copybit;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001587 ctx->device.finish = finish_copybit;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001588 ctx->device.flush_get_fence = flush_get_fence_copybit;
Naseer Ahmed183939d2013-03-14 20:44:17 -04001589 ctx->device.clear = clear_copybit;
Sushil Chauhan943797c2013-10-21 17:35:55 -07001590 ctx->device.fill_color = fill_color;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001591
1592 /* Create RGB Surface */
1593 surfDefinition.buffer = (void*)0xdddddddd;
1594 surfDefinition.phys = (void*)0xdddddddd;
1595 surfDefinition.stride = 1 * 4;
1596 surfDefinition.width = 1;
1597 surfDefinition.height = 1;
1598 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1599 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1600 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001601 C2D_SURFACE_WITH_PHYS |
1602 C2D_SURFACE_WITH_PHYS_DUMMY ),
1603 &surfDefinition)) {
1604 ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
1605 ctx->dst[RGB_SURFACE] = 0;
1606 clean_up(ctx);
1607 status = COPYBIT_FAILURE;
1608 *device = NULL;
1609 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001610 }
1611
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001612 unsigned int surface_id = 0;
1613 for (int i = 0; i < MAX_RGB_SURFACES; i++)
1614 {
1615 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001616 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001617 C2D_SURFACE_WITH_PHYS |
1618 C2D_SURFACE_WITH_PHYS_DUMMY ),
1619 &surfDefinition)) {
1620 ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
1621 ctx->blit_rgb_object[i].surface_id = 0;
1622 status = COPYBIT_FAILURE;
1623 break;
1624 } else {
1625 ctx->blit_rgb_object[i].surface_id = surface_id;
1626 ALOGW("%s i = %d surface_id=%d", __FUNCTION__, i,
1627 ctx->blit_rgb_object[i].surface_id);
1628 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001629 }
1630
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001631 if (status == COPYBIT_FAILURE) {
1632 clean_up(ctx);
1633 status = COPYBIT_FAILURE;
1634 *device = NULL;
1635 return status;
1636 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001637
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001638 // Create 2 plane YUV surfaces
1639 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001640 yuvSurfaceDef.width = 4;
1641 yuvSurfaceDef.height = 4;
1642 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1643 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1644 yuvSurfaceDef.stride0 = 4;
1645
1646 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1647 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1648 yuvSurfaceDef.stride1 = 4;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001649 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1650 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001651 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1652 C2D_SURFACE_WITH_PHYS |
1653 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001654 &yuvSurfaceDef)) {
1655 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001656 ctx->dst[YUV_SURFACE_2_PLANES] = 0;
1657 clean_up(ctx);
1658 status = COPYBIT_FAILURE;
1659 *device = NULL;
1660 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001661 }
1662
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001663 for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
1664 {
1665 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1666 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1667 C2D_SURFACE_WITH_PHYS |
1668 C2D_SURFACE_WITH_PHYS_DUMMY ),
1669 &yuvSurfaceDef)) {
1670 ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
1671 ctx->blit_yuv_2_plane_object[i].surface_id = 0;
1672 status = COPYBIT_FAILURE;
1673 break;
1674 } else {
1675 ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
1676 ALOGW("%s: 2 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1677 ctx->blit_yuv_2_plane_object[i].surface_id);
1678 }
1679 }
1680
1681 if (status == COPYBIT_FAILURE) {
1682 clean_up(ctx);
1683 status = COPYBIT_FAILURE;
1684 *device = NULL;
1685 return status;
1686 }
1687
1688 // Create YUV 3 plane surfaces
Naseer Ahmed29a26812012-06-14 00:56:20 -07001689 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1690 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1691 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1692 yuvSurfaceDef.stride2 = 4;
1693
Naseer Ahmed29a26812012-06-14 00:56:20 -07001694 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1695 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001696 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1697 C2D_SURFACE_WITH_PHYS |
1698 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001699 &yuvSurfaceDef)) {
1700 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001701 ctx->dst[YUV_SURFACE_3_PLANES] = 0;
1702 clean_up(ctx);
1703 status = COPYBIT_FAILURE;
1704 *device = NULL;
1705 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001706 }
1707
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001708 for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
1709 {
1710 if (LINK_c2dCreateSurface(&(surface_id),
1711 C2D_TARGET | C2D_SOURCE,
1712 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1713 C2D_SURFACE_WITH_PHYS |
1714 C2D_SURFACE_WITH_PHYS_DUMMY),
1715 &yuvSurfaceDef)) {
1716 ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
1717 ctx->blit_yuv_3_plane_object[i].surface_id = 0;
1718 status = COPYBIT_FAILURE;
1719 break;
1720 } else {
1721 ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
1722 ALOGW("%s: 3 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1723 ctx->blit_yuv_3_plane_object[i].surface_id);
1724 }
1725 }
1726
1727 if (status == COPYBIT_FAILURE) {
1728 clean_up(ctx);
1729 status = COPYBIT_FAILURE;
1730 *device = NULL;
1731 return status;
1732 }
1733
1734 if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
1735 ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
1736 clean_up(ctx);
1737 status = COPYBIT_FAILURE;
1738 *device = NULL;
1739 return status;
1740 }
1741 // Initialize context variables.
1742 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1743
Naseer Ahmed29a26812012-06-14 00:56:20 -07001744 ctx->temp_src_buffer.fd = -1;
1745 ctx->temp_src_buffer.base = 0;
1746 ctx->temp_src_buffer.size = 0;
1747
1748 ctx->temp_dst_buffer.fd = -1;
1749 ctx->temp_dst_buffer.base = 0;
1750 ctx->temp_dst_buffer.size = 0;
1751
1752 ctx->fb_width = 0;
1753 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001754
1755 ctx->blit_rgb_count = 0;
1756 ctx->blit_yuv_2_plane_count = 0;
1757 ctx->blit_yuv_3_plane_count = 0;
1758 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001759
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001760 ctx->wait_timestamp = false;
1761 ctx->stop_thread = false;
1762 pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
1763 pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
1764 /* Start the wait thread */
1765 pthread_attr_t attr;
1766 pthread_attr_init(&attr);
1767 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1768
1769 pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
1770 (void *)ctx);
1771 pthread_attr_destroy(&attr);
1772
Naseer Ahmed29a26812012-06-14 00:56:20 -07001773 *device = &ctx->device.common;
1774 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001775}