1 /*
2 // Copyright (c) 2014 Intel Corporation
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 #include <math.h>
18 #include <common/utils/HwcTrace.h>
19 #include <common/base/Drm.h>
20 #include <Hwcomposer.h>
21 #include <PhysicalDevice.h>
22 #include <ips/common/OverlayPlaneBase.h>
23 #include <ips/common/TTMBufferMapper.h>
24 #include <ips/common/GrallocSubBuffer.h>
25 #include <DisplayQuery.h>
26 #include <khronos/openmax/OMX_IntelVideoExt.h>
27 #include <hal_public.h>
28
29 namespace android {
30 namespace intel {
31
OverlayPlaneBase(int index,int disp)32 OverlayPlaneBase::OverlayPlaneBase(int index, int disp)
33 : DisplayPlane(index, PLANE_OVERLAY, disp),
34 mTTMBuffers(),
35 mActiveTTMBuffers(),
36 mCurrent(0),
37 mWsbm(0),
38 mPipeConfig(0),
39 mBobDeinterlace(0)
40 {
41 CTRACE();
42 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
43 mBackBuffer[i] = 0;
44 }
45 }
46
~OverlayPlaneBase()47 OverlayPlaneBase::~OverlayPlaneBase()
48 {
49 CTRACE();
50 }
51
initialize(uint32_t bufferCount)52 bool OverlayPlaneBase::initialize(uint32_t bufferCount)
53 {
54 Drm *drm = Hwcomposer::getInstance().getDrm();
55 CTRACE();
56
57 // NOTE: use overlay's data buffer count for the overlay plane
58 if (bufferCount < OVERLAY_DATA_BUFFER_COUNT) {
59 ILOGTRACE("override overlay buffer count from %d to %d",
60 bufferCount, OVERLAY_DATA_BUFFER_COUNT);
61 bufferCount = OVERLAY_DATA_BUFFER_COUNT;
62 }
63 if (!DisplayPlane::initialize(bufferCount)) {
64 DEINIT_AND_RETURN_FALSE("failed to initialize display plane");
65 }
66
67 mTTMBuffers.setCapacity(bufferCount);
68 mActiveTTMBuffers.setCapacity(MIN_DATA_BUFFER_COUNT);
69
70 // init wsbm
71 mWsbm = new Wsbm(drm->getDrmFd());
72 if (!mWsbm || !mWsbm->initialize()) {
73 DEINIT_AND_RETURN_FALSE("failed to create wsbm");
74 }
75
76 // create overlay back buffer
77 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
78 mBackBuffer[i] = createBackBuffer();
79 if (!mBackBuffer[i]) {
80 DEINIT_AND_RETURN_FALSE("failed to create overlay back buffer");
81 }
82 // reset back buffer
83 resetBackBuffer(i);
84 }
85
86 // disable overlay when created
87 flush(PLANE_DISABLE);
88
89 return true;
90 }
91
isDisabled()92 bool OverlayPlaneBase::isDisabled()
93 {
94 RETURN_FALSE_IF_NOT_INIT();
95
96 struct drm_psb_register_rw_arg arg;
97 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
98
99 arg.get_plane_state_mask = 1;
100 arg.plane.type = DC_OVERLAY_PLANE;
101 arg.plane.index = mIndex;
102 // pass the pipe index to check its enabled status
103 // now we can pass the device id directly since
104 // their values are just equal
105 arg.plane.ctx = mDevice; // not used in kernel
106
107 Drm *drm = Hwcomposer::getInstance().getDrm();
108 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
109 if (ret == false) {
110 WLOGTRACE("overlay plane query failed with error code %d", ret);
111 return false;
112 }
113
114 DLOGTRACE("overlay %d status %s on device %d, current device %d",
115 mIndex, arg.plane.ctx ? "DISABLED" : "ENABLED", mDevice, mDevice);
116
117 return arg.plane.ctx == PSB_DC_PLANE_DISABLED;
118 }
119
deinitialize()120 void OverlayPlaneBase::deinitialize()
121 {
122 if (mTTMBuffers.size()) {
123 invalidateBufferCache();
124 }
125
126 if (mActiveTTMBuffers.size() > 0) {
127 invalidateActiveTTMBuffers();
128 }
129
130 // delete back buffer
131 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
132 if (mBackBuffer[i]) {
133 deleteBackBuffer(i);
134 mBackBuffer[i] = NULL;
135 }
136 }
137 DEINIT_AND_DELETE_OBJ(mWsbm);
138
139 DisplayPlane::deinitialize();
140 }
141
invalidateBufferCache()142 void OverlayPlaneBase::invalidateBufferCache()
143 {
144 // clear plane buffer cache
145 DisplayPlane::invalidateBufferCache();
146 invalidateTTMBuffers();
147 }
148
assignToDevice(int disp)149 bool OverlayPlaneBase::assignToDevice(int disp)
150 {
151 uint32_t pipeConfig = 0;
152
153 RETURN_FALSE_IF_NOT_INIT();
154 VLOGTRACE("overlay %d assigned to disp %d", mIndex, disp);
155
156 switch (disp) {
157 case IDisplayDevice::DEVICE_EXTERNAL:
158 pipeConfig = (0x2 << 6);
159 break;
160 case IDisplayDevice::DEVICE_PRIMARY:
161 default:
162 pipeConfig = 0;
163 break;
164 }
165
166 // if pipe switching happened, then disable overlay first
167 if (mPipeConfig != pipeConfig) {
168 DLOGTRACE("overlay %d switched from %d to %d", mIndex, mDevice, disp);
169 disable();
170 }
171
172 mPipeConfig = pipeConfig;
173 DisplayPlane::assignToDevice(disp);
174
175 enable();
176
177 return true;
178 }
179
setZOrderConfig(ZOrderConfig & zorderConfig,void *)180 void OverlayPlaneBase::setZOrderConfig(ZOrderConfig& zorderConfig,
181 void * /*nativeConfig*/)
182 {
183 CTRACE();
184
185 // setup overlay z order
186 int ovaZOrder = -1;
187 int ovcZOrder = -1;
188 for (size_t i = 0; i < zorderConfig.size(); i++) {
189 DisplayPlane *plane = zorderConfig[i]->plane;
190 if (plane->getType() == DisplayPlane::PLANE_OVERLAY) {
191 if (plane->getIndex() == 0) {
192 ovaZOrder = i;
193 } else if (plane->getIndex() == 1) {
194 ovcZOrder = i;
195 }
196 }
197 }
198
199 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
200 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
201 if (!backBuffer)
202 return;
203
204 // force overlay c above overlay a
205 if ((ovaZOrder >= 0) && (ovaZOrder < ovcZOrder)) {
206 backBuffer->OCONFIG |= (1 << 15);
207 } else {
208 backBuffer->OCONFIG &= ~(1 << 15);
209 }
210 }
211 }
212
reset()213 bool OverlayPlaneBase::reset()
214 {
215 RETURN_FALSE_IF_NOT_INIT();
216
217 DisplayPlane::reset();
218
219 // invalidate active TTM buffers
220 if (mActiveTTMBuffers.size() > 0) {
221 invalidateActiveTTMBuffers();
222 }
223
224 // reset back buffers
225 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
226 resetBackBuffer(i);
227 }
228 return true;
229 }
230
enable()231 bool OverlayPlaneBase::enable()
232 {
233 RETURN_FALSE_IF_NOT_INIT();
234 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
235 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
236 if (!backBuffer)
237 return false;
238
239 if (backBuffer->OCMD & 0x1)
240 return true;
241
242 backBuffer->OCMD |= 0x1;
243 }
244
245 // flush
246 flush(PLANE_ENABLE);
247 return true;
248 }
249
disable()250 bool OverlayPlaneBase::disable()
251 {
252 RETURN_FALSE_IF_NOT_INIT();
253 for (int i = 0; i < OVERLAY_BACK_BUFFER_COUNT; i++) {
254 OverlayBackBufferBlk *backBuffer = mBackBuffer[i]->buf;
255 if (!backBuffer)
256 return false;
257
258 if (!(backBuffer->OCMD & 0x1))
259 return true;
260
261 backBuffer->OCMD &= ~0x1;
262 }
263
264 // flush
265 flush(PLANE_DISABLE);
266 return true;
267 }
268
createBackBuffer()269 OverlayBackBuffer* OverlayPlaneBase::createBackBuffer()
270 {
271 CTRACE();
272
273 // create back buffer
274 OverlayBackBuffer *backBuffer = (OverlayBackBuffer *)malloc(sizeof(OverlayBackBuffer));
275 if (!backBuffer) {
276 ELOGTRACE("failed to allocate back buffer");
277 return 0;
278 }
279
280
281 int size = sizeof(OverlayBackBufferBlk);
282 int alignment = 64 * 1024;
283 void *wsbmBufferObject = 0;
284 bool ret = mWsbm->allocateTTMBuffer(size, alignment, &wsbmBufferObject);
285 if (ret == false) {
286 ELOGTRACE("failed to allocate TTM buffer");
287 return 0;
288 }
289
290 void *virtAddr = mWsbm->getCPUAddress(wsbmBufferObject);
291 uint32_t gttOffsetInPage = mWsbm->getGttOffset(wsbmBufferObject);
292
293 backBuffer->buf = (OverlayBackBufferBlk *)virtAddr;
294 backBuffer->gttOffsetInPage = gttOffsetInPage;
295 backBuffer->bufObject = (uint32_t)wsbmBufferObject;
296
297 VLOGTRACE("cpu %p, gtt %d", virtAddr, gttOffsetInPage);
298
299 return backBuffer;
300 }
301
deleteBackBuffer(int buf)302 void OverlayPlaneBase::deleteBackBuffer(int buf)
303 {
304 if (!mBackBuffer[buf])
305 return;
306
307 void *wsbmBufferObject = (void *)mBackBuffer[buf]->bufObject;
308 bool ret = mWsbm->destroyTTMBuffer(wsbmBufferObject);
309 if (ret == false) {
310 WLOGTRACE("failed to destroy TTM buffer");
311 }
312 // free back buffer
313 free(mBackBuffer[buf]);
314 mBackBuffer[buf] = 0;
315 }
316
resetBackBuffer(int buf)317 void OverlayPlaneBase::resetBackBuffer(int buf)
318 {
319 CTRACE();
320
321 if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
322 return;
323
324 OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
325
326 memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
327
328 // reset overlay
329 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
330 (OVERLAY_INIT_BRIGHTNESS & 0xff);
331 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
332 backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
333 backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
334 backBuffer->OCONFIG = 0;
335 backBuffer->OCONFIG |= (0x1 << 3);
336 backBuffer->OCONFIG |= (0x1 << 27);
337 backBuffer->SCHRKEN &= ~(0x7 << 24);
338 backBuffer->SCHRKEN |= 0xff;
339 }
340
getTTMMapper(BufferMapper & grallocMapper,struct VideoPayloadBuffer * payload)341 BufferMapper* OverlayPlaneBase::getTTMMapper(BufferMapper& grallocMapper, struct VideoPayloadBuffer *payload)
342 {
343 uint32_t khandle;
344 uint32_t w, h;
345 uint32_t yStride, uvStride;
346 stride_t stride;
347 int srcX, srcY, srcW, srcH;
348
349 ssize_t index;
350 TTMBufferMapper *mapper;
351 bool ret;
352
353 if (!payload) {
354 ELOGTRACE("invalid payload buffer");
355 return 0;
356 }
357
358 srcX = grallocMapper.getCrop().x;
359 srcY = grallocMapper.getCrop().y;
360 srcW = grallocMapper.getCrop().w;
361 srcH = grallocMapper.getCrop().h;
362
363 // init ttm buffer
364 khandle = payload->rotated_buffer_handle;
365 index = mTTMBuffers.indexOfKey(khandle);
366 if (index < 0) {
367 VLOGTRACE("unmapped TTM buffer, will map it");
368
369 w = payload->rotated_width;
370 h = payload->rotated_height;
371 checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height);
372
373 uint32_t format = grallocMapper.getFormat();
374 // this is for sw decode with tiled buffer in landscape mode
375 if (payload->tiling)
376 format = OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled;
377
378 // calculate stride
379 switch (format) {
380 case HAL_PIXEL_FORMAT_YV12:
381 case HAL_PIXEL_FORMAT_INTEL_YV12:
382 case HAL_PIXEL_FORMAT_I420:
383 uint32_t yStride_align;
384 yStride_align = DisplayQuery::getOverlayLumaStrideAlignment(grallocMapper.getFormat());
385 if (yStride_align > 0)
386 {
387 yStride = align_to(align_to(w, 32), yStride_align);
388 }
389 else
390 {
391 yStride = align_to(align_to(w, 32), 64);
392 }
393 uvStride = align_to(yStride >> 1, 64);
394 stride.yuv.yStride = yStride;
395 stride.yuv.uvStride = uvStride;
396 break;
397 case HAL_PIXEL_FORMAT_NV12:
398 yStride = align_to(align_to(w, 32), 64);
399 uvStride = yStride;
400 stride.yuv.yStride = yStride;
401 stride.yuv.uvStride = uvStride;
402 break;
403 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:
404 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:
405 yStride = align_to(align_to(w, 32), 64);
406 uvStride = yStride;
407 stride.yuv.yStride = yStride;
408 stride.yuv.uvStride = uvStride;
409 break;
410 case HAL_PIXEL_FORMAT_YUY2:
411 case HAL_PIXEL_FORMAT_UYVY:
412 yStride = align_to((align_to(w, 32) << 1), 64);
413 uvStride = 0;
414 stride.yuv.yStride = yStride;
415 stride.yuv.uvStride = uvStride;
416 break;
417 }
418
419 DataBuffer buf(khandle);
420 // update buffer
421 buf.setStride(stride);
422 buf.setWidth(w);
423 buf.setHeight(h);
424 buf.setCrop(srcX, srcY, srcW, srcH);
425 buf.setFormat(format);
426
427 // create buffer mapper
428 bool res = false;
429 do {
430 mapper = new TTMBufferMapper(*mWsbm, buf);
431 if (!mapper) {
432 ELOGTRACE("failed to allocate mapper");
433 break;
434 }
435 // map ttm buffer
436 ret = mapper->map();
437 if (!ret) {
438 ELOGTRACE("failed to map");
439 invalidateTTMBuffers();
440 ret = mapper->map();
441 if (!ret) {
442 ELOGTRACE("failed to remap");
443 break;
444 }
445 }
446
447 if (mTTMBuffers.size() >= OVERLAY_DATA_BUFFER_COUNT) {
448 invalidateTTMBuffers();
449 }
450
451 // add mapper
452 index = mTTMBuffers.add(khandle, mapper);
453 if (index < 0) {
454 ELOGTRACE("failed to add TTMMapper");
455 break;
456 }
457
458 // increase mapper refCount since it is added to mTTMBuffers
459 mapper->incRef();
460 res = true;
461 } while (0);
462
463 if (!res) {
464 // error handling
465 if (mapper) {
466 mapper->unmap();
467 delete mapper;
468 mapper = NULL;
469 }
470 return 0;
471 }
472 } else {
473 VLOGTRACE("got mapper in saved ttm buffers");
474 mapper = reinterpret_cast<TTMBufferMapper *>(mTTMBuffers.valueAt(index));
475 if (mapper->getCrop().x != srcX || mapper->getCrop().y != srcY ||
476 mapper->getCrop().w != srcW || mapper->getCrop().h != srcH) {
477 checkCrop(srcX, srcY, srcW, srcH, payload->coded_width, payload->coded_height);
478 mapper->setCrop(srcX, srcY, srcW, srcH);
479 }
480 }
481
482 XLOGTRACE();
483 return mapper;
484 }
485
putTTMMapper(BufferMapper * mapper)486 void OverlayPlaneBase::putTTMMapper(BufferMapper* mapper)
487 {
488 if (!mapper)
489 return;
490
491 if (!mapper->decRef()) {
492 // unmap it
493 mapper->unmap();
494
495 // destroy this mapper
496 delete mapper;
497 }
498 }
499
isActiveTTMBuffer(BufferMapper * mapper)500 bool OverlayPlaneBase::isActiveTTMBuffer(BufferMapper *mapper)
501 {
502 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) {
503 BufferMapper *activeMapper = mActiveTTMBuffers.itemAt(i);
504 if (!activeMapper)
505 continue;
506 if (activeMapper->getKey() == mapper->getKey())
507 return true;
508 }
509
510 return false;
511 }
512
updateActiveTTMBuffers(BufferMapper * mapper)513 void OverlayPlaneBase::updateActiveTTMBuffers(BufferMapper *mapper)
514 {
515 // unmap the first entry (oldest buffer)
516 if (mActiveTTMBuffers.size() >= MAX_ACTIVE_TTM_BUFFERS) {
517 BufferMapper *oldest = mActiveTTMBuffers.itemAt(0);
518 putTTMMapper(oldest);
519 mActiveTTMBuffers.removeAt(0);
520 }
521
522 // queue it to cached buffers
523 if (!isActiveTTMBuffer(mapper)) {
524 mapper->incRef();
525 mActiveTTMBuffers.push_back(mapper);
526 }
527 }
528
invalidateActiveTTMBuffers()529 void OverlayPlaneBase::invalidateActiveTTMBuffers()
530 {
531 BufferMapper* mapper;
532
533 RETURN_VOID_IF_NOT_INIT();
534
535 for (size_t i = 0; i < mActiveTTMBuffers.size(); i++) {
536 mapper = mActiveTTMBuffers.itemAt(i);
537 // unmap it
538 putTTMMapper(mapper);
539 }
540
541 // clear recorded data buffers
542 mActiveTTMBuffers.clear();
543 }
544
invalidateTTMBuffers()545 void OverlayPlaneBase::invalidateTTMBuffers()
546 {
547 BufferMapper* mapper;
548 for (size_t i = 0; i < mTTMBuffers.size(); i++) {
549 mapper = mTTMBuffers.valueAt(i);
550 // putTTMMapper removes mapper from cache
551 putTTMMapper(mapper);
552 }
553 mTTMBuffers.clear();
554 }
555
556
rotatedBufferReady(BufferMapper & mapper,BufferMapper * & rotatedMapper)557 bool OverlayPlaneBase::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
558 {
559 struct VideoPayloadBuffer *payload;
560 uint32_t format;
561
562 // only NV12_VED has rotated buffer
563 format = mapper.getFormat();
564 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
565 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled)
566 return false;
567
568 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
569 // check payload
570 if (!payload) {
571 ELOGTRACE("no payload found");
572 return false;
573 }
574
575 if (payload->force_output_method == FORCE_OUTPUT_GPU)
576 return false;
577
578 if (payload->client_transform != mTransform) {
579 if (payload->surface_protected) {
580 payload->hwc_timestamp = systemTime();
581 payload->layer_transform = mTransform;
582 }
583 WLOGTRACE("client is not ready");
584 return false;
585 }
586
587 rotatedMapper = getTTMMapper(mapper, payload);
588 return true;
589 }
590
591
useOverlayRotation(BufferMapper &)592 bool OverlayPlaneBase::useOverlayRotation(BufferMapper& /* mapper */)
593 {
594 // by default overlay plane does not support rotation.
595 return false;
596 }
597
checkPosition(int & x,int & y,int & w,int & h)598 void OverlayPlaneBase::checkPosition(int& x, int& y, int& w, int& h)
599 {
600 drmModeModeInfoPtr mode = &mModeInfo;
601
602 if (mode->hdisplay == 0 || mode->vdisplay == 0)
603 return;
604
605 if (x < 0)
606 x = 0;
607 if (y < 0)
608 y = 0;
609 if ((x + w) > mode->hdisplay)
610 w = mode->hdisplay - x;
611 if ((y + h) > mode->vdisplay)
612 h = mode->vdisplay - y;
613 }
614
checkCrop(int & srcX,int & srcY,int & srcW,int & srcH,int coded_width,int coded_height)615 void OverlayPlaneBase::checkCrop(int& srcX, int& srcY, int& srcW, int& srcH,
616 int coded_width, int coded_height)
617 {
618 int tmp;
619
620 if (mTransform)
621 srcH >>= mBobDeinterlace;
622
623 if (mTransform == HWC_TRANSFORM_ROT_90 || mTransform == HWC_TRANSFORM_ROT_270) {
624 tmp = srcH;
625 srcH = srcW;
626 srcW = tmp;
627
628 tmp = srcX;
629 srcX = srcY;
630 srcY = tmp;
631
632 tmp = coded_width;
633 coded_width = coded_height;
634 coded_height = tmp;
635 }
636
637 // skip pading bytes in rotate buffer
638 switch(mTransform) {
639 case HWC_TRANSFORM_ROT_90:
640 srcX = (coded_width >> mBobDeinterlace) - srcW - srcX;
641 break;
642 case HWC_TRANSFORM_ROT_180:
643 srcX = coded_width - srcW - srcX;
644 srcY = (coded_height >> mBobDeinterlace) - srcH - srcY;
645 break;
646 case HWC_TRANSFORM_ROT_270:
647 srcY = coded_height - srcH - srcY;
648 break;
649 default:
650 break;
651 }
652 }
653
654
bufferOffsetSetup(BufferMapper & mapper)655 bool OverlayPlaneBase::bufferOffsetSetup(BufferMapper& mapper)
656 {
657 CTRACE();
658
659 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
660 if (!backBuffer) {
661 ELOGTRACE("invalid back buffer");
662 return false;
663 }
664
665 uint32_t format = mapper.getFormat();
666 uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
667 uint32_t yStride = mapper.getStride().yuv.yStride;
668 uint32_t uvStride = mapper.getStride().yuv.uvStride;
669 uint32_t h = mapper.getHeight();
670 uint32_t srcX= mapper.getCrop().x;
671 uint32_t srcY= mapper.getCrop().y;
672
673 // clear original format setting
674 backBuffer->OCMD &= ~(0xf << 10);
675 backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
676
677 // Y/U/V plane must be 4k bytes aligned.
678 backBuffer->OSTART_0Y = gttOffsetInBytes;
679 if (mIsProtectedBuffer) {
680 // temporary workaround until vsync event logic is corrected.
681 // it seems that overlay buffer update and renderring can be overlapped,
682 // as such encryption bit may be cleared during HW rendering
683 backBuffer->OSTART_0Y |= 0x01;
684 }
685
686 backBuffer->OSTART_0U = gttOffsetInBytes;
687 backBuffer->OSTART_0V = gttOffsetInBytes;
688
689 backBuffer->OSTART_1Y = backBuffer->OSTART_0Y;
690 backBuffer->OSTART_1U = backBuffer->OSTART_0U;
691 backBuffer->OSTART_1V = backBuffer->OSTART_0V;
692
693 switch(format) {
694 case HAL_PIXEL_FORMAT_YV12: // YV12
695 backBuffer->OBUF_0Y = 0;
696 backBuffer->OBUF_0V = yStride * h;
697 backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (h / 2));
698 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
699 break;
700 case HAL_PIXEL_FORMAT_INTEL_YV12: // INTEL_YV12
701 backBuffer->OBUF_0Y = 0;
702 backBuffer->OBUF_0V = yStride * align_to(h, 32);
703 backBuffer->OBUF_0U = backBuffer->OBUF_0V + (uvStride * (align_to(h, 32) / 2));
704 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
705 break;
706 case HAL_PIXEL_FORMAT_I420: // I420
707 backBuffer->OBUF_0Y = 0;
708 backBuffer->OBUF_0U = yStride * h;
709 backBuffer->OBUF_0V = backBuffer->OBUF_0U + (uvStride * (h / 2));
710 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
711 break;
712 case HAL_PIXEL_FORMAT_NV12: // NV12
713 backBuffer->OBUF_0Y = 0;
714 backBuffer->OBUF_0U = yStride * h;
715 backBuffer->OBUF_0V = 0;
716 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
717 break;
718 // NOTE: this is the decoded video format, align the height to 32B
719 //as it's defined by video driver
720 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // Intel codec NV12
721 backBuffer->OBUF_0Y = 0;
722 backBuffer->OBUF_0U = yStride * align_to(h, 32);
723 backBuffer->OBUF_0V = 0;
724 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
725 break;
726 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled
727 backBuffer->OBUF_0Y = 0;
728 backBuffer->OBUF_0U = yStride * align_to(h, 32);
729 backBuffer->OBUF_0V = 0;
730 backBuffer->OSTART_0U += yStride * align_to(h, 32);
731 backBuffer->OSTART_0V += yStride * align_to(h, 32);
732 backBuffer->OSTART_1U = backBuffer->OSTART_0U;
733 backBuffer->OSTART_1V = backBuffer->OSTART_0V;
734 backBuffer->OTILEOFF_0Y = srcX + (srcY << 16);
735 backBuffer->OTILEOFF_1Y = backBuffer->OTILEOFF_0Y;
736 backBuffer->OTILEOFF_0U = srcX + ((srcY / 2) << 16);
737 backBuffer->OTILEOFF_1U = backBuffer->OTILEOFF_0U;
738 backBuffer->OTILEOFF_0V = backBuffer->OTILEOFF_0U;
739 backBuffer->OTILEOFF_1V = backBuffer->OTILEOFF_0U;
740 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
741 backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
742 break;
743 case HAL_PIXEL_FORMAT_YUY2: // YUY2
744 backBuffer->OBUF_0Y = 0;
745 backBuffer->OBUF_0U = 0;
746 backBuffer->OBUF_0V = 0;
747 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
748 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
749 break;
750 case HAL_PIXEL_FORMAT_UYVY: // UYVY
751 backBuffer->OBUF_0Y = 0;
752 backBuffer->OBUF_0U = 0;
753 backBuffer->OBUF_0V = 0;
754 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
755 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
756 break;
757 default:
758 ELOGTRACE("unsupported format %d", format);
759 return false;
760 }
761
762 backBuffer->OBUF_0Y += srcY * yStride + srcX;
763 backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
764 backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
765 backBuffer->OBUF_1Y = backBuffer->OBUF_0Y;
766 backBuffer->OBUF_1U = backBuffer->OBUF_0U;
767 backBuffer->OBUF_1V = backBuffer->OBUF_0V;
768
769 VLOGTRACE("done. offset (%d, %d, %d)",
770 backBuffer->OBUF_0Y,
771 backBuffer->OBUF_0U,
772 backBuffer->OBUF_0V);
773 return true;
774 }
775
calculateSWidthSW(uint32_t offset,uint32_t width)776 uint32_t OverlayPlaneBase::calculateSWidthSW(uint32_t offset, uint32_t width)
777 {
778 ALOGTRACE("offset = %d, width = %d", offset, width);
779
780 uint32_t swidth = ((offset + width + 0x3F) >> 6) - (offset >> 6);
781
782 swidth <<= 1;
783 swidth -= 1;
784
785 return swidth;
786 }
787
coordinateSetup(BufferMapper & mapper)788 bool OverlayPlaneBase::coordinateSetup(BufferMapper& mapper)
789 {
790 CTRACE();
791
792 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
793 if (!backBuffer) {
794 ELOGTRACE("invalid back buffer");
795 return false;
796 }
797
798 uint32_t swidthy = 0;
799 uint32_t swidthuv = 0;
800 uint32_t format = mapper.getFormat();
801 uint32_t width = mapper.getCrop().w;
802 uint32_t height = mapper.getCrop().h;
803 uint32_t yStride = mapper.getStride().yuv.yStride;
804 uint32_t uvStride = mapper.getStride().yuv.uvStride;
805 uint32_t offsety = backBuffer->OBUF_0Y;
806 uint32_t offsetu = backBuffer->OBUF_0U;
807
808 switch (format) {
809 case HAL_PIXEL_FORMAT_YV12: // YV12
810 case HAL_PIXEL_FORMAT_INTEL_YV12: // INTEL_YV12
811 case HAL_PIXEL_FORMAT_I420: // I420
812 case HAL_PIXEL_FORMAT_NV12: // NV12
813 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12
814 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: // NV12_tiled
815 break;
816 case HAL_PIXEL_FORMAT_YUY2: // YUY2
817 case HAL_PIXEL_FORMAT_UYVY: // UYVY
818 width <<= 1;
819 break;
820 default:
821 ELOGTRACE("unsupported format %d", format);
822 return false;
823 }
824
825 if (width <= 0 || height <= 0) {
826 ELOGTRACE("invalid src dim");
827 return false;
828 }
829
830 if (yStride <=0 && uvStride <= 0) {
831 ELOGTRACE("invalid source stride");
832 return false;
833 }
834
835 backBuffer->SWIDTH = width | ((width / 2) << 16);
836 swidthy = calculateSWidthSW(offsety, width);
837 swidthuv = calculateSWidthSW(offsetu, width / 2);
838 backBuffer->SWIDTHSW = (swidthy << 2) | (swidthuv << 18);
839 backBuffer->SHEIGHT = height | ((height / 2) << 16);
840 backBuffer->OSTRIDE = (yStride & (~0x3f)) | ((uvStride & (~0x3f)) << 16);
841
842 XLOGTRACE();
843
844 return true;
845 }
846
setCoeffRegs(double * coeff,int mantSize,coeffPtr pCoeff,int pos)847 bool OverlayPlaneBase::setCoeffRegs(double *coeff, int mantSize,
848 coeffPtr pCoeff, int pos)
849 {
850 int maxVal, icoeff, res;
851 int sign;
852 double c;
853
854 sign = 0;
855 maxVal = 1 << mantSize;
856 c = *coeff;
857 if (c < 0.0) {
858 sign = 1;
859 c = -c;
860 }
861
862 res = 12 - mantSize;
863 if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) {
864 pCoeff[pos].exponent = 3;
865 pCoeff[pos].mantissa = icoeff << res;
866 *coeff = (double)icoeff / (double)(4 * maxVal);
867 } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) {
868 pCoeff[pos].exponent = 2;
869 pCoeff[pos].mantissa = icoeff << res;
870 *coeff = (double)icoeff / (double)(2 * maxVal);
871 } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) {
872 pCoeff[pos].exponent = 1;
873 pCoeff[pos].mantissa = icoeff << res;
874 *coeff = (double)icoeff / (double)(maxVal);
875 } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) {
876 pCoeff[pos].exponent = 0;
877 pCoeff[pos].mantissa = icoeff << res;
878 *coeff = (double)icoeff / (double)(maxVal / 2);
879 } else {
880 // Coeff out of range
881 return false;
882 }
883
884 pCoeff[pos].sign = sign;
885 if (sign)
886 *coeff = -(*coeff);
887 return true;
888 }
889
updateCoeff(int taps,double fCutoff,bool isHoriz,bool isY,coeffPtr pCoeff)890 void OverlayPlaneBase::updateCoeff(int taps, double fCutoff,
891 bool isHoriz, bool isY,
892 coeffPtr pCoeff)
893 {
894 int i, j, j1, num, pos, mantSize;
895 double pi = 3.1415926535, val, sinc, window, sum;
896 double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS];
897 double diff;
898 int tapAdjust[MAX_TAPS], tap2Fix;
899 bool isVertAndUV;
900
901 if (isHoriz)
902 mantSize = 7;
903 else
904 mantSize = 6;
905
906 isVertAndUV = !isHoriz && !isY;
907 num = taps * 16;
908 for (i = 0; i < num * 2; i++) {
909 val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num);
910 if (val == 0.0)
911 sinc = 1.0;
912 else
913 sinc = sin(val) / val;
914
915 // Hamming window
916 window = (0.54 - 0.46 * cos(2 * i * pi / (2 * num - 1)));
917 rawCoeff[i] = sinc * window;
918 }
919
920 for (i = 0; i < N_PHASES; i++) {
921 // Normalise the coefficients
922 sum = 0.0;
923 for (j = 0; j < taps; j++) {
924 pos = i + j * 32;
925 sum += rawCoeff[pos];
926 }
927 for (j = 0; j < taps; j++) {
928 pos = i + j * 32;
929 coeffs[i][j] = rawCoeff[pos] / sum;
930 }
931
932 // Set the register values
933 for (j = 0; j < taps; j++) {
934 pos = j + i * taps;
935 if ((j == (taps - 1) / 2) && !isVertAndUV)
936 setCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos);
937 else
938 setCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos);
939 }
940
941 tapAdjust[0] = (taps - 1) / 2;
942 for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) {
943 tapAdjust[j1] = tapAdjust[0] - j;
944 tapAdjust[++j1] = tapAdjust[0] + j;
945 }
946
947 // Adjust the coefficients
948 sum = 0.0;
949 for (j = 0; j < taps; j++)
950 sum += coeffs[i][j];
951 if (sum != 1.0) {
952 for (j1 = 0; j1 < taps; j1++) {
953 tap2Fix = tapAdjust[j1];
954 diff = 1.0 - sum;
955 coeffs[i][tap2Fix] += diff;
956 pos = tap2Fix + i * taps;
957 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV)
958 setCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos);
959 else
960 setCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos);
961
962 sum = 0.0;
963 for (j = 0; j < taps; j++)
964 sum += coeffs[i][j];
965 if (sum == 1.0)
966 break;
967 }
968 }
969 }
970 }
971
scalingSetup(BufferMapper & mapper)972 bool OverlayPlaneBase::scalingSetup(BufferMapper& mapper)
973 {
974 int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
975 int xscaleIntUV, xscaleFractUV;
976 int yscaleIntUV, yscaleFractUV;
977 int deinterlace_factor = 1;
978 // UV is half the size of Y -- YUV420
979 int uvratio = 2;
980 uint32_t newval;
981 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
982 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
983 int i, j, pos;
984 bool scaleChanged = false;
985 int x, y, w, h;
986
987 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
988 if (!backBuffer) {
989 ELOGTRACE("invalid back buffer");
990 return false;
991 }
992
993 x = mPosition.x;
994 y = mPosition.y;
995 w = mPosition.w;
996 h = mPosition.h;
997
998 // check position
999 checkPosition(x, y, w, h);
1000 VLOGTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
1001
1002 if ((w <= 0) || (h <= 0)) {
1003 ELOGTRACE("invalid dst width/height");
1004 return false;
1005 }
1006
1007 // setup dst position
1008 backBuffer->DWINPOS = (y << 16) | x;
1009 backBuffer->DWINSZ = (h << 16) | w;
1010
1011 uint32_t srcWidth = mapper.getCrop().w;
1012 uint32_t srcHeight = mapper.getCrop().h;
1013 uint32_t dstWidth = w;
1014 uint32_t dstHeight = h;
1015
1016 VLOGTRACE("src (%dx%d), dst (%dx%d)",
1017 srcWidth, srcHeight,
1018 dstWidth, dstHeight);
1019
1020 // Y down-scale factor as a multiple of 4096
1021 if (srcWidth == dstWidth && srcHeight == dstHeight) {
1022 xscaleFract = (1 << 12);
1023 yscaleFract = (1 << 12)/deinterlace_factor;
1024 } else {
1025 xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
1026 yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
1027 }
1028
1029 // Calculate the UV scaling factor
1030 xscaleFractUV = xscaleFract / uvratio;
1031 yscaleFractUV = yscaleFract / uvratio;
1032
1033 // To keep the relative Y and UV ratios exact, round the Y scales
1034 // to a multiple of the Y/UV ratio.
1035 xscaleFract = xscaleFractUV * uvratio;
1036 yscaleFract = yscaleFractUV * uvratio;
1037
1038 // Integer (un-multiplied) values
1039 xscaleInt = xscaleFract >> 12;
1040 yscaleInt = yscaleFract >> 12;
1041
1042 xscaleIntUV = xscaleFractUV >> 12;
1043 yscaleIntUV = yscaleFractUV >> 12;
1044
1045 // Check scaling ratio
1046 if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
1047 ELOGTRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
1048 return false;
1049 }
1050
1051 // shouldn't get here
1052 if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
1053 ELOGTRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
1054 return false;
1055 }
1056
1057 newval = (xscaleInt << 15) |
1058 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
1059 if (newval != backBuffer->YRGBSCALE) {
1060 scaleChanged = true;
1061 backBuffer->YRGBSCALE = newval;
1062 }
1063
1064 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
1065 ((yscaleFractUV & 0xFFF) << 20);
1066 if (newval != backBuffer->UVSCALE) {
1067 scaleChanged = true;
1068 backBuffer->UVSCALE = newval;
1069 }
1070
1071 newval = yscaleInt << 16 | yscaleIntUV;
1072 if (newval != backBuffer->UVSCALEV) {
1073 scaleChanged = true;
1074 backBuffer->UVSCALEV = newval;
1075 }
1076
1077 // Recalculate coefficients if the scaling changed
1078 // Only Horizontal coefficients so far.
1079 if (scaleChanged) {
1080 double fCutoffY;
1081 double fCutoffUV;
1082
1083 fCutoffY = xscaleFract / 4096.0;
1084 fCutoffUV = xscaleFractUV / 4096.0;
1085
1086 // Limit to between 1.0 and 3.0
1087 if (fCutoffY < MIN_CUTOFF_FREQ)
1088 fCutoffY = MIN_CUTOFF_FREQ;
1089 if (fCutoffY > MAX_CUTOFF_FREQ)
1090 fCutoffY = MAX_CUTOFF_FREQ;
1091 if (fCutoffUV < MIN_CUTOFF_FREQ)
1092 fCutoffUV = MIN_CUTOFF_FREQ;
1093 if (fCutoffUV > MAX_CUTOFF_FREQ)
1094 fCutoffUV = MAX_CUTOFF_FREQ;
1095
1096 updateCoeff(N_HORIZ_Y_TAPS, fCutoffY, true, true, xcoeffY);
1097 updateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, true, false, xcoeffUV);
1098
1099 for (i = 0; i < N_PHASES; i++) {
1100 for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
1101 pos = i * N_HORIZ_Y_TAPS + j;
1102 backBuffer->Y_HCOEFS[pos] =
1103 (xcoeffY[pos].sign << 15 |
1104 xcoeffY[pos].exponent << 12 |
1105 xcoeffY[pos].mantissa);
1106 }
1107 }
1108 for (i = 0; i < N_PHASES; i++) {
1109 for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
1110 pos = i * N_HORIZ_UV_TAPS + j;
1111 backBuffer->UV_HCOEFS[pos] =
1112 (xcoeffUV[pos].sign << 15 |
1113 xcoeffUV[pos].exponent << 12 |
1114 xcoeffUV[pos].mantissa);
1115 }
1116 }
1117 }
1118
1119 XLOGTRACE();
1120 return true;
1121 }
1122
colorSetup(BufferMapper & mapper)1123 bool OverlayPlaneBase::colorSetup(BufferMapper& mapper)
1124 {
1125 CTRACE();
1126
1127 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
1128 if (!backBuffer) {
1129 ELOGTRACE("invalid back buffer");
1130 return false;
1131 }
1132
1133 if (mPipeConfig == (0x2 << 6))
1134 return true;
1135
1136 uint32_t format = mapper.getFormat();
1137 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
1138 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
1139
1140 VLOGTRACE("Not video layer, use default color setting");
1141 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
1142 (OVERLAY_INIT_BRIGHTNESS & 0xff);
1143 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
1144 backBuffer->OCONFIG &= ~(1 << 5);
1145
1146 return true;
1147 }
1148
1149 struct VideoPayloadBuffer *payload;
1150 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
1151 // check payload
1152 if (!payload) {
1153 ELOGTRACE("no payload found");
1154 return false;
1155 }
1156
1157 // BT.601 or BT.709
1158 backBuffer->OCONFIG &= ~(1 << 5);
1159 backBuffer->OCONFIG |= (payload->csc_mode << 5);
1160
1161 if (payload->video_range) {
1162 // full range, no need to do level expansion
1163 backBuffer->OCLRC0 = 0x1000000;
1164 backBuffer->OCLRC1 = 0x80;
1165 } else {
1166 // level expansion for limited range
1167 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
1168 (OVERLAY_INIT_BRIGHTNESS & 0xff);
1169 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
1170 }
1171
1172 return true;
1173 }
1174
setDataBuffer(BufferMapper & grallocMapper)1175 bool OverlayPlaneBase::setDataBuffer(BufferMapper& grallocMapper)
1176 {
1177 BufferMapper *mapper;
1178 BufferMapper *rotatedMapper = 0;
1179 bool ret;
1180 uint32_t format;
1181
1182 RETURN_FALSE_IF_NOT_INIT();
1183
1184 // get gralloc mapper
1185 mapper = &grallocMapper;
1186 format = grallocMapper.getFormat();
1187 if (format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar ||
1188 format == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
1189 struct VideoPayloadBuffer *payload;
1190 payload = (struct VideoPayloadBuffer *)grallocMapper.getCpuAddress(SUB_BUFFER1);
1191 if (!payload) {
1192 ELOGTRACE("invalid payload buffer");
1193 return 0;
1194 }
1195
1196 mBobDeinterlace = payload->bob_deinterlace;
1197 }
1198
1199 if (mTransform && !useOverlayRotation(grallocMapper)) {
1200 if (!rotatedBufferReady(grallocMapper, rotatedMapper)) {
1201 DLOGTRACE("rotated buffer is not ready");
1202 return false;
1203 }
1204
1205 if (!rotatedMapper) {
1206 ELOGTRACE("failed to get rotated buffer");
1207 return false;
1208 }
1209 mapper = rotatedMapper;
1210 }
1211
1212 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
1213 if (!backBuffer) {
1214 ELOGTRACE("invalid back buffer");
1215 return false;
1216 }
1217
1218 ret = bufferOffsetSetup(*mapper);
1219 if (ret == false) {
1220 ELOGTRACE("failed to set up buffer offsets");
1221 return false;
1222 }
1223
1224 ret = coordinateSetup(*mapper);
1225 if (ret == false) {
1226 ELOGTRACE("failed to set up overlay coordinates");
1227 return false;
1228 }
1229
1230 ret = scalingSetup(*mapper);
1231 if (ret == false) {
1232 ELOGTRACE("failed to set up scaling parameters");
1233 return false;
1234 }
1235
1236 backBuffer->OCMD |= 0x1;
1237
1238 if (mBobDeinterlace && !mTransform) {
1239 backBuffer->OCMD |= BUF_TYPE_FIELD;
1240 backBuffer->OCMD &= ~FIELD_SELECT;
1241 backBuffer->OCMD |= FIELD0;
1242 backBuffer->OCMD &= ~(BUFFER_SELECT);
1243 backBuffer->OCMD |= BUFFER0;
1244 } else {
1245 backBuffer->OCMD &= ~BUF_TYPE;
1246 backBuffer->OCMD &= ~FIELD_SELECT;
1247 backBuffer->OCMD &= ~(BUFFER_SELECT);
1248 }
1249
1250 ret = colorSetup(*mapper);
1251 if (ret == false) {
1252 ELOGTRACE("failed to set up color parameters");
1253 return false;
1254 }
1255
1256 // add to active ttm buffers if it's a rotated buffer
1257 if (rotatedMapper) {
1258 updateActiveTTMBuffers(mapper);
1259 }
1260
1261 return true;
1262 }
1263
1264 } // namespace intel
1265 } // namespace android
1266
1267