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 <anniedale/AnnOverlayPlane.h>
22#include <tangier/TngGrallocBuffer.h>
23
24// FIXME: remove it
25#include <OMX_IVCommon.h>
26#include <OMX_IntelVideoExt.h>
27
28namespace android {
29namespace intel {
30
31AnnOverlayPlane::AnnOverlayPlane(int index, int disp)
32    : OverlayPlaneBase(index, disp),
33      mRotationBufProvider(NULL),
34      mRotationConfig(0),
35      mZOrderConfig(0),
36      mUseOverlayRotation(true)
37{
38    CTRACE();
39
40    memset(&mContext, 0, sizeof(mContext));
41}
42
43AnnOverlayPlane::~AnnOverlayPlane()
44{
45    CTRACE();
46}
47
48void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
49                                            void *nativeConfig)
50{
51    long slot = (long)nativeConfig;
52
53    CTRACE();
54
55    switch (slot) {
56    case 0:
57        mZOrderConfig = 0;
58        break;
59    case 1:
60        mZOrderConfig = (1 << 8);
61        break;
62    case 2:
63        mZOrderConfig = (2 << 8);
64        break;
65    case 3:
66        mZOrderConfig = (3 << 8);
67        break;
68    default:
69        ETRACE("Invalid overlay plane zorder %ld", slot);
70        return;
71    }
72}
73
74bool AnnOverlayPlane::reset()
75{
76    OverlayPlaneBase::reset();
77    if (mRotationBufProvider) {
78        mRotationBufProvider->reset();
79    }
80    return true;
81}
82
83bool AnnOverlayPlane::enable()
84{
85    RETURN_FALSE_IF_NOT_INIT();
86
87    // by default always use overlay rotation
88    mUseOverlayRotation = true;
89
90    if (mContext.ctx.ov_ctx.ovadd & (0x1 << 15))
91        return true;
92
93    mContext.ctx.ov_ctx.ovadd |= (0x1 << 15);
94
95    // flush
96    flush(PLANE_ENABLE);
97
98    return true;
99}
100
101bool AnnOverlayPlane::disable()
102{
103    RETURN_FALSE_IF_NOT_INIT();
104
105    if (!(mContext.ctx.ov_ctx.ovadd & (0x1 << 15)))
106        return true;
107
108    mContext.ctx.ov_ctx.ovadd &= ~(0x1 << 15);
109
110    mContext.ctx.ov_ctx.ovadd &= ~(0x300);
111
112    mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
113
114    // flush
115    flush(PLANE_DISABLE);
116
117    return true;
118}
119
120void AnnOverlayPlane::postFlip()
121{
122    // when using AnnOverlayPlane through AnnDisplayPlane as proxy, postFlip is never
123    // called so mUpdateMasks is never reset.
124    // When using AnnOverlayPlane directly, postFlip is invoked and mUpdateMasks is reset
125    // post-flip.
126
127    // need to check why mUpdateMasks = 0 causes video freeze.
128
129    //DisplayPlane::postFlip();
130}
131
132
133void AnnOverlayPlane::resetBackBuffer(int buf)
134{
135    CTRACE();
136
137    if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
138        return;
139
140    OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
141
142    memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
143
144    // reset overlay
145    backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
146                         (OVERLAY_INIT_BRIGHTNESS & 0xff);
147    backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
148    backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
149    backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
150    backBuffer->OCONFIG = 0;
151    backBuffer->OCONFIG |= (0x1 << 27);
152    // use 3 line buffers
153    backBuffer->OCONFIG |= 0x1;
154    backBuffer->SCHRKEN &= ~(0x7 << 24);
155    backBuffer->SCHRKEN |= 0xff;
156}
157
158bool AnnOverlayPlane::bufferOffsetSetup(BufferMapper& mapper)
159{
160    CTRACE();
161
162    OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
163    if (!backBuffer) {
164        ETRACE("invalid back buffer");
165        return false;
166    }
167
168    uint32_t format = mapper.getFormat();
169    uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
170    uint32_t yStride = mapper.getStride().yuv.yStride;
171    uint32_t uvStride = mapper.getStride().yuv.uvStride;
172    uint32_t w = mapper.getWidth();
173    uint32_t h = mapper.getHeight();
174    uint32_t srcX= mapper.getCrop().x;
175    uint32_t srcY= mapper.getCrop().y;
176    uint32_t ySurface, uSurface, vSurface;
177    uint32_t yTileOffsetX, yTileOffsetY;
178    uint32_t uTileOffsetX, uTileOffsetY;
179    uint32_t vTileOffsetX, vTileOffsetY;
180
181    // clear original format setting
182    backBuffer->OCMD &= ~(0xf << 10);
183    backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
184
185    backBuffer->OBUF_0Y = 0;
186    backBuffer->OBUF_0V = 0;
187    backBuffer->OBUF_0U = 0;
188    // Y/U/V plane must be 4k bytes aligned.
189    ySurface = gttOffsetInBytes;
190    if (mIsProtectedBuffer) {
191        // temporary workaround until vsync event logic is corrected.
192        // it seems that overlay buffer update and renderring can be overlapped,
193        // as such encryption bit may be cleared during HW rendering
194        ySurface |= 0x01;
195    }
196
197    switch(format) {
198    case HAL_PIXEL_FORMAT_YV12:    // YV12
199        vSurface = ySurface + yStride * h;
200        uSurface = vSurface + uvStride * (h / 2);
201        yTileOffsetX = srcX;
202        yTileOffsetY = srcY;
203        uTileOffsetX = srcX / 2;
204        uTileOffsetY = srcY / 2;
205        vTileOffsetX = uTileOffsetX;
206        vTileOffsetY = uTileOffsetY;
207        backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
208        break;
209    case HAL_PIXEL_FORMAT_I420:    // I420
210        uSurface = ySurface + yStride * h;
211        vSurface = uSurface + uvStride * (h / 2);
212        yTileOffsetX = srcX;
213        yTileOffsetY = srcY;
214        uTileOffsetX = srcX / 2;
215        uTileOffsetY = srcY / 2;
216        vTileOffsetX = uTileOffsetX;
217        vTileOffsetY = uTileOffsetY;
218        backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
219        break;
220    case HAL_PIXEL_FORMAT_NV12:    // NV12
221        uSurface = ySurface;
222        vSurface = ySurface;
223        backBuffer->OBUF_0U = yStride * h;
224        yTileOffsetX = srcX;
225        yTileOffsetY = srcY;
226        uTileOffsetX = srcX / 2;
227        uTileOffsetY = srcY / 2 + h;
228        vTileOffsetX = uTileOffsetX;
229        vTileOffsetY = uTileOffsetY;
230        backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
231        break;
232    // NOTE: this is the decoded video format, align the height to 32B
233    //as it's defined by video driver
234    case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar:    // NV12
235        uSurface = ySurface + yStride * align_to(h, 32);
236        vSurface = ySurface + yStride * align_to(h, 32);
237        yTileOffsetX = srcX;
238        yTileOffsetY = srcY;
239        uTileOffsetX = srcX;
240        uTileOffsetY = srcY / 2;
241        vTileOffsetX = uTileOffsetX;
242        vTileOffsetY = uTileOffsetY;
243        backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
244        break;
245    case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled:  //NV12_tiled
246        uSurface = ySurface + yStride * align_to(h, 32);
247        vSurface = ySurface + yStride * align_to(h, 32);
248        yTileOffsetX = srcX;
249        yTileOffsetY = srcY;
250        uTileOffsetX = srcX;
251        uTileOffsetY = srcY / 2;
252        vTileOffsetX = uTileOffsetX;
253        vTileOffsetY = uTileOffsetY;
254        backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
255        backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
256        break;
257    case HAL_PIXEL_FORMAT_YUY2:    // YUY2
258        uSurface = ySurface;
259        vSurface = ySurface;
260        yTileOffsetX = srcX;
261        yTileOffsetY = srcY;
262        uTileOffsetX = yTileOffsetX;
263        uTileOffsetY = yTileOffsetY;
264        vTileOffsetX = yTileOffsetX;
265        vTileOffsetY = yTileOffsetY;
266        backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
267        backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
268        break;
269    case HAL_PIXEL_FORMAT_UYVY:    // UYVY
270        uSurface = ySurface;
271        vSurface = ySurface;
272        yTileOffsetX = srcX;
273        yTileOffsetY = srcY;
274        uTileOffsetX = yTileOffsetX;
275        uTileOffsetY = yTileOffsetY;
276        vTileOffsetX = yTileOffsetX;
277        vTileOffsetY = yTileOffsetY;
278        backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
279        backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
280        break;
281    default:
282        ETRACE("unsupported format %d", format);
283        return false;
284    }
285
286    backBuffer->OSTART_0Y = ySurface;
287    backBuffer->OSTART_0U = uSurface;
288    backBuffer->OSTART_0V = vSurface;
289    backBuffer->OBUF_0Y += srcY * yStride + srcX;
290    backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
291    backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
292    backBuffer->OTILEOFF_0Y = yTileOffsetY << 16 | yTileOffsetX;
293    backBuffer->OTILEOFF_0U = uTileOffsetY << 16 | uTileOffsetX;
294    backBuffer->OTILEOFF_0V = vTileOffsetY << 16 | vTileOffsetX;
295
296    VTRACE("done. offset (%d, %d, %d)",
297          backBuffer->OBUF_0Y,
298          backBuffer->OBUF_0U,
299          backBuffer->OBUF_0V);
300
301    return true;
302}
303
304bool AnnOverlayPlane::scalingSetup(BufferMapper& mapper)
305{
306    int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
307    int xscaleIntUV, xscaleFractUV;
308    int yscaleIntUV, yscaleFractUV;
309    // UV is half the size of Y -- YUV420
310    int uvratio = 2;
311    uint32_t newval;
312    coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
313    coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
314    coeffRec ycoeffY[N_VERT_Y_TAPS * N_PHASES];
315    coeffRec ycoeffUV[N_VERT_UV_TAPS * N_PHASES];
316    int i, j, pos;
317    bool scaleChanged = false;
318    int x, y, w, h;
319    int deinterlace_factor = 1;
320    drmModeModeInfoPtr mode = &mModeInfo;
321
322    OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
323    if (!backBuffer) {
324        ETRACE("invalid back buffer");
325        return false;
326    }
327
328    if (mPanelOrientation == PANEL_ORIENTATION_180) {
329        if (mode->hdisplay)
330            x = mode->hdisplay - mPosition.x - mPosition.w;
331        else
332            x = mPosition.x;
333        if (mode->vdisplay)
334            y = mode->vdisplay - mPosition.y - mPosition.h;
335        else
336            y = mPosition.y;
337    } else {
338        x = mPosition.x;
339        y = mPosition.y;
340    }
341
342    w = mPosition.w;
343    h = mPosition.h;
344
345    // check position
346    checkPosition(x, y, w, h);
347    VTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
348
349    if ((w <= 0) || (h <= 0)) {
350         ETRACE("invalid dst width/height");
351         return false;
352    }
353
354    // setup dst position
355    backBuffer->DWINPOS = (y << 16) | x;
356    backBuffer->DWINSZ = (h << 16) | w;
357
358    uint32_t srcWidth = mapper.getCrop().w;
359    uint32_t srcHeight = mapper.getCrop().h;
360    uint32_t dstWidth = w;
361    uint32_t dstHeight = h;
362
363    if (mBobDeinterlace && !mTransform)
364        deinterlace_factor = 2;
365
366    VTRACE("src (%dx%d), dst (%dx%d), transform %d",
367          srcWidth, srcHeight,
368          dstWidth, dstHeight,
369          mTransform);
370
371    // switch destination width/height for scale factor calculation
372    // for 90/270 transformation
373    if (mUseOverlayRotation && ((mTransform == HWC_TRANSFORM_ROT_90) ||
374        (mTransform == HWC_TRANSFORM_ROT_270))) {
375        uint32_t tmp = srcHeight;
376        srcHeight = srcWidth;
377        srcWidth = tmp;
378    }
379
380     // Y down-scale factor as a multiple of 4096
381    if (srcWidth == dstWidth && srcHeight == dstHeight) {
382        xscaleFract = (1 << 12);
383        yscaleFract = (1 << 12) / deinterlace_factor;
384    } else {
385        xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
386        yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
387    }
388
389    // Calculate the UV scaling factor
390    xscaleFractUV = xscaleFract / uvratio;
391    yscaleFractUV = yscaleFract / uvratio;
392
393
394    // To keep the relative Y and UV ratios exact, round the Y scales
395    // to a multiple of the Y/UV ratio.
396    xscaleFract = xscaleFractUV * uvratio;
397    yscaleFract = yscaleFractUV * uvratio;
398
399    // Integer (un-multiplied) values
400    xscaleInt = xscaleFract >> 12;
401    yscaleInt = yscaleFract >> 12;
402
403    xscaleIntUV = xscaleFractUV >> 12;
404    yscaleIntUV = yscaleFractUV >> 12;
405
406    // Check scaling ratio
407    if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
408        ETRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
409        return false;
410    }
411
412    // shouldn't get here
413    if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
414        ETRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
415        return false;
416    }
417
418    newval = (xscaleInt << 15) |
419    ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
420    if (newval != backBuffer->YRGBSCALE) {
421        scaleChanged = true;
422        backBuffer->YRGBSCALE = newval;
423    }
424
425    newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
426    ((yscaleFractUV & 0xFFF) << 20);
427    if (newval != backBuffer->UVSCALE) {
428        scaleChanged = true;
429        backBuffer->UVSCALE = newval;
430    }
431
432    newval = yscaleInt << 16 | yscaleIntUV;
433    if (newval != backBuffer->UVSCALEV) {
434        scaleChanged = true;
435        backBuffer->UVSCALEV = newval;
436    }
437
438    // Recalculate coefficients if the scaling changed
439    // Only Horizontal coefficients so far.
440    if (scaleChanged) {
441        double fHCutoffY;
442        double fHCutoffUV;
443        double fVCutoffY;
444        double fVCutoffUV;
445
446        fHCutoffY = xscaleFract / 4096.0;
447        fHCutoffUV = xscaleFractUV / 4096.0;
448        fVCutoffY = yscaleFract / 4096.0;
449        fVCutoffUV = yscaleFractUV / 4096.0;
450
451        // Limit to between 1.0 and 3.0
452        if (fHCutoffY < MIN_CUTOFF_FREQ)
453            fHCutoffY = MIN_CUTOFF_FREQ;
454        if (fHCutoffY > MAX_CUTOFF_FREQ)
455            fHCutoffY = MAX_CUTOFF_FREQ;
456        if (fHCutoffUV < MIN_CUTOFF_FREQ)
457            fHCutoffUV = MIN_CUTOFF_FREQ;
458        if (fHCutoffUV > MAX_CUTOFF_FREQ)
459            fHCutoffUV = MAX_CUTOFF_FREQ;
460
461        if (fVCutoffY < MIN_CUTOFF_FREQ)
462            fVCutoffY = MIN_CUTOFF_FREQ;
463        if (fVCutoffY > MAX_CUTOFF_FREQ)
464            fVCutoffY = MAX_CUTOFF_FREQ;
465        if (fVCutoffUV < MIN_CUTOFF_FREQ)
466            fVCutoffUV = MIN_CUTOFF_FREQ;
467        if (fVCutoffUV > MAX_CUTOFF_FREQ)
468            fVCutoffUV = MAX_CUTOFF_FREQ;
469
470        updateCoeff(N_HORIZ_Y_TAPS, fHCutoffY, true, true, xcoeffY);
471        updateCoeff(N_HORIZ_UV_TAPS, fHCutoffUV, true, false, xcoeffUV);
472        updateCoeff(N_VERT_Y_TAPS, fVCutoffY, false, true, ycoeffY);
473        updateCoeff(N_VERT_UV_TAPS, fVCutoffUV, false, false, ycoeffUV);
474
475        for (i = 0; i < N_PHASES; i++) {
476            for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
477                pos = i * N_HORIZ_Y_TAPS + j;
478                backBuffer->Y_HCOEFS[pos] =
479                        (xcoeffY[pos].sign << 15 |
480                         xcoeffY[pos].exponent << 12 |
481                         xcoeffY[pos].mantissa);
482            }
483        }
484        for (i = 0; i < N_PHASES; i++) {
485            for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
486                pos = i * N_HORIZ_UV_TAPS + j;
487                backBuffer->UV_HCOEFS[pos] =
488                         (xcoeffUV[pos].sign << 15 |
489                          xcoeffUV[pos].exponent << 12 |
490                          xcoeffUV[pos].mantissa);
491            }
492        }
493
494        for (i = 0; i < N_PHASES; i++) {
495            for (j = 0; j < N_VERT_Y_TAPS; j++) {
496                pos = i * N_VERT_Y_TAPS + j;
497                backBuffer->Y_VCOEFS[pos] =
498                        (ycoeffY[pos].sign << 15 |
499                         ycoeffY[pos].exponent << 12 |
500                         ycoeffY[pos].mantissa);
501            }
502        }
503        for (i = 0; i < N_PHASES; i++) {
504            for (j = 0; j < N_VERT_UV_TAPS; j++) {
505                pos = i * N_VERT_UV_TAPS + j;
506                backBuffer->UV_VCOEFS[pos] =
507                         (ycoeffUV[pos].sign << 15 |
508                          ycoeffUV[pos].exponent << 12 |
509                          ycoeffUV[pos].mantissa);
510            }
511        }
512    }
513
514    XTRACE();
515    return true;
516}
517
518void AnnOverlayPlane::setTransform(int transform)
519{
520    RETURN_VOID_IF_NOT_INIT();
521
522    if (mPanelOrientation == PANEL_ORIENTATION_180)
523       transform ^=  HWC_TRANSFORM_ROT_180;
524
525    DisplayPlane::setTransform(transform);
526
527    // setup transform config
528    switch (mTransform) {
529    case HWC_TRANSFORM_ROT_90:
530        mRotationConfig = (0x1 << 10);
531        break;
532    case HWC_TRANSFORM_ROT_180:
533        mRotationConfig = (0x2 << 10);
534        break;
535    case HWC_TRANSFORM_ROT_270:
536        mRotationConfig = (0x3 << 10);
537        break;
538    case 0:
539        mRotationConfig = 0;
540        break;
541    default:
542        ETRACE("Invalid transform %d", mTransform);
543        mRotationConfig = 0;
544        break;
545    }
546}
547
548// HSD 4645510:
549// This is a SOC limition, that when source buffer width range is
550// in (960, 1024] - one cache line length, and rotation bit is set
551// in portrait mode, video will show distortion.
552bool AnnOverlayPlane::isSettingRotBitAllowed()
553{
554    uint32_t width = mSrcCrop.w;
555
556    if ((width > 960 && width <= 1024) &&
557            (mTransform == 0 || mTransform == HAL_TRANSFORM_ROT_180))
558        return false;
559    return true;
560}
561
562bool AnnOverlayPlane::flip(void *ctx)
563{
564    uint32_t ovadd = 0;
565
566    RETURN_FALSE_IF_NOT_INIT();
567
568    if (!DisplayPlane::flip(ctx)) {
569        ETRACE("failed to flip display plane.");
570        return false;
571    }
572
573    // update back buffer address
574    ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
575
576    // enable rotation mode and setup rotation config
577    // if video is interlaced, cannot use overlay rotation
578    if (mIndex == 0 && !mBobDeinterlace) {
579        if (isSettingRotBitAllowed())
580            ovadd |= (1 << 12);
581        ovadd |= mRotationConfig;
582    }
583
584    // setup z-order config
585    ovadd |= mZOrderConfig;
586
587    // load coefficients
588    ovadd |= 0x1;
589
590    // enable overlay
591    ovadd |= (1 << 15);
592
593    mContext.type = DC_OVERLAY_PLANE;
594    mContext.ctx.ov_ctx.ovadd = ovadd;
595    mContext.ctx.ov_ctx.index = mIndex;
596    mContext.ctx.ov_ctx.pipe = mDevice;
597    mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
598
599    // move to next back buffer
600    mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
601
602    VTRACE("ovadd = %#x, index = %d, device = %d",
603          mContext.ctx.ov_ctx.ovadd,
604          mIndex,
605          mDevice);
606
607    return true;
608}
609
610void* AnnOverlayPlane::getContext() const
611{
612    CTRACE();
613    return (void *)&mContext;
614}
615
616bool AnnOverlayPlane::setDataBuffer(BufferMapper& mapper)
617{
618    if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
619        return false;
620    }
621
622    signalVideoRotation(mapper);
623
624    if (mIsProtectedBuffer) {
625        // Bit 0: Decryption request, only allowed to change on a synchronous flip
626        // This request will be qualified with the separate decryption enable bit for OV
627        mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
628        mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
629    }
630
631    mContext.gtt_key = (unsigned long)mapper.getCpuAddress(0);
632
633    return true;
634}
635
636bool AnnOverlayPlane::initialize(uint32_t bufferCount)
637{
638    if (!OverlayPlaneBase::initialize(bufferCount)) {
639        ETRACE("failed to initialize OverlayPlaneBase");
640        return false;
641    }
642
643    // setup rotation buffer
644    mRotationBufProvider = new RotationBufferProvider(mWsbm);
645    if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
646        DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
647    }
648    return true;
649}
650
651void AnnOverlayPlane::deinitialize()
652{
653    DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
654    OverlayPlaneBase::deinitialize();
655}
656
657bool AnnOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
658{
659    struct VideoPayloadBuffer *payload;
660    uint32_t format;
661    // only NV12_VED has rotated buffer
662    format = mapper.getFormat();
663    if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
664        format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
665        ETRACE("invalid video format %#x", format);
666        return false;
667    }
668
669    payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
670    // check payload
671    if (!payload) {
672        ETRACE("no payload found");
673        return false;
674    }
675
676    if (payload->force_output_method == FORCE_OUTPUT_GPU) {
677        ETRACE("Output method is not supported!");
678        return false;
679    }
680
681    if (payload->client_transform != mTransform ||
682        mBobDeinterlace) {
683        if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
684            DTRACE("failed to setup rotation buffer");
685            return false;
686        }
687    }
688
689    rotatedMapper = getTTMMapper(mapper, payload);
690    return true;
691}
692
693void AnnOverlayPlane::signalVideoRotation(BufferMapper& mapper)
694{
695    struct VideoPayloadBuffer *payload;
696    uint32_t format;
697
698    // check if it's video layer
699    format = mapper.getFormat();
700    if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
701        format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
702        return;
703    }
704
705    payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
706    if (!payload) {
707        ETRACE("no payload found");
708        return;
709    }
710
711    /* if use overlay rotation, signal decoder to stop rotation */
712    if (mUseOverlayRotation) {
713        if (payload->client_transform) {
714            WTRACE("signal decoder to stop generate rotation buffer");
715            payload->hwc_timestamp = systemTime();
716            payload->layer_transform = 0;
717        }
718    } else {
719        /* if overlay rotation cannot be used, signal decoder to start rotation */
720        if (payload->client_transform != mTransform) {
721            WTRACE("signal decoder to generate rotation buffer with transform %d", mTransform);
722            payload->hwc_timestamp = systemTime();
723            payload->layer_transform = mTransform;
724        }
725    }
726}
727
728bool AnnOverlayPlane::useOverlayRotation(BufferMapper& mapper)
729{
730    if (mTransform == 0)
731        return true;
732
733    if (!isSettingRotBitAllowed()) {
734        mUseOverlayRotation = false;
735        mRotationConfig = 0;
736        return false;
737    }
738
739    // workaround limitation of overlay rotation by falling back to use VA rotated buffer
740    bool fallback = false;
741    float scaleX = (float)mSrcCrop.w / mPosition.w;
742    float scaleY = (float)mSrcCrop.h / mPosition.h;
743    if (mTransform == HAL_TRANSFORM_ROT_270 || mTransform == HAL_TRANSFORM_ROT_90) {
744        scaleX = (float)mSrcCrop.w / mPosition.h;
745        scaleY = (float)mSrcCrop.h / mPosition.w;
746    }
747    if (scaleX >= 3 || scaleY >= 3) {
748        if (mUseOverlayRotation) {
749            DTRACE("overlay rotation with scaling >= 3, use VA rotated buffer");
750        }
751        fallback = true;
752    } else if ((int)mSrcCrop.x & 63) {
753        if (mUseOverlayRotation) {
754            DTRACE("offset is not 64 bytes aligned, use VA rotated buffer");
755        }
756        fallback = true;
757    }
758#if 0
759    else if (mTransform != HAL_TRANSFORM_ROT_180 && scaleX != scaleY) {
760        if (mUseOverlayRotation) {
761            DTRACE("overlay rotation with uneven scaling, use VA rotated buffer");
762        }
763        fallback = true;
764    }
765#endif
766
767    // per DC spec, if video is 1080(H)x1920(V), the buffer
768    // need 1920 of 64-pixel strip if using hw rotation.
769    // fallback to video ration buffer in such case.
770    if (mSrcCrop.w == 1080 && mSrcCrop.h == 1920 && mTransform != 0) {
771        DTRACE("1080(H)x1920(V) cannot use hw rotation, use VA rotated buffer");
772        fallback = true;
773    }
774
775    if (fallback || mBobDeinterlace) {
776        mUseOverlayRotation = false;
777        mRotationConfig = 0;
778    } else {
779        mUseOverlayRotation = true;
780    }
781    return mUseOverlayRotation;
782}
783
784bool AnnOverlayPlane::scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload)
785{
786    mUseScaledBuffer = (payload->scaling_khandle != 0);
787
788    if (mUseScaledBuffer) {
789        mapper.setCrop(mapper.getCrop().x, mapper.getCrop().y, payload->scaling_width, payload->scaling_height);
790        scaledMapper = getTTMMapper(mapper, payload);
791        return (scaledMapper != 0);
792    }
793
794    return mUseScaledBuffer;
795}
796
797bool AnnOverlayPlane::flush(uint32_t flags)
798{
799    RETURN_FALSE_IF_NOT_INIT();
800    ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
801
802    if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) {
803        ETRACE("invalid flush flags.");
804        return false;
805    }
806
807    struct drm_psb_register_rw_arg arg;
808    memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
809
810    if (flags & PLANE_DISABLE)
811        arg.plane_disable_mask = 1;
812    else if (flags & PLANE_ENABLE)
813        arg.plane_enable_mask = 1;
814
815    arg.plane.type = DC_OVERLAY_PLANE;
816    arg.plane.index = mIndex;
817    arg.plane.ctx = mContext.ctx.ov_ctx.ovadd;
818    if (flags & PLANE_DISABLE) {
819        DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
820    }
821
822    // issue ioctl
823    Drm *drm = Hwcomposer::getInstance().getDrm();
824    bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
825    if (ret == false) {
826        WTRACE("overlay update failed with error code %d", ret);
827        return false;
828    }
829
830    return true;
831}
832
833} // namespace intel
834} // namespace android
835