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