1 /*
2 // Copyright (c) 2014 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <math.h>
18 #include <HwcTrace.h>
19 #include <Drm.h>
20 #include <Hwcomposer.h>
21 #include <anniedale/AnnOverlayPlane.h>
22 #include <tangier/TngGrallocBuffer.h>
23
24 // FIXME: remove it
25 #include <OMX_IVCommon.h>
26 #include <OMX_IntelVideoExt.h>
27
28 namespace android {
29 namespace intel {
30
AnnOverlayPlane(int index,int disp)31 AnnOverlayPlane::AnnOverlayPlane(int index, int disp)
32 : OverlayPlaneBase(index, disp),
33 mRotationBufProvider(NULL),
34 mRotationConfig(0),
35 mZOrderConfig(0),
36 mUseOverlayRotation(true)
37 {
38 CTRACE();
39
40 memset(&mContext, 0, sizeof(mContext));
41 }
42
~AnnOverlayPlane()43 AnnOverlayPlane::~AnnOverlayPlane()
44 {
45 CTRACE();
46 }
47
setZOrderConfig(ZOrderConfig & zorderConfig,void * nativeConfig)48 void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& zorderConfig,
49 void *nativeConfig)
50 {
51 long slot = (long)nativeConfig;
52
53 CTRACE();
54
55 switch (slot) {
56 case 0:
57 mZOrderConfig = 0;
58 break;
59 case 1:
60 mZOrderConfig = (1 << 8);
61 break;
62 case 2:
63 mZOrderConfig = (2 << 8);
64 break;
65 case 3:
66 mZOrderConfig = (3 << 8);
67 break;
68 default:
69 ETRACE("Invalid overlay plane zorder %ld", slot);
70 return;
71 }
72 }
73
reset()74 bool AnnOverlayPlane::reset()
75 {
76 OverlayPlaneBase::reset();
77 if (mRotationBufProvider) {
78 mRotationBufProvider->reset();
79 }
80 return true;
81 }
82
enable()83 bool AnnOverlayPlane::enable()
84 {
85 RETURN_FALSE_IF_NOT_INIT();
86
87 // by default always use overlay rotation
88 mUseOverlayRotation = true;
89
90 if (mContext.ctx.ov_ctx.ovadd & (0x1 << 15))
91 return true;
92
93 mContext.ctx.ov_ctx.ovadd |= (0x1 << 15);
94
95 // flush
96 flush(PLANE_ENABLE);
97
98 return true;
99 }
100
disable()101 bool AnnOverlayPlane::disable()
102 {
103 RETURN_FALSE_IF_NOT_INIT();
104
105 if (!(mContext.ctx.ov_ctx.ovadd & (0x1 << 15)))
106 return true;
107
108 mContext.ctx.ov_ctx.ovadd &= ~(0x1 << 15);
109
110 mContext.ctx.ov_ctx.ovadd &= ~(0x300);
111
112 mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
113
114 // flush
115 flush(PLANE_DISABLE);
116
117 return true;
118 }
119
postFlip()120 void AnnOverlayPlane::postFlip()
121 {
122 // when using AnnOverlayPlane through AnnDisplayPlane as proxy, postFlip is never
123 // called so mUpdateMasks is never reset.
124 // When using AnnOverlayPlane directly, postFlip is invoked and mUpdateMasks is reset
125 // post-flip.
126
127 // need to check why mUpdateMasks = 0 causes video freeze.
128
129 //DisplayPlane::postFlip();
130 }
131
132
resetBackBuffer(int buf)133 void AnnOverlayPlane::resetBackBuffer(int buf)
134 {
135 CTRACE();
136
137 if (!mBackBuffer[buf] || !mBackBuffer[buf]->buf)
138 return;
139
140 OverlayBackBufferBlk *backBuffer = mBackBuffer[buf]->buf;
141
142 memset(backBuffer, 0, sizeof(OverlayBackBufferBlk));
143
144 // reset overlay
145 backBuffer->OCLRC0 = (OVERLAY_INIT_CONTRAST << 18) |
146 (OVERLAY_INIT_BRIGHTNESS & 0xff);
147 backBuffer->OCLRC1 = OVERLAY_INIT_SATURATION;
148 backBuffer->DCLRKV = OVERLAY_INIT_COLORKEY;
149 backBuffer->DCLRKM = OVERLAY_INIT_COLORKEYMASK;
150 backBuffer->OCONFIG = 0;
151 backBuffer->OCONFIG |= (0x1 << 27);
152 // use 3 line buffers
153 backBuffer->OCONFIG |= 0x1;
154 backBuffer->SCHRKEN &= ~(0x7 << 24);
155 backBuffer->SCHRKEN |= 0xff;
156 }
157
bufferOffsetSetup(BufferMapper & mapper)158 bool AnnOverlayPlane::bufferOffsetSetup(BufferMapper& mapper)
159 {
160 CTRACE();
161
162 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
163 if (!backBuffer) {
164 ETRACE("invalid back buffer");
165 return false;
166 }
167
168 uint32_t format = mapper.getFormat();
169 uint32_t gttOffsetInBytes = (mapper.getGttOffsetInPage(0) << 12);
170 uint32_t yStride = mapper.getStride().yuv.yStride;
171 uint32_t uvStride = mapper.getStride().yuv.uvStride;
172 uint32_t w = mapper.getWidth();
173 uint32_t h = mapper.getHeight();
174 uint32_t srcX= mapper.getCrop().x;
175 uint32_t srcY= mapper.getCrop().y;
176 uint32_t ySurface, uSurface, vSurface;
177 uint32_t yTileOffsetX, yTileOffsetY;
178 uint32_t uTileOffsetX, uTileOffsetY;
179 uint32_t vTileOffsetX, vTileOffsetY;
180
181 // clear original format setting
182 backBuffer->OCMD &= ~(0xf << 10);
183 backBuffer->OCMD &= ~OVERLAY_MEMORY_LAYOUT_TILED;
184
185 backBuffer->OBUF_0Y = 0;
186 backBuffer->OBUF_0V = 0;
187 backBuffer->OBUF_0U = 0;
188 // Y/U/V plane must be 4k bytes aligned.
189 ySurface = gttOffsetInBytes;
190 if (mIsProtectedBuffer) {
191 // temporary workaround until vsync event logic is corrected.
192 // it seems that overlay buffer update and renderring can be overlapped,
193 // as such encryption bit may be cleared during HW rendering
194 ySurface |= 0x01;
195 }
196
197 switch(format) {
198 case HAL_PIXEL_FORMAT_YV12: // YV12
199 vSurface = ySurface + yStride * h;
200 uSurface = vSurface + uvStride * (h / 2);
201 yTileOffsetX = srcX;
202 yTileOffsetY = srcY;
203 uTileOffsetX = srcX / 2;
204 uTileOffsetY = srcY / 2;
205 vTileOffsetX = uTileOffsetX;
206 vTileOffsetY = uTileOffsetY;
207 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
208 break;
209 case HAL_PIXEL_FORMAT_I420: // I420
210 uSurface = ySurface + yStride * h;
211 vSurface = uSurface + uvStride * (h / 2);
212 yTileOffsetX = srcX;
213 yTileOffsetY = srcY;
214 uTileOffsetX = srcX / 2;
215 uTileOffsetY = srcY / 2;
216 vTileOffsetX = uTileOffsetX;
217 vTileOffsetY = uTileOffsetY;
218 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_YUV420;
219 break;
220 case HAL_PIXEL_FORMAT_NV12: // NV12
221 uSurface = ySurface;
222 vSurface = ySurface;
223 backBuffer->OBUF_0U = yStride * h;
224 yTileOffsetX = srcX;
225 yTileOffsetY = srcY;
226 uTileOffsetX = srcX / 2;
227 uTileOffsetY = srcY / 2 + h;
228 vTileOffsetX = uTileOffsetX;
229 vTileOffsetY = uTileOffsetY;
230 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
231 break;
232 // NOTE: this is the decoded video format, align the height to 32B
233 //as it's defined by video driver
234 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar: // NV12
235 uSurface = ySurface + yStride * align_to(h, 32);
236 vSurface = ySurface + yStride * align_to(h, 32);
237 yTileOffsetX = srcX;
238 yTileOffsetY = srcY;
239 uTileOffsetX = srcX;
240 uTileOffsetY = srcY / 2;
241 vTileOffsetX = uTileOffsetX;
242 vTileOffsetY = uTileOffsetY;
243 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
244 break;
245 case OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled: //NV12_tiled
246 uSurface = ySurface + yStride * align_to(h, 32);
247 vSurface = ySurface + yStride * align_to(h, 32);
248 yTileOffsetX = srcX;
249 yTileOffsetY = srcY;
250 uTileOffsetX = srcX;
251 uTileOffsetY = srcY / 2;
252 vTileOffsetX = uTileOffsetX;
253 vTileOffsetY = uTileOffsetY;
254 backBuffer->OCMD |= OVERLAY_FORMAT_PLANAR_NV12_2;
255 backBuffer->OCMD |= OVERLAY_MEMORY_LAYOUT_TILED;
256 break;
257 case HAL_PIXEL_FORMAT_YUY2: // YUY2
258 uSurface = ySurface;
259 vSurface = ySurface;
260 yTileOffsetX = srcX;
261 yTileOffsetY = srcY;
262 uTileOffsetX = yTileOffsetX;
263 uTileOffsetY = yTileOffsetY;
264 vTileOffsetX = yTileOffsetX;
265 vTileOffsetY = yTileOffsetY;
266 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
267 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_YUY2;
268 break;
269 case HAL_PIXEL_FORMAT_UYVY: // UYVY
270 uSurface = ySurface;
271 vSurface = ySurface;
272 yTileOffsetX = srcX;
273 yTileOffsetY = srcY;
274 uTileOffsetX = yTileOffsetX;
275 uTileOffsetY = yTileOffsetY;
276 vTileOffsetX = yTileOffsetX;
277 vTileOffsetY = yTileOffsetY;
278 backBuffer->OCMD |= OVERLAY_FORMAT_PACKED_YUV422;
279 backBuffer->OCMD |= OVERLAY_PACKED_ORDER_UYVY;
280 break;
281 default:
282 ETRACE("unsupported format %d", format);
283 return false;
284 }
285
286 backBuffer->OSTART_0Y = ySurface;
287 backBuffer->OSTART_0U = uSurface;
288 backBuffer->OSTART_0V = vSurface;
289 backBuffer->OBUF_0Y += srcY * yStride + srcX;
290 backBuffer->OBUF_0V += (srcY / 2) * uvStride + srcX;
291 backBuffer->OBUF_0U += (srcY / 2) * uvStride + srcX;
292 backBuffer->OTILEOFF_0Y = yTileOffsetY << 16 | yTileOffsetX;
293 backBuffer->OTILEOFF_0U = uTileOffsetY << 16 | uTileOffsetX;
294 backBuffer->OTILEOFF_0V = vTileOffsetY << 16 | vTileOffsetX;
295
296 VTRACE("done. offset (%d, %d, %d)",
297 backBuffer->OBUF_0Y,
298 backBuffer->OBUF_0U,
299 backBuffer->OBUF_0V);
300
301 return true;
302 }
303
scalingSetup(BufferMapper & mapper)304 bool AnnOverlayPlane::scalingSetup(BufferMapper& mapper)
305 {
306 int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
307 int xscaleIntUV, xscaleFractUV;
308 int yscaleIntUV, yscaleFractUV;
309 // UV is half the size of Y -- YUV420
310 int uvratio = 2;
311 uint32_t newval;
312 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES];
313 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES];
314 coeffRec ycoeffY[N_VERT_Y_TAPS * N_PHASES];
315 coeffRec ycoeffUV[N_VERT_UV_TAPS * N_PHASES];
316 int i, j, pos;
317 bool scaleChanged = false;
318 int x, y, w, h;
319 int deinterlace_factor = 1;
320 drmModeModeInfoPtr mode = &mModeInfo;
321
322 OverlayBackBufferBlk *backBuffer = mBackBuffer[mCurrent]->buf;
323 if (!backBuffer) {
324 ETRACE("invalid back buffer");
325 return false;
326 }
327
328 if (mPanelOrientation == PANEL_ORIENTATION_180) {
329 if (mode->hdisplay)
330 x = mode->hdisplay - mPosition.x - mPosition.w;
331 else
332 x = mPosition.x;
333 if (mode->vdisplay)
334 y = mode->vdisplay - mPosition.y - mPosition.h;
335 else
336 y = mPosition.y;
337 } else {
338 x = mPosition.x;
339 y = mPosition.y;
340 }
341
342 w = mPosition.w;
343 h = mPosition.h;
344
345 // check position
346 checkPosition(x, y, w, h);
347 VTRACE("final position (%d, %d, %d, %d)", x, y, w, h);
348
349 if ((w <= 0) || (h <= 0)) {
350 ETRACE("invalid dst width/height");
351 return false;
352 }
353
354 // setup dst position
355 backBuffer->DWINPOS = (y << 16) | x;
356 backBuffer->DWINSZ = (h << 16) | w;
357
358 uint32_t srcWidth = mapper.getCrop().w;
359 uint32_t srcHeight = mapper.getCrop().h;
360 uint32_t dstWidth = w;
361 uint32_t dstHeight = h;
362
363 if (mBobDeinterlace && !mTransform)
364 deinterlace_factor = 2;
365
366 VTRACE("src (%dx%d), dst (%dx%d), transform %d",
367 srcWidth, srcHeight,
368 dstWidth, dstHeight,
369 mTransform);
370
371 // switch destination width/height for scale factor calculation
372 // for 90/270 transformation
373 if (mUseOverlayRotation && ((mTransform == HWC_TRANSFORM_ROT_90) ||
374 (mTransform == HWC_TRANSFORM_ROT_270))) {
375 uint32_t tmp = srcHeight;
376 srcHeight = srcWidth;
377 srcWidth = tmp;
378 }
379
380 // Y down-scale factor as a multiple of 4096
381 if (srcWidth == dstWidth && srcHeight == dstHeight) {
382 xscaleFract = (1 << 12);
383 yscaleFract = (1 << 12) / deinterlace_factor;
384 } else {
385 xscaleFract = ((srcWidth - 1) << 12) / dstWidth;
386 yscaleFract = ((srcHeight - 1) << 12) / (dstHeight * deinterlace_factor);
387 }
388
389 // Calculate the UV scaling factor
390 xscaleFractUV = xscaleFract / uvratio;
391 yscaleFractUV = yscaleFract / uvratio;
392
393
394 // To keep the relative Y and UV ratios exact, round the Y scales
395 // to a multiple of the Y/UV ratio.
396 xscaleFract = xscaleFractUV * uvratio;
397 yscaleFract = yscaleFractUV * uvratio;
398
399 // Integer (un-multiplied) values
400 xscaleInt = xscaleFract >> 12;
401 yscaleInt = yscaleFract >> 12;
402
403 xscaleIntUV = xscaleFractUV >> 12;
404 yscaleIntUV = yscaleFractUV >> 12;
405
406 // Check scaling ratio
407 if (xscaleInt > INTEL_OVERLAY_MAX_SCALING_RATIO) {
408 ETRACE("xscaleInt > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
409 return false;
410 }
411
412 // shouldn't get here
413 if (xscaleIntUV > INTEL_OVERLAY_MAX_SCALING_RATIO) {
414 ETRACE("xscaleIntUV > %d", INTEL_OVERLAY_MAX_SCALING_RATIO);
415 return false;
416 }
417
418 newval = (xscaleInt << 15) |
419 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20);
420 if (newval != backBuffer->YRGBSCALE) {
421 scaleChanged = true;
422 backBuffer->YRGBSCALE = newval;
423 }
424
425 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) |
426 ((yscaleFractUV & 0xFFF) << 20);
427 if (newval != backBuffer->UVSCALE) {
428 scaleChanged = true;
429 backBuffer->UVSCALE = newval;
430 }
431
432 newval = yscaleInt << 16 | yscaleIntUV;
433 if (newval != backBuffer->UVSCALEV) {
434 scaleChanged = true;
435 backBuffer->UVSCALEV = newval;
436 }
437
438 // Recalculate coefficients if the scaling changed
439 // Only Horizontal coefficients so far.
440 if (scaleChanged) {
441 double fHCutoffY;
442 double fHCutoffUV;
443 double fVCutoffY;
444 double fVCutoffUV;
445
446 fHCutoffY = xscaleFract / 4096.0;
447 fHCutoffUV = xscaleFractUV / 4096.0;
448 fVCutoffY = yscaleFract / 4096.0;
449 fVCutoffUV = yscaleFractUV / 4096.0;
450
451 // Limit to between 1.0 and 3.0
452 if (fHCutoffY < MIN_CUTOFF_FREQ)
453 fHCutoffY = MIN_CUTOFF_FREQ;
454 if (fHCutoffY > MAX_CUTOFF_FREQ)
455 fHCutoffY = MAX_CUTOFF_FREQ;
456 if (fHCutoffUV < MIN_CUTOFF_FREQ)
457 fHCutoffUV = MIN_CUTOFF_FREQ;
458 if (fHCutoffUV > MAX_CUTOFF_FREQ)
459 fHCutoffUV = MAX_CUTOFF_FREQ;
460
461 if (fVCutoffY < MIN_CUTOFF_FREQ)
462 fVCutoffY = MIN_CUTOFF_FREQ;
463 if (fVCutoffY > MAX_CUTOFF_FREQ)
464 fVCutoffY = MAX_CUTOFF_FREQ;
465 if (fVCutoffUV < MIN_CUTOFF_FREQ)
466 fVCutoffUV = MIN_CUTOFF_FREQ;
467 if (fVCutoffUV > MAX_CUTOFF_FREQ)
468 fVCutoffUV = MAX_CUTOFF_FREQ;
469
470 updateCoeff(N_HORIZ_Y_TAPS, fHCutoffY, true, true, xcoeffY);
471 updateCoeff(N_HORIZ_UV_TAPS, fHCutoffUV, true, false, xcoeffUV);
472 updateCoeff(N_VERT_Y_TAPS, fVCutoffY, false, true, ycoeffY);
473 updateCoeff(N_VERT_UV_TAPS, fVCutoffUV, false, false, ycoeffUV);
474
475 for (i = 0; i < N_PHASES; i++) {
476 for (j = 0; j < N_HORIZ_Y_TAPS; j++) {
477 pos = i * N_HORIZ_Y_TAPS + j;
478 backBuffer->Y_HCOEFS[pos] =
479 (xcoeffY[pos].sign << 15 |
480 xcoeffY[pos].exponent << 12 |
481 xcoeffY[pos].mantissa);
482 }
483 }
484 for (i = 0; i < N_PHASES; i++) {
485 for (j = 0; j < N_HORIZ_UV_TAPS; j++) {
486 pos = i * N_HORIZ_UV_TAPS + j;
487 backBuffer->UV_HCOEFS[pos] =
488 (xcoeffUV[pos].sign << 15 |
489 xcoeffUV[pos].exponent << 12 |
490 xcoeffUV[pos].mantissa);
491 }
492 }
493
494 for (i = 0; i < N_PHASES; i++) {
495 for (j = 0; j < N_VERT_Y_TAPS; j++) {
496 pos = i * N_VERT_Y_TAPS + j;
497 backBuffer->Y_VCOEFS[pos] =
498 (ycoeffY[pos].sign << 15 |
499 ycoeffY[pos].exponent << 12 |
500 ycoeffY[pos].mantissa);
501 }
502 }
503 for (i = 0; i < N_PHASES; i++) {
504 for (j = 0; j < N_VERT_UV_TAPS; j++) {
505 pos = i * N_VERT_UV_TAPS + j;
506 backBuffer->UV_VCOEFS[pos] =
507 (ycoeffUV[pos].sign << 15 |
508 ycoeffUV[pos].exponent << 12 |
509 ycoeffUV[pos].mantissa);
510 }
511 }
512 }
513
514 XTRACE();
515 return true;
516 }
517
setTransform(int transform)518 void AnnOverlayPlane::setTransform(int transform)
519 {
520 RETURN_VOID_IF_NOT_INIT();
521
522 if (mPanelOrientation == PANEL_ORIENTATION_180)
523 transform ^= HWC_TRANSFORM_ROT_180;
524
525 DisplayPlane::setTransform(transform);
526
527 // setup transform config
528 switch (mTransform) {
529 case HWC_TRANSFORM_ROT_90:
530 mRotationConfig = (0x1 << 10);
531 break;
532 case HWC_TRANSFORM_ROT_180:
533 mRotationConfig = (0x2 << 10);
534 break;
535 case HWC_TRANSFORM_ROT_270:
536 mRotationConfig = (0x3 << 10);
537 break;
538 case 0:
539 mRotationConfig = 0;
540 break;
541 default:
542 ETRACE("Invalid transform %d", mTransform);
543 mRotationConfig = 0;
544 break;
545 }
546 }
547
548 // HSD 4645510:
549 // This is a SOC limition, that when source buffer width range is
550 // in (960, 1024] - one cache line length, and rotation bit is set
551 // in portrait mode, video will show distortion.
isSettingRotBitAllowed()552 bool AnnOverlayPlane::isSettingRotBitAllowed()
553 {
554 uint32_t width = mSrcCrop.w;
555
556 if ((width > 960 && width <= 1024) &&
557 (mTransform == 0 || mTransform == HAL_TRANSFORM_ROT_180))
558 return false;
559 return true;
560 }
561
flip(void * ctx)562 bool AnnOverlayPlane::flip(void *ctx)
563 {
564 uint32_t ovadd = 0;
565
566 RETURN_FALSE_IF_NOT_INIT();
567
568 if (!DisplayPlane::flip(ctx)) {
569 ETRACE("failed to flip display plane.");
570 return false;
571 }
572
573 // update back buffer address
574 ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12);
575
576 // enable rotation mode and setup rotation config
577 // if video is interlaced, cannot use overlay rotation
578 if (mIndex == 0 && !mBobDeinterlace) {
579 if (isSettingRotBitAllowed())
580 ovadd |= (1 << 12);
581 ovadd |= mRotationConfig;
582 }
583
584 // setup z-order config
585 ovadd |= mZOrderConfig;
586
587 // load coefficients
588 ovadd |= 0x1;
589
590 // enable overlay
591 ovadd |= (1 << 15);
592
593 mContext.type = DC_OVERLAY_PLANE;
594 mContext.ctx.ov_ctx.ovadd = ovadd;
595 mContext.ctx.ov_ctx.index = mIndex;
596 mContext.ctx.ov_ctx.pipe = mDevice;
597 mContext.ctx.ov_ctx.ovadd |= mPipeConfig;
598
599 // move to next back buffer
600 mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT;
601
602 VTRACE("ovadd = %#x, index = %d, device = %d",
603 mContext.ctx.ov_ctx.ovadd,
604 mIndex,
605 mDevice);
606
607 return true;
608 }
609
getContext() const610 void* AnnOverlayPlane::getContext() const
611 {
612 CTRACE();
613 return (void *)&mContext;
614 }
615
setDataBuffer(BufferMapper & mapper)616 bool AnnOverlayPlane::setDataBuffer(BufferMapper& mapper)
617 {
618 if (OverlayPlaneBase::setDataBuffer(mapper) == false) {
619 return false;
620 }
621
622 signalVideoRotation(mapper);
623
624 if (mIsProtectedBuffer) {
625 // Bit 0: Decryption request, only allowed to change on a synchronous flip
626 // This request will be qualified with the separate decryption enable bit for OV
627 mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1;
628 mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1;
629 }
630
631 mContext.gtt_key = (unsigned long)mapper.getCpuAddress(0);
632
633 return true;
634 }
635
initialize(uint32_t bufferCount)636 bool AnnOverlayPlane::initialize(uint32_t bufferCount)
637 {
638 if (!OverlayPlaneBase::initialize(bufferCount)) {
639 ETRACE("failed to initialize OverlayPlaneBase");
640 return false;
641 }
642
643 // setup rotation buffer
644 mRotationBufProvider = new RotationBufferProvider(mWsbm);
645 if (!mRotationBufProvider || !mRotationBufProvider->initialize()) {
646 DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider");
647 }
648 return true;
649 }
650
deinitialize()651 void AnnOverlayPlane::deinitialize()
652 {
653 DEINIT_AND_DELETE_OBJ(mRotationBufProvider);
654 OverlayPlaneBase::deinitialize();
655 }
656
rotatedBufferReady(BufferMapper & mapper,BufferMapper * & rotatedMapper)657 bool AnnOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper)
658 {
659 struct VideoPayloadBuffer *payload;
660 uint32_t format;
661 // only NV12_VED has rotated buffer
662 format = mapper.getFormat();
663 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
664 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
665 ETRACE("invalid video format %#x", format);
666 return false;
667 }
668
669 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
670 // check payload
671 if (!payload) {
672 ETRACE("no payload found");
673 return false;
674 }
675
676 if (payload->force_output_method == FORCE_OUTPUT_GPU) {
677 ETRACE("Output method is not supported!");
678 return false;
679 }
680
681 if (payload->client_transform != mTransform ||
682 mBobDeinterlace) {
683 if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) {
684 DTRACE("failed to setup rotation buffer");
685 return false;
686 }
687 }
688
689 rotatedMapper = getTTMMapper(mapper, payload);
690 return true;
691 }
692
signalVideoRotation(BufferMapper & mapper)693 void AnnOverlayPlane::signalVideoRotation(BufferMapper& mapper)
694 {
695 struct VideoPayloadBuffer *payload;
696 uint32_t format;
697
698 // check if it's video layer
699 format = mapper.getFormat();
700 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar &&
701 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled) {
702 return;
703 }
704
705 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1);
706 if (!payload) {
707 ETRACE("no payload found");
708 return;
709 }
710
711 /* if use overlay rotation, signal decoder to stop rotation */
712 if (mUseOverlayRotation) {
713 if (payload->client_transform) {
714 WTRACE("signal decoder to stop generate rotation buffer");
715 payload->hwc_timestamp = systemTime();
716 payload->layer_transform = 0;
717 }
718 } else {
719 /* if overlay rotation cannot be used, signal decoder to start rotation */
720 if (payload->client_transform != mTransform) {
721 WTRACE("signal decoder to generate rotation buffer with transform %d", mTransform);
722 payload->hwc_timestamp = systemTime();
723 payload->layer_transform = mTransform;
724 }
725 }
726 }
727
useOverlayRotation(BufferMapper & mapper)728 bool AnnOverlayPlane::useOverlayRotation(BufferMapper& mapper)
729 {
730 if (mTransform == 0)
731 return true;
732
733 if (!isSettingRotBitAllowed()) {
734 mUseOverlayRotation = false;
735 mRotationConfig = 0;
736 return false;
737 }
738
739 // workaround limitation of overlay rotation by falling back to use VA rotated buffer
740 bool fallback = false;
741 float scaleX = (float)mSrcCrop.w / mPosition.w;
742 float scaleY = (float)mSrcCrop.h / mPosition.h;
743 if (mTransform == HAL_TRANSFORM_ROT_270 || mTransform == HAL_TRANSFORM_ROT_90) {
744 scaleX = (float)mSrcCrop.w / mPosition.h;
745 scaleY = (float)mSrcCrop.h / mPosition.w;
746 }
747 if (scaleX >= 3 || scaleY >= 3) {
748 if (mUseOverlayRotation) {
749 DTRACE("overlay rotation with scaling >= 3, use VA rotated buffer");
750 }
751 fallback = true;
752 } else if ((int)mSrcCrop.x & 63) {
753 if (mUseOverlayRotation) {
754 DTRACE("offset is not 64 bytes aligned, use VA rotated buffer");
755 }
756 fallback = true;
757 }
758 #if 0
759 else if (mTransform != HAL_TRANSFORM_ROT_180 && scaleX != scaleY) {
760 if (mUseOverlayRotation) {
761 DTRACE("overlay rotation with uneven scaling, use VA rotated buffer");
762 }
763 fallback = true;
764 }
765 #endif
766
767 // per DC spec, if video is 1080(H)x1920(V), the buffer
768 // need 1920 of 64-pixel strip if using hw rotation.
769 // fallback to video ration buffer in such case.
770 if (mSrcCrop.w == 1080 && mSrcCrop.h == 1920 && mTransform != 0) {
771 DTRACE("1080(H)x1920(V) cannot use hw rotation, use VA rotated buffer");
772 fallback = true;
773 }
774
775 if (fallback || mBobDeinterlace) {
776 mUseOverlayRotation = false;
777 mRotationConfig = 0;
778 } else {
779 mUseOverlayRotation = true;
780 }
781 return mUseOverlayRotation;
782 }
783
scaledBufferReady(BufferMapper & mapper,BufferMapper * & scaledMapper,VideoPayloadBuffer * payload)784 bool AnnOverlayPlane::scaledBufferReady(BufferMapper& mapper, BufferMapper* &scaledMapper, VideoPayloadBuffer *payload)
785 {
786 mUseScaledBuffer = (payload->scaling_khandle != 0);
787
788 if (mUseScaledBuffer) {
789 mapper.setCrop(mapper.getCrop().x, mapper.getCrop().y, payload->scaling_width, payload->scaling_height);
790 scaledMapper = getTTMMapper(mapper, payload);
791 return (scaledMapper != 0);
792 }
793
794 return mUseScaledBuffer;
795 }
796
flush(uint32_t flags)797 bool AnnOverlayPlane::flush(uint32_t flags)
798 {
799 RETURN_FALSE_IF_NOT_INIT();
800 ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex);
801
802 if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) {
803 ETRACE("invalid flush flags.");
804 return false;
805 }
806
807 struct drm_psb_register_rw_arg arg;
808 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg));
809
810 if (flags & PLANE_DISABLE)
811 arg.plane_disable_mask = 1;
812 else if (flags & PLANE_ENABLE)
813 arg.plane_enable_mask = 1;
814
815 arg.plane.type = DC_OVERLAY_PLANE;
816 arg.plane.index = mIndex;
817 arg.plane.ctx = mContext.ctx.ov_ctx.ovadd;
818 if (flags & PLANE_DISABLE) {
819 DTRACE("disabling overlay %d on device %d", mIndex, mDevice);
820 }
821
822 // issue ioctl
823 Drm *drm = Hwcomposer::getInstance().getDrm();
824 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg));
825 if (ret == false) {
826 WTRACE("overlay update failed with error code %d", ret);
827 return false;
828 }
829
830 return true;
831 }
832
833 } // namespace intel
834 } // namespace android
835