summaryrefslogtreecommitdiff
path: root/hwc2/common/composers/GE2DComposer.cpp (plain)
blob: bbe2f41f884b3b141bc1ee57c23db84e54ba4a21
1/*
2// Copyright(c) 2016 Amlogic Corporation
3*/
4#include <HwcTrace.h>
5#include <HwcFenceControl.h>
6#include <GE2DComposer.h>
7#include <inttypes.h>
8#include <linux/ion.h>
9#include <ion/ion.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <sys/fcntl.h>
13
14namespace android {
15namespace amlogic {
16
17GE2DComposer::GE2DComposer(IDisplayDevice& disp)
18 : Composers(disp),
19 mDisplayDevice(disp),
20 mLock(),
21 mSyncTimelineFd(-1),
22 mCondition(),
23 mQueueItems(),
24 mQueuedFrames(0),
25 mBufferMask(0),
26 mNumBuffers(1),
27 mFbSlot(0),
28 mCurGlesFbSlot(-1),
29 mSingleFbSize(0),
30 mGe2dBufHnd(NULL),
31 mGe2dFd(-1),
32 mSharedFd(-1),
33 mVideoLayerId(0),
34 mSrcBufferInfo(NULL),
35 mDebug(false),
36 mExitThread(false),
37 mInitialized(false)
38{
39 mName = "GE2D";
40
41 mQueueItems.setCapacity(8);
42 mQueueItems.clear();
43}
44
45GE2DComposer::~GE2DComposer()
46{
47 WARN_IF_NOT_DEINIT();
48}
49
50int32_t GE2DComposer::allocBuffer(private_module_t* module, size_t size, int32_t usage, buffer_handle_t* pHandle)
51{
52 ion_user_handle_t ion_hnd;
53 unsigned char *cpu_ptr = NULL;
54 int32_t shared_fd;
55 int32_t ret;
56 int32_t ion_flags = 0;
57 int32_t lock_state = 0;
58
59 if (usage & GRALLOC_USAGE_HW_COMPOSER)
60 {
61 ret = ion_alloc(module->ion_client, size, 0, 1<<ION_HEAP_TYPE_CHUNK,
62 ion_flags, &ion_hnd);
63 }
64
65 if ( ret != 0)
66 {
67 ETRACE("Failed to ion_alloc from ion_client:%d", module->ion_client);
68 return -1;
69 }
70
71 ret = ion_share( module->ion_client, ion_hnd, &shared_fd );
72 if ( ret != 0 )
73 {
74 ETRACE( "ion_share( %d ) failed", module->ion_client );
75 if ( 0 != ion_free( module->ion_client, ion_hnd ) )
76 ETRACE( "ion_free( %d ) failed", module->ion_client );
77 return -1;
78 }
79
80 if (!(usage & GRALLOC_USAGE_PROTECTED))
81 {
82 cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );
83
84 if ( MAP_FAILED == cpu_ptr )
85 {
86 ETRACE( "ion_map( %d ) failed", module->ion_client );
87 if ( 0 != ion_free( module->ion_client, ion_hnd ) )
88 ETRACE( "ion_free( %d ) failed", module->ion_client );
89 close( shared_fd );
90 return -1;
91 }
92 lock_state = private_handle_t::LOCK_STATE_MAPPED;
93 }
94
95 private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION /*TODO ion extend*| priv_heap_flag*/,
96 usage, size, cpu_ptr, lock_state );
97
98 if ( NULL != hnd )
99 {
100 hnd->share_fd = shared_fd;
101 hnd->ion_hnd = ion_hnd;
102 /*TODO ion extend hnd->min_pgsz = min_pgsz; */
103 *pHandle = hnd;
104 return 0;
105 }
106 else
107 {
108 ETRACE( "Gralloc out of mem for ion_client:%d", module->ion_client );
109 }
110
111 close( shared_fd );
112
113 if (!(usage & GRALLOC_USAGE_PROTECTED))
114 {
115 ret = munmap( cpu_ptr, size );
116 if ( 0 != ret )
117 ETRACE( "munmap failed for base:%p size: %zd", cpu_ptr, size );
118 }
119
120 ret = ion_free( module->ion_client, ion_hnd );
121 if ( 0 != ret )
122 ETRACE( "ion_free( %d ) failed", module->ion_client );
123 return -1;
124}
125
126void GE2DComposer::freeBuffer(private_handle_t const* hnd, private_module_t* m)
127{
128 if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION )
129 {
130 /* Buffer might be unregistered already so we need to assure we have a valid handle*/
131 if ( 0 != hnd->base )
132 {
133 if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) ETRACE( "Failed to munmap handle %p", hnd );
134 }
135 close( hnd->share_fd );
136 if ( 0 != ion_free( m->ion_client, hnd->ion_hnd ) ) ETRACE( "Failed to ion_free( ion_client: %d ion_hnd: %p )", m->ion_client, hnd->ion_hnd );
137 memset( (void*)hnd, 0, sizeof( *hnd ) );
138 }
139}
140
141bool GE2DComposer::initialize(framebuffer_info_t* fbInfo)
142{
143 Mutex::Autolock _l(mLock);
144
145 if (mInitialized) {
146 WTRACE("object has been initialized");
147 return true;
148 }
149
150 // create a release fence timeline.
151 mSyncTimelineFd = HwcFenceControl::createFenceTimeline();
152 if (mSyncTimelineFd == -1) {
153 DEINIT_AND_RETURN_FALSE("sync timeline create failed!");
154 }
155 mCurrentSyncTime = 1;
156
157 // create ge2d composer thread.
158 mExitThread = false;
159 mThread = new GE2DRenderThread(this);
160 if (!mThread.get()) {
161 DEINIT_AND_RETURN_FALSE("failed to create ge2d composer thread.");
162 }
163 mThread->run("GE2DComposer", PRIORITY_URGENT_DISPLAY);
164
165 // framebuffer stuff.
166 mFbInfo = fbInfo;
167 mSingleFbSize = fbInfo->finfo.line_length * fbInfo->info.yres;
168 mNumBuffers = fbInfo->fbSize / mSingleFbSize;
169
170 if (!mGe2dBufHnd) {
171 int32_t usage = GRALLOC_USAGE_HW_COMPOSER;
172 int32_t ret = allocBuffer(mFbInfo->grallocModule, mFbInfo->fbSize, usage, &mGe2dBufHnd);
173 if (ret < 0) {
174 ETRACE("allocBuffer failed!");
175 return false;
176 }
177 private_handle_t const *pHandle = reinterpret_cast<private_handle_t const*> (mGe2dBufHnd);
178 if (pHandle) {
179 mSharedFd = pHandle->share_fd;
180 }
181 } else {
182 DTRACE("Buffer alloced already.");
183 }
184
185 // ge2d info.
186 mSrcBufferInfo = new aml_ge2d_info_t();
187
188 // ge2d init.
189 mGe2dFd = ge2d_open();
190 mInitialized = true;
191 return true;
192}
193
194void GE2DComposer::deinitialize()
195{
196 mExitThread = true;
197 mCondition.signal();
198
199 if (mThread.get()) {
200 mThread->requestExitAndWait();
201 mThread = NULL;
202 }
203
204 if (mSrcBufferInfo) {
205 delete mSrcBufferInfo;
206 mSrcBufferInfo = NULL;
207 }
208
209 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(mGe2dBufHnd);
210 if (NULL != hnd) {
211 freeBuffer(hnd, mFbInfo->grallocModule);
212 mGe2dBufHnd = NULL;
213 }
214
215 // ge2d exit.
216 ge2d_close(mGe2dFd);
217 mInitialized = false;
218}
219
220const char* GE2DComposer::getName() const
221{
222 return mName;
223}
224
225const buffer_handle_t GE2DComposer::getBufHnd()
226{
227 Mutex::Autolock _l(mLock);
228
229 return mGe2dBufHnd;
230}
231
232/* void GE2DComposer::setCurGlesFbSlot(uint32_t slot)
233{
234 Mutex::Autolock _l(mLock);
235
236 mCurGlesFbSlot = slot;
237}*/
238
239void GE2DComposer::mergeRetireFence(int32_t slot, int32_t retireFence)
240{
241 Mutex::Autolock _l(mLock);
242 DTRACE("slot:%d, retireFence: %d", slot, retireFence);
243
244 int32_t index = slot / mFbInfo->info.yres;
245 mSlots[index].mSlot = slot;
246 int32_t tempFence = HwcFenceControl::merge(String8("retire_fences"), mSlots[index].mFence, retireFence);
247 HwcFenceControl::closeFd(retireFence);
248 HwcFenceControl::closeFd(mSlots[index].mFence);
249 mSlots[index].mFence = tempFence;
250}
251
252void GE2DComposer::removeRetireFence(int32_t slot)
253{
254 Mutex::Autolock _l(mLock);
255 DTRACE("slot:%d", slot);
256
257 int32_t index = slot / mFbInfo->info.yres;
258 // mSlots[index].mSlot = 0;
259 HwcFenceControl::closeFd(mSlots[index].mFence);
260 mSlots[index].mFence = -1;
261}
262
263void GE2DComposer::setVideoOverlayLayerId(hwc2_layer_t layerId)
264{
265 Mutex::Autolock _l(mLock);
266 DTRACE("layerId:%d", layerId);
267
268 mVideoLayerId = layerId;
269}
270
271uint32_t GE2DComposer::findFreeFbSlot()
272{
273 int32_t fbSlot = 0;
274
275 if (mNumBuffers == 1) {
276 // If we have only one buffer, we never use page-flipping.
277 return 0;
278 }
279
280 if (mBufferMask >= ((1LU<<mNumBuffers)-1)) {
281 // We ran out of buffers. reinit to 0;
282 mBufferMask = 0x1;
283 return 0;
284 }
285
286 // find a free slot
287 for (uint32_t i=0 ; i<mNumBuffers ; i++) {
288 if ((mBufferMask & (1LU<<i)) == 0) {
289 mBufferMask |= (1LU<<i);
290 break;
291 }
292
293 fbSlot += mFbInfo->info.yres;
294 }
295
296 return fbSlot;
297}
298
299int32_t GE2DComposer::startCompose(
300 Vector< hwc2_layer_t > hwcLayers,
301 int32_t *offset, int32_t frameCount)
302{
303 Mutex::Autolock _l(mLock);
304
305 // find a free slot of fb.
306 *offset = mFbSlot = findFreeFbSlot();
307
308 // add hwcLayers to work queue.
309 int32_t index = mFbSlot / mFbInfo->info.yres;
310 mSlots[index].mSlot = mFbSlot;
311 mSlots[index].mVideoLayerId = mVideoLayerId;
312 if (frameCount < 3) {
313 mSlots[index].mClearBuffer = true;
314 } else {
315 mSlots[index].mClearBuffer = false;
316 }
317 mSlots[index].mLayersState.clear();
318 for (uint32_t i=0; i<hwcLayers.size(); i++) {
319 hwc2_layer_t layerId = hwcLayers.itemAt(i);
320 HwcLayer* hwcLayer = mDisplayDevice.getLayerById(layerId);
321 if (NULL != hwcLayer) {
322 // Merge layers's fences and prior retire fence.
323 int32_t fence = hwcLayer->getDuppedAcquireFence();
324 int32_t tempFence = HwcFenceControl::merge(String8("layers"), fence, mSlots[index].mFence);
325 HwcFenceControl::closeFd(mSlots[index].mFence);
326 HwcFenceControl::closeFd(fence);
327 mSlots[index].mFence = tempFence;
328
329 // push layers state to mQueueItems.
330 LayerState* layerState = new LayerState();
331 layerState->setLayerState(hwcLayer);
332 mSlots[index].mLayersState.push_back(layerState);
333 }
334 }
335 // mSlots[index].mLayersState = layersState;
336 android_atomic_inc(&mQueuedFrames);
337 mQueueItems.push_back(mSlots[index]);
338
339 mSlots[index].mFence = -1;
340 mSlots[index].mVideoLayerId = 0;
341 mVideoLayerId = 0;
342
343 int32_t ge2dFence = HwcFenceControl::createFence(mSyncTimelineFd, "ge2d_flag_fence", mCurrentSyncTime++);
344
345 mCondition.signal();
346 return ge2dFence;
347}
348
349void GE2DComposer::fillRectangle(hwc_rect_t clipRect, uint32_t color, uint32_t offset, int shared_fd)
350{
351 mSrcBufferInfo->src_info[0].offset = offset;
352 mSrcBufferInfo->src_info[0].shared_fd = shared_fd;
353 mSrcBufferInfo->src_info[0].format = HAL_PIXEL_FORMAT_RGBA_8888;
354 mSrcBufferInfo->src_info[0].rect.x = clipRect.left;
355 mSrcBufferInfo->src_info[0].rect.y = clipRect.top;
356 mSrcBufferInfo->src_info[0].rect.w = clipRect.right - clipRect.left;
357 mSrcBufferInfo->src_info[0].rect.h = clipRect.bottom - clipRect.top;
358 mSrcBufferInfo->src_info[0].canvas_w = clipRect.right - clipRect.left;
359 mSrcBufferInfo->src_info[0].canvas_h = clipRect.bottom - clipRect.top;
360 mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
361
362 mSrcBufferInfo->dst_info.offset = offset;
363 mSrcBufferInfo->dst_info.shared_fd = shared_fd;
364 mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
365 mSrcBufferInfo->color = color;
366 mSrcBufferInfo->offset = 0;
367 mSrcBufferInfo->dst_info.rect.x = clipRect.left;
368 mSrcBufferInfo->dst_info.rect.y = clipRect.top;
369 mSrcBufferInfo->dst_info.rect.w = clipRect.right - clipRect.left;
370 mSrcBufferInfo->dst_info.rect.h = clipRect.bottom - clipRect.top;
371 mSrcBufferInfo->dst_info.canvas_w = clipRect.right - clipRect.left;
372 mSrcBufferInfo->dst_info.canvas_h = clipRect.bottom - clipRect.top;
373 mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
374 mSrcBufferInfo->ge2d_op = AML_GE2D_FILLRECTANGLE;
375 ge2d_process(mGe2dFd, mSrcBufferInfo);
376}
377
378bool GE2DComposer::isFullScreen(
379 hwc_rect_t displayFrame)
380{
381 if (displayFrame.left == 0
382 && displayFrame.top == 0
383 && displayFrame.right == mFbInfo->info.xres
384 && displayFrame.bottom == mFbInfo->info.yres) {
385 return true;
386 }
387
388 return false;
389}
390
391void GE2DComposer::tracer()
392{
393 static char const* ge2dOp[] = {
394 "AML_GE2D_FILLRECTANGLE",
395 "AML_GE2D_BLEND",
396 "AML_GE2D_STRETCHBLIT",
397 "AML_GE2D_BLIT",
398 "AML_GE2D_NONE"};
399
400 static char const* memType[] = {
401 "CANVAS_OSD0",
402 "CANVAS_OSD1",
403 "CANVAS_ALLOC",
404 "CANVAS_INVALID"};
405 ETRACE(" OP: %22s", ge2dOp[mSrcBufferInfo->ge2d_op]);
406 ETRACE(
407 " addr | memtype | canvas size | fmt | tr | blnd |"
408 " source crop (x,y,w,h) |\n"
409 " --------------+-----------------+-------------+-----+----+------|"
410 "--------------------------------+\n");
411 ETRACE(
412 " SRC0:\n"
413 " %12x | %15s | %5dx%5d | %03x | %02s | %04s |%5d,%5d,%5d,%5d \n",
414 mSrcBufferInfo->src_info[0].offset, memType[mSrcBufferInfo->src_info[0].memtype],
415 mSrcBufferInfo->src_info[0].canvas_w, mSrcBufferInfo->src_info[0].canvas_h, mSrcBufferInfo->src_info[0].format,
416 "no", " no", mSrcBufferInfo->src_info[0].rect.x, mSrcBufferInfo->src_info[0].rect.y,
417 mSrcBufferInfo->src_info[0].rect.w, mSrcBufferInfo->src_info[0].rect.h);
418 ETRACE(
419 " SRC1:\n"
420 " %12x | %15s | %5dx%5d | %03x | %02s | %04s |%5d,%5d,%5d,%5d \n",
421 mSrcBufferInfo->src_info[1].offset, memType[mSrcBufferInfo->src_info[1].memtype],
422 mSrcBufferInfo->src_info[1].canvas_w, mSrcBufferInfo->src_info[1].canvas_h, mSrcBufferInfo->src_info[1].format,
423 "no", " no", mSrcBufferInfo->src_info[1].rect.x, mSrcBufferInfo->src_info[1].rect.y,
424 mSrcBufferInfo->src_info[1].rect.w, mSrcBufferInfo->src_info[1].rect.h);
425 ETRACE(
426 " DST:\n"
427 " %12x | %15s | %5dx%5d | %03x | %02x | %04x |%5d,%5d,%5d,%5d \n",
428 mSrcBufferInfo->dst_info.offset, memType[mSrcBufferInfo->dst_info.memtype],
429 mSrcBufferInfo->dst_info.canvas_w, mSrcBufferInfo->dst_info.canvas_h, mSrcBufferInfo->dst_info.format,
430 mSrcBufferInfo->dst_info.rotation, mSrcBufferInfo->blend_mode,
431 mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y,
432 mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
433 ETRACE(
434 " --------------+-----------------+-------------+-----+----+------|"
435 "--------------------------------+\n\n");
436}
437
438void GE2DComposer::dumpLayers(
439 private_handle_t const* hnd)
440{
441 void *layerBuffer = NULL;
442
443 layerBuffer = mmap(NULL, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->share_fd, 0);
444 if (layerBuffer != MAP_FAILED) {
445#if 1
446 int32_t base = 4 * (hnd->stride * (hnd->height / 2) + 10);
447 char* tmp = (char*)layerBuffer + base;
448 DTRACE("[0x%x, 0x%x, 0x%x, 0x%x]\n"
449 "[0x%x, 0x%x, 0x%x, 0x%x]\n"
450 "[0x%x, 0x%x, 0x%x, 0x%x]\n"
451 "[0x%x, 0x%x, 0x%x, 0x%x]\n",
452 tmp[0], tmp[1], tmp[2], tmp[3],
453 tmp[4], tmp[5], tmp[6], tmp[7],
454 tmp[8], tmp[9], tmp[10], tmp[11],
455 tmp[12], tmp[13], tmp[14], tmp[15]);
456#else
457 int fd;
458 char path[128];
459
460 sprintf(path, "/data/local/tmp/layer_%" PRId64 ".bin", systemTime(SYSTEM_TIME_MONOTONIC));
461 fd = open(path, O_RDWR | O_CREAT);
462 if (-1 == fd) {
463 ETRACE("Stark, open file failed!");
464 return;
465 }
466 write(fd, layerBuffer, hnd->size);
467 sync();
468 close(fd);
469#endif
470 munmap(layerBuffer, hnd->size);
471 DTRACE("dumpLayer ok");
472 } else {
473 ETRACE("layerBuffer mmap fail");
474 }
475}
476
477void GE2DComposer::runGE2DProcess(int32_t slot, Vector< LayerState* > &hwcLayersState)
478{
479 bool sameSize = false;
480 hwc_frect_t sourceCrop[HWC2_MAX_LAYERS];
481 const LayerState* layer[HWC2_MAX_LAYERS] = { NULL };
482 private_handle_t const* hnd[HWC2_MAX_LAYERS] = { NULL };
483 uint32_t layerNum = hwcLayersState.size();
484 hwc_rect_t displayFrame[HWC2_MAX_LAYERS];
485
486 for (int32_t i=0; i<layerNum; i++) {
487 layer[i] = hwcLayersState.itemAt(i);
488 sourceCrop[i] = layer[i]->mSourceCrop;
489 displayFrame[i] = layer[i]->mDisplayFrame;
490 hnd[i] = reinterpret_cast<private_handle_t const*>(layer[i]->mBufferHnd);
491 DTRACE("layer[%d] zorder: %d, blend: %d, PlaneAlpha: %f, "
492 "mColor: [%d, %d, %d, %d], mDataSpace: %d, format hnd[%d]: %x",
493 i, layer[i]->mZ, layer[i]->mBlendMode, layer[i]->mPlaneAlpha,
494 layer[i]->mColor.r, layer[i]->mColor.g, layer[i]->mColor.b,
495 layer[i]->mColor.a, layer[i]->mDataSpace, i, hnd[i]->format);
496 }
497
498 bool debugSameSize = Utils::checkBoolProp("sys.sf.debug.ss");
499 // TODO:2 same size layers case.
500 if (!debugSameSize && layerNum > HWC2_ONE_LAYER) {
501 if (Utils::compareRect(sourceCrop[0], sourceCrop[1])
502 && Utils::compareRect(sourceCrop[0], displayFrame[0])
503 && Utils::compareRect(sourceCrop[1], displayFrame[1])) {
504 sameSize = true;
505 // swap layers and hnds.
506 Utils::swap(layer[0], layer[1]);
507 Utils::swap(hnd[0], hnd[1]);
508 }
509 }
510
511 if ((layerNum == HWC2_TWO_LAYERS && !hnd[1])
512 || (layerNum == HWC2_MAX_LAYERS && (!hnd[1] || !hnd[2]))) {
513 ETRACE("%d layers compose, hnd should not be null", layerNum);
514 return;
515 }
516
517 mSrcBufferInfo->offset = 0;
518 if (sameSize) {
519 for (int32_t i=0; i<HWC2_TWO_LAYERS; i++) {
520 mSrcBufferInfo->src_info[i].offset = 0;
521 mSrcBufferInfo->src_info[i].shared_fd = hnd[i]->share_fd;
522 mSrcBufferInfo->src_info[i].format = hnd[i]->format;
523 mSrcBufferInfo->src_info[i].rect.x = (int32_t)sourceCrop[i].left;
524 mSrcBufferInfo->src_info[i].rect.y = (int32_t)sourceCrop[i].top;
525 mSrcBufferInfo->src_info[i].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
526 mSrcBufferInfo->src_info[i].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
527 mSrcBufferInfo->src_info[i].canvas_w = hnd[i]->stride;
528 mSrcBufferInfo->src_info[i].canvas_h = hnd[i]->height;
529 mSrcBufferInfo->src_info[i].memtype = CANVAS_ALLOC;
530 }
531
532 mSrcBufferInfo->blend_mode = layer[0]->mBlendMode;
533
534 mSrcBufferInfo->dst_info.offset = slot * mFbInfo->finfo.line_length;
535 mSrcBufferInfo->dst_info.shared_fd = mSharedFd;
536 mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
537 mSrcBufferInfo->dst_info.rect.x = displayFrame[0].left;
538 mSrcBufferInfo->dst_info.rect.y = displayFrame[0].top;
539 mSrcBufferInfo->dst_info.rect.w = displayFrame[0].right - displayFrame[0].left;
540 mSrcBufferInfo->dst_info.rect.h = displayFrame[0].bottom - displayFrame[0].top;
541 mSrcBufferInfo->dst_info.canvas_w = mFbInfo->info.xres;
542 mSrcBufferInfo->dst_info.canvas_h = mFbInfo->info.yres;
543 mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
544 mSrcBufferInfo->dst_info.rotation = layer[0]->mTransform;
545
546 // ge2d processing.
547 mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
548 ge2d_process(mGe2dFd, mSrcBufferInfo);
549
550 if (mDebug) {
551 // ETRACE("hnd[0]->format: 0x%x, hnd[1]->format: 0x%x", hnd[0]->format, hnd[1]->format);
552 // dumpLayers(hnd[0]);
553
554 ETRACE(" same crop");
555 tracer();
556 }
557
558 if (layerNum == HWC2_TWO_LAYERS) return;
559 }
560
561 int32_t beginWith = 0;
562 if (sameSize) {
563 if (layerNum == HWC2_THREE_LAYERS) {
564 beginWith = HWC2_THREE_LAYERS -1;
565 }
566 }
567
568 bool canBlend = false;
569 for (int32_t i=beginWith; i<layerNum; i++) {
570 mSrcBufferInfo->blend_mode = layer[i]->mBlendMode;
571 canBlend = Utils::compareSize(sourceCrop[i], displayFrame[i]);
572
573 if (0 == i && !isFullScreen(displayFrame[i])) {
574 hwc_rect_t clipRect;
575 clipRect.left = 0;
576 clipRect.top = 0;
577 clipRect.right = mFbInfo->info.xres;
578 clipRect.bottom = mFbInfo->info.yres;
579 fillRectangle(clipRect, 0, slot * mFbInfo->finfo.line_length, mSharedFd);
580 }
581
582 mSrcBufferInfo->src_info[0].offset = 0;
583 mSrcBufferInfo->src_info[0].shared_fd = hnd[i]->share_fd;
584 mSrcBufferInfo->src_info[0].format = hnd[i]->format;
585 mSrcBufferInfo->src_info[0].rect.x = (int32_t)sourceCrop[i].left;
586 mSrcBufferInfo->src_info[0].rect.y = (int32_t)sourceCrop[i].top;
587 mSrcBufferInfo->src_info[0].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
588 mSrcBufferInfo->src_info[0].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
589 mSrcBufferInfo->src_info[0].canvas_w = hnd[i]->stride;
590 mSrcBufferInfo->src_info[0].canvas_h = hnd[i]->height;
591 mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
592
593 // SRC1 equals DST.
594 mSrcBufferInfo->src_info[1].offset = slot * mFbInfo->finfo.line_length;
595 mSrcBufferInfo->src_info[1].shared_fd = mSharedFd;
596 mSrcBufferInfo->src_info[1].format = HAL_PIXEL_FORMAT_RGBA_8888;
597 mSrcBufferInfo->src_info[1].rect.x = displayFrame[i].left;
598 mSrcBufferInfo->src_info[1].rect.y = displayFrame[i].top;
599 mSrcBufferInfo->src_info[1].rect.w = displayFrame[i].right - displayFrame[i].left;
600 mSrcBufferInfo->src_info[1].rect.h = displayFrame[i].bottom - displayFrame[i].top;
601 mSrcBufferInfo->src_info[1].canvas_w = mFbInfo->info.xres;
602 mSrcBufferInfo->src_info[1].canvas_h = mFbInfo->info.yres;
603 mSrcBufferInfo->src_info[1].memtype = CANVAS_ALLOC;
604
605 mSrcBufferInfo->dst_info.offset = slot * mFbInfo->finfo.line_length;
606 mSrcBufferInfo->dst_info.shared_fd = mSharedFd;
607 mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
608 mSrcBufferInfo->dst_info.rect.x = displayFrame[i].left;
609 mSrcBufferInfo->dst_info.rect.y = displayFrame[i].top;
610 /*mSrcBufferInfo->dst_info.rect.w = displayFrame.right - displayFrame.left;
611 mSrcBufferInfo->dst_info.rect.h = displayFrame.bottom - displayFrame.top;*/
612 mSrcBufferInfo->dst_info.canvas_w = mFbInfo->info.xres;
613 mSrcBufferInfo->dst_info.canvas_h = mFbInfo->info.yres;
614 mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
615
616 mSrcBufferInfo->dst_info.rotation = layer[i]->mTransform;
617
618 // ge2d processing.
619 if (0 == i || !canBlend || BLEND_MODE_INVALID == mSrcBufferInfo->blend_mode) {
620 mSrcBufferInfo->dst_info.rect.w = displayFrame[i].right - displayFrame[i].left;
621 mSrcBufferInfo->dst_info.rect.h = displayFrame[i].bottom - displayFrame[i].top;
622 mSrcBufferInfo->ge2d_op = AML_GE2D_STRETCHBLIT;
623 } else {
624 mSrcBufferInfo->dst_info.rect.w = Utils::min(mSrcBufferInfo->src_info[0].rect.w, mSrcBufferInfo->src_info[1].rect.w);
625 mSrcBufferInfo->dst_info.rect.h = Utils::min(mSrcBufferInfo->src_info[0].rect.h, mSrcBufferInfo->src_info[1].rect.h);
626 mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
627 // if (mDebug) dumpLayers(hnd[i]);
628 }
629
630 ge2d_process(mGe2dFd, mSrcBufferInfo);
631 if (mDebug) {
632 ETRACE(" layers sameSize is %d", sameSize);
633 tracer();
634 }
635 }
636}
637
638// #define GE2D_PORCESS_TIMESTAMP
639bool GE2DComposer::threadLoop()
640{
641 Mutex::Autolock _l(mLock);
642 mCondition.wait(mLock);
643 if (mExitThread) {
644 ITRACE("exiting thread loop");
645 return false;
646 }
647
648 Fifo::iterator front(mQueueItems.begin());
649 // do ge2d compose.
650 while (mQueuedFrames > 0 && mQueueItems.size() > 0) {
651#ifdef GE2D_PORCESS_TIMESTAMP
652 nsecs_t beforeTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
653#endif
654 // wait all layers fence here.
655 int32_t slot = front->mSlot;
656 int32_t mergedFence = front->mFence;
657 Vector< LayerState* > layersState = front->mLayersState;
658
659 { // clear display region.
660 bool clearBuffer = front->mClearBuffer;
661 hwc_rect_t clipRect;
662 uint32_t offset = slot * mFbInfo->finfo.line_length;
663 if (clearBuffer) {
664 clipRect.left = 0;
665 clipRect.top = 0;
666 clipRect.right = mFbInfo->info.xres;
667 clipRect.bottom = mFbInfo->info.yres;
668 fillRectangle(clipRect, 0, offset, mSharedFd);
669 }
670
671 hwc2_layer_t videoLayerId = front->mVideoLayerId;
672 HwcLayer* videoLayer = mDisplayDevice.getLayerById(videoLayerId);
673 if (!clearBuffer && videoLayer) {
674 clipRect = videoLayer->getDisplayFrame();
675 fillRectangle(clipRect, 0, offset, mSharedFd);
676 }
677 }
678
679 // wait all fence to be signaled here.
680 HwcFenceControl::waitAndCloseFd(mergedFence, 2800);
681
682 // run ge2d process here.
683 runGE2DProcess(slot, layersState);
684
685 // ge2d finished process, make sure fd close here.
686 for (int32_t i=0; i<layersState.size(); i++) {
687 LayerState* layer = layersState.itemAt(i);
688 // ETRACE("close->layer:[%12" PRIxPTR ", %d]", layer->mBufferHnd, layer->mBufferFd);
689 if (layer != NULL) {
690 Utils::closeFd(layer->mBufferFd);
691 layer->mBufferFd = -1;
692 delete layer;
693 }
694 }
695
696#ifdef GE2D_PORCESS_TIMESTAMP
697 nsecs_t afterTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
698 ETRACE("Ge2d process Period: %" PRId64 "", afterTimeStamp - beforeTimeStamp);
699#endif
700 // usleep(1000*100);
701 // signal ge2d's release fence.
702 HwcFenceControl::syncTimelineInc(mSyncTimelineFd);
703
704 mQueueItems.erase(front);
705 front = mQueueItems.begin();
706 android_atomic_dec(&mQueuedFrames);
707 }
708
709 return true;
710}
711
712} // namespace amlogic
713} // namesapce android
714
715