blob: 852b8c0b5d3cde0e3d4708a42bee22303797cea4 [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;
262 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
263 C2D_FORMAT_SWAP_RB |
264 C2D_FORMAT_DISABLE_ALPHA;
265 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
266 C2D_FORMAT_SWAP_RB;
267 case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700268 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
269 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
270 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
271 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
272 C2D_FORMAT_MACROTILED;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800273 default: ALOGE("%s: invalid format (0x%x",
274 __FUNCTION__, format);
275 return -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700276 }
277 return -EINVAL;
278}
279
280/* Get the C2D formats needed for conversion to YUV */
281static int get_c2d_format_for_yuv_destination(int halFormat) {
282 switch (halFormat) {
283 // We do not swap the RB when the target is YUV
284 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
285 C2D_FORMAT_DISABLE_ALPHA;
286 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800287 // The U and V need to be interchanged when the target is YUV
Naseer Ahmed29a26812012-06-14 00:56:20 -0700288 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
289 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
290 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
291 default: return get_format(halFormat);
292 }
293 return -EINVAL;
294}
295
296/* ------------------------------------------------------------------- *//*!
297 * \internal
298 * \brief Get the bpp for a particular color format
299 * \param color format
300 * \return bits per pixel
301 *//* ------------------------------------------------------------------- */
302int c2diGetBpp(int32 colorformat)
303{
304
305 int c2dBpp = 0;
306
307 switch(colorformat&0xFF)
308 {
309 case C2D_COLOR_FORMAT_4444_RGBA:
310 case C2D_COLOR_FORMAT_4444_ARGB:
311 case C2D_COLOR_FORMAT_1555_ARGB:
312 case C2D_COLOR_FORMAT_565_RGB:
313 case C2D_COLOR_FORMAT_5551_RGBA:
314 c2dBpp = 16;
315 break;
316 case C2D_COLOR_FORMAT_8888_RGBA:
317 case C2D_COLOR_FORMAT_8888_ARGB:
318 c2dBpp = 32;
319 break;
320 case C2D_COLOR_FORMAT_8_L:
321 case C2D_COLOR_FORMAT_8_A:
322 c2dBpp = 8;
323 break;
324 case C2D_COLOR_FORMAT_4_A:
325 c2dBpp = 4;
326 break;
327 case C2D_COLOR_FORMAT_1:
328 c2dBpp = 1;
329 break;
330 default:
331 ALOGE("%s ERROR", __func__);
332 break;
333 }
334 return c2dBpp;
335}
336
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530337static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700338 struct private_handle_t *handle, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700339{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530340 uint32 memtype;
341 size_t *gpuaddr = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700342 C2D_STATUS rc;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700343 int freeindex = 0;
344 bool mapaddr = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700345
346 if(!handle)
347 return 0;
348
349 if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
350 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
351 memtype = KGSL_USER_MEM_TYPE_PMEM;
352 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
353 memtype = KGSL_USER_MEM_TYPE_ASHMEM;
354 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
355 memtype = KGSL_USER_MEM_TYPE_ION;
356 else {
357 ALOGE("Invalid handle flags: 0x%x", handle->flags);
358 return 0;
359 }
360
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700361 // Check for a freeindex in the mapped_gpu_addr list
362 for (freeindex = 0; freeindex < MAX_SURFACES; freeindex++) {
363 if (ctx->mapped_gpu_addr[freeindex] == 0) {
364 // free index is available
365 // map GPU addr and use this as mapped_idx
366 mapaddr = true;
367 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800368 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700369 }
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700370
371 if(mapaddr) {
372 rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
373 handle->offset, memtype, (void**)&gpuaddr);
374
375 if (rc == C2D_STATUS_OK) {
376 // We have mapped the GPU address inside copybit. We need to unmap
377 // this address after the blit. Store this address
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530378 ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700379 mapped_idx = freeindex;
380 }
381 }
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530382 return (size_t)gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700383}
384
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800385static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
386{
387 if (!ctx || (mapped_idx == -1))
388 return;
389
390 if (ctx->mapped_gpu_addr[mapped_idx]) {
391 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
392 ctx->mapped_gpu_addr[mapped_idx] = 0;
393 }
394}
395
Naseer Ahmed29a26812012-06-14 00:56:20 -0700396static int is_supported_rgb_format(int format)
397{
398 switch(format) {
399 case HAL_PIXEL_FORMAT_RGBA_8888:
400 case HAL_PIXEL_FORMAT_RGBX_8888:
401 case HAL_PIXEL_FORMAT_RGB_565:
Mathias Agopiane4001e72013-09-17 10:37:22 -0700402 case HAL_PIXEL_FORMAT_BGRA_8888: {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700403 return COPYBIT_SUCCESS;
404 }
405 default:
406 return COPYBIT_FAILURE;
407 }
408}
409
410static int get_num_planes(int format)
411{
412 switch(format) {
413 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
414 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
415 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
416 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
417 return 2;
418 }
419 case HAL_PIXEL_FORMAT_YV12: {
420 return 3;
421 }
422 default:
423 return COPYBIT_FAILURE;
424 }
425}
426
427static int is_supported_yuv_format(int format)
428{
429 switch(format) {
430 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
431 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
432 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
433 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
434 return COPYBIT_SUCCESS;
435 }
436 default:
437 return COPYBIT_FAILURE;
438 }
439}
440
441static int is_valid_destination_format(int format)
442{
443 if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
444 // C2D does not support NV12Tile as a destination format.
445 return COPYBIT_FAILURE;
446 }
447 return COPYBIT_SUCCESS;
448}
449
450static int calculate_yuv_offset_and_stride(const bufferInfo& info,
451 yuvPlaneInfo& yuvInfo)
452{
453 int width = info.width;
454 int height = info.height;
455 int format = info.format;
456
457 int aligned_height = 0;
458 int aligned_width = 0, size = 0;
459
460 switch (format) {
461 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
462 /* NV12 Tile buffers have their luma height aligned to 32bytes and width
463 * aligned to 128 bytes. The chroma offset starts at an 8K boundary
464 */
465 aligned_height = ALIGN(height, 32);
466 aligned_width = ALIGN(width, 128);
467 size = aligned_width * aligned_height;
468 yuvInfo.plane1_offset = ALIGN(size,8192);
469 yuvInfo.yStride = aligned_width;
470 yuvInfo.plane1_stride = aligned_width;
471 break;
472 }
473 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
474 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
475 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
476 aligned_width = ALIGN(width, 32);
477 yuvInfo.yStride = aligned_width;
478 yuvInfo.plane1_stride = aligned_width;
479 if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
480 // The encoder requires a 2K aligned chroma offset
481 yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
482 } else
483 yuvInfo.plane1_offset = aligned_width * height;
484
485 break;
486 }
487 default: {
488 return COPYBIT_FAILURE;
489 }
490 }
491 return COPYBIT_SUCCESS;
492}
493
494/** create C2D surface from copybit image */
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800495static int set_image(copybit_context_t* ctx, uint32 surfaceId,
496 const struct copybit_image_t *rhs,
497 const eC2DFlags flags, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700498{
499 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
500 C2D_SURFACE_TYPE surfaceType;
501 int status = COPYBIT_SUCCESS;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530502 uintptr_t gpuaddr = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800503 int c2d_format;
504 mapped_idx = -1;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700505
506 if (flags & FLAGS_YUV_DESTINATION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800507 c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700508 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800509 c2d_format = get_format(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700510 }
511
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800512 if(c2d_format == -EINVAL) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700513 ALOGE("%s: invalid format", __FUNCTION__);
514 return -EINVAL;
515 }
516
517 if(handle == NULL) {
518 ALOGE("%s: invalid handle", __func__);
519 return -EINVAL;
520 }
521
522 if (handle->gpuaddr == 0) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800523 gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
524 if(!gpuaddr) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700525 ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
526 return COPYBIT_FAILURE;
527 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800528 } else {
529 gpuaddr = handle->gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700530 }
531
532 /* create C2D surface */
533 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
534 /* RGB */
535 C2D_RGB_SURFACE_DEF surfaceDef;
536
537 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
538
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800539 surfaceDef.phys = (void*) gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700540 surfaceDef.buffer = (void*) (handle->base);
541
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800542 surfaceDef.format = c2d_format |
Naseer Ahmed29a26812012-06-14 00:56:20 -0700543 ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
544 surfaceDef.width = rhs->w;
545 surfaceDef.height = rhs->h;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530546 int aligned_width = ALIGN((int)surfaceDef.width,32);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700547 surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
548
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800549 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
550 &surfaceDef)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700551 ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800552 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700553 status = COPYBIT_FAILURE;
554 }
555 } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
556 C2D_YUV_SURFACE_DEF surfaceDef;
557 memset(&surfaceDef, 0, sizeof(surfaceDef));
558 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800559 surfaceDef.format = c2d_format;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700560
561 bufferInfo info;
562 info.width = rhs->w;
563 info.height = rhs->h;
564 info.format = rhs->format;
565
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700566 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700567 status = calculate_yuv_offset_and_stride(info, yuvInfo);
568 if(status != COPYBIT_SUCCESS) {
569 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800570 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700571 }
572
573 surfaceDef.width = rhs->w;
574 surfaceDef.height = rhs->h;
575 surfaceDef.plane0 = (void*) (handle->base);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800576 surfaceDef.phys0 = (void*) (gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700577 surfaceDef.stride0 = yuvInfo.yStride;
578
579 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800580 surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700581 surfaceDef.stride1 = yuvInfo.plane1_stride;
582 if (3 == get_num_planes(rhs->format)) {
583 surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800584 surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700585 surfaceDef.stride2 = yuvInfo.plane2_stride;
586 }
587
588 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
589 &surfaceDef)) {
590 ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800591 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700592 status = COPYBIT_FAILURE;
593 }
594 } else {
595 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
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
600 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700601}
602
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800603/** copy the bits */
604static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700605{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800606 if (ctx->blit_count == 0) {
607 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700608 }
609
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800610 for (int i = 0; i < ctx->blit_count; i++)
611 {
612 ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
613 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800614 ctx->blit_list[ctx->blit_count-1].next = NULL;
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800615 uint32_t target_transform = ctx->trg_transform;
616 if (ctx->c2d_driver_info.capabilities_mask &
617 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
618 // For A3xx - set 0x0 as the transform is set in the config_mask
619 target_transform = 0x0;
620 }
621 if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800622 ctx->blit_count)) {
623 ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
624 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700625 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700626 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700627}
628
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800629
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800630
631static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
632{
633 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
634 int status = COPYBIT_FAILURE;
635 if (!ctx)
636 return COPYBIT_FAILURE;
637 pthread_mutex_lock(&ctx->wait_cleanup_lock);
638 status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
639
640 if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
641 ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
642 // unlock the mutex and return failure
643 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
644 return COPYBIT_FAILURE;
645 }
646 if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
647 fd)) {
648 ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
649 status = COPYBIT_FAILURE;
650 }
651 if(status == COPYBIT_SUCCESS) {
652 //signal the wait_thread
653 ctx->wait_timestamp = true;
654 pthread_cond_signal(&ctx->wait_cleanup_cond);
655 }
656 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
657 return status;
658}
659
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800660static int finish_copybit(struct copybit_device_t *dev)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700661{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800662 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
663 if (!ctx)
664 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700665
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800666 int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700667
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800668 if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
669 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
670 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700671 }
672
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800673 // Unmap any mapped addresses.
674 for (int i = 0; i < MAX_SURFACES; i++) {
675 if (ctx->mapped_gpu_addr[i]) {
676 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
677 ctx->mapped_gpu_addr[i] = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700678 }
679 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700680
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800681 // Reset the counts after the draw.
682 ctx->blit_rgb_count = 0;
683 ctx->blit_yuv_2_plane_count = 0;
684 ctx->blit_yuv_3_plane_count = 0;
685 ctx->blit_count = 0;
Pawan Kumar74d9ea92013-05-03 14:25:49 +0530686 ctx->dst_surface_mapped = false;
687 ctx->dst_surface_base = 0;
688
Naseer Ahmed29a26812012-06-14 00:56:20 -0700689 return status;
690}
691
Naseer Ahmed183939d2013-03-14 20:44:17 -0400692static int clear_copybit(struct copybit_device_t *dev,
693 struct copybit_image_t const *buf,
694 struct copybit_rect_t *rect)
695{
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700696 int ret = COPYBIT_SUCCESS;
Naseer Ahmed183939d2013-03-14 20:44:17 -0400697 int flags = FLAGS_PREMULTIPLIED_ALPHA;
698 int mapped_dst_idx = -1;
699 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
700 C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700701 pthread_mutex_lock(&ctx->wait_cleanup_lock);
Arun Kumar K.R14031eb2013-04-15 14:26:43 -0700702 if(!ctx->dst_surface_mapped) {
703 ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
704 (eC2DFlags)flags, mapped_dst_idx);
705 if(ret) {
706 ALOGE("%s: set_image error", __FUNCTION__);
707 unmap_gpuaddr(ctx, mapped_dst_idx);
708 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
709 return COPYBIT_FAILURE;
710 }
711 //clear_copybit is the first call made by HWC for each composition
712 //with the dest surface, hence set dst_surface_mapped.
713 ctx->dst_surface_mapped = true;
714 ctx->dst_surface_base = buf->base;
715 ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
Naseer Ahmed183939d2013-03-14 20:44:17 -0400716 }
Arun Kumar K.R71cfd812013-04-03 11:25:41 -0700717 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
Naseer Ahmed183939d2013-03-14 20:44:17 -0400718 return ret;
719}
720
721
Naseer Ahmed29a26812012-06-14 00:56:20 -0700722/** setup rectangles */
723static void set_rects(struct copybit_context_t *ctx,
724 C2D_OBJECT *c2dObject,
725 const struct copybit_rect_t *dst,
726 const struct copybit_rect_t *src,
727 const struct copybit_rect_t *scissor)
728{
729 // Set the target rect.
730 if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
731 (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
732 /* target rotation is 270 */
733 c2dObject->target_rect.x = (dst->t)<<16;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530734 c2dObject->target_rect.y = ctx->fb_width?
735 (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700736 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
737 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
738 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
739 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
740 c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
741 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
742 c2dObject->target_rect.y = (dst->l)<<16;
743 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
744 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
745 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
746 c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
747 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530748 c2dObject->target_rect.x = ctx->fb_width?
749 (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700750 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
751 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
752 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
753 } else {
754 c2dObject->target_rect.x = (dst->l)<<16;
755 c2dObject->target_rect.y = (dst->t)<<16;
756 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
757 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
758 }
759 c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
760
761 // Set the source rect
762 c2dObject->source_rect.x = (src->l)<<16;
763 c2dObject->source_rect.y = (src->t)<<16;
764 c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
765 c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
766 c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
767
768 // Set the scissor rect
769 c2dObject->scissor_rect.x = scissor->l;
770 c2dObject->scissor_rect.y = scissor->t;
771 c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
772 c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
773 c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
774}
775
Naseer Ahmed29a26812012-06-14 00:56:20 -0700776/*****************************************************************************/
777
778/** Set a parameter to value */
779static int set_parameter_copybit(
780 struct copybit_device_t *dev,
781 int name,
782 int value)
783{
784 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800785 int status = COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700786 if (!ctx) {
787 ALOGE("%s: null context", __FUNCTION__);
788 return -EINVAL;
789 }
790
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800791 pthread_mutex_lock(&ctx->wait_cleanup_lock);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700792 switch(name) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700793 case COPYBIT_PLANE_ALPHA:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800794 {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700795 if (value < 0) value = 0;
796 if (value >= 256) value = 255;
797
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800798 ctx->src_global_alpha = value;
799 if (value < 255)
800 ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700801 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800802 ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
803 }
804 break;
805 case COPYBIT_BLEND_MODE:
806 {
807 if (value == COPYBIT_BLENDING_NONE) {
808 ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
809 ctx->is_premultiplied_alpha = true;
810 } else if (value == COPYBIT_BLENDING_PREMULT) {
811 ctx->is_premultiplied_alpha = true;
812 } else {
813 ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700814 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800815 }
816 break;
817 case COPYBIT_TRANSFORM:
818 {
819 unsigned int transform = 0;
820 uint32 config_mask = 0;
821 config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
822 if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
823 transform = C2D_TARGET_ROTATE_180;
824 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
825 } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
826 transform = C2D_TARGET_ROTATE_90;
827 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
828 } else if(value == COPYBIT_TRANSFORM_ROT_90) {
829 transform = C2D_TARGET_ROTATE_270;
830 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
831 } else {
832 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
833 if(value & COPYBIT_TRANSFORM_FLIP_H) {
834 config_mask |= C2D_MIRROR_H_BIT;
835 } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
836 config_mask |= C2D_MIRROR_V_BIT;
837 }
838 }
839
Arun Kumar K.Rb2fc9562013-02-25 16:28:51 -0800840 if (ctx->c2d_driver_info.capabilities_mask &
841 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
842 ctx->config_mask |= config_mask;
843 } else {
844 // The transform for this surface does not match the current
845 // target transform. Draw all previous surfaces. This will be
846 // changed once we have a new mechanism to send different
847 // target rotations to c2d.
848 finish_copybit(dev);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800849 }
850 ctx->trg_transform = transform;
851 }
852 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700853 case COPYBIT_FRAMEBUFFER_WIDTH:
854 ctx->fb_width = value;
855 break;
856 case COPYBIT_FRAMEBUFFER_HEIGHT:
857 ctx->fb_height = value;
858 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800859 case COPYBIT_ROTATION_DEG:
860 case COPYBIT_DITHER:
861 case COPYBIT_BLUR:
Naseer Ahmed45a99602012-07-31 19:15:24 -0700862 case COPYBIT_BLIT_TO_FRAMEBUFFER:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800863 // Do nothing
Naseer Ahmed45a99602012-07-31 19:15:24 -0700864 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700865 default:
866 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800867 status = -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700868 break;
869 }
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -0800870 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
871 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700872}
873
874/** Get a static info value */
875static int get(struct copybit_device_t *dev, int name)
876{
877 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
878 int value;
879
880 if (!ctx) {
881 ALOGE("%s: null context error", __FUNCTION__);
882 return -EINVAL;
883 }
884
885 switch(name) {
886 case COPYBIT_MINIFICATION_LIMIT:
887 value = MAX_SCALE_FACTOR;
888 break;
889 case COPYBIT_MAGNIFICATION_LIMIT:
890 value = MAX_SCALE_FACTOR;
891 break;
892 case COPYBIT_SCALING_FRAC_BITS:
893 value = 32;
894 break;
895 case COPYBIT_ROTATION_STEP_DEG:
896 value = 1;
897 break;
898 default:
899 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
900 value = -EINVAL;
901 }
902 return value;
903}
904
905static int is_alpha(int cformat)
906{
907 int alpha = 0;
908 switch (cformat & 0xFF) {
909 case C2D_COLOR_FORMAT_8888_ARGB:
910 case C2D_COLOR_FORMAT_8888_RGBA:
911 case C2D_COLOR_FORMAT_5551_RGBA:
912 case C2D_COLOR_FORMAT_4444_ARGB:
913 alpha = 1;
914 break;
915 default:
916 alpha = 0;
917 break;
918 }
919
920 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
921 alpha = 0;
922
923 return alpha;
924}
925
926/* Function to check if we need a temporary buffer for the blit.
927 * This would happen if the requested destination stride and the
928 * C2D stride do not match. We ignore RGB buffers, since their
929 * stride is always aligned to 32.
930 */
931static bool need_temp_buffer(struct copybit_image_t const *img)
932{
933 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
934 return false;
935
936 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
937
938 // The width parameter in the handle contains the aligned_w. We check if we
939 // need to convert based on this param. YUV formats have bpp=1, so checking
940 // if the requested stride is aligned should suffice.
941 if (0 == (handle->width)%32) {
942 return false;
943 }
944
945 return true;
946}
947
948/* Function to extract the information from the copybit image and set the corresponding
949 * values in the bufferInfo struct.
950 */
951static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
952{
953 info.width = img->w;
954 info.height = img->h;
955 info.format = img->format;
956}
957
958/* Function to get the required size for a particular format, inorder for C2D to perform
959 * the blit operation.
960 */
961static size_t get_size(const bufferInfo& info)
962{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +0530963 int size = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700964 int w = info.width;
965 int h = info.height;
966 int aligned_w = ALIGN(w, 32);
967 switch(info.format) {
968 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
969 {
970 // Chroma for this format is aligned to 2K.
971 size = ALIGN((aligned_w*h), 2048) +
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800972 ALIGN(aligned_w/2, 32) * (h/2) *2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700973 size = ALIGN(size, 4096);
974 } break;
975 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
976 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
977 {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800978 size = aligned_w * h +
979 ALIGN(aligned_w/2, 32) * (h/2) * 2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700980 size = ALIGN(size, 4096);
981 } break;
982 default: break;
983 }
984 return size;
985}
986
987/* Function to allocate memory for the temporary buffer. This memory is
988 * allocated from Ashmem. It is the caller's responsibility to free this
989 * memory.
990 */
991static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
992{
993 ALOGD("%s E", __FUNCTION__);
994 // Alloc memory from system heap
995 data.base = 0;
996 data.fd = -1;
997 data.offset = 0;
998 data.size = get_size(info);
999 data.align = getpagesize();
1000 data.uncached = true;
1001 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
1002
1003 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001004 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -07001005 }
1006
1007 if (sAlloc == 0) {
1008 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
1009 return COPYBIT_FAILURE;
1010 }
1011
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001012 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001013 if (0 != err) {
1014 ALOGE("%s: allocate failed", __FUNCTION__);
1015 return COPYBIT_FAILURE;
1016 }
1017
1018 ALOGD("%s X", __FUNCTION__);
1019 return err;
1020}
1021
1022/* Function to free the temporary allocated memory.*/
1023static void free_temp_buffer(alloc_data &data)
1024{
1025 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001026 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001027 memalloc->free_buffer(data.base, data.size, 0, data.fd);
1028 }
1029}
1030
1031/* Function to perform the software color conversion. Convert the
1032 * C2D compatible format to the Android compatible format
1033 */
1034static int copy_image(private_handle_t *src_handle,
1035 struct copybit_image_t const *rhs,
1036 eConversionType conversionType)
1037{
1038 if (src_handle->fd == -1) {
1039 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
1040 return COPYBIT_FAILURE;
1041 }
1042
1043 // Copy the info.
1044 int ret = COPYBIT_SUCCESS;
1045 switch(rhs->format) {
1046 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1047 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1048 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1049 {
1050 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
1051 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
1052 } else {
1053 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
1054 }
1055
1056 } break;
1057 default: {
1058 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
1059 ret = COPYBIT_FAILURE;
1060 } break;
1061 }
1062 return ret;
1063}
1064
1065static void delete_handle(private_handle_t *handle)
1066{
1067 if (handle) {
1068 delete handle;
1069 handle = 0;
1070 }
1071}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001072
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301073static bool need_to_execute_draw(eC2DFlags flags)
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001074{
1075 if (flags & FLAGS_TEMP_SRC_DST) {
1076 return true;
1077 }
1078 if (flags & FLAGS_YUV_DESTINATION) {
1079 return true;
1080 }
1081 return false;
1082}
1083
Naseer Ahmed29a26812012-06-14 00:56:20 -07001084/** do a stretch blit type operation */
1085static int stretch_copybit_internal(
1086 struct copybit_device_t *dev,
1087 struct copybit_image_t const *dst,
1088 struct copybit_image_t const *src,
1089 struct copybit_rect_t const *dst_rect,
1090 struct copybit_rect_t const *src_rect,
1091 struct copybit_region_t const *region,
1092 bool enableBlend)
1093{
1094 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1095 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001096 int flags = 0;
1097 int src_surface_type;
1098 int mapped_src_idx = -1, mapped_dst_idx = -1;
1099 C2D_OBJECT_STR src_surface;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001100
1101 if (!ctx) {
1102 ALOGE("%s: null context error", __FUNCTION__);
1103 return -EINVAL;
1104 }
1105
1106 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1107 ALOGE("%s: src dimension error", __FUNCTION__);
1108 return -EINVAL;
1109 }
1110
1111 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001112 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w,
1113 dst->h);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001114 return -EINVAL;
1115 }
1116
Naseer Ahmed29a26812012-06-14 00:56:20 -07001117 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001118 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
1119 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001120 return COPYBIT_FAILURE;
1121 }
1122
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001123 int dst_surface_type;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001124 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001125 dst_surface_type = RGB_SURFACE;
1126 flags |= FLAGS_PREMULTIPLIED_ALPHA;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001127 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001128 int num_planes = get_num_planes(dst->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001129 flags |= FLAGS_YUV_DESTINATION;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001130 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001131 dst_surface_type = YUV_SURFACE_2_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001132 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001133 dst_surface_type = YUV_SURFACE_3_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001134 } else {
1135 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1136 __FUNCTION__, dst->format);
1137 return COPYBIT_FAILURE;
1138 }
1139 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001140 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
1141 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001142 return COPYBIT_FAILURE;
1143 }
1144
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001145 if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
1146 ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1147 ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1148 ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
1149 ctx->dst_surface_type != dst_surface_type) {
1150 // we have reached the max. limits of our internal structures or
1151 // changed the target.
1152 // Draw the remaining surfaces. We need to do the finish here since
1153 // we need to free up the surface templates.
1154 finish_copybit(dev);
1155 }
1156
1157 ctx->dst_surface_type = dst_surface_type;
1158
1159 // Update the destination
Naseer Ahmed29a26812012-06-14 00:56:20 -07001160 copybit_image_t dst_image;
1161 dst_image.w = dst->w;
1162 dst_image.h = dst->h;
1163 dst_image.format = dst->format;
1164 dst_image.handle = dst->handle;
1165 // Check if we need a temp. copy for the destination. We'd need this the destination
1166 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1167 // aligned to 32.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001168 bool need_temp_dst = need_temp_buffer(dst);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001169 bufferInfo dst_info;
1170 populate_buffer_info(dst, dst_info);
1171 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1172 dst_info.width, dst_info.height);
1173 if (dst_hnd == NULL) {
1174 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1175 return COPYBIT_FAILURE;
1176 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001177 if (need_temp_dst) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001178 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1179 free_temp_buffer(ctx->temp_dst_buffer);
1180 // Create a temp buffer and set that as the destination.
1181 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1182 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1183 delete_handle(dst_hnd);
1184 return COPYBIT_FAILURE;
1185 }
1186 }
1187 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1188 dst_hnd->size = ctx->temp_dst_buffer.size;
1189 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301190 dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001191 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1192 dst_hnd->gpuaddr = 0;
1193 dst_image.handle = dst_hnd;
1194 }
Arun Kumar K.R14031eb2013-04-15 14:26:43 -07001195 if(!ctx->dst_surface_mapped) {
1196 //map the destination surface to GPU address
1197 status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
1198 (eC2DFlags)flags, mapped_dst_idx);
1199 if(status) {
1200 ALOGE("%s: dst: set_image error", __FUNCTION__);
1201 delete_handle(dst_hnd);
1202 unmap_gpuaddr(ctx, mapped_dst_idx);
1203 return COPYBIT_FAILURE;
1204 }
1205 ctx->dst_surface_mapped = true;
1206 ctx->dst_surface_base = dst->base;
1207 } else if(ctx->dst_surface_mapped && ctx->dst_surface_base != dst->base) {
1208 // Destination surface for the operation should be same for multiple
1209 // requests, this check is catch if there is any case when the
1210 // destination changes
1211 ALOGE("%s: a different destination surface!!", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001212 }
1213
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001214 // Update the source
1215 flags = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001216 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001217 src_surface_type = RGB_SURFACE;
1218 src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001219 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1220 int num_planes = get_num_planes(src->format);
1221 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001222 src_surface_type = YUV_SURFACE_2_PLANES;
1223 src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001224 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001225 src_surface_type = YUV_SURFACE_3_PLANES;
1226 src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001227 } else {
1228 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1229 __FUNCTION__, src->format);
1230 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001231 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001232 return -EINVAL;
1233 }
1234 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001235 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
1236 src->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001237 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001238 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001239 return -EINVAL;
1240 }
1241
1242 copybit_image_t src_image;
1243 src_image.w = src->w;
1244 src_image.h = src->h;
1245 src_image.format = src->format;
1246 src_image.handle = src->handle;
1247
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001248 bool need_temp_src = need_temp_buffer(src);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001249 bufferInfo src_info;
1250 populate_buffer_info(src, src_info);
1251 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 -08001252 src_info.width, src_info.height);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001253 if (NULL == src_hnd) {
1254 ALOGE("%s: src_hnd is null", __FUNCTION__);
1255 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001256 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001257 return COPYBIT_FAILURE;
1258 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001259 if (need_temp_src) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001260 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1261 free_temp_buffer(ctx->temp_src_buffer);
1262 // Create a temp buffer and set that as the destination.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001263 if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
1264 ctx->temp_src_buffer)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001265 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1266 delete_handle(dst_hnd);
1267 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001268 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001269 return COPYBIT_FAILURE;
1270 }
1271 }
1272 src_hnd->fd = ctx->temp_src_buffer.fd;
1273 src_hnd->size = ctx->temp_src_buffer.size;
1274 src_hnd->flags = ctx->temp_src_buffer.allocType;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301275 src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001276 src_hnd->offset = ctx->temp_src_buffer.offset;
1277 src_hnd->gpuaddr = 0;
1278 src_image.handle = src_hnd;
1279
1280 // Copy the source.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001281 status = copy_image((private_handle_t *)src->handle, &src_image,
1282 CONVERT_TO_C2D_FORMAT);
1283 if (status == COPYBIT_FAILURE) {
1284 ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
1285 delete_handle(dst_hnd);
1286 delete_handle(src_hnd);
1287 unmap_gpuaddr(ctx, mapped_dst_idx);
1288 return status;
1289 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001290
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001291 // Clean the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001292 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001293 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001294 src_hnd->offset, src_hnd->fd,
1295 gralloc::CACHE_CLEAN)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001296 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1297 delete_handle(dst_hnd);
1298 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001299 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001300 return COPYBIT_FAILURE;
1301 }
1302 }
1303
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001304 flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1305 flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
1306 status = set_image(ctx, src_surface.surface_id, &src_image,
1307 (eC2DFlags)flags, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001308 if(status) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001309 ALOGE("%s: set_image (src) error", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001310 delete_handle(dst_hnd);
1311 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001312 unmap_gpuaddr(ctx, mapped_dst_idx);
1313 unmap_gpuaddr(ctx, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001314 return COPYBIT_FAILURE;
1315 }
1316
Arun Kumar K.Re29916b2013-03-20 11:42:53 -07001317 src_surface.config_mask = C2D_NO_ANTIALIASING_BIT | ctx->config_mask;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001318 src_surface.global_alpha = ctx->src_global_alpha;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001319 if (enableBlend) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001320 if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1321 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1322 if(!(src_surface.global_alpha)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001323 // src alpha is zero
Naseer Ahmed29a26812012-06-14 00:56:20 -07001324 delete_handle(dst_hnd);
1325 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001326 unmap_gpuaddr(ctx, mapped_dst_idx);
1327 unmap_gpuaddr(ctx, mapped_src_idx);
1328 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001329 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001330 }
1331 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001332 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001333 }
1334
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001335 if (src_surface_type == RGB_SURFACE) {
1336 ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
1337 ctx->blit_rgb_count++;
1338 } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
1339 ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
1340 ctx->blit_yuv_2_plane_count++;
1341 } else {
1342 ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
1343 ctx->blit_yuv_3_plane_count++;
1344 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001345
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001346 struct copybit_rect_t clip;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001347 while ((status == 0) && region->next(region, &clip)) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001348 set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
1349 if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
1350 ALOGW("Reached end of blit count");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001351 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001352 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001353 ctx->blit_list[ctx->blit_count] = src_surface;
1354 ctx->blit_count++;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001355 }
1356
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001357 // Check if we need to perform an early draw-finish.
1358 flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301359 if (need_to_execute_draw((eC2DFlags)flags))
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001360 {
1361 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001362 }
1363
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001364 if (need_temp_dst) {
1365 // copy the temp. destination without the alignment to the actual
1366 // destination.
1367 status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1368 if (status == COPYBIT_FAILURE) {
1369 ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
1370 delete_handle(dst_hnd);
1371 delete_handle(src_hnd);
1372 unmap_gpuaddr(ctx, mapped_dst_idx);
1373 unmap_gpuaddr(ctx, mapped_src_idx);
1374 return status;
1375 }
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001376 // Clean the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001377 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001378 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
Naseer Ahmedaeab91f2013-03-20 21:01:19 -04001379 dst_hnd->offset, dst_hnd->fd,
1380 gralloc::CACHE_CLEAN);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001381 }
1382 delete_handle(dst_hnd);
1383 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001384
1385 ctx->is_premultiplied_alpha = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001386 ctx->fb_width = 0;
1387 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001388 ctx->config_mask = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001389 return status;
1390}
1391
Terence Hampsonadf47302013-05-23 12:21:02 -04001392static int set_sync_copybit(struct copybit_device_t *dev,
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301393 int /*acquireFenceFd*/)
Terence Hampsonadf47302013-05-23 12:21:02 -04001394{
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301395 if(!dev)
1396 return -EINVAL;
1397
Terence Hampsonadf47302013-05-23 12:21:02 -04001398 return 0;
1399}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001400
Naseer Ahmed29a26812012-06-14 00:56:20 -07001401static int stretch_copybit(
1402 struct copybit_device_t *dev,
1403 struct copybit_image_t const *dst,
1404 struct copybit_image_t const *src,
1405 struct copybit_rect_t const *dst_rect,
1406 struct copybit_rect_t const *src_rect,
1407 struct copybit_region_t const *region)
1408{
1409 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001410 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001411 bool needsBlending = (ctx->src_global_alpha != 0);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001412 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1413 status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001414 region, needsBlending);
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001415 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1416 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001417}
1418
1419/** Perform a blit type operation */
1420static int blit_copybit(
1421 struct copybit_device_t *dev,
1422 struct copybit_image_t const *dst,
1423 struct copybit_image_t const *src,
1424 struct copybit_region_t const *region)
1425{
Arun Kumar K.R71cfd812013-04-03 11:25:41 -07001426 int status = COPYBIT_SUCCESS;
1427 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Naseer Ahmedbb887bd2013-04-16 14:12:27 -04001428 struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
1429 struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
Arun Kumar K.R71cfd812013-04-03 11:25:41 -07001430 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1431 status = stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1432 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1433 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001434}
1435
Sushil Chauhan943797c2013-10-21 17:35:55 -07001436/** Fill the rect on dst with RGBA color **/
1437static int fill_color(struct copybit_device_t *dev,
1438 struct copybit_image_t const *dst,
1439 struct copybit_rect_t const *rect,
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301440 uint32_t /*color*/)
Sushil Chauhan943797c2013-10-21 17:35:55 -07001441{
1442 // TODO: Implement once c2d driver supports color fill
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301443 if(!dev || !dst || !rect)
1444 return -EINVAL;
1445
Sushil Chauhan943797c2013-10-21 17:35:55 -07001446 return -EINVAL;
1447}
1448
Naseer Ahmed29a26812012-06-14 00:56:20 -07001449/*****************************************************************************/
1450
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001451static void clean_up(copybit_context_t* ctx)
1452{
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001453 void* ret;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001454 if (!ctx)
1455 return;
1456
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001457 // stop the wait_cleanup_thread
1458 pthread_mutex_lock(&ctx->wait_cleanup_lock);
1459 ctx->stop_thread = true;
1460 // Signal waiting thread
1461 pthread_cond_signal(&ctx->wait_cleanup_cond);
1462 pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1463 // waits for the cleanup thread to exit
1464 pthread_join(ctx->wait_thread_id, &ret);
1465 pthread_mutex_destroy(&ctx->wait_cleanup_lock);
1466 pthread_cond_destroy (&ctx->wait_cleanup_cond);
1467
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001468 for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
1469 if (ctx->dst[i])
1470 LINK_c2dDestroySurface(ctx->dst[i]);
1471 }
1472
1473 for (int i = 0; i < MAX_RGB_SURFACES; i++) {
1474 if (ctx->blit_rgb_object[i].surface_id)
1475 LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
1476 }
1477
1478 for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
1479 if (ctx->blit_yuv_2_plane_object[i].surface_id)
1480 LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
1481 }
1482
1483 for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
1484 if (ctx->blit_yuv_3_plane_object[i].surface_id)
1485 LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
1486 }
1487
1488 if (ctx->libc2d2) {
1489 ::dlclose(ctx->libc2d2);
1490 ALOGV("dlclose(libc2d2)");
1491 }
1492
1493 free(ctx);
1494}
1495
Naseer Ahmed29a26812012-06-14 00:56:20 -07001496/** Close the copybit device */
1497static int close_copybit(struct hw_device_t *dev)
1498{
1499 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1500 if (ctx) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001501 free_temp_buffer(ctx->temp_src_buffer);
1502 free_temp_buffer(ctx->temp_dst_buffer);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001503 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001504 clean_up(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001505 return 0;
1506}
1507
1508/** Open a new instance of a copybit device using name */
1509static int open_copybit(const struct hw_module_t* module, const char* name,
1510 struct hw_device_t** device)
1511{
1512 int status = COPYBIT_SUCCESS;
Praveena Pachipulusuaef031c2014-02-12 11:46:39 +05301513 if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
1514 return COPYBIT_FAILURE;
1515 }
1516
Naseer Ahmed29a26812012-06-14 00:56:20 -07001517 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1518 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1519 struct copybit_context_t *ctx;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001520
1521 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1522 if(!ctx) {
1523 ALOGE("%s: malloc failed", __FUNCTION__);
1524 return COPYBIT_FAILURE;
1525 }
1526
1527 /* initialize drawstate */
1528 memset(ctx, 0, sizeof(*ctx));
Naseer Ahmed29a26812012-06-14 00:56:20 -07001529 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1530 if (!ctx->libc2d2) {
1531 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001532 clean_up(ctx);
1533 status = COPYBIT_FAILURE;
1534 *device = NULL;
1535 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001536 }
1537 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1538 "c2dCreateSurface");
1539 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1540 "c2dUpdateSurface");
1541 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1542 "c2dReadSurface");
1543 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1544 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1545 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1546 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1547 "c2dWaitTimestamp");
1548 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1549 "c2dDestroySurface");
1550 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1551 "c2dMapAddr");
1552 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1553 "c2dUnMapAddr");
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001554 *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
1555 "c2dGetDriverCapabilities");
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001556 *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
1557 "c2dCreateFenceFD");
Naseer Ahmed183939d2013-03-14 20:44:17 -04001558 *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
1559 "c2dFillSurface");
Naseer Ahmed29a26812012-06-14 00:56:20 -07001560
1561 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001562 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
1563 !LINK_c2dFinish || !LINK_c2dDestroySurface ||
Naseer Ahmed183939d2013-03-14 20:44:17 -04001564 !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
1565 !LINK_c2dFillSurface) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001566 ALOGE("%s: dlsym ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001567 clean_up(ctx);
1568 status = COPYBIT_FAILURE;
1569 *device = NULL;
1570 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001571 }
1572
1573 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1574 ctx->device.common.version = 1;
1575 ctx->device.common.module = (hw_module_t*)(module);
1576 ctx->device.common.close = close_copybit;
1577 ctx->device.set_parameter = set_parameter_copybit;
1578 ctx->device.get = get;
1579 ctx->device.blit = blit_copybit;
Terence Hampsonadf47302013-05-23 12:21:02 -04001580 ctx->device.set_sync = set_sync_copybit;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001581 ctx->device.stretch = stretch_copybit;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001582 ctx->device.finish = finish_copybit;
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001583 ctx->device.flush_get_fence = flush_get_fence_copybit;
Naseer Ahmed183939d2013-03-14 20:44:17 -04001584 ctx->device.clear = clear_copybit;
Sushil Chauhan943797c2013-10-21 17:35:55 -07001585 ctx->device.fill_color = fill_color;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001586
1587 /* Create RGB Surface */
1588 surfDefinition.buffer = (void*)0xdddddddd;
1589 surfDefinition.phys = (void*)0xdddddddd;
1590 surfDefinition.stride = 1 * 4;
1591 surfDefinition.width = 1;
1592 surfDefinition.height = 1;
1593 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1594 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1595 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001596 C2D_SURFACE_WITH_PHYS |
1597 C2D_SURFACE_WITH_PHYS_DUMMY ),
1598 &surfDefinition)) {
1599 ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
1600 ctx->dst[RGB_SURFACE] = 0;
1601 clean_up(ctx);
1602 status = COPYBIT_FAILURE;
1603 *device = NULL;
1604 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001605 }
1606
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001607 unsigned int surface_id = 0;
1608 for (int i = 0; i < MAX_RGB_SURFACES; i++)
1609 {
1610 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001611 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001612 C2D_SURFACE_WITH_PHYS |
1613 C2D_SURFACE_WITH_PHYS_DUMMY ),
1614 &surfDefinition)) {
1615 ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
1616 ctx->blit_rgb_object[i].surface_id = 0;
1617 status = COPYBIT_FAILURE;
1618 break;
1619 } else {
1620 ctx->blit_rgb_object[i].surface_id = surface_id;
1621 ALOGW("%s i = %d surface_id=%d", __FUNCTION__, i,
1622 ctx->blit_rgb_object[i].surface_id);
1623 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001624 }
1625
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001626 if (status == COPYBIT_FAILURE) {
1627 clean_up(ctx);
1628 status = COPYBIT_FAILURE;
1629 *device = NULL;
1630 return status;
1631 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001632
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001633 // Create 2 plane YUV surfaces
1634 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001635 yuvSurfaceDef.width = 4;
1636 yuvSurfaceDef.height = 4;
1637 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1638 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1639 yuvSurfaceDef.stride0 = 4;
1640
1641 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1642 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1643 yuvSurfaceDef.stride1 = 4;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001644 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1645 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001646 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1647 C2D_SURFACE_WITH_PHYS |
1648 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001649 &yuvSurfaceDef)) {
1650 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001651 ctx->dst[YUV_SURFACE_2_PLANES] = 0;
1652 clean_up(ctx);
1653 status = COPYBIT_FAILURE;
1654 *device = NULL;
1655 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001656 }
1657
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001658 for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
1659 {
1660 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1661 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1662 C2D_SURFACE_WITH_PHYS |
1663 C2D_SURFACE_WITH_PHYS_DUMMY ),
1664 &yuvSurfaceDef)) {
1665 ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
1666 ctx->blit_yuv_2_plane_object[i].surface_id = 0;
1667 status = COPYBIT_FAILURE;
1668 break;
1669 } else {
1670 ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
1671 ALOGW("%s: 2 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1672 ctx->blit_yuv_2_plane_object[i].surface_id);
1673 }
1674 }
1675
1676 if (status == COPYBIT_FAILURE) {
1677 clean_up(ctx);
1678 status = COPYBIT_FAILURE;
1679 *device = NULL;
1680 return status;
1681 }
1682
1683 // Create YUV 3 plane surfaces
Naseer Ahmed29a26812012-06-14 00:56:20 -07001684 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1685 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1686 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1687 yuvSurfaceDef.stride2 = 4;
1688
Naseer Ahmed29a26812012-06-14 00:56:20 -07001689 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1690 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001691 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1692 C2D_SURFACE_WITH_PHYS |
1693 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001694 &yuvSurfaceDef)) {
1695 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001696 ctx->dst[YUV_SURFACE_3_PLANES] = 0;
1697 clean_up(ctx);
1698 status = COPYBIT_FAILURE;
1699 *device = NULL;
1700 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001701 }
1702
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001703 for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
1704 {
1705 if (LINK_c2dCreateSurface(&(surface_id),
1706 C2D_TARGET | C2D_SOURCE,
1707 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1708 C2D_SURFACE_WITH_PHYS |
1709 C2D_SURFACE_WITH_PHYS_DUMMY),
1710 &yuvSurfaceDef)) {
1711 ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
1712 ctx->blit_yuv_3_plane_object[i].surface_id = 0;
1713 status = COPYBIT_FAILURE;
1714 break;
1715 } else {
1716 ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
1717 ALOGW("%s: 3 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1718 ctx->blit_yuv_3_plane_object[i].surface_id);
1719 }
1720 }
1721
1722 if (status == COPYBIT_FAILURE) {
1723 clean_up(ctx);
1724 status = COPYBIT_FAILURE;
1725 *device = NULL;
1726 return status;
1727 }
1728
1729 if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
1730 ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
1731 clean_up(ctx);
1732 status = COPYBIT_FAILURE;
1733 *device = NULL;
1734 return status;
1735 }
1736 // Initialize context variables.
1737 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1738
Naseer Ahmed29a26812012-06-14 00:56:20 -07001739 ctx->temp_src_buffer.fd = -1;
1740 ctx->temp_src_buffer.base = 0;
1741 ctx->temp_src_buffer.size = 0;
1742
1743 ctx->temp_dst_buffer.fd = -1;
1744 ctx->temp_dst_buffer.base = 0;
1745 ctx->temp_dst_buffer.size = 0;
1746
1747 ctx->fb_width = 0;
1748 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001749
1750 ctx->blit_rgb_count = 0;
1751 ctx->blit_yuv_2_plane_count = 0;
1752 ctx->blit_yuv_3_plane_count = 0;
1753 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001754
Arun Kumar K.Reb128aa2012-12-18 12:38:28 -08001755 ctx->wait_timestamp = false;
1756 ctx->stop_thread = false;
1757 pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
1758 pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
1759 /* Start the wait thread */
1760 pthread_attr_t attr;
1761 pthread_attr_init(&attr);
1762 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1763
1764 pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
1765 (void *)ctx);
1766 pthread_attr_destroy(&attr);
1767
Naseer Ahmed29a26812012-06-14 00:56:20 -07001768 *device = &ctx->device.common;
1769 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001770}