blob: 6cda9a5479c02a9e7d2f862b276057f9ae3dd373 [file] [log] [blame]
Naseer Ahmed29a26812012-06-14 00:56:20 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08003 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
Naseer Ahmed29a26812012-06-14 00:56:20 -07007 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
Naseer Ahmed29a26812012-06-14 00:56:20 -070021#include <cutils/log.h>
22
23#include <stdint.h>
24#include <string.h>
25#include <unistd.h>
26#include <errno.h>
27#include <fcntl.h>
28
29#include <sys/ioctl.h>
30#include <sys/types.h>
31#include <sys/mman.h>
32
33#include <linux/msm_kgsl.h>
34
35#include <EGL/eglplatform.h>
36#include <cutils/native_handle.h>
37#include <cutils/ashmem.h>
38#include <linux/ashmem.h>
39#include <gralloc_priv.h>
40
41#include <copybit.h>
42#include <alloc_controller.h>
43#include <memalloc.h>
44
45#include "c2d2.h"
46#include "software_converter.h"
47
48#include <dlfcn.h>
49
50using gralloc::IMemAlloc;
51using gralloc::IonController;
52using gralloc::alloc_data;
Naseer Ahmed29a26812012-06-14 00:56:20 -070053
54C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
55 uint32 surface_bits,
56 C2D_SURFACE_TYPE surface_type,
57 void *surface_definition );
58
59C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
60 uint32 surface_bits,
61 C2D_SURFACE_TYPE surface_type,
62 void *surface_definition );
63
64C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
65 C2D_SURFACE_TYPE surface_type,
66 void *surface_definition,
67 int32 x, int32 y );
68
69C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
70 uint32 target_config, C2D_RECT *target_scissor,
71 uint32 target_mask_id, uint32 target_color_key,
72 C2D_OBJECT *objects_list, uint32 num_objects );
73
74C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
75
76C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
77
78C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
79
80C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
81
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -080082C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len,
83 uint32 offset, uint32 flags, void ** gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -070084
85C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
86
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -080087C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
Naseer Ahmed29a26812012-06-14 00:56:20 -070088/******************************************************************************/
89
90#if defined(COPYBIT_Z180)
91#define MAX_SCALE_FACTOR (4096)
92#define MAX_DIMENSION (4096)
93#else
94#error "Unsupported HW version"
95#endif
96
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -080097// The following defines can be changed as required i.e. as we encounter
98// complex use cases.
99#define MAX_RGB_SURFACES 8 // Max. RGB layers currently supported per draw
100#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
101#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
102// +1 for the destination surface. We cannot have multiple destination surfaces.
103#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
104#define NUM_SURFACE_TYPES 3 // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
105#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
Naseer Ahmed29a26812012-06-14 00:56:20 -0700106
107enum {
108 RGB_SURFACE,
109 YUV_SURFACE_2_PLANES,
110 YUV_SURFACE_3_PLANES
111};
112
113enum eConversionType {
114 CONVERT_TO_ANDROID_FORMAT,
115 CONVERT_TO_C2D_FORMAT
116};
117
118enum eC2DFlags {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800119 FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
120 FLAGS_YUV_DESTINATION = 1<<1,
121 FLAGS_TEMP_SRC_DST = 1<<2
Naseer Ahmed29a26812012-06-14 00:56:20 -0700122};
123
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700124static gralloc::IAllocController* sAlloc = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700125/******************************************************************************/
126
127/** State information for each device instance */
128struct copybit_context_t {
129 struct copybit_device_t device;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800130 // Templates for the various source surfaces. These templates are created
131 // to avoid the expensive create/destroy C2D Surfaces
132 C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
133 C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
134 C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
135 C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
136 C2D_DRIVER_INFO c2d_driver_info;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700137 void *libc2d2;
138 alloc_data temp_src_buffer;
139 alloc_data temp_dst_buffer;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800140 unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
141 unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
142 int blit_rgb_count; // Total RGB surfaces being blit
143 int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
144 int blit_yuv_3_plane_count; // Total 3 plane YUV surfaces being blit
145 int blit_count; // Total blit objects.
146 unsigned int trg_transform; /* target transform */
Naseer Ahmed29a26812012-06-14 00:56:20 -0700147 int fb_width;
148 int fb_height;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800149 int src_global_alpha;
150 int config_mask;
151 int dst_surface_type;
152 bool is_premultiplied_alpha;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700153};
154
155struct bufferInfo {
156 int width;
157 int height;
158 int format;
159};
160
161struct yuvPlaneInfo {
162 int yStride; //luma stride
163 int plane1_stride;
164 int plane2_stride;
165 int plane1_offset;
166 int plane2_offset;
167};
168
169/**
170 * Common hardware methods
171 */
172
173static int open_copybit(const struct hw_module_t* module, const char* name,
174 struct hw_device_t** device);
175
176static struct hw_module_methods_t copybit_module_methods = {
177open: open_copybit
178};
179
180/*
181 * The COPYBIT Module
182 */
183struct copybit_module_t HAL_MODULE_INFO_SYM = {
184common: {
185tag: HARDWARE_MODULE_TAG,
186 version_major: 1,
187 version_minor: 0,
188 id: COPYBIT_HARDWARE_MODULE_ID,
189 name: "QCT COPYBIT C2D 2.0 Module",
190 author: "Qualcomm",
191 methods: &copybit_module_methods
192 }
193};
194
195
196/* convert COPYBIT_FORMAT to C2D format */
197static int get_format(int format) {
198 switch (format) {
199 case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
200 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
201 C2D_FORMAT_SWAP_RB |
202 C2D_FORMAT_DISABLE_ALPHA;
203 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB |
204 C2D_FORMAT_SWAP_RB;
205 case HAL_PIXEL_FORMAT_BGRA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
206 case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA;
207 case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA;
208 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12;
209 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
210 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21;
211 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
212 C2D_FORMAT_MACROTILED;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800213 default: ALOGE("%s: invalid format (0x%x",
214 __FUNCTION__, format);
215 return -EINVAL;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700216 }
217 return -EINVAL;
218}
219
220/* Get the C2D formats needed for conversion to YUV */
221static int get_c2d_format_for_yuv_destination(int halFormat) {
222 switch (halFormat) {
223 // We do not swap the RB when the target is YUV
224 case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
225 C2D_FORMAT_DISABLE_ALPHA;
226 case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800227 // The U and V need to be interchanged when the target is YUV
Naseer Ahmed29a26812012-06-14 00:56:20 -0700228 case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21;
229 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
230 case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12;
231 default: return get_format(halFormat);
232 }
233 return -EINVAL;
234}
235
236/* ------------------------------------------------------------------- *//*!
237 * \internal
238 * \brief Get the bpp for a particular color format
239 * \param color format
240 * \return bits per pixel
241 *//* ------------------------------------------------------------------- */
242int c2diGetBpp(int32 colorformat)
243{
244
245 int c2dBpp = 0;
246
247 switch(colorformat&0xFF)
248 {
249 case C2D_COLOR_FORMAT_4444_RGBA:
250 case C2D_COLOR_FORMAT_4444_ARGB:
251 case C2D_COLOR_FORMAT_1555_ARGB:
252 case C2D_COLOR_FORMAT_565_RGB:
253 case C2D_COLOR_FORMAT_5551_RGBA:
254 c2dBpp = 16;
255 break;
256 case C2D_COLOR_FORMAT_8888_RGBA:
257 case C2D_COLOR_FORMAT_8888_ARGB:
258 c2dBpp = 32;
259 break;
260 case C2D_COLOR_FORMAT_8_L:
261 case C2D_COLOR_FORMAT_8_A:
262 c2dBpp = 8;
263 break;
264 case C2D_COLOR_FORMAT_4_A:
265 c2dBpp = 4;
266 break;
267 case C2D_COLOR_FORMAT_1:
268 c2dBpp = 1;
269 break;
270 default:
271 ALOGE("%s ERROR", __func__);
272 break;
273 }
274 return c2dBpp;
275}
276
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800277static uint32 c2d_get_gpuaddr(copybit_context_t* ctx, struct private_handle_t *handle,
278 int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700279{
280 uint32 memtype, *gpuaddr;
281 C2D_STATUS rc;
282
283 if(!handle)
284 return 0;
285
286 if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
287 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
288 memtype = KGSL_USER_MEM_TYPE_PMEM;
289 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
290 memtype = KGSL_USER_MEM_TYPE_ASHMEM;
291 else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
292 memtype = KGSL_USER_MEM_TYPE_ION;
293 else {
294 ALOGE("Invalid handle flags: 0x%x", handle->flags);
295 return 0;
296 }
297
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800298 rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
299 handle->offset, memtype, (void**)&gpuaddr);
300
Naseer Ahmed29a26812012-06-14 00:56:20 -0700301 if (rc == C2D_STATUS_OK) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800302 // We have mapped the GPU address inside copybit. We need to unmap this
303 // address after the blit. Store this address
304 for (int i = 0; i < MAX_SURFACES; i++) {
305 if (ctx->mapped_gpu_addr[i] == 0) {
306 ctx->mapped_gpu_addr[i] = (uint32) gpuaddr;
307 mapped_idx = i;
308 break;
309 }
310 }
311
Naseer Ahmed29a26812012-06-14 00:56:20 -0700312 return (uint32) gpuaddr;
313 }
314 return 0;
315}
316
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800317static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
318{
319 if (!ctx || (mapped_idx == -1))
320 return;
321
322 if (ctx->mapped_gpu_addr[mapped_idx]) {
323 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
324 ctx->mapped_gpu_addr[mapped_idx] = 0;
325 }
326}
327
Naseer Ahmed29a26812012-06-14 00:56:20 -0700328static int is_supported_rgb_format(int format)
329{
330 switch(format) {
331 case HAL_PIXEL_FORMAT_RGBA_8888:
332 case HAL_PIXEL_FORMAT_RGBX_8888:
333 case HAL_PIXEL_FORMAT_RGB_565:
334 case HAL_PIXEL_FORMAT_BGRA_8888:
335 case HAL_PIXEL_FORMAT_RGBA_5551:
336 case HAL_PIXEL_FORMAT_RGBA_4444: {
337 return COPYBIT_SUCCESS;
338 }
339 default:
340 return COPYBIT_FAILURE;
341 }
342}
343
344static int get_num_planes(int format)
345{
346 switch(format) {
347 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
348 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
349 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
350 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
351 return 2;
352 }
353 case HAL_PIXEL_FORMAT_YV12: {
354 return 3;
355 }
356 default:
357 return COPYBIT_FAILURE;
358 }
359}
360
361static int is_supported_yuv_format(int format)
362{
363 switch(format) {
364 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
365 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
366 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
367 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
368 return COPYBIT_SUCCESS;
369 }
370 default:
371 return COPYBIT_FAILURE;
372 }
373}
374
375static int is_valid_destination_format(int format)
376{
377 if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
378 // C2D does not support NV12Tile as a destination format.
379 return COPYBIT_FAILURE;
380 }
381 return COPYBIT_SUCCESS;
382}
383
384static int calculate_yuv_offset_and_stride(const bufferInfo& info,
385 yuvPlaneInfo& yuvInfo)
386{
387 int width = info.width;
388 int height = info.height;
389 int format = info.format;
390
391 int aligned_height = 0;
392 int aligned_width = 0, size = 0;
393
394 switch (format) {
395 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
396 /* NV12 Tile buffers have their luma height aligned to 32bytes and width
397 * aligned to 128 bytes. The chroma offset starts at an 8K boundary
398 */
399 aligned_height = ALIGN(height, 32);
400 aligned_width = ALIGN(width, 128);
401 size = aligned_width * aligned_height;
402 yuvInfo.plane1_offset = ALIGN(size,8192);
403 yuvInfo.yStride = aligned_width;
404 yuvInfo.plane1_stride = aligned_width;
405 break;
406 }
407 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
408 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
409 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
410 aligned_width = ALIGN(width, 32);
411 yuvInfo.yStride = aligned_width;
412 yuvInfo.plane1_stride = aligned_width;
413 if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
414 // The encoder requires a 2K aligned chroma offset
415 yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
416 } else
417 yuvInfo.plane1_offset = aligned_width * height;
418
419 break;
420 }
421 default: {
422 return COPYBIT_FAILURE;
423 }
424 }
425 return COPYBIT_SUCCESS;
426}
427
428/** create C2D surface from copybit image */
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800429static int set_image(copybit_context_t* ctx, uint32 surfaceId,
430 const struct copybit_image_t *rhs,
431 const eC2DFlags flags, int &mapped_idx)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700432{
433 struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
434 C2D_SURFACE_TYPE surfaceType;
435 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800436 uint32 gpuaddr = 0;
437 int c2d_format;
438 mapped_idx = -1;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700439
440 if (flags & FLAGS_YUV_DESTINATION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800441 c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700442 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800443 c2d_format = get_format(rhs->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700444 }
445
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800446 if(c2d_format == -EINVAL) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700447 ALOGE("%s: invalid format", __FUNCTION__);
448 return -EINVAL;
449 }
450
451 if(handle == NULL) {
452 ALOGE("%s: invalid handle", __func__);
453 return -EINVAL;
454 }
455
456 if (handle->gpuaddr == 0) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800457 gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
458 if(!gpuaddr) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700459 ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
460 return COPYBIT_FAILURE;
461 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800462 } else {
463 gpuaddr = handle->gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700464 }
465
466 /* create C2D surface */
467 if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
468 /* RGB */
469 C2D_RGB_SURFACE_DEF surfaceDef;
470
471 surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
472
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800473 surfaceDef.phys = (void*) gpuaddr;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700474 surfaceDef.buffer = (void*) (handle->base);
475
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800476 surfaceDef.format = c2d_format |
Naseer Ahmed29a26812012-06-14 00:56:20 -0700477 ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
478 surfaceDef.width = rhs->w;
479 surfaceDef.height = rhs->h;
480 int aligned_width = ALIGN(surfaceDef.width,32);
481 surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
482
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800483 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
484 &surfaceDef)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700485 ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800486 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700487 status = COPYBIT_FAILURE;
488 }
489 } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
490 C2D_YUV_SURFACE_DEF surfaceDef;
491 memset(&surfaceDef, 0, sizeof(surfaceDef));
492 surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800493 surfaceDef.format = c2d_format;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700494
495 bufferInfo info;
496 info.width = rhs->w;
497 info.height = rhs->h;
498 info.format = rhs->format;
499
Naseer Ahmedb16edac2012-07-15 23:56:21 -0700500 yuvPlaneInfo yuvInfo = {0};
Naseer Ahmed29a26812012-06-14 00:56:20 -0700501 status = calculate_yuv_offset_and_stride(info, yuvInfo);
502 if(status != COPYBIT_SUCCESS) {
503 ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800504 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700505 }
506
507 surfaceDef.width = rhs->w;
508 surfaceDef.height = rhs->h;
509 surfaceDef.plane0 = (void*) (handle->base);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800510 surfaceDef.phys0 = (void*) (gpuaddr);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700511 surfaceDef.stride0 = yuvInfo.yStride;
512
513 surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800514 surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700515 surfaceDef.stride1 = yuvInfo.plane1_stride;
516 if (3 == get_num_planes(rhs->format)) {
517 surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800518 surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700519 surfaceDef.stride2 = yuvInfo.plane2_stride;
520 }
521
522 if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
523 &surfaceDef)) {
524 ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800525 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700526 status = COPYBIT_FAILURE;
527 }
528 } else {
529 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800530 unmap_gpuaddr(ctx, mapped_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700531 status = COPYBIT_FAILURE;
532 }
533
534 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700535}
536
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800537/** copy the bits */
538static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700539{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800540 if (ctx->blit_count == 0) {
541 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700542 }
543
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800544 for (int i = 0; i < ctx->blit_count; i++)
545 {
546 ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
547 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700548
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800549 ctx->blit_list[ctx->blit_count-1].next = NULL;
550 if(LINK_c2dDraw(target,ctx->trg_transform, 0x0, 0, 0, ctx->blit_list,
551 ctx->blit_count)) {
552 ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
553 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700554 }
555
556 return COPYBIT_SUCCESS;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700557}
558
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800559
560static int finish_copybit(struct copybit_device_t *dev)
Naseer Ahmed29a26812012-06-14 00:56:20 -0700561{
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800562 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
563 if (!ctx)
564 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700565
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800566 int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700567
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800568 if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
569 ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
570 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700571 }
572
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800573 // Unmap any mapped addresses.
574 for (int i = 0; i < MAX_SURFACES; i++) {
575 if (ctx->mapped_gpu_addr[i]) {
576 LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
577 ctx->mapped_gpu_addr[i] = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700578 }
579 }
Naseer Ahmed29a26812012-06-14 00:56:20 -0700580
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800581 // Reset the counts after the draw.
582 ctx->blit_rgb_count = 0;
583 ctx->blit_yuv_2_plane_count = 0;
584 ctx->blit_yuv_3_plane_count = 0;
585 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700586 return status;
587}
588
589/** setup rectangles */
590static void set_rects(struct copybit_context_t *ctx,
591 C2D_OBJECT *c2dObject,
592 const struct copybit_rect_t *dst,
593 const struct copybit_rect_t *src,
594 const struct copybit_rect_t *scissor)
595{
596 // Set the target rect.
597 if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
598 (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
599 /* target rotation is 270 */
600 c2dObject->target_rect.x = (dst->t)<<16;
601 c2dObject->target_rect.y = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
602 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
603 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
604 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
605 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
606 c2dObject->target_rect.x = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
607 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
608 c2dObject->target_rect.y = (dst->l)<<16;
609 c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
610 c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
611 } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
612 c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
613 c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
614 c2dObject->target_rect.x = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
615 c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
616 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
617 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
618 } else {
619 c2dObject->target_rect.x = (dst->l)<<16;
620 c2dObject->target_rect.y = (dst->t)<<16;
621 c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
622 c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
623 }
624 c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
625
626 // Set the source rect
627 c2dObject->source_rect.x = (src->l)<<16;
628 c2dObject->source_rect.y = (src->t)<<16;
629 c2dObject->source_rect.height = ((src->b) - (src->t))<<16;
630 c2dObject->source_rect.width = ((src->r) - (src->l))<<16;
631 c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
632
633 // Set the scissor rect
634 c2dObject->scissor_rect.x = scissor->l;
635 c2dObject->scissor_rect.y = scissor->t;
636 c2dObject->scissor_rect.height = (scissor->b) - (scissor->t);
637 c2dObject->scissor_rect.width = (scissor->r) - (scissor->l);
638 c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
639}
640
Naseer Ahmed29a26812012-06-14 00:56:20 -0700641/*****************************************************************************/
642
643/** Set a parameter to value */
644static int set_parameter_copybit(
645 struct copybit_device_t *dev,
646 int name,
647 int value)
648{
649 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
650 if (!ctx) {
651 ALOGE("%s: null context", __FUNCTION__);
652 return -EINVAL;
653 }
654
655 switch(name) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700656 case COPYBIT_PLANE_ALPHA:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800657 {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700658 if (value < 0) value = 0;
659 if (value >= 256) value = 255;
660
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800661 ctx->src_global_alpha = value;
662 if (value < 255)
663 ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700664 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800665 ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
666 }
667 break;
668 case COPYBIT_BLEND_MODE:
669 {
670 if (value == COPYBIT_BLENDING_NONE) {
671 ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
672 ctx->is_premultiplied_alpha = true;
673 } else if (value == COPYBIT_BLENDING_PREMULT) {
674 ctx->is_premultiplied_alpha = true;
675 } else {
676 ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700677 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800678 }
679 break;
680 case COPYBIT_TRANSFORM:
681 {
682 unsigned int transform = 0;
683 uint32 config_mask = 0;
684 config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
685 if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
686 transform = C2D_TARGET_ROTATE_180;
687 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
688 } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
689 transform = C2D_TARGET_ROTATE_90;
690 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
691 } else if(value == COPYBIT_TRANSFORM_ROT_90) {
692 transform = C2D_TARGET_ROTATE_270;
693 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
694 } else {
695 config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
696 if(value & COPYBIT_TRANSFORM_FLIP_H) {
697 config_mask |= C2D_MIRROR_H_BIT;
698 } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
699 config_mask |= C2D_MIRROR_V_BIT;
700 }
701 }
702
703 if (transform != ctx->trg_transform) {
704 if (ctx->c2d_driver_info.capabilities_mask &
705 C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
706 ctx->config_mask |= config_mask;
707 } else {
708 // The transform for this surface does not match the current
709 // target transform. Draw all previous surfaces. This will be
710 // changed once we have a new mechanism to send different
711 // target rotations to c2d.
712 finish_copybit(dev);
713 }
714 }
715 ctx->trg_transform = transform;
716 }
717 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700718 case COPYBIT_FRAMEBUFFER_WIDTH:
719 ctx->fb_width = value;
720 break;
721 case COPYBIT_FRAMEBUFFER_HEIGHT:
722 ctx->fb_height = value;
723 break;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800724 case COPYBIT_ROTATION_DEG:
725 case COPYBIT_DITHER:
726 case COPYBIT_BLUR:
Naseer Ahmed45a99602012-07-31 19:15:24 -0700727 case COPYBIT_BLIT_TO_FRAMEBUFFER:
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800728 // Do nothing
Naseer Ahmed45a99602012-07-31 19:15:24 -0700729 break;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700730 default:
731 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
732 return -EINVAL;
733 break;
734 }
735
736 return COPYBIT_SUCCESS;
737}
738
739/** Get a static info value */
740static int get(struct copybit_device_t *dev, int name)
741{
742 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
743 int value;
744
745 if (!ctx) {
746 ALOGE("%s: null context error", __FUNCTION__);
747 return -EINVAL;
748 }
749
750 switch(name) {
751 case COPYBIT_MINIFICATION_LIMIT:
752 value = MAX_SCALE_FACTOR;
753 break;
754 case COPYBIT_MAGNIFICATION_LIMIT:
755 value = MAX_SCALE_FACTOR;
756 break;
757 case COPYBIT_SCALING_FRAC_BITS:
758 value = 32;
759 break;
760 case COPYBIT_ROTATION_STEP_DEG:
761 value = 1;
762 break;
763 default:
764 ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
765 value = -EINVAL;
766 }
767 return value;
768}
769
770static int is_alpha(int cformat)
771{
772 int alpha = 0;
773 switch (cformat & 0xFF) {
774 case C2D_COLOR_FORMAT_8888_ARGB:
775 case C2D_COLOR_FORMAT_8888_RGBA:
776 case C2D_COLOR_FORMAT_5551_RGBA:
777 case C2D_COLOR_FORMAT_4444_ARGB:
778 alpha = 1;
779 break;
780 default:
781 alpha = 0;
782 break;
783 }
784
785 if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
786 alpha = 0;
787
788 return alpha;
789}
790
791/* Function to check if we need a temporary buffer for the blit.
792 * This would happen if the requested destination stride and the
793 * C2D stride do not match. We ignore RGB buffers, since their
794 * stride is always aligned to 32.
795 */
796static bool need_temp_buffer(struct copybit_image_t const *img)
797{
798 if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
799 return false;
800
801 struct private_handle_t* handle = (struct private_handle_t*)img->handle;
802
803 // The width parameter in the handle contains the aligned_w. We check if we
804 // need to convert based on this param. YUV formats have bpp=1, so checking
805 // if the requested stride is aligned should suffice.
806 if (0 == (handle->width)%32) {
807 return false;
808 }
809
810 return true;
811}
812
813/* Function to extract the information from the copybit image and set the corresponding
814 * values in the bufferInfo struct.
815 */
816static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
817{
818 info.width = img->w;
819 info.height = img->h;
820 info.format = img->format;
821}
822
823/* Function to get the required size for a particular format, inorder for C2D to perform
824 * the blit operation.
825 */
826static size_t get_size(const bufferInfo& info)
827{
828 size_t size = 0;
829 int w = info.width;
830 int h = info.height;
831 int aligned_w = ALIGN(w, 32);
832 switch(info.format) {
833 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
834 {
835 // Chroma for this format is aligned to 2K.
836 size = ALIGN((aligned_w*h), 2048) +
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800837 ALIGN(aligned_w/2, 32) * (h/2) *2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700838 size = ALIGN(size, 4096);
839 } break;
840 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
841 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
842 {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800843 size = aligned_w * h +
844 ALIGN(aligned_w/2, 32) * (h/2) * 2;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700845 size = ALIGN(size, 4096);
846 } break;
847 default: break;
848 }
849 return size;
850}
851
852/* Function to allocate memory for the temporary buffer. This memory is
853 * allocated from Ashmem. It is the caller's responsibility to free this
854 * memory.
855 */
856static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
857{
858 ALOGD("%s E", __FUNCTION__);
859 // Alloc memory from system heap
860 data.base = 0;
861 data.fd = -1;
862 data.offset = 0;
863 data.size = get_size(info);
864 data.align = getpagesize();
865 data.uncached = true;
866 int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
867
868 if (sAlloc == 0) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700869 sAlloc = gralloc::IAllocController::getInstance();
Naseer Ahmed29a26812012-06-14 00:56:20 -0700870 }
871
872 if (sAlloc == 0) {
873 ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
874 return COPYBIT_FAILURE;
875 }
876
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700877 int err = sAlloc->allocate(data, allocFlags);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700878 if (0 != err) {
879 ALOGE("%s: allocate failed", __FUNCTION__);
880 return COPYBIT_FAILURE;
881 }
882
883 ALOGD("%s X", __FUNCTION__);
884 return err;
885}
886
887/* Function to free the temporary allocated memory.*/
888static void free_temp_buffer(alloc_data &data)
889{
890 if (-1 != data.fd) {
Naseer Ahmed01d3fd32012-07-14 21:08:13 -0700891 IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700892 memalloc->free_buffer(data.base, data.size, 0, data.fd);
893 }
894}
895
896/* Function to perform the software color conversion. Convert the
897 * C2D compatible format to the Android compatible format
898 */
899static int copy_image(private_handle_t *src_handle,
900 struct copybit_image_t const *rhs,
901 eConversionType conversionType)
902{
903 if (src_handle->fd == -1) {
904 ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
905 return COPYBIT_FAILURE;
906 }
907
908 // Copy the info.
909 int ret = COPYBIT_SUCCESS;
910 switch(rhs->format) {
911 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
912 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
913 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
914 {
915 if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
916 return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
917 } else {
918 return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
919 }
920
921 } break;
922 default: {
923 ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
924 ret = COPYBIT_FAILURE;
925 } break;
926 }
927 return ret;
928}
929
930static void delete_handle(private_handle_t *handle)
931{
932 if (handle) {
933 delete handle;
934 handle = 0;
935 }
936}
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800937
938static bool need_to_execute_draw(struct copybit_context_t* ctx,
939 eC2DFlags flags)
940{
941 if (flags & FLAGS_TEMP_SRC_DST) {
942 return true;
943 }
944 if (flags & FLAGS_YUV_DESTINATION) {
945 return true;
946 }
947 return false;
948}
949
Naseer Ahmed29a26812012-06-14 00:56:20 -0700950/** do a stretch blit type operation */
951static int stretch_copybit_internal(
952 struct copybit_device_t *dev,
953 struct copybit_image_t const *dst,
954 struct copybit_image_t const *src,
955 struct copybit_rect_t const *dst_rect,
956 struct copybit_rect_t const *src_rect,
957 struct copybit_region_t const *region,
958 bool enableBlend)
959{
960 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
961 int status = COPYBIT_SUCCESS;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800962 int flags = 0;
963 int src_surface_type;
964 int mapped_src_idx = -1, mapped_dst_idx = -1;
965 C2D_OBJECT_STR src_surface;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700966
967 if (!ctx) {
968 ALOGE("%s: null context error", __FUNCTION__);
969 return -EINVAL;
970 }
971
972 if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
973 ALOGE("%s: src dimension error", __FUNCTION__);
974 return -EINVAL;
975 }
976
977 if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800978 ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w,
979 dst->h);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700980 return -EINVAL;
981 }
982
Naseer Ahmed29a26812012-06-14 00:56:20 -0700983 if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800984 ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
985 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -0700986 return COPYBIT_FAILURE;
987 }
988
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800989 int dst_surface_type;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700990 if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800991 dst_surface_type = RGB_SURFACE;
992 flags |= FLAGS_PREMULTIPLIED_ALPHA;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700993 } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
Naseer Ahmed29a26812012-06-14 00:56:20 -0700994 int num_planes = get_num_planes(dst->format);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800995 flags |= FLAGS_YUV_DESTINATION;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700996 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800997 dst_surface_type = YUV_SURFACE_2_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -0700998 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -0800999 dst_surface_type = YUV_SURFACE_3_PLANES;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001000 } else {
1001 ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1002 __FUNCTION__, dst->format);
1003 return COPYBIT_FAILURE;
1004 }
1005 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001006 ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
1007 dst->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001008 return COPYBIT_FAILURE;
1009 }
1010
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001011 if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
1012 ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1013 ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1014 ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
1015 ctx->dst_surface_type != dst_surface_type) {
1016 // we have reached the max. limits of our internal structures or
1017 // changed the target.
1018 // Draw the remaining surfaces. We need to do the finish here since
1019 // we need to free up the surface templates.
1020 finish_copybit(dev);
1021 }
1022
1023 ctx->dst_surface_type = dst_surface_type;
1024
1025 // Update the destination
Naseer Ahmed29a26812012-06-14 00:56:20 -07001026 copybit_image_t dst_image;
1027 dst_image.w = dst->w;
1028 dst_image.h = dst->h;
1029 dst_image.format = dst->format;
1030 dst_image.handle = dst->handle;
1031 // Check if we need a temp. copy for the destination. We'd need this the destination
1032 // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1033 // aligned to 32.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001034 bool need_temp_dst = need_temp_buffer(dst);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001035 bufferInfo dst_info;
1036 populate_buffer_info(dst, dst_info);
1037 private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1038 dst_info.width, dst_info.height);
1039 if (dst_hnd == NULL) {
1040 ALOGE("%s: dst_hnd is null", __FUNCTION__);
1041 return COPYBIT_FAILURE;
1042 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001043 if (need_temp_dst) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001044 if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1045 free_temp_buffer(ctx->temp_dst_buffer);
1046 // Create a temp buffer and set that as the destination.
1047 if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1048 ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1049 delete_handle(dst_hnd);
1050 return COPYBIT_FAILURE;
1051 }
1052 }
1053 dst_hnd->fd = ctx->temp_dst_buffer.fd;
1054 dst_hnd->size = ctx->temp_dst_buffer.size;
1055 dst_hnd->flags = ctx->temp_dst_buffer.allocType;
1056 dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
1057 dst_hnd->offset = ctx->temp_dst_buffer.offset;
1058 dst_hnd->gpuaddr = 0;
1059 dst_image.handle = dst_hnd;
1060 }
1061
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001062 status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
1063 (eC2DFlags)flags, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001064 if(status) {
1065 ALOGE("%s: dst: set_image error", __FUNCTION__);
1066 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001067 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001068 return COPYBIT_FAILURE;
1069 }
1070
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001071 // Update the source
1072 flags = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001073 if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001074 src_surface_type = RGB_SURFACE;
1075 src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001076 } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1077 int num_planes = get_num_planes(src->format);
1078 if (num_planes == 2) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001079 src_surface_type = YUV_SURFACE_2_PLANES;
1080 src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001081 } else if (num_planes == 3) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001082 src_surface_type = YUV_SURFACE_3_PLANES;
1083 src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
Naseer Ahmed29a26812012-06-14 00:56:20 -07001084 } else {
1085 ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1086 __FUNCTION__, src->format);
1087 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001088 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001089 return -EINVAL;
1090 }
1091 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001092 ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
1093 src->format);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001094 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001095 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001096 return -EINVAL;
1097 }
1098
1099 copybit_image_t src_image;
1100 src_image.w = src->w;
1101 src_image.h = src->h;
1102 src_image.format = src->format;
1103 src_image.handle = src->handle;
1104
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001105 bool need_temp_src = need_temp_buffer(src);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001106 bufferInfo src_info;
1107 populate_buffer_info(src, src_info);
1108 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 -08001109 src_info.width, src_info.height);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001110 if (NULL == src_hnd) {
1111 ALOGE("%s: src_hnd is null", __FUNCTION__);
1112 delete_handle(dst_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001113 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001114 return COPYBIT_FAILURE;
1115 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001116 if (need_temp_src) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001117 if (get_size(src_info) != ctx->temp_src_buffer.size) {
1118 free_temp_buffer(ctx->temp_src_buffer);
1119 // Create a temp buffer and set that as the destination.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001120 if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
1121 ctx->temp_src_buffer)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001122 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1123 delete_handle(dst_hnd);
1124 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001125 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001126 return COPYBIT_FAILURE;
1127 }
1128 }
1129 src_hnd->fd = ctx->temp_src_buffer.fd;
1130 src_hnd->size = ctx->temp_src_buffer.size;
1131 src_hnd->flags = ctx->temp_src_buffer.allocType;
1132 src_hnd->base = (int)(ctx->temp_src_buffer.base);
1133 src_hnd->offset = ctx->temp_src_buffer.offset;
1134 src_hnd->gpuaddr = 0;
1135 src_image.handle = src_hnd;
1136
1137 // Copy the source.
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001138 status = copy_image((private_handle_t *)src->handle, &src_image,
1139 CONVERT_TO_C2D_FORMAT);
1140 if (status == COPYBIT_FAILURE) {
1141 ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
1142 delete_handle(dst_hnd);
1143 delete_handle(src_hnd);
1144 unmap_gpuaddr(ctx, mapped_dst_idx);
1145 return status;
1146 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001147
1148 // Flush the cache
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001149 IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001150 if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
1151 src_hnd->offset, src_hnd->fd)) {
1152 ALOGE("%s: clean_buffer failed", __FUNCTION__);
1153 delete_handle(dst_hnd);
1154 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001155 unmap_gpuaddr(ctx, mapped_dst_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001156 return COPYBIT_FAILURE;
1157 }
1158 }
1159
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001160 flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1161 flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
1162 status = set_image(ctx, src_surface.surface_id, &src_image,
1163 (eC2DFlags)flags, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001164 if(status) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001165 ALOGE("%s: set_image (src) error", __FUNCTION__);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001166 delete_handle(dst_hnd);
1167 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001168 unmap_gpuaddr(ctx, mapped_dst_idx);
1169 unmap_gpuaddr(ctx, mapped_src_idx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001170 return COPYBIT_FAILURE;
1171 }
1172
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001173 src_surface.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT |
1174 ctx->config_mask;
1175 src_surface.global_alpha = ctx->src_global_alpha;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001176 if (enableBlend) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001177 if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1178 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1179 if(!(src_surface.global_alpha)) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001180 // src alpha is zero
Naseer Ahmed29a26812012-06-14 00:56:20 -07001181 delete_handle(dst_hnd);
1182 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001183 unmap_gpuaddr(ctx, mapped_dst_idx);
1184 unmap_gpuaddr(ctx, mapped_src_idx);
1185 return COPYBIT_FAILURE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001186 }
1187 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001188 int c2d_format = get_format(src->format);
1189 if(is_alpha(c2d_format))
1190 src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001191 else
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001192 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001193 }
1194 } else {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001195 src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001196 }
1197
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001198 if (src_surface_type == RGB_SURFACE) {
1199 ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
1200 ctx->blit_rgb_count++;
1201 } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
1202 ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
1203 ctx->blit_yuv_2_plane_count++;
1204 } else {
1205 ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
1206 ctx->blit_yuv_3_plane_count++;
1207 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001208
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001209 struct copybit_rect_t clip;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001210 while ((status == 0) && region->next(region, &clip)) {
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001211 set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
1212 if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
1213 ALOGW("Reached end of blit count");
1214 finish_copybit(dev);;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001215 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001216 ctx->blit_list[ctx->blit_count] = src_surface;
1217 ctx->blit_count++;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001218 }
1219
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001220 // Check if we need to perform an early draw-finish.
1221 flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
1222 if (need_to_execute_draw(ctx, (eC2DFlags)flags))
1223 {
1224 finish_copybit(dev);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001225 }
1226
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001227 if (need_temp_dst) {
1228 // copy the temp. destination without the alignment to the actual
1229 // destination.
1230 status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1231 if (status == COPYBIT_FAILURE) {
1232 ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
1233 delete_handle(dst_hnd);
1234 delete_handle(src_hnd);
1235 unmap_gpuaddr(ctx, mapped_dst_idx);
1236 unmap_gpuaddr(ctx, mapped_src_idx);
1237 return status;
1238 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001239 // Invalidate the cache.
Naseer Ahmed01d3fd32012-07-14 21:08:13 -07001240 IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001241 memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
1242 dst_hnd->offset, dst_hnd->fd);
1243 }
1244 delete_handle(dst_hnd);
1245 delete_handle(src_hnd);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001246
1247 ctx->is_premultiplied_alpha = false;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001248 ctx->fb_width = 0;
1249 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001250 ctx->config_mask = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001251 return status;
1252}
1253
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001254
Naseer Ahmed29a26812012-06-14 00:56:20 -07001255static int stretch_copybit(
1256 struct copybit_device_t *dev,
1257 struct copybit_image_t const *dst,
1258 struct copybit_image_t const *src,
1259 struct copybit_rect_t const *dst_rect,
1260 struct copybit_rect_t const *src_rect,
1261 struct copybit_region_t const *region)
1262{
1263 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001264 bool needsBlending = (ctx->src_global_alpha != 0);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001265 return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
1266 region, needsBlending);
1267}
1268
1269/** Perform a blit type operation */
1270static int blit_copybit(
1271 struct copybit_device_t *dev,
1272 struct copybit_image_t const *dst,
1273 struct copybit_image_t const *src,
1274 struct copybit_region_t const *region)
1275{
1276 struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
1277 struct copybit_rect_t sr = { 0, 0, src->w, src->h };
1278 return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1279}
1280
1281/*****************************************************************************/
1282
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001283static void clean_up(copybit_context_t* ctx)
1284{
1285 if (!ctx)
1286 return;
1287
1288 for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
1289 if (ctx->dst[i])
1290 LINK_c2dDestroySurface(ctx->dst[i]);
1291 }
1292
1293 for (int i = 0; i < MAX_RGB_SURFACES; i++) {
1294 if (ctx->blit_rgb_object[i].surface_id)
1295 LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
1296 }
1297
1298 for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
1299 if (ctx->blit_yuv_2_plane_object[i].surface_id)
1300 LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
1301 }
1302
1303 for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
1304 if (ctx->blit_yuv_3_plane_object[i].surface_id)
1305 LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
1306 }
1307
1308 if (ctx->libc2d2) {
1309 ::dlclose(ctx->libc2d2);
1310 ALOGV("dlclose(libc2d2)");
1311 }
1312
1313 free(ctx);
1314}
1315
Naseer Ahmed29a26812012-06-14 00:56:20 -07001316/** Close the copybit device */
1317static int close_copybit(struct hw_device_t *dev)
1318{
1319 struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1320 if (ctx) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001321 free_temp_buffer(ctx->temp_src_buffer);
1322 free_temp_buffer(ctx->temp_dst_buffer);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001323 }
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001324 clean_up(ctx);
Naseer Ahmed29a26812012-06-14 00:56:20 -07001325 return 0;
1326}
1327
1328/** Open a new instance of a copybit device using name */
1329static int open_copybit(const struct hw_module_t* module, const char* name,
1330 struct hw_device_t** device)
1331{
1332 int status = COPYBIT_SUCCESS;
1333 C2D_RGB_SURFACE_DEF surfDefinition = {0};
1334 C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1335 struct copybit_context_t *ctx;
1336 char fbName[64];
1337
1338 ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1339 if(!ctx) {
1340 ALOGE("%s: malloc failed", __FUNCTION__);
1341 return COPYBIT_FAILURE;
1342 }
1343
1344 /* initialize drawstate */
1345 memset(ctx, 0, sizeof(*ctx));
Naseer Ahmed29a26812012-06-14 00:56:20 -07001346 ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1347 if (!ctx->libc2d2) {
1348 ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001349 clean_up(ctx);
1350 status = COPYBIT_FAILURE;
1351 *device = NULL;
1352 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001353 }
1354 *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1355 "c2dCreateSurface");
1356 *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1357 "c2dUpdateSurface");
1358 *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1359 "c2dReadSurface");
1360 *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1361 *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1362 *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1363 *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1364 "c2dWaitTimestamp");
1365 *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1366 "c2dDestroySurface");
1367 *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1368 "c2dMapAddr");
1369 *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1370 "c2dUnMapAddr");
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001371 *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
1372 "c2dGetDriverCapabilities");
Naseer Ahmed29a26812012-06-14 00:56:20 -07001373
1374 if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001375 || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
1376 !LINK_c2dFinish || !LINK_c2dDestroySurface ||
1377 !LINK_c2dGetDriverCapabilities) {
Naseer Ahmed29a26812012-06-14 00:56:20 -07001378 ALOGE("%s: dlsym ERROR", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001379 clean_up(ctx);
1380 status = COPYBIT_FAILURE;
1381 *device = NULL;
1382 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001383 }
1384
1385 ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1386 ctx->device.common.version = 1;
1387 ctx->device.common.module = (hw_module_t*)(module);
1388 ctx->device.common.close = close_copybit;
1389 ctx->device.set_parameter = set_parameter_copybit;
1390 ctx->device.get = get;
1391 ctx->device.blit = blit_copybit;
1392 ctx->device.stretch = stretch_copybit;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001393 ctx->device.finish = finish_copybit;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001394
1395 /* Create RGB Surface */
1396 surfDefinition.buffer = (void*)0xdddddddd;
1397 surfDefinition.phys = (void*)0xdddddddd;
1398 surfDefinition.stride = 1 * 4;
1399 surfDefinition.width = 1;
1400 surfDefinition.height = 1;
1401 surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1402 if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1403 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001404 C2D_SURFACE_WITH_PHYS |
1405 C2D_SURFACE_WITH_PHYS_DUMMY ),
1406 &surfDefinition)) {
1407 ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
1408 ctx->dst[RGB_SURFACE] = 0;
1409 clean_up(ctx);
1410 status = COPYBIT_FAILURE;
1411 *device = NULL;
1412 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001413 }
1414
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001415 unsigned int surface_id = 0;
1416 for (int i = 0; i < MAX_RGB_SURFACES; i++)
1417 {
1418 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
Naseer Ahmed29a26812012-06-14 00:56:20 -07001419 (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001420 C2D_SURFACE_WITH_PHYS |
1421 C2D_SURFACE_WITH_PHYS_DUMMY ),
1422 &surfDefinition)) {
1423 ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
1424 ctx->blit_rgb_object[i].surface_id = 0;
1425 status = COPYBIT_FAILURE;
1426 break;
1427 } else {
1428 ctx->blit_rgb_object[i].surface_id = surface_id;
1429 ALOGW("%s i = %d surface_id=%d", __FUNCTION__, i,
1430 ctx->blit_rgb_object[i].surface_id);
1431 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001432 }
1433
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001434 if (status == COPYBIT_FAILURE) {
1435 clean_up(ctx);
1436 status = COPYBIT_FAILURE;
1437 *device = NULL;
1438 return status;
1439 }
Naseer Ahmed29a26812012-06-14 00:56:20 -07001440
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001441 // Create 2 plane YUV surfaces
1442 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001443 yuvSurfaceDef.width = 4;
1444 yuvSurfaceDef.height = 4;
1445 yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1446 yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1447 yuvSurfaceDef.stride0 = 4;
1448
1449 yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1450 yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1451 yuvSurfaceDef.stride1 = 4;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001452 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1453 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001454 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1455 C2D_SURFACE_WITH_PHYS |
1456 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001457 &yuvSurfaceDef)) {
1458 ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001459 ctx->dst[YUV_SURFACE_2_PLANES] = 0;
1460 clean_up(ctx);
1461 status = COPYBIT_FAILURE;
1462 *device = NULL;
1463 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001464 }
1465
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001466 for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
1467 {
1468 if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1469 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1470 C2D_SURFACE_WITH_PHYS |
1471 C2D_SURFACE_WITH_PHYS_DUMMY ),
1472 &yuvSurfaceDef)) {
1473 ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
1474 ctx->blit_yuv_2_plane_object[i].surface_id = 0;
1475 status = COPYBIT_FAILURE;
1476 break;
1477 } else {
1478 ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
1479 ALOGW("%s: 2 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1480 ctx->blit_yuv_2_plane_object[i].surface_id);
1481 }
1482 }
1483
1484 if (status == COPYBIT_FAILURE) {
1485 clean_up(ctx);
1486 status = COPYBIT_FAILURE;
1487 *device = NULL;
1488 return status;
1489 }
1490
1491 // Create YUV 3 plane surfaces
Naseer Ahmed29a26812012-06-14 00:56:20 -07001492 yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1493 yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1494 yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1495 yuvSurfaceDef.stride2 = 4;
1496
Naseer Ahmed29a26812012-06-14 00:56:20 -07001497 if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1498 C2D_TARGET | C2D_SOURCE,
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001499 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1500 C2D_SURFACE_WITH_PHYS |
1501 C2D_SURFACE_WITH_PHYS_DUMMY),
Naseer Ahmed29a26812012-06-14 00:56:20 -07001502 &yuvSurfaceDef)) {
1503 ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001504 ctx->dst[YUV_SURFACE_3_PLANES] = 0;
1505 clean_up(ctx);
1506 status = COPYBIT_FAILURE;
1507 *device = NULL;
1508 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001509 }
1510
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001511 for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
1512 {
1513 if (LINK_c2dCreateSurface(&(surface_id),
1514 C2D_TARGET | C2D_SOURCE,
1515 (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1516 C2D_SURFACE_WITH_PHYS |
1517 C2D_SURFACE_WITH_PHYS_DUMMY),
1518 &yuvSurfaceDef)) {
1519 ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
1520 ctx->blit_yuv_3_plane_object[i].surface_id = 0;
1521 status = COPYBIT_FAILURE;
1522 break;
1523 } else {
1524 ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
1525 ALOGW("%s: 3 Plane YUV i=%d surface_id=%d", __FUNCTION__, i,
1526 ctx->blit_yuv_3_plane_object[i].surface_id);
1527 }
1528 }
1529
1530 if (status == COPYBIT_FAILURE) {
1531 clean_up(ctx);
1532 status = COPYBIT_FAILURE;
1533 *device = NULL;
1534 return status;
1535 }
1536
1537 if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
1538 ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
1539 clean_up(ctx);
1540 status = COPYBIT_FAILURE;
1541 *device = NULL;
1542 return status;
1543 }
1544 // Initialize context variables.
1545 ctx->trg_transform = C2D_TARGET_ROTATE_0;
1546
Naseer Ahmed29a26812012-06-14 00:56:20 -07001547 ctx->temp_src_buffer.fd = -1;
1548 ctx->temp_src_buffer.base = 0;
1549 ctx->temp_src_buffer.size = 0;
1550
1551 ctx->temp_dst_buffer.fd = -1;
1552 ctx->temp_dst_buffer.base = 0;
1553 ctx->temp_dst_buffer.size = 0;
1554
1555 ctx->fb_width = 0;
1556 ctx->fb_height = 0;
Arun Kumar K.R6b353bd2012-11-27 17:18:45 -08001557
1558 ctx->blit_rgb_count = 0;
1559 ctx->blit_yuv_2_plane_count = 0;
1560 ctx->blit_yuv_3_plane_count = 0;
1561 ctx->blit_count = 0;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001562
1563 *device = &ctx->device.common;
1564 return status;
Naseer Ahmed29a26812012-06-14 00:56:20 -07001565}