/* // Copyright (c) 2014 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include <HwcTrace.h> #include <Hwcomposer.h> #include <BufferManager.h> #include <BufferManager.h> #include <tangier/TngCursorPlane.h> #include <tangier/TngGrallocBuffer.h> #include <hal_public.h> namespace android { namespace intel { TngCursorPlane::TngCursorPlane(int index, int disp) : DisplayPlane(index, PLANE_CURSOR, disp) { CTRACE(); memset(&mContext, 0, sizeof(mContext)); memset(&mCrop, 0, sizeof(mCrop)); } TngCursorPlane::~TngCursorPlane() { CTRACE(); } bool TngCursorPlane::enable() { return enablePlane(true); } bool TngCursorPlane::disable() { return enablePlane(false); } void* TngCursorPlane::getContext() const { CTRACE(); return (void *)&mContext; } void TngCursorPlane::setZOrderConfig(ZOrderConfig& config, void *nativeConfig) { (void) config; (void) nativeConfig; VTRACE("\n *** need to implement zorder config *** "); CTRACE(); } bool TngCursorPlane::setDataBuffer(buffer_handle_t handle) { bool ret; if (!handle) { ETRACE("handle is NULL"); return false; } ret = DisplayPlane::setDataBuffer(handle); if (ret == false) { ETRACE("failed to set data buffer"); return ret; } return true; } bool TngCursorPlane::setDataBuffer(BufferMapper& mapper) { int w = mapper.getWidth(); int h = mapper.getHeight(); int cursorSize = 0; CTRACE(); // setup plane position int dstX = mPosition.x; int dstY = mPosition.y; if (h < w) { cursorSize = h; } else { cursorSize = w; } #if ENABLE_ROTATION_180 dstX = mModeInfo.hdisplay - dstX - cursorSize; dstY = mModeInfo.vdisplay - dstY - cursorSize; #endif uint32_t cntr = 0; if (64 <= cursorSize && cursorSize < 128) { cursorSize = 64; cntr = 0x7; } else if (128 <= cursorSize && cursorSize < 256) { cursorSize = 128; cntr = 0x2; } else { cursorSize = 256; cntr = 0x3; } if (mapper.getFormat() == HAL_PIXEL_FORMAT_RGBA_8888) { cntr |= 1 << 5; } else if (mapper.getFormat() == HAL_PIXEL_FORMAT_BGRA_8888) { // swap color from BGRA to RGBA - alpha is MSB uint8_t *p = (uint8_t *)(mapper.getCpuAddress(0)); uint8_t *srcPixel; uint32_t stride = mapper.getStride().rgb.stride; uint8_t temp; if (!p) { return false; } for (int i = 0; i < cursorSize; i++) { for (int j = 0; j < cursorSize; j++) { srcPixel = p + i*stride + j*4; temp = srcPixel[0]; srcPixel[0] = srcPixel[2]; srcPixel[2] = temp; } } cntr |= 1 << 5; } else { ETRACE("invalid color format"); return false; } // TODO: clean spare mem to be 0 in gralloc instead uint8_t *p = (uint8_t *)(mapper.getCpuAddress(0)); uint8_t *srcPixel; uint32_t stride = mapper.getStride().rgb.stride; uint8_t temp; if (!p) { return false; } if (mCrop.w == 0 && mCrop.h == 0) { mCrop = mSrcCrop; for (int i = 0; i < cursorSize; i++) { for (int j = 0; j < cursorSize; j++) { srcPixel = p + i*stride + j*4; temp = srcPixel[0]; if (i >= mCrop.h || j >= mCrop.w) { if (srcPixel[0] == 0 && srcPixel[3] == 0xff) srcPixel[3] = 0; } } } } // update context mContext.type = DC_CURSOR_PLANE; mContext.ctx.cs_ctx.index = mIndex; mContext.ctx.cs_ctx.pipe = mDevice; mContext.ctx.cs_ctx.cntr = cntr | (mIndex << 28); mContext.ctx.cs_ctx.surf = mapper.getGttOffsetInPage(0) << 12; mContext.ctx.cs_ctx.pos = 0; if (dstX < 0) { mContext.ctx.cs_ctx.pos |= 1 << 15; dstX = -dstX; } if (dstY < 0) { mContext.ctx.cs_ctx.pos |= 1 << 31; dstY = -dstY; } mContext.ctx.cs_ctx.pos |= (dstY & 0xfff) << 16 | (dstX & 0xfff); return true; } bool TngCursorPlane::enablePlane(bool enabled) { RETURN_FALSE_IF_NOT_INIT(); struct drm_psb_register_rw_arg arg; memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); if (enabled) { arg.plane_enable_mask = 1; } else { arg.plane_disable_mask = 1; } arg.plane.type = DC_CURSOR_PLANE; arg.plane.index = mIndex; arg.plane.ctx = 0; // issue ioctl Drm *drm = Hwcomposer::getInstance().getDrm(); bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); if (ret == false) { WTRACE("plane enabling (%d) failed with error code %d", enabled, ret); return false; } return true; } bool TngCursorPlane::isDisabled() { RETURN_FALSE_IF_NOT_INIT(); struct drm_psb_register_rw_arg arg; memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); arg.plane.type = DC_CURSOR_PLANE; arg.get_plane_state_mask = 1; arg.plane.index = mIndex; arg.plane.ctx = 0; // issue ioctl Drm *drm = Hwcomposer::getInstance().getDrm(); bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); if (ret == false) { WTRACE("plane state query failed with error code %d", ret); return false; } return arg.plane.ctx == PSB_DC_PLANE_DISABLED; //return arg.plane.ctx == 0; //implement this PSB_DC_PLANE_DISABLED similar in imin_legacy return true; } void TngCursorPlane::postFlip() { // prevent mUpdateMasks from being reset // skipping flip may cause flicking } } // namespace intel } // namespace android