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