blob: adcd4dcdff60e5bac695a06e93ac3a6c21c90b90 [file] [log] [blame]
Naseer Ahmed31da0b12012-07-31 18:55:33 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
4 *
5 * Not a Contribution, Apache license notifications and license are retained
6 * for attribution purposes only.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "hwc_copybit.h"
22#include "hwc_copybitEngine.h"
23
24namespace qhwc {
25
26
27struct range {
28 int current;
29 int end;
30};
31struct region_iterator : public copybit_region_t {
32
33 region_iterator(hwc_region_t region) {
34 mRegion = region;
35 r.end = region.numRects;
36 r.current = 0;
37 this->next = iterate;
38 }
39
40private:
41 static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
42 if (!self || !rect) {
43 ALOGE("iterate invalid parameters");
44 return 0;
45 }
46
47 region_iterator const* me =
48 static_cast<region_iterator const*>(self);
49 if (me->r.current != me->r.end) {
50 rect->l = me->mRegion.rects[me->r.current].left;
51 rect->t = me->mRegion.rects[me->r.current].top;
52 rect->r = me->mRegion.rects[me->r.current].right;
53 rect->b = me->mRegion.rects[me->r.current].bottom;
54 me->r.current++;
55 return 1;
56 }
57 return 0;
58 }
59
60 hwc_region_t mRegion;
61 mutable range r;
62};
63
64// Initialize CopyBit Class Static Mmembers.
65functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID
66 = NULL;
67functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL;
68int CopyBit::sYuvCount = 0;
69int CopyBit::sYuvLayerIndex = -1;
70bool CopyBit::sIsModeOn = false;
71bool CopyBit::sIsLayerSkip = false;
72void* CopyBit::egl_lib = NULL;
73
74void CopyBit::updateEglHandles(void* egl_lib)
75{
76 if(egl_lib != NULL) {
77 *(void **)&CopyBit::LINK_eglGetRenderBufferANDROID =
78 ::dlsym(egl_lib, "eglGetRenderBufferANDROID");
79 *(void **)&CopyBit::LINK_eglGetCurrentSurface =
80 ::dlsym(egl_lib, "eglGetCurrentSurface");
81 }else {
82 LINK_eglGetCurrentSurface = NULL;
83 LINK_eglGetCurrentSurface = NULL;
84 }
85}
86
87bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
88 for (int i=list->numHwLayers-1; i >= 0 ; i--) {
89 private_handle_t *hnd =
90 (private_handle_t *)list->hwLayers[i].handle;
91 if (isSkipLayer(&list->hwLayers[i])) {
92 break;
93 } else if(canUseCopybit(ctx, list, getYuvCount())
94 && !ctx->overlayInUse){
95 list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
96 } else {
97 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
98 }
99 }
100 return true;
101}
102bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy,
103 EGLSurface sur){
104 for (size_t i=0; i<list->numHwLayers; i++) {
105 if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
106 continue;
107 } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
108 drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
109 (EGLDisplay)dpy,
110 (EGLSurface)sur,
111 LINK_eglGetRenderBufferANDROID,
112 LINK_eglGetCurrentSurface);
113 }
114 }
115 return true;
116}
117
118int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer,
119 EGLDisplay dpy,
120 EGLSurface surface,
121 functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
122 functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
123{
124 hwc_context_t* ctx = (hwc_context_t*)(dev);
125 if(!ctx) {
126 ALOGE("%s: null context ", __FUNCTION__);
127 return -1;
128 }
129
130 private_handle_t *hnd = (private_handle_t *)layer->handle;
131 if(!hnd) {
132 ALOGE("%s: invalid handle", __FUNCTION__);
133 return -1;
134 }
135
136 // Lock this buffer for read.
137 genlock_lock_type lockType = GENLOCK_READ_LOCK;
138 int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
139 if (GENLOCK_FAILURE == err) {
140 ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
141 return -1;
142 }
143 //render buffer
144 EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW);
145 android_native_buffer_t *renderBuffer =
146 (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface);
147 if (!renderBuffer) {
148 ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__);
149 genlock_unlock_buffer(hnd);
150 return -1;
151 }
152 private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
153 if(!fbHandle) {
154 ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
155 genlock_unlock_buffer(hnd);
156 return -1;
157 }
158
159 // Set the copybit source:
160 copybit_image_t src;
161 src.w = hnd->width;
162 src.h = hnd->height;
163 src.format = hnd->format;
164 src.base = (void *)hnd->base;
165 src.handle = (native_handle_t *)layer->handle;
166 src.horiz_padding = src.w - hnd->width;
167 // Initialize vertical padding to zero for now,
168 // this needs to change to accomodate vertical stride
169 // if needed in the future
170 src.vert_padding = 0;
171 // Remove the srcBufferTransform if any
172 layer->transform = (layer->transform & FINAL_TRANSFORM_MASK);
173
174 // Copybit source rect
175 hwc_rect_t sourceCrop = layer->sourceCrop;
176 copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
177 sourceCrop.right,
178 sourceCrop.bottom};
179
180 // Copybit destination rect
181 hwc_rect_t displayFrame = layer->displayFrame;
182 copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
183 displayFrame.right,
184 displayFrame.bottom};
185
186 // Copybit dst
187 copybit_image_t dst;
188 dst.w = ALIGN(fbHandle->width,32);
189 dst.h = fbHandle->height;
190 dst.format = fbHandle->format;
191 dst.base = (void *)fbHandle->base;
192 dst.handle = (native_handle_t *)renderBuffer->handle;
193
194 copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
195
196 int32_t screen_w = displayFrame.right - displayFrame.left;
197 int32_t screen_h = displayFrame.bottom - displayFrame.top;
198 int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
199 int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
200
201 // Copybit dst
202 float copybitsMaxScale =
203 (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
204 float copybitsMinScale =
205 (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
206
207 if((layer->transform == HWC_TRANSFORM_ROT_90) ||
208 (layer->transform == HWC_TRANSFORM_ROT_270)) {
209 //swap screen width and height
210 int tmp = screen_w;
211 screen_w = screen_h;
212 screen_h = tmp;
213 }
214 private_handle_t *tmpHnd = NULL;
215
216 if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
217 ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
218 screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
219 src_crop_width,screen_w,src_crop_width);
220 genlock_unlock_buffer(hnd);
221 return -1;
222 }
223
224 float dsdx = (float)screen_w/src_crop_width;
225 float dtdy = (float)screen_h/src_crop_height;
226
227 float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
228 float scaleLimitMin = copybitsMinScale * copybitsMinScale;
229 if(dsdx > scaleLimitMax ||
230 dtdy > scaleLimitMax ||
231 dsdx < 1/scaleLimitMin ||
232 dtdy < 1/scaleLimitMin) {
233 ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \
234 scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
235 scaleLimitMax,1/scaleLimitMin);
236 genlock_unlock_buffer(hnd);
237 return -1;
238 }
239 if(dsdx > copybitsMaxScale ||
240 dtdy > copybitsMaxScale ||
241 dsdx < 1/copybitsMinScale ||
242 dtdy < 1/copybitsMinScale){
243 // The requested scale is out of the range the hardware
244 // can support.
245 ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
246 copybitsMinScale=%f,screen_w=%d,screen_h=%d \
247 src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
248 dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
249 src_crop_width,src_crop_height);
250
251 //Driver makes width and height as even
252 //that may cause wrong calculation of the ratio
253 //in display and crop.Hence we make
254 //crop width and height as even.
255 src_crop_width = (src_crop_width/2)*2;
256 src_crop_height = (src_crop_height/2)*2;
257
258 int tmp_w = src_crop_width;
259 int tmp_h = src_crop_height;
260
261 if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
262 tmp_w = src_crop_width*copybitsMaxScale;
263 tmp_h = src_crop_height*copybitsMaxScale;
264 }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
265 tmp_w = src_crop_width/copybitsMinScale;
266 tmp_h = src_crop_height/copybitsMinScale;
267 tmp_w = (tmp_w/2)*2;
268 tmp_h = (tmp_h/2)*2;
269 }
270 ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
271
272 int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
273
274 if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
275 copybit_image_t tmp_dst;
276 copybit_rect_t tmp_rect;
277 tmp_dst.w = tmp_w;
278 tmp_dst.h = tmp_h;
279 tmp_dst.format = tmpHnd->format;
280 tmp_dst.handle = tmpHnd;
281 tmp_dst.horiz_padding = src.horiz_padding;
282 tmp_dst.vert_padding = src.vert_padding;
283 tmp_rect.l = 0;
284 tmp_rect.t = 0;
285 tmp_rect.r = tmp_dst.w;
286 tmp_rect.b = tmp_dst.h;
287 //create one clip region
288 hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
289 hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
290 region_iterator tmp_it(tmp_hwc_reg);
291 copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
292 // TODO : alpha not defined , fix this
293 // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
294 // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
295 err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
296 &srcRect, &tmp_it);
297 if(err < 0){
298 ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
299 __LINE__);
300 if(tmpHnd)
301 free_buffer(tmpHnd);
302 genlock_unlock_buffer(hnd);
303 return err;
304 }
305 // copy new src and src rect crop
306 src = tmp_dst;
307 srcRect = tmp_rect;
308 }
309 }
310 // Copybit region
311 hwc_region_t region = layer->visibleRegionScreen;
312 region_iterator copybitRegion(region);
313
314 copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
315 renderBuffer->width);
316 copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
317 renderBuffer->height);
318 copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
319 layer->transform);
320 // TODO : alpha not defined , fix this
321 // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
322 // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
323 copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
324 (layer->blending == HWC_BLENDING_PREMULT)?
325 COPYBIT_ENABLE : COPYBIT_DISABLE);
326 copybit->set_parameter(copybit, COPYBIT_DITHER,
327 (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
328 COPYBIT_ENABLE : COPYBIT_DISABLE);
329 copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
330 COPYBIT_ENABLE);
331 err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
332 &copybitRegion);
333 copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
334 COPYBIT_DISABLE);
335
336 if(tmpHnd)
337 free_buffer(tmpHnd);
338
339 if(err < 0)
340 ALOGE("%s: copybit stretch failed",__FUNCTION__);
341
342 // Unlock this buffer since copybit is done with it.
343 err = genlock_unlock_buffer(hnd);
344 if (GENLOCK_FAILURE == err) {
345 ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
346 }
347
348 return err;
349}
350
351void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width,
352 int& height)
353{
354 hwc_rect_t displayFrame = layer->displayFrame;
355
356 width = displayFrame.right - displayFrame.left;
357 height = displayFrame.bottom - displayFrame.top;
358}
359
360bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list,
361 const int numYUVBuffers)
362{
363 // XXX : TODO , currently returning false for MDP4 targets,
364 // This has to be modified after adding C2D support.
365 if(ctx->hasOverlay)
366 return false;
367
368 framebuffer_device_t* fbDev = ctx->mFbDevice->getFb();
369 if(!fbDev) {
370 ALOGE("ERROR: canUseCopybit : fb device is invalid");
371 return false;
372 }
373
374 if (!list)
375 return false;
376
377 // If , couldnt link to adreno library return false.
378 if(LINK_eglGetRenderBufferANDROID == NULL ||
379 LINK_eglGetCurrentSurface == NULL )
380 return false;
381
382 if(!ctx->hasOverlay) {
383 if (numYUVBuffers)
384 return true;
385 }
386
387 int fb_w = fbDev->width;
388 int fb_h = fbDev->height;
389
390 /*
391 * Use copybit only when we need to blit
392 * max 2 full screen sized regions
393 */
394
395 unsigned int renderArea = 0;
396
397 for(unsigned int i = 0; i < list->numHwLayers; i++ ) {
398 int w, h;
399 getLayerResolution(&list->hwLayers[i], w, h);
400 renderArea += w*h;
401 }
402
403 return (renderArea <= (2 * fb_w * fb_h));
404}
405void CopyBit::openEglLibAndGethandle()
406{
407 egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
408 if (!egl_lib) {
409 return;
410 }
411 updateEglHandles(egl_lib);
412}
413void CopyBit::closeEglLib()
414{
415 if(egl_lib)
416 ::dlclose(egl_lib);
417
418 egl_lib = NULL;
419 updateEglHandles(NULL);
420}
421
422
423
424//CopybitEngine Class functions
425CopybitEngine* CopybitEngine::sInstance = 0;;
426
427struct copybit_device_t* CopybitEngine::getEngine() {
428 return sEngine;
429}
430CopybitEngine* CopybitEngine::getInstance() {
431 if(sInstance == NULL)
432 sInstance = new CopybitEngine();
433 return sInstance;
434}
435
436CopybitEngine::CopybitEngine(){
437 hw_module_t const *module;
438 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
439 copybit_open(module, &sEngine);
440 } else {
441 ALOGE("FATAL ERROR: copybit open failed.");
442 }
443}
444CopybitEngine::~CopybitEngine()
445{
446 if(sEngine)
447 {
448 copybit_close(sEngine);
449 sEngine = NULL;
450 }
451}
452
453}; //namespace qhwc