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#include <HwcTrace.h> 17#include <Hwcomposer.h> 18#include <BufferManager.h> 19#include <anniedale/AnnRGBPlane.h> 20#include <tangier/TngGrallocBuffer.h> 21#include <common/PixelFormat.h> 22 23namespace android { 24namespace intel { 25 26AnnRGBPlane::AnnRGBPlane(int index, int type, int disp) 27 : DisplayPlane(index, type, disp) 28{ 29 CTRACE(); 30 memset(&mContext, 0, sizeof(mContext)); 31} 32 33AnnRGBPlane::~AnnRGBPlane() 34{ 35 CTRACE(); 36} 37 38bool AnnRGBPlane::enable() 39{ 40 return enablePlane(true); 41} 42 43bool AnnRGBPlane::disable() 44{ 45 return enablePlane(false); 46} 47 48void* AnnRGBPlane::getContext() const 49{ 50 CTRACE(); 51 return (void *)&mContext; 52} 53 54void AnnRGBPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig) 55{ 56 CTRACE(); 57} 58 59bool AnnRGBPlane::setDataBuffer(buffer_handle_t handle) 60{ 61 if (!handle) { 62 setFramebufferTarget(handle); 63 return true; 64 } 65 66 TngGrallocBuffer tmpBuf(handle); 67 uint32_t usage; 68 bool ret; 69 70 ATRACE("handle = %#x", handle); 71 72 usage = tmpBuf.getUsage(); 73 if (GRALLOC_USAGE_HW_FB & usage) { 74 setFramebufferTarget(handle); 75 return true; 76 } 77 78 // use primary as a sprite 79 ret = DisplayPlane::setDataBuffer(handle); 80 if (ret == false) { 81 ETRACE("failed to set data buffer"); 82 return ret; 83 } 84 85 return true; 86} 87 88bool AnnRGBPlane::setDataBuffer(BufferMapper& mapper) 89{ 90 int bpp; 91 int srcX, srcY, srcW, srcH; 92 int dstX, dstY, dstW, dstH; 93 uint32_t spriteFormat; 94 uint32_t stride; 95 uint32_t linoff; 96 uint32_t planeAlpha; 97 drmModeModeInfoPtr mode = &mModeInfo; 98 99 CTRACE(); 100 101 // setup plane position 102 dstX = mPosition.x; 103 dstY = mPosition.y; 104 dstW = mPosition.w; 105 dstH = mPosition.h; 106 107 checkPosition(dstX, dstY, dstW, dstH); 108 109 // setup plane format 110 if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) { 111 ETRACE("unsupported format %#x", mapper.getFormat()); 112 return false; 113 } 114 115 // setup stride and source buffer crop 116 srcX = mapper.getCrop().x; 117 srcY = mapper.getCrop().y; 118 srcW = mapper.getWidth(); 119 srcH = mapper.getHeight(); 120 stride = mapper.getStride().rgb.stride; 121 122 if (mPanelOrientation == PANEL_ORIENTATION_180) 123 linoff = srcY * stride + srcX * bpp + (mapper.getCrop().h - 1) * stride + (mapper.getCrop().w - 1) * bpp; 124 else 125 linoff = srcY * stride + srcX * bpp; 126 127 // unlikely happen, but still we need make sure linoff is valid 128 if (linoff > (stride * mapper.getHeight())) { 129 ETRACE("invalid source crop"); 130 return false; 131 } 132 133 // update context 134 if (mType == PLANE_SPRITE) 135 mContext.type = DC_SPRITE_PLANE; 136 else 137 mContext.type = DC_PRIMARY_PLANE; 138 139 // setup plane alpha 140 if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) { 141 planeAlpha = mPlaneAlpha | 0x80000000; 142 } else { 143 // disable plane alpha to offload HW 144 planeAlpha = 0xff; 145 } 146 147 mContext.ctx.sp_ctx.index = mIndex; 148 mContext.ctx.sp_ctx.pipe = mDevice; 149 mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000; 150 mContext.ctx.sp_ctx.linoff = linoff; 151 mContext.ctx.sp_ctx.stride = stride; 152 153 // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE 154 if (mBlending == HWC_BLENDING_COVERAGE) { 155 mContext.ctx.sp_ctx.cntr |= (0x1 << 23); 156 } 157 158 if (mPanelOrientation == PANEL_ORIENTATION_180) 159 mContext.ctx.sp_ctx.cntr |= (0x1 << 15); 160 161 if (mapper.isCompression()) { 162 mContext.ctx.sp_ctx.stride = align_to(srcW, 32) * 4; 163 mContext.ctx.sp_ctx.linoff = (align_to(srcW, 32) * srcH / 64) - 1; 164 mContext.ctx.sp_ctx.tileoff = (srcY & 0xfff) << 16 | (srcX & 0xfff); 165 mContext.ctx.sp_ctx.cntr |= (0x1 << 11); 166 } 167 168 mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12; 169 mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0); 170 171 if (mPanelOrientation == PANEL_ORIENTATION_180) { 172 if (mode->vdisplay && mode->hdisplay) 173 mContext.ctx.sp_ctx.pos = ((mode->vdisplay - dstY - dstH) & 0xfff) << 16 | ((mode->hdisplay - dstX - dstW) & 0xfff); 174 else 175 mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff); 176 } else { 177 mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff); 178 } 179 180 mContext.ctx.sp_ctx.size = 181 ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff); 182 mContext.ctx.sp_ctx.contalpa = planeAlpha; 183 mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL; 184 185 VTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x," 186 "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex, 187 mContext.ctx.sp_ctx.cntr, 188 mContext.ctx.sp_ctx.linoff, 189 mContext.ctx.sp_ctx.stride, 190 mContext.ctx.sp_ctx.surf, 191 mContext.ctx.sp_ctx.pos, 192 mContext.ctx.sp_ctx.size, 193 mContext.ctx.sp_ctx.contalpa); 194 return true; 195} 196 197bool AnnRGBPlane::enablePlane(bool enabled) 198{ 199 RETURN_FALSE_IF_NOT_INIT(); 200 201 struct drm_psb_register_rw_arg arg; 202 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); 203 if (enabled) { 204 arg.plane_enable_mask = 1; 205 } else { 206 arg.plane_disable_mask = 1; 207 } 208 209 if (mType == PLANE_SPRITE) 210 arg.plane.type = DC_SPRITE_PLANE; 211 else 212 arg.plane.type = DC_PRIMARY_PLANE; 213 214 arg.plane.index = mIndex; 215 arg.plane.ctx = 0; 216 217 // issue ioctl 218 Drm *drm = Hwcomposer::getInstance().getDrm(); 219 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); 220 if (ret == false) { 221 WTRACE("plane enabling (%d) failed with error code %d", enabled, ret); 222 return false; 223 } 224 225 return true; 226} 227 228bool AnnRGBPlane::isDisabled() 229{ 230 RETURN_FALSE_IF_NOT_INIT(); 231 232 struct drm_psb_register_rw_arg arg; 233 memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); 234 235 if (mType == PLANE_SPRITE) 236 arg.plane.type = DC_SPRITE_PLANE; 237 else 238 arg.plane.type = DC_PRIMARY_PLANE; 239 240 arg.get_plane_state_mask = 1; 241 arg.plane.index = mIndex; 242 arg.plane.ctx = 0; 243 244 // issue ioctl 245 Drm *drm = Hwcomposer::getInstance().getDrm(); 246 bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); 247 if (ret == false) { 248 WTRACE("plane state query failed with error code %d", ret); 249 return false; 250 } 251 252 return arg.plane.ctx == PSB_DC_PLANE_DISABLED; 253} 254 255void AnnRGBPlane::postFlip() 256{ 257 // prevent mUpdateMasks from being reset 258 // skipping flip may cause flicking 259} 260 261void AnnRGBPlane::setFramebufferTarget(buffer_handle_t handle) 262{ 263 uint32_t stride; 264 uint32_t planeAlpha; 265 266 CTRACE(); 267 268 // do not need to update the buffer handle 269 if (mCurrentDataBuffer != handle) 270 mUpdateMasks |= PLANE_BUFFER_CHANGED; 271 else 272 mUpdateMasks &= ~PLANE_BUFFER_CHANGED; 273 274 // if no update then do Not need set data buffer 275 if (!mUpdateMasks) 276 return; 277 278 // don't need to map data buffer for primary plane 279 if (mType == PLANE_SPRITE) 280 mContext.type = DC_SPRITE_PLANE; 281 else 282 mContext.type = DC_PRIMARY_PLANE; 283 284 stride = align_to((4 * align_to(mPosition.w, 32)), 64); 285 286 if (0 < mPlaneAlpha && mPlaneAlpha < 0xff) { 287 planeAlpha = mPlaneAlpha | 0x80000000; 288 } else { 289 // disable plane alpha to offload HW 290 planeAlpha = 0xff; 291 } 292 293 // FIXME: use sprite context for sprite plane 294 mContext.ctx.prim_ctx.update_mask = SPRITE_UPDATE_ALL; 295 mContext.ctx.prim_ctx.index = mIndex; 296 mContext.ctx.prim_ctx.pipe = mDevice; 297 298 if (mPanelOrientation == PANEL_ORIENTATION_180) 299 mContext.ctx.prim_ctx.linoff = (mPosition.h - 1) * stride + (mPosition.w - 1) * 4; 300 else 301 mContext.ctx.prim_ctx.linoff = 0; 302 303 mContext.ctx.prim_ctx.stride = stride; 304 mContext.ctx.prim_ctx.tileoff = 0; 305 mContext.ctx.prim_ctx.pos = 0; 306 mContext.ctx.prim_ctx.size = 307 ((mPosition.h - 1) & 0xfff) << 16 | ((mPosition.w - 1) & 0xfff); 308 mContext.ctx.prim_ctx.surf = 0; 309 mContext.ctx.prim_ctx.contalpa = planeAlpha; 310 mContext.ctx.prim_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888; 311 mContext.ctx.prim_ctx.cntr |= 0x80000000; 312 313 // turn off premultipled alpha blending for HWC_BLENDING_COVERAGE 314 if (mBlending == HWC_BLENDING_COVERAGE) { 315 mContext.ctx.prim_ctx.cntr |= (0x1 << 23); 316 } 317 318 if (mPanelOrientation == PANEL_ORIENTATION_180) 319 mContext.ctx.prim_ctx.cntr |= (0x1 << 15); 320 321 VTRACE("type = %d, index = %d, cntr = %#x, linoff = %#x, stride = %#x," 322 "surf = %#x, pos = %#x, size = %#x, contalpa = %#x", mType, mIndex, 323 mContext.ctx.prim_ctx.cntr, 324 mContext.ctx.prim_ctx.linoff, 325 mContext.ctx.prim_ctx.stride, 326 mContext.ctx.prim_ctx.surf, 327 mContext.ctx.prim_ctx.pos, 328 mContext.ctx.prim_ctx.size, 329 mContext.ctx.sp_ctx.contalpa); 330 331 mCurrentDataBuffer = handle; 332} 333 334} // namespace intel 335} // namespace android 336