1ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*
2ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Copyright (C) 2008 The Android Open Source Project
32130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
4ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
5ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Not a Contribution, Apache license notifications and license are retained
6ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * for attribution purposes only.
7ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
8ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Licensed under the Apache License, Version 2.0 (the "License");
9ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * you may not use this file except in compliance with the License.
10ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * You may obtain a copy of the License at
11ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
12ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *      http://www.apache.org/licenses/LICENSE-2.0
13ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *
14ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Unless required by applicable law or agreed to in writing, software
15ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * distributed under the License is distributed on an "AS IS" BASIS,
16ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * See the License for the specific language governing permissions and
18ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * limitations under the License.
19ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
20ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/log.h>
21ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/resource.h>
22ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/prctl.h>
23ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
24ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <stdint.h>
25ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <string.h>
26ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <unistd.h>
27ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <errno.h>
28ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <fcntl.h>
29ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
30ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/ioctl.h>
31ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/types.h>
32ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <sys/mman.h>
33ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
34ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <linux/msm_kgsl.h>
35ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
36ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <EGL/eglplatform.h>
37ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <cutils/native_handle.h>
38ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <gralloc_priv.h>
39ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
40ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <copybit.h>
41ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <alloc_controller.h>
42ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <memalloc.h>
43ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
44ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include "c2d2.h"
45ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include "software_converter.h"
46ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
47ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#include <dlfcn.h>
48ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
49ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonusing gralloc::IMemAlloc;
50ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonusing gralloc::IonController;
51ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonusing gralloc::alloc_data;
52ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
53ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
54ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     uint32 surface_bits,
55ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     C2D_SURFACE_TYPE surface_type,
56ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     void *surface_definition );
57ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
58ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
59ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     uint32 surface_bits,
60ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     C2D_SURFACE_TYPE surface_type,
61ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                     void *surface_definition );
62ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
63ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
64ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   C2D_SURFACE_TYPE surface_type,
65ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   void *surface_definition,
66ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   int32 x, int32 y );
67ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
68ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
69ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                            uint32 target_config, C2D_RECT *target_scissor,
70ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                            uint32 target_mask_id, uint32 target_color_key,
71ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                            C2D_OBJECT *objects_list, uint32 num_objects );
72ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
73ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
74ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
75ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
76ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
77ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
78ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
79ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
80ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
812130dc33b27b36880920f72b11529c7e1087ae21Praveena PachipulusuC2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
822130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu                                size_t offset, uint32 flags, void ** gpuaddr);
83ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
84ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
85ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
86ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
87ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
88ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* create a fence fd for the timestamp */
89ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
90ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                            int32 *fd);
91ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
92ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon WilsonC2D_STATUS (*LINK_c2dFillSurface) ( uint32 surface_id, uint32 fill_color,
93ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                    C2D_RECT * fill_rect);
94ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
95ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/******************************************************************************/
96ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
97ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#if defined(COPYBIT_Z180)
98ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_SCALE_FACTOR    (4096)
99ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_DIMENSION       (4096)
100ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#else
101ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#error "Unsupported HW version"
102ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#endif
103ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
104ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson// The following defines can be changed as required i.e. as we encounter
105ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson// complex use cases.
106ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_RGB_SURFACES 32       // Max. RGB layers currently supported per draw
107ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
108ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
109ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson// +1 for the destination surface. We cannot have multiple destination surfaces.
110ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
111ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define NUM_SURFACE_TYPES 3      // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
112ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
113ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
114ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonenum {
115ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    RGB_SURFACE,
116ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    YUV_SURFACE_2_PLANES,
117ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    YUV_SURFACE_3_PLANES
118ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
119ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
120ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonenum eConversionType {
121ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    CONVERT_TO_ANDROID_FORMAT,
122ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    CONVERT_TO_C2D_FORMAT
123ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
124ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
125ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonenum eC2DFlags {
126ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    FLAGS_PREMULTIPLIED_ALPHA  = 1<<0,
127ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    FLAGS_YUV_DESTINATION      = 1<<1,
128ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    FLAGS_TEMP_SRC_DST         = 1<<2
129ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
130ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
131ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic gralloc::IAllocController* sAlloc = 0;
132ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/******************************************************************************/
133ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
134ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** State information for each device instance */
135ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct copybit_context_t {
136ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_device_t device;
137ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Templates for the various source surfaces. These templates are created
138ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // to avoid the expensive create/destroy C2D Surfaces
139ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
140ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
141ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
142ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
143ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_DRIVER_INFO c2d_driver_info;
144ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    void *libc2d2;
145ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    alloc_data temp_src_buffer;
146ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    alloc_data temp_dst_buffer;
147ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
1482130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
149ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int blit_rgb_count;         // Total RGB surfaces being blit
150ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
151ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int blit_yuv_3_plane_count; // Total 3 plane YUV  surfaces being blit
152ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int blit_count;             // Total blit objects.
153ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    unsigned int trg_transform;      /* target transform */
154ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int fb_width;
155ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int fb_height;
156ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int src_global_alpha;
157ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int config_mask;
158ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int dst_surface_type;
159ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool is_premultiplied_alpha;
160ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    void* time_stamp;
161ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool dst_surface_mapped; // Set when dst surface is mapped to GPU addr
162ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    void* dst_surface_base; // Stores the dst surface addr
163ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
164ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // used for signaling the wait thread
165ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool wait_timestamp;
166ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_t wait_thread_id;
167ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool stop_thread;
168ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_t wait_cleanup_lock;
169ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_cond_t wait_cleanup_cond;
170ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
171ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
172ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
173ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct bufferInfo {
174ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int width;
175ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int height;
176ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int format;
177ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
178ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
179ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct yuvPlaneInfo {
180ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int yStride;       //luma stride
181ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int plane1_stride;
182ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int plane2_stride;
1832130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    size_t plane1_offset;
1842130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    size_t plane2_offset;
185ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
186ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
187ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/**
188ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * Common hardware methods
189ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
190ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
191ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int open_copybit(const struct hw_module_t* module, const char* name,
192ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                        struct hw_device_t** device);
193ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
194ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic struct hw_module_methods_t copybit_module_methods = {
195ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonopen:  open_copybit
196ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
197ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
198ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*
199ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * The COPYBIT Module
200ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
201ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstruct copybit_module_t HAL_MODULE_INFO_SYM = {
202ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsoncommon: {
203ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsontag: HARDWARE_MODULE_TAG,
204ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     version_major: 1,
205ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     version_minor: 0,
206ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     id: COPYBIT_HARDWARE_MODULE_ID,
207ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     name: "QCT COPYBIT C2D 2.0 Module",
208ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     author: "Qualcomm",
209ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson     methods: &copybit_module_methods
210ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
211ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson};
212ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
213ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
214ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* thread function which waits on the timeStamp and cleans up the surfaces */
215ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void* c2d_wait_loop(void* ptr) {
216ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    copybit_context_t* ctx = (copybit_context_t*)(ptr);
217ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    char thread_name[64] = "copybitWaitThr";
218ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
219ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
220ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
221ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    while(ctx->stop_thread == false) {
222ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        pthread_mutex_lock(&ctx->wait_cleanup_lock);
223ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        while(ctx->wait_timestamp == false && !ctx->stop_thread) {
224ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            pthread_cond_wait(&(ctx->wait_cleanup_cond),
225ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              &(ctx->wait_cleanup_lock));
226ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
227ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(ctx->wait_timestamp) {
228ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
229ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
230ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
231ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->wait_timestamp = false;
232ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // Unmap any mapped addresses.
233ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            for (int i = 0; i < MAX_SURFACES; i++) {
234ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                if (ctx->mapped_gpu_addr[i]) {
235ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
236ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    ctx->mapped_gpu_addr[i] = 0;
237ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                }
238ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
239ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // Reset the counts after the draw.
240ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_rgb_count = 0;
241ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_2_plane_count = 0;
242ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_3_plane_count = 0;
243ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_count = 0;
244ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->dst_surface_mapped = false;
245ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->dst_surface_base = 0;
246ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
247ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
248ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(ctx->stop_thread)
249ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
250ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
251ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_exit(NULL);
252ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return NULL;
253ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
254ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
255ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
256ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* convert COPYBIT_FORMAT to C2D format */
257ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int get_format(int format) {
258ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch (format) {
259ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
260f005bbaf0e3c0649d5f287e42604a84c8bf3acdbOmprakash Dhyade        case HAL_PIXEL_FORMAT_RGB_888:        return C2D_COLOR_FORMAT_888_RGB |
261f005bbaf0e3c0649d5f287e42604a84c8bf3acdbOmprakash Dhyade                                              C2D_FORMAT_SWAP_RB;
262ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
263ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                              C2D_FORMAT_SWAP_RB |
264ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                  C2D_FORMAT_DISABLE_ALPHA;
265ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
266ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                              C2D_FORMAT_SWAP_RB;
267ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_BGRA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
268ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
269ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
270ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
271ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
272ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                  C2D_FORMAT_MACROTILED;
273ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:                              ALOGE("%s: invalid format (0x%x",
274ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                     __FUNCTION__, format);
275ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                              return -EINVAL;
276ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
277ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return -EINVAL;
278ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
279ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
280ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Get the C2D formats needed for conversion to YUV */
281ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int get_c2d_format_for_yuv_destination(int halFormat) {
282ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch (halFormat) {
283ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // We do not swap the RB when the target is YUV
284ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
285ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                              C2D_FORMAT_DISABLE_ALPHA;
286ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
287ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // The U and V need to be interchanged when the target is YUV
288ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
289ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
290ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
291ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:                              return get_format(halFormat);
292ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
293ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return -EINVAL;
294ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
295ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
296ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* ------------------------------------------------------------------- *//*!
297ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * \internal
298ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * \brief Get the bpp for a particular color format
299ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * \param color format
300ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * \return bits per pixel
301ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson *//* ------------------------------------------------------------------- */
302ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonint c2diGetBpp(int32 colorformat)
303ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
304ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
305ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int c2dBpp = 0;
306ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
307ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(colorformat&0xFF)
308ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
309ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_4444_RGBA:
310ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_4444_ARGB:
311ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_1555_ARGB:
312ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_565_RGB:
313ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_5551_RGBA:
314ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            c2dBpp = 16;
315ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
316ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8888_RGBA:
317ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8888_ARGB:
318ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            c2dBpp = 32;
319ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
320f9d1b7d83fbbc669d1d6b10a3908b2bbb7c97804Sushil Chauhan        case C2D_COLOR_FORMAT_888_RGB:
321f9d1b7d83fbbc669d1d6b10a3908b2bbb7c97804Sushil Chauhan            c2dBpp = 24;
322f9d1b7d83fbbc669d1d6b10a3908b2bbb7c97804Sushil Chauhan            break;
323ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8_L:
324ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8_A:
325ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            c2dBpp = 8;
326ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
327ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_4_A:
328ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            c2dBpp = 4;
329ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
330ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_1:
331ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            c2dBpp = 1;
332ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
333ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
334ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s ERROR", __func__);
335ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
336ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
337ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return c2dBpp;
338ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
339ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
3402130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusustatic size_t c2d_get_gpuaddr(copybit_context_t* ctx,
341ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              struct private_handle_t *handle, int &mapped_idx)
342ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
3432130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    uint32 memtype;
3442130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    size_t *gpuaddr = 0;
345ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_STATUS rc;
346ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int freeindex = 0;
347ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool mapaddr = false;
348ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
349ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(!handle)
350ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return 0;
351ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
352ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
353ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                         private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
354ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memtype = KGSL_USER_MEM_TYPE_PMEM;
355ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
356ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memtype = KGSL_USER_MEM_TYPE_ASHMEM;
357ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
358ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memtype = KGSL_USER_MEM_TYPE_ION;
359ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    else {
360ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("Invalid handle flags: 0x%x", handle->flags);
361ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return 0;
362ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
363ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
364ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Check for a freeindex in the mapped_gpu_addr list
365ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (freeindex = 0; freeindex < MAX_SURFACES; freeindex++) {
366ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->mapped_gpu_addr[freeindex] == 0) {
367ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // free index is available
368ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // map GPU addr and use this as mapped_idx
369ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            mapaddr = true;
370ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
371ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
372ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
373ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
374ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(mapaddr) {
375ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
376ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                             handle->offset, memtype, (void**)&gpuaddr);
377ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
378ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (rc == C2D_STATUS_OK) {
379ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // We have mapped the GPU address inside copybit. We need to unmap
380ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // this address after the blit. Store this address
3812130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu            ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
382ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            mapped_idx = freeindex;
383ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
384ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
3852130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    return (size_t)gpuaddr;
386ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
387ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
388ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
389ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
390ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx || (mapped_idx == -1))
391ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return;
392ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
393ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx->mapped_gpu_addr[mapped_idx]) {
394ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
395ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->mapped_gpu_addr[mapped_idx] = 0;
396ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
397ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
398ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
399ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int is_supported_rgb_format(int format)
400ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
401ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(format) {
402ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBA_8888:
403ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGBX_8888:
404f9d1b7d83fbbc669d1d6b10a3908b2bbb7c97804Sushil Chauhan        case HAL_PIXEL_FORMAT_RGB_888:
405ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_RGB_565:
406ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_BGRA_8888: {
407ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_SUCCESS;
408ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
409ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
410ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
411ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
412ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
413ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
414ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int get_num_planes(int format)
415ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
416ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(format) {
417ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
418ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
419ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
420ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
421ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return 2;
422ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
423ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YV12: {
424ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return 3;
425ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
426ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
427ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
428ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
429ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
430ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
431ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int is_supported_yuv_format(int format)
432ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
433ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(format) {
434ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
435ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
436ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
437ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
438ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_SUCCESS;
439ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
440ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
441ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
442ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
443ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
444ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
445ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int is_valid_destination_format(int format)
446ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
447ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
448ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // C2D does not support NV12Tile as a destination format.
449ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
450ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
451ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return COPYBIT_SUCCESS;
452ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
453ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
454ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int calculate_yuv_offset_and_stride(const bufferInfo& info,
455ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                           yuvPlaneInfo& yuvInfo)
456ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
457ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int width  = info.width;
458ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int height = info.height;
459ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int format = info.format;
460ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
461ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int aligned_height = 0;
462ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int aligned_width = 0, size = 0;
463ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
464ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch (format) {
465ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
466ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            /* NV12 Tile buffers have their luma height aligned to 32bytes and width
467ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson             * aligned to 128 bytes. The chroma offset starts at an 8K boundary
468ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson             */
469ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            aligned_height = ALIGN(height, 32);
470ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            aligned_width  = ALIGN(width, 128);
471ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            size = aligned_width * aligned_height;
472ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            yuvInfo.plane1_offset = ALIGN(size,8192);
473ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            yuvInfo.yStride = aligned_width;
474ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            yuvInfo.plane1_stride = aligned_width;
475ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
476ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
477ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
478ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
479ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
480ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            aligned_width = ALIGN(width, 32);
481ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            yuvInfo.yStride = aligned_width;
482ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            yuvInfo.plane1_stride = aligned_width;
483ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
484ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // The encoder requires a 2K aligned chroma offset
485ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
486ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else
487ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                yuvInfo.plane1_offset = aligned_width * height;
488ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
489ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
490ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
491ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default: {
492ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
493ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
494ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
495ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return COPYBIT_SUCCESS;
496ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
497ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
498ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** create C2D surface from copybit image */
499ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int set_image(copybit_context_t* ctx, uint32 surfaceId,
500ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      const struct copybit_image_t *rhs,
501ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      const eC2DFlags flags, int &mapped_idx)
502ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
503ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
504ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_SURFACE_TYPE surfaceType;
505ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
5062130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    uintptr_t gpuaddr = 0;
507ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int c2d_format;
508ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    mapped_idx = -1;
509ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
510ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (flags & FLAGS_YUV_DESTINATION) {
511ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
512ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
513ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2d_format = get_format(rhs->format);
514ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
515ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
516ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(c2d_format == -EINVAL) {
517ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: invalid format", __FUNCTION__);
518ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
519ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
520ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
521ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(handle == NULL) {
522ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: invalid handle", __func__);
523ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
524ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
525ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
526ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (handle->gpuaddr == 0) {
527ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
528ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(!gpuaddr) {
529ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
530ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
531ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
532ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
533ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        gpuaddr = handle->gpuaddr;
534ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
535ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
536ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    /* create C2D surface */
537ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
538ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        /* RGB */
539ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        C2D_RGB_SURFACE_DEF surfaceDef;
540ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
541ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
542ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
543ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.phys = (void*) gpuaddr;
544ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.buffer = (void*) (handle->base);
545ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
546ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.format = c2d_format |
547ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
548ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.width = rhs->w;
549ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.height = rhs->h;
5502130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        int aligned_width = ALIGN((int)surfaceDef.width,32);
551ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
552ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
553ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
554ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                  &surfaceDef)) {
555ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
556ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_idx);
557ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = COPYBIT_FAILURE;
558ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
559ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
560ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        C2D_YUV_SURFACE_DEF surfaceDef;
561ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memset(&surfaceDef, 0, sizeof(surfaceDef));
562ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
563ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.format = c2d_format;
564ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
565ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        bufferInfo info;
566ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        info.width = rhs->w;
567ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        info.height = rhs->h;
568ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        info.format = rhs->format;
569ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
570ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        yuvPlaneInfo yuvInfo = {0};
571ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = calculate_yuv_offset_and_stride(info, yuvInfo);
572ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(status != COPYBIT_SUCCESS) {
573ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
574ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_idx);
575ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
576ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
577ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.width = rhs->w;
578ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.height = rhs->h;
579ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.plane0 = (void*) (handle->base);
580ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.phys0 = (void*) (gpuaddr);
581ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.stride0 = yuvInfo.yStride;
582ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
583ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
584ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
585ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        surfaceDef.stride1 = yuvInfo.plane1_stride;
586ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (3 == get_num_planes(rhs->format)) {
587ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
588ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
589ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            surfaceDef.stride2 = yuvInfo.plane2_stride;
590ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
591ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
592ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
593ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                  &surfaceDef)) {
594ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
595ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_idx);
596ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = COPYBIT_FAILURE;
597ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
598ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
599ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
600ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        unmap_gpuaddr(ctx, mapped_idx);
601ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
602ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
603ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
604ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
605ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
606ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
607ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** copy the bits */
608ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
609ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
610ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx->blit_count == 0) {
611ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_SUCCESS;
612ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
613ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
614ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < ctx->blit_count; i++)
615ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
616ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
617ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
618ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_list[ctx->blit_count-1].next = NULL;
619ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    uint32_t target_transform = ctx->trg_transform;
620ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx->c2d_driver_info.capabilities_mask &
621ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
622ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // For A3xx - set 0x0 as the transform is set in the config_mask
623ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        target_transform = 0x0;
624ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
625ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
626ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    ctx->blit_count)) {
627ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
628ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
629ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
630ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return COPYBIT_SUCCESS;
631ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
632ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
633ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
634ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
635ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
636ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
637ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
638ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_FAILURE;
639ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx)
640ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
641ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
642ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
643ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
644ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
645ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
646ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // unlock the mutex and return failure
647ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
648ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
649ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
650ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
651ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                                        fd)) {
652ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
653ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
654ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
655ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(status == COPYBIT_SUCCESS) {
656ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        //signal the wait_thread
657ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->wait_timestamp = true;
658ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        pthread_cond_signal(&ctx->wait_cleanup_cond);
659ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
660ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
661ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
662ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
663ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
664ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int finish_copybit(struct copybit_device_t *dev)
665ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
666ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
667ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx)
668ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
669ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
670ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson   int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
671ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
672ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson   if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
673ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
674ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
675ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
676ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
677ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Unmap any mapped addresses.
678ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < MAX_SURFACES; i++) {
679ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->mapped_gpu_addr[i]) {
680ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
681ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->mapped_gpu_addr[i] = 0;
682ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
683ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
684ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
685ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Reset the counts after the draw.
686ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_rgb_count = 0;
687ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_yuv_2_plane_count = 0;
688ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_yuv_3_plane_count = 0;
689ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_count = 0;
690ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->dst_surface_mapped = false;
691ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->dst_surface_base = 0;
692ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
693ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
694ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
695ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
696ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int clear_copybit(struct copybit_device_t *dev,
697ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                         struct copybit_image_t const *buf,
698ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                         struct copybit_rect_t *rect)
699ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
700ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int ret = COPYBIT_SUCCESS;
701ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int flags = FLAGS_PREMULTIPLIED_ALPHA;
702ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int mapped_dst_idx = -1;
703ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
704ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
705ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
706ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(!ctx->dst_surface_mapped) {
707ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
708ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                        (eC2DFlags)flags, mapped_dst_idx);
709ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(ret) {
710ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: set_image error", __FUNCTION__);
711ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
712ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            pthread_mutex_unlock(&ctx->wait_cleanup_lock);
713ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
714ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
715ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        //clear_copybit is the first call made by HWC for each composition
716ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        //with the dest surface, hence set dst_surface_mapped.
717ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst_surface_mapped = true;
718ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst_surface_base = buf->base;
719ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
720ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
721ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
722ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return ret;
723ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
724ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
725ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
726ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** setup rectangles */
727ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void set_rects(struct copybit_context_t *ctx,
728ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      C2D_OBJECT *c2dObject,
729ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      const struct copybit_rect_t *dst,
730ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      const struct copybit_rect_t *src,
731ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      const struct copybit_rect_t *scissor)
732ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
733ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Set the target rect.
734ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
735ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson       (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
736ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        /* target rotation is 270 */
737ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.x        = (dst->t)<<16;
7382130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        c2dObject->target_rect.y        = ctx->fb_width?
7392130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu                (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
740ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
741ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
742ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
743ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
744ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.x        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
745ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
746ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.y        = (dst->l)<<16;
747ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
748ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
749ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
750ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.y        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
751ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
7522130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        c2dObject->target_rect.x        = ctx->fb_width?
7532130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu                (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
754ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
755ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
756ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
757ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
758ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.x        = (dst->l)<<16;
759ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.y        = (dst->t)<<16;
760ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
761ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
762ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
763ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
764ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
765ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Set the source rect
766ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->source_rect.x        = (src->l)<<16;
767ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->source_rect.y        = (src->t)<<16;
768ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->source_rect.height   = ((src->b) - (src->t))<<16;
769ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->source_rect.width    = ((src->r) - (src->l))<<16;
770ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
771ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
772ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Set the scissor rect
773ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->scissor_rect.x       = scissor->l;
774ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->scissor_rect.y       = scissor->t;
775ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->scissor_rect.height  = (scissor->b) - (scissor->t);
776ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->scissor_rect.width   = (scissor->r) - (scissor->l);
777ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
778ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
779ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
780ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*****************************************************************************/
781ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
782ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Set a parameter to value */
783ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int set_parameter_copybit(
784ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_device_t *dev,
785ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int name,
786ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int value)
787ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
788ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
789ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
790ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx) {
791ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: null context", __FUNCTION__);
792ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
793ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
794ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
795ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
796ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(name) {
797ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_PLANE_ALPHA:
798ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        {
799ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (value < 0)      value = 0;
800ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (value >= 256)   value = 255;
801ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
802ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->src_global_alpha = value;
803ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (value < 255)
804ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
805ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            else
806ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
807ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
808ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        break;
809ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_BLEND_MODE:
810ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        {
811ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (value == COPYBIT_BLENDING_NONE) {
812ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
813ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->is_premultiplied_alpha = true;
814ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else if (value == COPYBIT_BLENDING_PREMULT) {
815ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->is_premultiplied_alpha = true;
816ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else {
817ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
818ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
819ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
820ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        break;
821ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_TRANSFORM:
822ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        {
823ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unsigned int transform = 0;
824ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            uint32 config_mask = 0;
825ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
826ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
827ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                transform = C2D_TARGET_ROTATE_180;
828ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
829ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
830ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                transform = C2D_TARGET_ROTATE_90;
831ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
832ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else if(value == COPYBIT_TRANSFORM_ROT_90) {
833ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                transform = C2D_TARGET_ROTATE_270;
834ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
835ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else {
836ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
837ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                if(value & COPYBIT_TRANSFORM_FLIP_H) {
838ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    config_mask |= C2D_MIRROR_H_BIT;
839ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
840ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    config_mask |= C2D_MIRROR_V_BIT;
841ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                }
842ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
843ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
844ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (ctx->c2d_driver_info.capabilities_mask &
845ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
846ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ctx->config_mask |= config_mask;
847ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } else {
848ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // The transform for this surface does not match the current
849ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // target transform. Draw all previous surfaces. This will be
850ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // changed once we have a new mechanism to send different
851ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // target rotations to c2d.
852ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                finish_copybit(dev);
853ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
854ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->trg_transform = transform;
855ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
856ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        break;
857ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_FRAMEBUFFER_WIDTH:
858ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->fb_width = value;
859ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
860ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_FRAMEBUFFER_HEIGHT:
861ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->fb_height = value;
862ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
863ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_ROTATION_DEG:
864ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_DITHER:
865ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_BLUR:
866ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_BLIT_TO_FRAMEBUFFER:
867ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // Do nothing
868ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
869ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
870ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
871ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = -EINVAL;
872ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
873ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
874ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
875ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
876ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
877ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
878ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Get a static info value */
879ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int get(struct copybit_device_t *dev, int name)
880ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
881ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
882ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int value;
883ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
884ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx) {
885ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: null context error", __FUNCTION__);
886ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
887ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
888ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
889ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(name) {
890ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_MINIFICATION_LIMIT:
891ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            value = MAX_SCALE_FACTOR;
892ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
893ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_MAGNIFICATION_LIMIT:
894ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            value = MAX_SCALE_FACTOR;
895ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
896ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_SCALING_FRAC_BITS:
897ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            value = 32;
898ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
899ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case COPYBIT_ROTATION_STEP_DEG:
900ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            value = 1;
901ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
902ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
903ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
904ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            value = -EINVAL;
905ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
906ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return value;
907ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
908ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
909ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int is_alpha(int cformat)
910ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
911ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int alpha = 0;
912ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch (cformat & 0xFF) {
913ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8888_ARGB:
914ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_8888_RGBA:
915ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_5551_RGBA:
916ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case C2D_COLOR_FORMAT_4444_ARGB:
917ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            alpha = 1;
918ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
919ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default:
920ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            alpha = 0;
921ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
922ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
923ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
924ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
925ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        alpha = 0;
926ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
927ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return alpha;
928ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
929ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
930ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to check if we need a temporary buffer for the blit.
931ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * This would happen if the requested destination stride and the
932ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * C2D stride do not match. We ignore RGB buffers, since their
933ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * stride is always aligned to 32.
934ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
935ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic bool need_temp_buffer(struct copybit_image_t const *img)
936ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
937ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
938ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return false;
939ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
940ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct private_handle_t* handle = (struct private_handle_t*)img->handle;
941ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
942ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // The width parameter in the handle contains the aligned_w. We check if we
943ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // need to convert based on this param. YUV formats have bpp=1, so checking
944ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // if the requested stride is aligned should suffice.
945ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (0 == (handle->width)%32) {
946ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return false;
947ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
948ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
949ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return true;
950ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
951ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
952ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to extract the information from the copybit image and set the corresponding
953ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * values in the bufferInfo struct.
954ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
955ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
956ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
957ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    info.width = img->w;
958ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    info.height = img->h;
959ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    info.format = img->format;
960ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
961ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
962ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to get the required size for a particular format, inorder for C2D to perform
963ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * the blit operation.
964ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
965cfb968873b9e94dca883aadabee42b01558faea9Shalaj Jainstatic int get_size(const bufferInfo& info)
966ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
9672130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    int size = 0;
968ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int w = info.width;
969ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int h = info.height;
970ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int aligned_w = ALIGN(w, 32);
971ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(info.format) {
972ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
973ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            {
974ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // Chroma for this format is aligned to 2K.
975ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                size = ALIGN((aligned_w*h), 2048) +
976ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                        ALIGN(aligned_w/2, 32) * (h/2) *2;
977ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                size = ALIGN(size, 4096);
978ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } break;
979ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
980ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
981ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            {
982ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                size = aligned_w * h +
983ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                       ALIGN(aligned_w/2, 32) * (h/2) * 2;
984ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                size = ALIGN(size, 4096);
985ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } break;
986ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default: break;
987ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
988ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return size;
989ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
990ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
991ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to allocate memory for the temporary buffer. This memory is
992ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * allocated from Ashmem. It is the caller's responsibility to free this
993ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * memory.
994ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
995ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int get_temp_buffer(const bufferInfo& info, alloc_data& data)
996ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
997ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ALOGD("%s E", __FUNCTION__);
998ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Alloc memory from system heap
999ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.base = 0;
1000ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.fd = -1;
1001ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.offset = 0;
1002ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.size = get_size(info);
1003ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.align = getpagesize();
1004ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    data.uncached = true;
1005ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
1006ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1007ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (sAlloc == 0) {
1008ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        sAlloc = gralloc::IAllocController::getInstance();
1009ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1010ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1011ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (sAlloc == 0) {
1012ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
1013ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1014ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1015ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1016ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int err = sAlloc->allocate(data, allocFlags);
1017ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (0 != err) {
1018ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: allocate failed", __FUNCTION__);
1019ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1020ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1021ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1022ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ALOGD("%s X", __FUNCTION__);
1023ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return err;
1024ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1025ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1026ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to free the temporary allocated memory.*/
1027ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void free_temp_buffer(alloc_data &data)
1028ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1029ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (-1 != data.fd) {
1030ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
1031ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memalloc->free_buffer(data.base, data.size, 0, data.fd);
1032ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1033ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1034ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1035ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/* Function to perform the software color conversion. Convert the
1036ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson * C2D compatible format to the Android compatible format
1037ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson */
1038ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int copy_image(private_handle_t *src_handle,
1039ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      struct copybit_image_t const *rhs,
1040ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                      eConversionType conversionType)
1041ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1042ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (src_handle->fd == -1) {
1043ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
1044ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1045ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1046ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1047ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Copy the info.
1048ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int ret = COPYBIT_SUCCESS;
1049ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    switch(rhs->format) {
1050ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
1051ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
1052ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
1053ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            {
1054ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
1055ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
1056ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                } else {
1057ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                    return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
1058ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                }
1059ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1060ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            } break;
1061ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        default: {
1062ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
1063ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ret = COPYBIT_FAILURE;
1064ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } break;
1065ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1066ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return ret;
1067ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1068ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1069ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void delete_handle(private_handle_t *handle)
1070ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1071ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (handle) {
1072ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        delete handle;
1073ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        handle = 0;
1074ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1075ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1076ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
10772130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusustatic bool need_to_execute_draw(eC2DFlags flags)
1078ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1079ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (flags & FLAGS_TEMP_SRC_DST) {
1080ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return true;
1081ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1082ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (flags & FLAGS_YUV_DESTINATION) {
1083ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return true;
1084ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1085ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return false;
1086ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1087ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1088ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** do a stretch blit type operation */
1089ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int stretch_copybit_internal(
1090ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_device_t *dev,
1091ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *dst,
1092ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *src,
1093ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t const *dst_rect,
1094ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t const *src_rect,
1095ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_region_t const *region,
1096ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool enableBlend)
1097ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1098ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1099ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
1100ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int flags = 0;
1101ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int src_surface_type;
1102ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int mapped_src_idx = -1, mapped_dst_idx = -1;
1103ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_OBJECT_STR src_surface;
1104ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1105ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx) {
1106ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: null context error", __FUNCTION__);
1107ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
1108ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1109ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1110ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
1111ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: src dimension error", __FUNCTION__);
1112ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
1113ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1114ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1115ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
1116ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w,
1117ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                         dst->h);
1118ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
1119ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1120ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1121ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
1122ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
1123ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                              dst->format);
1124ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1125ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1126ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1127ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int dst_surface_type;
1128ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
1129ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_surface_type = RGB_SURFACE;
1130ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        flags |= FLAGS_PREMULTIPLIED_ALPHA;
1131ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
1132ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        int num_planes = get_num_planes(dst->format);
1133ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        flags |= FLAGS_YUV_DESTINATION;
1134ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (num_planes == 2) {
1135ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            dst_surface_type = YUV_SURFACE_2_PLANES;
1136ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else if (num_planes == 3) {
1137ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            dst_surface_type = YUV_SURFACE_3_PLANES;
1138ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else {
1139ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
1140ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                  __FUNCTION__, dst->format);
1141ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
1142ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1143ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
1144ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
1145ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                     dst->format);
1146ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1147ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1148ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1149ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
1150ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1151ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
1152ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
1153ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst_surface_type != dst_surface_type) {
1154ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // we have reached the max. limits of our internal structures or
1155ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // changed the target.
1156ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // Draw the remaining surfaces. We need to do the finish here since
1157ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // we need to free up the surface templates.
1158ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        finish_copybit(dev);
1159ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1160ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1161ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->dst_surface_type = dst_surface_type;
1162ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1163ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Update the destination
1164ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    copybit_image_t dst_image;
1165ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dst_image.w = dst->w;
1166ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dst_image.h = dst->h;
1167ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dst_image.format = dst->format;
1168ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    dst_image.handle = dst->handle;
1169ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Check if we need a temp. copy for the destination. We'd need this the destination
1170ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
1171ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // aligned to 32.
1172ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool need_temp_dst = need_temp_buffer(dst);
1173ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bufferInfo dst_info;
1174ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    populate_buffer_info(dst, dst_info);
1175ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
1176ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                     dst_info.width, dst_info.height);
1177ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (dst_hnd == NULL) {
1178ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: dst_hnd is null", __FUNCTION__);
1179ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1180ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1181ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (need_temp_dst) {
1182ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
1183ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            free_temp_buffer(ctx->temp_dst_buffer);
1184ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // Create a temp buffer and set that as the destination.
1185ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
1186ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
1187ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                delete_handle(dst_hnd);
1188ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                return COPYBIT_FAILURE;
1189ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
1190ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1191ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_hnd->fd = ctx->temp_dst_buffer.fd;
1192ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_hnd->size = ctx->temp_dst_buffer.size;
1193ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_hnd->flags = ctx->temp_dst_buffer.allocType;
11942130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
1195ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_hnd->offset = ctx->temp_dst_buffer.offset;
1196ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_hnd->gpuaddr = 0;
1197ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        dst_image.handle = dst_hnd;
1198ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1199ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(!ctx->dst_surface_mapped) {
1200ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        //map the destination surface to GPU address
1201ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
1202ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                           (eC2DFlags)flags, mapped_dst_idx);
1203ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(status) {
1204ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: dst: set_image error", __FUNCTION__);
1205ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(dst_hnd);
1206ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
1207ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
1208ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1209ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst_surface_mapped = true;
1210ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst_surface_base = dst->base;
1211ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if(ctx->dst_surface_mapped && ctx->dst_surface_base != dst->base) {
1212ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // Destination surface for the operation should be same for multiple
1213ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // requests, this check is catch if there is any case when the
1214ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // destination changes
1215ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: a different destination surface!!", __FUNCTION__);
1216ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1217ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1218ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Update the source
1219ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    flags = 0;
1220ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
1221ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_surface_type = RGB_SURFACE;
1222ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
1223ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
1224ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        int num_planes = get_num_planes(src->format);
1225ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (num_planes == 2) {
1226ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            src_surface_type = YUV_SURFACE_2_PLANES;
1227ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
1228ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else if (num_planes == 3) {
1229ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            src_surface_type = YUV_SURFACE_3_PLANES;
1230ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
1231ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else {
1232ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
1233ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                  __FUNCTION__, src->format);
1234ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(dst_hnd);
1235ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
1236ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return -EINVAL;
1237ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1238ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
1239ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
1240ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                        src->format);
1241ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        delete_handle(dst_hnd);
1242ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        unmap_gpuaddr(ctx, mapped_dst_idx);
1243ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return -EINVAL;
1244ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1245ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1246ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    copybit_image_t src_image;
1247ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_image.w = src->w;
1248ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_image.h = src->h;
1249ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_image.format = src->format;
1250ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_image.handle = src->handle;
1251ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1252ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool need_temp_src = need_temp_buffer(src);
1253ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bufferInfo src_info;
1254ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    populate_buffer_info(src, src_info);
1255ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
1256ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 src_info.width, src_info.height);
1257ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (NULL == src_hnd) {
1258ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: src_hnd is null", __FUNCTION__);
1259ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        delete_handle(dst_hnd);
1260ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        unmap_gpuaddr(ctx, mapped_dst_idx);
1261ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1262ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1263ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (need_temp_src) {
1264ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (get_size(src_info) != ctx->temp_src_buffer.size) {
1265ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            free_temp_buffer(ctx->temp_src_buffer);
1266ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            // Create a temp buffer and set that as the destination.
1267ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
1268ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                               ctx->temp_src_buffer)) {
1269ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
1270ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                delete_handle(dst_hnd);
1271ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                delete_handle(src_hnd);
1272ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                unmap_gpuaddr(ctx, mapped_dst_idx);
1273ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                return COPYBIT_FAILURE;
1274ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
1275ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1276ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_hnd->fd = ctx->temp_src_buffer.fd;
1277ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_hnd->size = ctx->temp_src_buffer.size;
1278ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_hnd->flags = ctx->temp_src_buffer.allocType;
12792130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
1280ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_hnd->offset = ctx->temp_src_buffer.offset;
1281ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_hnd->gpuaddr = 0;
1282ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_image.handle = src_hnd;
1283ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1284ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // Copy the source.
1285ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = copy_image((private_handle_t *)src->handle, &src_image,
1286ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                CONVERT_TO_C2D_FORMAT);
1287ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (status == COPYBIT_FAILURE) {
1288ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
1289ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(dst_hnd);
1290ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(src_hnd);
1291ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
1292ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return status;
1293ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1294ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1295ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // Clean the cache
1296ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
1297ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
1298ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   src_hnd->offset, src_hnd->fd,
1299ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   gralloc::CACHE_CLEAN)) {
1300ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: clean_buffer failed", __FUNCTION__);
1301ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(dst_hnd);
1302ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(src_hnd);
1303ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
1304ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return COPYBIT_FAILURE;
1305ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1306ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1307ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1308ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
1309ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
1310ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    status = set_image(ctx, src_surface.surface_id, &src_image,
1311ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                       (eC2DFlags)flags, mapped_src_idx);
1312ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(status) {
1313ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: set_image (src) error", __FUNCTION__);
1314ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        delete_handle(dst_hnd);
1315ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        delete_handle(src_hnd);
1316ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        unmap_gpuaddr(ctx, mapped_dst_idx);
1317ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        unmap_gpuaddr(ctx, mapped_src_idx);
1318ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1319ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1320ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1321ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_surface.config_mask = C2D_NO_ANTIALIASING_BIT | ctx->config_mask;
1322ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    src_surface.global_alpha = ctx->src_global_alpha;
1323ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (enableBlend) {
1324ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
1325ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
1326ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            if(!(src_surface.global_alpha)) {
1327ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                // src alpha is zero
1328ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                delete_handle(dst_hnd);
1329ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                delete_handle(src_hnd);
1330ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                unmap_gpuaddr(ctx, mapped_dst_idx);
1331ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                unmap_gpuaddr(ctx, mapped_src_idx);
1332ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                return COPYBIT_FAILURE;
1333ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            }
1334ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1335ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
1336ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
1337ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1338ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1339ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (src_surface_type == RGB_SURFACE) {
1340ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
1341ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_rgb_count++;
1342ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
1343ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
1344ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_2_plane_count++;
1345ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    } else {
1346ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
1347ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_yuv_3_plane_count++;
1348ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1349ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1350ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t clip;
1351ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    while ((status == 0) && region->next(region, &clip)) {
1352ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
1353ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
1354ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGW("Reached end of blit count");
1355ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            finish_copybit(dev);
1356ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1357ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_list[ctx->blit_count] = src_surface;
1358ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->blit_count++;
1359ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1360ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1361ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Check if we need to perform an early draw-finish.
1362ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
13632130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    if (need_to_execute_draw((eC2DFlags)flags))
1364ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
1365ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        finish_copybit(dev);
1366ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1367ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1368ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (need_temp_dst) {
1369ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // copy the temp. destination without the alignment to the actual
1370ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // destination.
1371ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
1372ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (status == COPYBIT_FAILURE) {
1373ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
1374ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(dst_hnd);
1375ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            delete_handle(src_hnd);
1376ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_dst_idx);
1377ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            unmap_gpuaddr(ctx, mapped_src_idx);
1378ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            return status;
1379ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1380ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        // Clean the cache.
1381ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
1382ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
1383ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                               dst_hnd->offset, dst_hnd->fd,
1384ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                               gralloc::CACHE_CLEAN);
1385ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1386ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    delete_handle(dst_hnd);
1387ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    delete_handle(src_hnd);
1388ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1389ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->is_premultiplied_alpha = false;
1390ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->fb_width = 0;
1391ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->fb_height = 0;
1392ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->config_mask = 0;
1393ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
1394ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1395ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1396ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int set_sync_copybit(struct copybit_device_t *dev,
13972130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    int /*acquireFenceFd*/)
1398ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
13992130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    if(!dev)
14002130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        return -EINVAL;
14012130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu
1402ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
1403ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1404ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1405ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int stretch_copybit(
1406ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_device_t *dev,
1407ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *dst,
1408ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *src,
1409ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t const *dst_rect,
1410ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t const *src_rect,
1411ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_region_t const *region)
1412ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1413ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1414ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
1415ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    bool needsBlending = (ctx->src_global_alpha != 0);
1416ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
1417ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
1418ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                    region, needsBlending);
1419ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1420ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
1421ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1422ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1423ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Perform a blit type operation */
1424ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int blit_copybit(
1425ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_device_t *dev,
1426ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *dst,
1427ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_image_t const *src,
1428ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_region_t const *region)
1429ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1430ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
1431ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1432ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
1433ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
1434ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
1435ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    status = stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
1436ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1437ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
1438ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1439ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1440a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson/** Fill the rect on dst with RGBA color **/
1441a653efede03423aa840da24634f1ec6f20796f1eSimon Wilsonstatic int fill_color(struct copybit_device_t *dev,
1442a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson                      struct copybit_image_t const *dst,
1443a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson                      struct copybit_rect_t const *rect,
14442130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu                      uint32_t /*color*/)
1445a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson{
1446a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    // TODO: Implement once c2d driver supports color fill
14472130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    if(!dev || !dst || !rect)
14482130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu       return -EINVAL;
14492130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu
1450a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    return -EINVAL;
1451a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson}
1452a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson
1453ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/*****************************************************************************/
1454ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1455ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic void clean_up(copybit_context_t* ctx)
1456ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1457ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    void* ret;
1458ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx)
1459ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return;
1460ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1461ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // stop the wait_cleanup_thread
1462ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_lock(&ctx->wait_cleanup_lock);
1463ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->stop_thread = true;
1464ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Signal waiting thread
1465ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_cond_signal(&ctx->wait_cleanup_cond);
1466ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
1467ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // waits for the cleanup thread to exit
1468ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_join(ctx->wait_thread_id, &ret);
1469ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_destroy(&ctx->wait_cleanup_lock);
1470ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_cond_destroy (&ctx->wait_cleanup_cond);
1471ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1472ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
1473ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->dst[i])
1474ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            LINK_c2dDestroySurface(ctx->dst[i]);
1475ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1476ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1477ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < MAX_RGB_SURFACES; i++) {
1478ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->blit_rgb_object[i].surface_id)
1479ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
1480ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1481ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1482ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
1483ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->blit_yuv_2_plane_object[i].surface_id)
1484ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
1485ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1486ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1487ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
1488ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (ctx->blit_yuv_3_plane_object[i].surface_id)
1489ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
1490ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1491ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1492ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx->libc2d2) {
1493ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ::dlclose(ctx->libc2d2);
1494ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGV("dlclose(libc2d2)");
1495ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1496ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1497ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    free(ctx);
1498ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1499ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1500ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Close the copybit device */
1501ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int close_copybit(struct hw_device_t *dev)
1502ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1503ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
1504ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (ctx) {
1505ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        free_temp_buffer(ctx->temp_src_buffer);
1506ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        free_temp_buffer(ctx->temp_dst_buffer);
1507ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1508ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    clean_up(ctx);
1509ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return 0;
1510ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1511ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1512ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson/** Open a new instance of a copybit device using name */
1513ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilsonstatic int open_copybit(const struct hw_module_t* module, const char* name,
1514ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                        struct hw_device_t** device)
1515ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson{
1516ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    int status = COPYBIT_SUCCESS;
15172130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
15182130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu        return COPYBIT_FAILURE;
15192130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu    }
15202130dc33b27b36880920f72b11529c7e1087ae21Praveena Pachipulusu
1521ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_RGB_SURFACE_DEF surfDefinition = {0};
1522ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
1523ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    struct copybit_context_t *ctx;
1524ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1525ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
1526ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if(!ctx) {
1527ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: malloc failed", __FUNCTION__);
1528ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return COPYBIT_FAILURE;
1529ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1530ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1531ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    /* initialize drawstate */
1532ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    memset(ctx, 0, sizeof(*ctx));
1533ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
1534ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!ctx->libc2d2) {
1535ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
1536ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1537ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1538ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1539ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1540ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1541ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
1542ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                               "c2dCreateSurface");
1543ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
1544ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                               "c2dUpdateSurface");
1545ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
1546ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                             "c2dReadSurface");
1547ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
1548ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
1549ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
1550ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
1551ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                               "c2dWaitTimestamp");
1552ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
1553ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                "c2dDestroySurface");
1554ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
1555ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                         "c2dMapAddr");
1556ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
1557ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                           "c2dUnMapAddr");
1558ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
1559ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                           "c2dGetDriverCapabilities");
1560ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
1561ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                           "c2dCreateFenceFD");
1562ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
1563ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                           "c2dFillSurface");
1564ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1565ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
1566ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
1567ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        !LINK_c2dFinish  || !LINK_c2dDestroySurface ||
1568ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
1569ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        !LINK_c2dFillSurface) {
1570ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: dlsym ERROR", __FUNCTION__);
1571ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1572ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1573ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1574ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1575ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1576ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1577ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
1578ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.common.version = 1;
1579ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.common.module = (hw_module_t*)(module);
1580ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.common.close = close_copybit;
1581ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.set_parameter = set_parameter_copybit;
1582ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.get = get;
1583ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.blit = blit_copybit;
1584ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.set_sync = set_sync_copybit;
1585ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.stretch = stretch_copybit;
1586ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.finish = finish_copybit;
1587ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.flush_get_fence = flush_get_fence_copybit;
1588ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->device.clear = clear_copybit;
1589a653efede03423aa840da24634f1ec6f20796f1eSimon Wilson    ctx->device.fill_color = fill_color;
1590ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1591ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    /* Create RGB Surface */
1592ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.buffer = (void*)0xdddddddd;
1593ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.phys = (void*)0xdddddddd;
1594ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.stride = 1 * 4;
1595ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.width = 1;
1596ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.height = 1;
1597ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
1598ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
1599ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1600ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS |
1601ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
1602ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 &surfDefinition)) {
1603ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
1604ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst[RGB_SURFACE] = 0;
1605ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1606ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1607ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1608ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1609ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1610ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1611ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    unsigned int surface_id = 0;
1612ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i = 0; i < MAX_RGB_SURFACES; i++)
1613ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
1614ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1615ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
1616ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS |
1617ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
1618ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 &surfDefinition)) {
1619ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
1620ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_rgb_object[i].surface_id = 0;
1621ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = COPYBIT_FAILURE;
1622ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
1623ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else {
1624ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_rgb_object[i].surface_id = surface_id;
1625ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGW("%s i = %d surface_id=%d",  __FUNCTION__, i,
1626ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                          ctx->blit_rgb_object[i].surface_id);
1627ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1628ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1629ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1630ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (status == COPYBIT_FAILURE) {
1631ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1632ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1633ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1634ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1635ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1636ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1637ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Create 2 plane YUV surfaces
1638ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
1639ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.width = 4;
1640ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.height = 4;
1641ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
1642ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
1643ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.stride0 = 4;
1644ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1645ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
1646ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
1647ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.stride1 = 4;
1648ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
1649ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              C2D_TARGET | C2D_SOURCE,
1650ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1651ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                               C2D_SURFACE_WITH_PHYS |
1652ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                               C2D_SURFACE_WITH_PHYS_DUMMY),
1653ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              &yuvSurfaceDef)) {
1654ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
1655ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst[YUV_SURFACE_2_PLANES] = 0;
1656ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1657ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1658ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1659ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1660ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1661ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1662ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
1663ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
1664ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
1665ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1666ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS |
1667ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
1668ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              &yuvSurfaceDef)) {
1669ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
1670ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_2_plane_object[i].surface_id = 0;
1671ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = COPYBIT_FAILURE;
1672ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
1673ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else {
1674ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
1675ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGW("%s: 2 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
1676ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   ctx->blit_yuv_2_plane_object[i].surface_id);
1677ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1678ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1679ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1680ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (status == COPYBIT_FAILURE) {
1681ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1682ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1683ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1684ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1685ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1686ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1687ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Create YUV 3 plane surfaces
1688ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
1689ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
1690ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
1691ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    yuvSurfaceDef.stride2 = 4;
1692ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1693ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
1694ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              C2D_TARGET | C2D_SOURCE,
1695ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1696ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS |
1697ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
1698ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              &yuvSurfaceDef)) {
1699ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
1700ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        ctx->dst[YUV_SURFACE_3_PLANES] = 0;
1701ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1702ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1703ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1704ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1705ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1706ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1707ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
1708ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    {
1709ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        if (LINK_c2dCreateSurface(&(surface_id),
1710ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              C2D_TARGET | C2D_SOURCE,
1711ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
1712ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS |
1713ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
1714ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                              &yuvSurfaceDef)) {
1715ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
1716ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_3_plane_object[i].surface_id = 0;
1717ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            status = COPYBIT_FAILURE;
1718ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            break;
1719ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        } else {
1720ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
1721ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson            ALOGW("%s: 3 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
1722ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                   ctx->blit_yuv_3_plane_object[i].surface_id);
1723ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        }
1724ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1725ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1726ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (status == COPYBIT_FAILURE) {
1727ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        clean_up(ctx);
1728ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        status = COPYBIT_FAILURE;
1729ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1730ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1731ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1732ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1733ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
1734ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson         ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
1735ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson         clean_up(ctx);
1736ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson         status = COPYBIT_FAILURE;
1737ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        *device = NULL;
1738ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson        return status;
1739ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    }
1740ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    // Initialize context variables.
1741ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->trg_transform = C2D_TARGET_ROTATE_0;
1742ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1743ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_src_buffer.fd = -1;
1744ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_src_buffer.base = 0;
1745ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_src_buffer.size = 0;
1746ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1747ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_dst_buffer.fd = -1;
1748ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_dst_buffer.base = 0;
1749ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->temp_dst_buffer.size = 0;
1750ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1751ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->fb_width = 0;
1752ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->fb_height = 0;
1753ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1754ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_rgb_count = 0;
1755ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_yuv_2_plane_count = 0;
1756ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_yuv_3_plane_count = 0;
1757ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->blit_count = 0;
1758ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1759ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->wait_timestamp = false;
1760ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    ctx->stop_thread = false;
1761ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
1762ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
1763ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    /* Start the wait thread */
1764ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_attr_t attr;
1765ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_attr_init(&attr);
1766ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1767ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1768ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
1769ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson                                                            (void *)ctx);
1770ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    pthread_attr_destroy(&attr);
1771ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson
1772ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    *device = &ctx->device.common;
1773ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson    return status;
1774ef53c1c84ec55ed50f607d52b7abfbb86239408eSimon Wilson}
1775