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