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