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