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