1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 15 */ 16 #include <math.h> 17 #include <HwcTrace.h> 18 #include <Drm.h> 19 #include <Hwcomposer.h> 20 #include <tangier/TngOverlayPlane.h> 21 #include <tangier/TngGrallocBuffer.h> 22 23 namespace android { 24 namespace intel { 25 26 TngOverlayPlane::TngOverlayPlane(int index, int disp) 27 : OverlayPlaneBase(index, disp), 28 mRotationBufProvider(NULL) 29 { 30 CTRACE(); 31 32 memset(&mContext, 0, sizeof(mContext)); 33 } 34 35 TngOverlayPlane::~TngOverlayPlane() 36 { 37 CTRACE(); 38 } 39 40 bool TngOverlayPlane::flip(void *ctx) 41 { 42 RETURN_FALSE_IF_NOT_INIT(); 43 44 if (!DisplayPlane::flip(ctx)) 45 return false; 46 47 mContext.type = DC_OVERLAY_PLANE; 48 mContext.ctx.ov_ctx.ovadd = 0x0; 49 mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12); 50 mContext.ctx.ov_ctx.index = mIndex; 51 mContext.ctx.ov_ctx.pipe = mDevice; 52 mContext.ctx.ov_ctx.ovadd |= mPipeConfig; 53 mContext.ctx.ov_ctx.ovadd |= 0x1; 54 55 // move to next back buffer 56 //mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT; 57 58 VTRACE("ovadd = %#x, index = %d, device = %d", 59 mContext.ctx.ov_ctx.ovadd, 60 mIndex, 61 mDevice); 62 63 return true; 64 } 65 66 bool TngOverlayPlane::reset() 67 { 68 OverlayPlaneBase::reset(); 69 if (mRotationBufProvider) 70 mRotationBufProvider->reset(); 71 return true; 72 } 73 74 void* TngOverlayPlane::getContext() const 75 { 76 CTRACE(); 77 return (void *)&mContext; 78 } 79 80 bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper) 81 { 82 if (OverlayPlaneBase::setDataBuffer(mapper) == false) { 83 return false; 84 } 85 86 if (mIsProtectedBuffer) { 87 // Bit 0: Decryption request, only allowed to change on a synchronous flip 88 // This request will be qualified with the separate decryption enable bit for OV 89 mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1; 90 mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1; 91 } 92 93 mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0); 94 return true; 95 } 96 97 bool TngOverlayPlane::initialize(uint32_t bufferCount) 98 { 99 if (!OverlayPlaneBase::initialize(bufferCount)) { 100 ETRACE("failed to initialize OverlayPlaneBase"); 101 return false; 102 } 103 104 // setup rotation buffer 105 mRotationBufProvider = new RotationBufferProvider(mWsbm); 106 if (!mRotationBufProvider || !mRotationBufProvider->initialize()) { 107 DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider"); 108 } 109 return true; 110 } 111 112 void TngOverlayPlane::deinitialize() 113 { 114 DEINIT_AND_DELETE_OBJ(mRotationBufProvider); 115 OverlayPlaneBase::deinitialize(); 116 } 117 118 bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper) 119 { 120 struct VideoPayloadBuffer *payload; 121 VideoPayloadBuffer buffer_info; 122 uint32_t format; 123 // only NV12_VED has rotated buffer 124 format = mapper.getFormat(); 125 126 if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && 127 format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled && 128 format != HAL_PIXEL_FORMAT_NV12) { 129 ETRACE("Invalid video format %#x", format); 130 return false; 131 } 132 133 payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); 134 135 if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) { 136 // need to populate buffer_info 137 void *p = mapper.getCpuAddress(SUB_BUFFER0); 138 if (!p) { 139 ETRACE("failed to get buffer user pointer"); 140 return false; 141 } 142 143 bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(), 144 mapper.getHeight(), 145 mapper.getStride().yuv.yStride, 146 &buffer_info, p); 147 if (ret == false) { 148 ETRACE("failed to prepare buffer info"); 149 return false; 150 } 151 payload = &buffer_info; 152 } 153 154 // check payload 155 if (!payload) { 156 ETRACE("no payload found"); 157 return false; 158 } 159 160 if (payload->force_output_method == FORCE_OUTPUT_GPU) { 161 ETRACE("Output method is not supported!"); 162 return false; 163 } 164 165 if (payload->client_transform != mTransform || 166 mBobDeinterlace) { 167 payload->hwc_timestamp = systemTime(); 168 payload->layer_transform = mTransform; 169 if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) { 170 ETRACE("failed to setup rotation buffer"); 171 return false; 172 } 173 } 174 175 rotatedMapper = getTTMMapper(mapper, payload); 176 177 return true; 178 } 179 180 bool TngOverlayPlane::flush(uint32_t flags) 181 { 182 RETURN_FALSE_IF_NOT_INIT(); 183 ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex); 184 185 if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) 186 return false; 187 188 struct drm_psb_register_rw_arg arg; 189 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); 190 191 if (flags & PLANE_DISABLE) 192 arg.plane_disable_mask = 1; 193 else if (flags & PLANE_ENABLE) 194 arg.plane_enable_mask = 1; 195 196 arg.plane.type = DC_OVERLAY_PLANE; 197 arg.plane.index = mIndex; 198 arg.plane.ctx = (mBackBuffer[mCurrent]->gttOffsetInPage << 12); 199 // pipe select 200 arg.plane.ctx |= mPipeConfig; 201 202 if (flags & PLANE_DISABLE) { 203 DTRACE("disabling overlay %d on device %d", mIndex, mDevice); 204 } 205 206 // issue ioctl 207 Drm *drm = Hwcomposer::getInstance().getDrm(); 208 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); 209 if (ret == false) { 210 WTRACE("overlay update failed with error code %d", ret); 211 return false; 212 } 213 214 return true; 215 } 216 217 } // namespace intel 218 } // namespace android 219