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 
26 namespace android {
27 namespace intel {
28 
AnnOverlayPlane(int index,int disp)29 AnnOverlayPlane::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 
~AnnOverlayPlane()41 AnnOverlayPlane::~AnnOverlayPlane()
42 {
43     CTRACE();
44 }
45 
setDataBuffer(uint32_t handle)46 bool 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 
setZOrderConfig(ZOrderConfig &,void * nativeConfig)56 void 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 
reset()82 bool AnnOverlayPlane::reset()
83 {
84     OverlayPlaneBase::reset();
85     if (mRotationBufProvider) {
86         mRotationBufProvider->reset();
87     }
88     return true;
89 }
90 
enable()91 bool 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 
disable()109 bool 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 
postFlip()128 void 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 
resetBackBuffer(int buf)141 void 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 
bufferOffsetSetup(BufferMapper & mapper)166 bool 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 
coordinateSetup(BufferMapper & mapper)335 bool 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 
scalingSetup(BufferMapper & mapper)359 bool 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 
setTransform(int transform)586 void 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.
isSettingRotBitAllowed()620 bool 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 
flip(void * ctx)630 bool 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 
getContext() const677 void* AnnOverlayPlane::getContext() const
678 {
679     CTRACE();
680     return (void *)&mContext;
681 }
682 
setDataBuffer(BufferMapper & mapper)683 bool 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 
initialize(uint32_t bufferCount)723 bool 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 
deinitialize()738 void AnnOverlayPlane::deinitialize()
739 {
740     DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
741     OverlayPlaneBase::deinitialize();
742 }
743 
rotatedBufferReady(BufferMapper & mapper,BufferMapper * & rotatedMapper)744 bool 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 
signalVideoRotation(BufferMapper & mapper)780 void 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 
useOverlayRotation(BufferMapper &)815 bool 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 
flush(uint32_t flags)871 bool 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