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 
28 namespace android {
29 namespace intel {
30 
AnnOverlayPlane(int index,int disp)31 AnnOverlayPlane::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 
~AnnOverlayPlane()43 AnnOverlayPlane::~AnnOverlayPlane()
44 {
45     CTRACE();
46 }
47 
setZOrderConfig(ZOrderConfig & zorderConfig,void * nativeConfig)48 void 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 
reset()74 bool AnnOverlayPlane::reset()
75 {
76     OverlayPlaneBase::reset();
77     if (mRotationBufProvider) {
78         mRotationBufProvider->reset();
79     }
80     return true;
81 }
82 
enable()83 bool 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 
disable()101 bool 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 
postFlip()120 void 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 
resetBackBuffer(int buf)133 void 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 
bufferOffsetSetup(BufferMapper & mapper)158 bool 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 
scalingSetup(BufferMapper & mapper)304 bool 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 
setTransform(int transform)518 void 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.
isSettingRotBitAllowed()552 bool 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 
flip(void * ctx)562 bool 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 
getContext() const610 void* AnnOverlayPlane::getContext() const
611 {
612     CTRACE();
613     return (void *)&mContext;
614 }
615 
setDataBuffer(BufferMapper & mapper)616 bool 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 
initialize(uint32_t bufferCount)636 bool 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 
deinitialize()651 void AnnOverlayPlane::deinitialize()
652 {
653     DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
654     OverlayPlaneBase::deinitialize();
655 }
656 
rotatedBufferReady(BufferMapper & mapper,BufferMapper * & rotatedMapper)657 bool 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 
signalVideoRotation(BufferMapper & mapper)693 void 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 
useOverlayRotation(BufferMapper & mapper)728 bool 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 
scaledBufferReady(BufferMapper & mapper,BufferMapper * & scaledMapper,VideoPayloadBuffer * payload)784 bool 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 
flush(uint32_t flags)797 bool 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