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