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