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