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