blob: f14d00f4a41591ba69c85f5349fe78b9709a4eec [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
Naseer Ahmed45a99602012-07-31 19:15:24 -070021#define DEBUG_COPYBIT 0
Naseer Ahmed72cf9762012-07-21 12:17:13 -070022#include <copybit.h>
23#include <genlock.h>
Naseer Ahmed31da0b12012-07-31 18:55:33 -070024#include "hwc_copybit.h"
Naseer Ahmed45a99602012-07-31 19:15:24 -070025#include "hwc_copybit.h"
26#include "comptype.h"
Naseer Ahmed31da0b12012-07-31 18:55:33 -070027
28namespace qhwc {
29
30
31struct range {
32 int current;
33 int end;
34};
35struct region_iterator : public copybit_region_t {
36
37 region_iterator(hwc_region_t region) {
38 mRegion = region;
39 r.end = region.numRects;
40 r.current = 0;
41 this->next = iterate;
42 }
43
44private:
45 static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
46 if (!self || !rect) {
47 ALOGE("iterate invalid parameters");
48 return 0;
49 }
50
51 region_iterator const* me =
52 static_cast<region_iterator const*>(self);
53 if (me->r.current != me->r.end) {
54 rect->l = me->mRegion.rects[me->r.current].left;
55 rect->t = me->mRegion.rects[me->r.current].top;
56 rect->r = me->mRegion.rects[me->r.current].right;
57 rect->b = me->mRegion.rects[me->r.current].bottom;
58 me->r.current++;
59 return 1;
60 }
61 return 0;
62 }
63
64 hwc_region_t mRegion;
65 mutable range r;
66};
67
68// Initialize CopyBit Class Static Mmembers.
69functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID
70 = NULL;
71functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL;
72int CopyBit::sYuvCount = 0;
73int CopyBit::sYuvLayerIndex = -1;
74bool CopyBit::sIsModeOn = false;
75bool CopyBit::sIsLayerSkip = false;
76void* CopyBit::egl_lib = NULL;
77
Naseer Ahmed72cf9762012-07-21 12:17:13 -070078void CopyBit::openEglLibAndGethandle()
79{
80 egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
81 if (!egl_lib) {
82 return;
83 }
84 updateEglHandles(egl_lib);
85}
86void CopyBit::closeEglLib()
87{
88 if(egl_lib)
89 ::dlclose(egl_lib);
90
91 egl_lib = NULL;
92 updateEglHandles(NULL);
93}
94
Naseer Ahmed31da0b12012-07-31 18:55:33 -070095void CopyBit::updateEglHandles(void* egl_lib)
96{
97 if(egl_lib != NULL) {
98 *(void **)&CopyBit::LINK_eglGetRenderBufferANDROID =
99 ::dlsym(egl_lib, "eglGetRenderBufferANDROID");
100 *(void **)&CopyBit::LINK_eglGetCurrentSurface =
101 ::dlsym(egl_lib, "eglGetCurrentSurface");
102 }else {
103 LINK_eglGetCurrentSurface = NULL;
104 LINK_eglGetCurrentSurface = NULL;
105 }
106}
107
Naseer Ahmed45a99602012-07-31 19:15:24 -0700108bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) {
109 // return true for non-overlay targets
110 if(ctx->mMDP.hasOverlay) {
111 return false;
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700112 }
113 return true;
114}
Naseer Ahmed45a99602012-07-31 19:15:24 -0700115
116bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx, hwc_layer_list_t *list) {
117 int compositionType =
118 qdutils::QCCompositionType::getInstance().getCompositionType();
119
120 if ((compositionType & qdutils::COMPOSITION_TYPE_C2D) ||
121 (compositionType & qdutils::COMPOSITION_TYPE_DYN)) {
122 if (sYuvCount) {
123 //Overlay up & running. Dont use COPYBIT for RGB layers.
124 // TODO need to implement blending with C2D
125 return false;
126 }
127 }
128
129 if (compositionType & qdutils::COMPOSITION_TYPE_DYN) {
130 // DYN Composition:
131 // use copybit, if (TotalRGBRenderArea < 2 * FB Area)
132 // this is done based on perf inputs in ICS
133 // TODO: Above condition needs to be re-evaluated in JB
134
135 framebuffer_device_t *fbDev = ctx->mFbDev;
136 if (!fbDev) {
137 ALOGE("%s:Invalid FB device", __FUNCTION__);
138 return false;
139 }
140 unsigned int fbArea = (fbDev->width * fbDev->height);
141 unsigned int renderArea = getRGBRenderingArea(list);
142 ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
143 __FUNCTION__, renderArea, fbArea);
144 if (renderArea < (2 * fbArea)) {
145 return true;
146 }
147 } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
148 // MDP composition, use COPYBIT always
149 return true;
150 } else if ((compositionType & qdutils::COMPOSITION_TYPE_C2D)) {
151 // C2D composition, use COPYBIT
152 return true;
153 }
154 return false;
155}
156
157unsigned int CopyBit::getRGBRenderingArea(const hwc_layer_list_t *list) {
158 //Calculates total rendering area for RGB layers
159 unsigned int renderArea = 0;
160 unsigned int w=0, h=0;
161 for (unsigned int i=0; i<list->numHwLayers; i++) {
162 private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
163 if (hnd) {
164 if (BUFFER_TYPE_UI == hnd->bufferType) {
165 getLayerResolution(&list->hwLayers[i], w, h);
166 renderArea += (w*h);
167 }
168 }
169 }
170 return renderArea;
171}
172
173bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
174
175 int compositionType =
176 qdutils::QCCompositionType::getInstance().getCompositionType();
177
178 if ((compositionType & qdutils::COMPOSITION_TYPE_GPU) ||
179 (compositionType & qdutils::COMPOSITION_TYPE_CPU)) {
180 //GPU/CPU composition, don't change layer composition type
181 return true;
182 }
183
184 bool useCopybitForYUV = canUseCopybitForYUV(ctx);
185 bool useCopybitForRGB = canUseCopybitForRGB(ctx, list);
186
187 if(!(validateParams(ctx, list))) {
188 ALOGE("%s:Invalid Params", __FUNCTION__);
189 return false;
190 }
191
192 for (int i=list->numHwLayers-1; i >= 0 ; i--) {
193 private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
194
195 if (isSkipLayer(&list->hwLayers[i])) {
196 return true;
197 } else if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
198 //YUV layer, check, if copybit can be used
199 if (useCopybitForYUV) {
200 list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
201 }
202 } else if (hnd->bufferType == BUFFER_TYPE_UI) {
203 //RGB layer, check, if copybit can be used
204 if (useCopybitForRGB) {
205 list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
206 }
207 }
208 }
209 return true;
210}
211
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700212bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy,
Naseer Ahmed45a99602012-07-31 19:15:24 -0700213 EGLSurface sur){
214 // draw layers marked for COPYBIT
215 int retVal = true;
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700216 for (size_t i=0; i<list->numHwLayers; i++) {
Naseer Ahmed45a99602012-07-31 19:15:24 -0700217 if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
218 retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
219 (EGLDisplay)dpy,
220 (EGLSurface)sur,
221 LINK_eglGetRenderBufferANDROID,
222 LINK_eglGetCurrentSurface);
223 if(retVal<0) {
224 ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
225 }
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700226 }
227 }
228 return true;
229}
230
231int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer,
232 EGLDisplay dpy,
233 EGLSurface surface,
234 functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
235 functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
236{
237 hwc_context_t* ctx = (hwc_context_t*)(dev);
238 if(!ctx) {
239 ALOGE("%s: null context ", __FUNCTION__);
240 return -1;
241 }
242
243 private_handle_t *hnd = (private_handle_t *)layer->handle;
244 if(!hnd) {
245 ALOGE("%s: invalid handle", __FUNCTION__);
246 return -1;
247 }
248
249 // Lock this buffer for read.
250 genlock_lock_type lockType = GENLOCK_READ_LOCK;
251 int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
252 if (GENLOCK_FAILURE == err) {
253 ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
254 return -1;
255 }
256 //render buffer
257 EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW);
258 android_native_buffer_t *renderBuffer =
259 (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface);
260 if (!renderBuffer) {
261 ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__);
262 genlock_unlock_buffer(hnd);
263 return -1;
264 }
265 private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
266 if(!fbHandle) {
267 ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
268 genlock_unlock_buffer(hnd);
269 return -1;
270 }
271
272 // Set the copybit source:
273 copybit_image_t src;
274 src.w = hnd->width;
275 src.h = hnd->height;
276 src.format = hnd->format;
277 src.base = (void *)hnd->base;
278 src.handle = (native_handle_t *)layer->handle;
279 src.horiz_padding = src.w - hnd->width;
280 // Initialize vertical padding to zero for now,
281 // this needs to change to accomodate vertical stride
282 // if needed in the future
283 src.vert_padding = 0;
284 // Remove the srcBufferTransform if any
285 layer->transform = (layer->transform & FINAL_TRANSFORM_MASK);
286
287 // Copybit source rect
288 hwc_rect_t sourceCrop = layer->sourceCrop;
289 copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
290 sourceCrop.right,
291 sourceCrop.bottom};
292
293 // Copybit destination rect
294 hwc_rect_t displayFrame = layer->displayFrame;
295 copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
296 displayFrame.right,
297 displayFrame.bottom};
298
299 // Copybit dst
300 copybit_image_t dst;
301 dst.w = ALIGN(fbHandle->width,32);
302 dst.h = fbHandle->height;
303 dst.format = fbHandle->format;
304 dst.base = (void *)fbHandle->base;
305 dst.handle = (native_handle_t *)renderBuffer->handle;
306
307 copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
308
309 int32_t screen_w = displayFrame.right - displayFrame.left;
310 int32_t screen_h = displayFrame.bottom - displayFrame.top;
311 int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
312 int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
313
314 // Copybit dst
315 float copybitsMaxScale =
316 (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
317 float copybitsMinScale =
318 (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
319
320 if((layer->transform == HWC_TRANSFORM_ROT_90) ||
321 (layer->transform == HWC_TRANSFORM_ROT_270)) {
322 //swap screen width and height
323 int tmp = screen_w;
324 screen_w = screen_h;
325 screen_h = tmp;
326 }
327 private_handle_t *tmpHnd = NULL;
328
329 if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
330 ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
331 screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
332 src_crop_width,screen_w,src_crop_width);
333 genlock_unlock_buffer(hnd);
334 return -1;
335 }
336
337 float dsdx = (float)screen_w/src_crop_width;
338 float dtdy = (float)screen_h/src_crop_height;
339
340 float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
341 float scaleLimitMin = copybitsMinScale * copybitsMinScale;
342 if(dsdx > scaleLimitMax ||
343 dtdy > scaleLimitMax ||
344 dsdx < 1/scaleLimitMin ||
345 dtdy < 1/scaleLimitMin) {
346 ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \
347 scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
348 scaleLimitMax,1/scaleLimitMin);
349 genlock_unlock_buffer(hnd);
350 return -1;
351 }
352 if(dsdx > copybitsMaxScale ||
353 dtdy > copybitsMaxScale ||
354 dsdx < 1/copybitsMinScale ||
355 dtdy < 1/copybitsMinScale){
356 // The requested scale is out of the range the hardware
357 // can support.
358 ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
359 copybitsMinScale=%f,screen_w=%d,screen_h=%d \
360 src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
361 dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
362 src_crop_width,src_crop_height);
363
364 //Driver makes width and height as even
365 //that may cause wrong calculation of the ratio
366 //in display and crop.Hence we make
367 //crop width and height as even.
368 src_crop_width = (src_crop_width/2)*2;
369 src_crop_height = (src_crop_height/2)*2;
370
371 int tmp_w = src_crop_width;
372 int tmp_h = src_crop_height;
373
374 if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
375 tmp_w = src_crop_width*copybitsMaxScale;
376 tmp_h = src_crop_height*copybitsMaxScale;
377 }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
378 tmp_w = src_crop_width/copybitsMinScale;
379 tmp_h = src_crop_height/copybitsMinScale;
380 tmp_w = (tmp_w/2)*2;
381 tmp_h = (tmp_h/2)*2;
382 }
383 ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
384
385 int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
386
387 if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
388 copybit_image_t tmp_dst;
389 copybit_rect_t tmp_rect;
390 tmp_dst.w = tmp_w;
391 tmp_dst.h = tmp_h;
392 tmp_dst.format = tmpHnd->format;
393 tmp_dst.handle = tmpHnd;
394 tmp_dst.horiz_padding = src.horiz_padding;
395 tmp_dst.vert_padding = src.vert_padding;
396 tmp_rect.l = 0;
397 tmp_rect.t = 0;
398 tmp_rect.r = tmp_dst.w;
399 tmp_rect.b = tmp_dst.h;
400 //create one clip region
401 hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
402 hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
403 region_iterator tmp_it(tmp_hwc_reg);
404 copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
Naseer Ahmed45a99602012-07-31 19:15:24 -0700405 //TODO: once, we are able to read layer alpha, update this
406 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700407 err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
408 &srcRect, &tmp_it);
409 if(err < 0){
410 ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
411 __LINE__);
412 if(tmpHnd)
413 free_buffer(tmpHnd);
414 genlock_unlock_buffer(hnd);
415 return err;
416 }
417 // copy new src and src rect crop
418 src = tmp_dst;
419 srcRect = tmp_rect;
420 }
421 }
422 // Copybit region
423 hwc_region_t region = layer->visibleRegionScreen;
424 region_iterator copybitRegion(region);
425
426 copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
427 renderBuffer->width);
428 copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
429 renderBuffer->height);
430 copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
431 layer->transform);
Naseer Ahmed45a99602012-07-31 19:15:24 -0700432 //TODO: once, we are able to read layer alpha, update this
433 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700434 copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
435 (layer->blending == HWC_BLENDING_PREMULT)?
436 COPYBIT_ENABLE : COPYBIT_DISABLE);
437 copybit->set_parameter(copybit, COPYBIT_DITHER,
438 (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
439 COPYBIT_ENABLE : COPYBIT_DISABLE);
440 copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
441 COPYBIT_ENABLE);
442 err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
443 &copybitRegion);
444 copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
445 COPYBIT_DISABLE);
446
447 if(tmpHnd)
448 free_buffer(tmpHnd);
449
450 if(err < 0)
451 ALOGE("%s: copybit stretch failed",__FUNCTION__);
452
453 // Unlock this buffer since copybit is done with it.
454 err = genlock_unlock_buffer(hnd);
455 if (GENLOCK_FAILURE == err) {
456 ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
457 }
458
459 return err;
460}
461
Naseer Ahmed45a99602012-07-31 19:15:24 -0700462void CopyBit::getLayerResolution(const hwc_layer_t* layer,
463 unsigned int& width, unsigned int& height)
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700464{
465 hwc_rect_t displayFrame = layer->displayFrame;
466
467 width = displayFrame.right - displayFrame.left;
468 height = displayFrame.bottom - displayFrame.top;
469}
470
Naseer Ahmed45a99602012-07-31 19:15:24 -0700471bool CopyBit::validateParams(hwc_context_t *ctx, const hwc_layer_list_t *list) {
472 //Validate parameters
473 if (!ctx) {
474 ALOGE("%s:Invalid HWC context", __FUNCTION__);
475 return false;
476 } else if (!list) {
477 ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
478 return false;
479 }
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700480
Naseer Ahmed45a99602012-07-31 19:15:24 -0700481 framebuffer_device_t *fbDev = ctx->mFbDev;
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700482
Naseer Ahmed45a99602012-07-31 19:15:24 -0700483 if (!fbDev) {
484 ALOGE("%s:Invalid FB device", __FUNCTION__);
485 return false;
486 }
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700487
Naseer Ahmed45a99602012-07-31 19:15:24 -0700488 if (LINK_eglGetRenderBufferANDROID == NULL ||
489 LINK_eglGetCurrentSurface == NULL) {
490 ALOGE("%s:Not able to link to ADRENO", __FUNCTION__);
491 return false;
492 }
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700493
Naseer Ahmed45a99602012-07-31 19:15:24 -0700494 return true;
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700495}
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700496
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700497//CopybitEngine Class functions
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700498CopybitEngine* CopybitEngine::sInstance = 0;
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700499
500struct copybit_device_t* CopybitEngine::getEngine() {
501 return sEngine;
502}
503CopybitEngine* CopybitEngine::getInstance() {
504 if(sInstance == NULL)
505 sInstance = new CopybitEngine();
506 return sInstance;
507}
508
509CopybitEngine::CopybitEngine(){
510 hw_module_t const *module;
511 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
512 copybit_open(module, &sEngine);
513 } else {
514 ALOGE("FATAL ERROR: copybit open failed.");
515 }
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700516 CopyBit::openEglLibAndGethandle();
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700517}
518CopybitEngine::~CopybitEngine()
519{
Naseer Ahmed72cf9762012-07-21 12:17:13 -0700520 CopyBit::closeEglLib();
Naseer Ahmed31da0b12012-07-31 18:55:33 -0700521 if(sEngine)
522 {
523 copybit_close(sEngine);
524 sEngine = NULL;
525 }
526}
527
528}; //namespace qhwc