uint32_t BufferManager::allocGrallocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { RETURN_NULL_IF_NOT_INIT(); if (!mGralloc) { WLOGTRACE("Alloc device is not available"); return 0; } if (!width || !height) { ELOGTRACE("invalid input parameter"); return 0; } ILOGTRACE("size of graphic buffer to create: %dx%d", width, height); uint32_t handle = 0; int stride; status_t err = gralloc_device_alloc_img( mGralloc, width, height, format, usage, (buffer_handle_t *)&handle, &stride); if (err != 0) { ELOGTRACE("failed to allocate gralloc buffer, error = %d", err); return 0; } return handle; }
// HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs // this is needed so getActiveConfig/setActiveConfig work correctly. It is up to the // user space to decide what speed to send. drmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount) { RETURN_NULL_IF_NOT_INIT(); Mutex::Autolock _l(mLock); if (modeCount != NULL) *modeCount = 0; else return NULL; int outputIndex = getOutputIndex(device); if (outputIndex < 0) { ELOGTRACE("invalid device"); return NULL; } DrmOutput *output= &mOutputs[outputIndex]; if (!output->connected) { ELOGTRACE("device is not connected"); return NULL; } if (output->connector->count_modes <= 0) { ELOGTRACE("invalid count of modes"); return NULL; } *modeCount = output->connector->count_modes; return output->connector->modes; }
bool Drm::getModeInfo(int device, drmModeModeInfo& mode) { Mutex::Autolock _l(mLock); int outputIndex = getOutputIndex(device); if (outputIndex < 0 ) { return false; } DrmOutput *output= &mOutputs[outputIndex]; if (output->connected == false) { ELOGTRACE("device is not connected"); return false; } if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) { ELOGTRACE("invalid width or height"); return false; } memcpy(&mode, &output->mode, sizeof(drmModeModeInfo)); #ifdef INTEL_SUPPORT_HDMI_PRIMARY // FIXME: use default fb size instead of hdmi mode, because to // support hdmi primary, we cannot report dynamic mode to SF. mode.hdisplay = DEFAULT_DRM_FB_WIDTH; mode.vdisplay = DEFAULT_DRM_FB_HEIGHT; #endif return true; }
BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer) { BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); // invalidate buffer cache if cache is full if ((int)mDataBuffers.size() >= mCacheCapacity) { invalidateBufferCache(); } BufferMapper *mapper = bm->map(*buffer); if (!mapper) { ELOGTRACE("failed to map buffer"); return NULL; } // add it to data buffers ssize_t index = mDataBuffers.add(buffer->getKey(), mapper); if (index < 0) { ELOGTRACE("failed to add mapper"); bm->unmap(mapper); return NULL; } return mapper; }
static int hwc_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { if (!name) { ELOGTRACE("invalid name."); return -EINVAL; } ALOGTRACE("open device %s", name); if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) { ELOGTRACE("try to open unknown HWComposer %s", name); return -EINVAL; } Hwcomposer& hwc = Hwcomposer::getInstance(); // initialize our state here if (hwc.initialize() == false) { ELOGTRACE("failed to intialize HWComposer"); Hwcomposer::releaseInstance(); return -EINVAL; } // initialize the procs hwc.hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG; hwc.hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module); hwc.hwc_composer_device_1_t::common.close = hwc_device_close; hwc.hwc_composer_device_1_t::prepare = hwc_prepare; hwc.hwc_composer_device_1_t::set = hwc_set; hwc.hwc_composer_device_1_t::dump = hwc_dump; hwc.hwc_composer_device_1_t::registerProcs = hwc_registerProcs; hwc.hwc_composer_device_1_t::query = hwc_query; hwc.hwc_composer_device_1_t::eventControl = hwc_eventControl; hwc.hwc_composer_device_1_t::getDisplayConfigs = hwc_getDisplayConfigs; hwc.hwc_composer_device_1_t::getDisplayAttributes = hwc_getDisplayAttributes; // This is used to hack FBO switch flush issue in SurfaceFlinger. hwc.hwc_composer_device_1_t::reserved_proc[0] = (void*)hwc_compositionComplete; hwc.hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4; hwc.hwc_composer_device_1_t::setPowerMode = hwc_setPowerMode; hwc.hwc_composer_device_1_t::getActiveConfig = hwc_getActiveConfig; hwc.hwc_composer_device_1_t::setActiveConfig = hwc_setActiveConfig; // Todo: add hwc_setCursorPositionAsync after supporting patches hwc.hwc_composer_device_1_t::setCursorPositionAsync = NULL; *device = &hwc.hwc_composer_device_1_t::common; return 0; }
bool Drm::setDpmsMode(int device, int mode) { Mutex::Autolock _l(mLock); int output = getOutputIndex(device); if (output < 0 ) { return false; } if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF && mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY && mode != IDisplayDevice::DEVICE_DISPLAY_ON) { ELOGTRACE("invalid mode %d", mode); return false; } DrmOutput *out = &mOutputs[output]; if (!out->connected) { ELOGTRACE("device is not connected"); return false; } drmModePropertyPtr props; for (int i = 0; i < out->connector->count_props; i++) { props = drmModeGetProperty(mDrmFd, out->connector->props[i]); if (!props) { continue; } if (strcmp(props->name, "DPMS") == 0) { int ret = drmModeConnectorSetProperty( mDrmFd, out->connector->connector_id, props->prop_id, (mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON : IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ? DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF); drmModeFreeProperty(props); if (ret != 0) { ELOGTRACE("unable to set DPMS %d", mode); return false; } else { return true; } } drmModeFreeProperty(props); } return false; }
bool BufferManager::initialize() { CTRACE(); // create buffer pool mBufferPool = new BufferCache(DEFAULT_BUFFER_POOL_SIZE); if (!mBufferPool) { ELOGTRACE("failed to create gralloc buffer cache"); return false; } // init gralloc module if (gralloc_open_img(&mGralloc)) { DEINIT_AND_RETURN_FALSE("failed to get gralloc module"); } // create a dummy data buffer mDataBuffer = createDataBuffer(0); if (!mDataBuffer) { DEINIT_AND_RETURN_FALSE("failed to create data buffer"); } mInitialized = true; return true; }
bool TngGrallocBufferMapper::gttMap(void *vaddr, uint32_t size, uint32_t gttAlign, int *offset) { struct psb_gtt_mapping_arg arg; bool ret; ALOGTRACE("vaddr = %p, size = %d", vaddr, size); if (!vaddr || !size || !offset) { VLOGTRACE("invalid parameters"); return false; } arg.type = PSB_GTT_MAP_TYPE_VIRTUAL; arg.page_align = gttAlign; arg.vaddr = (uint32_t)vaddr; arg.size = size; Drm *drm = Hwcomposer::getInstance().getDrm(); ret = drm->writeReadIoctl(DRM_PSB_GTT_MAP, &arg, sizeof(arg)); if (ret == false) { ELOGTRACE("gtt mapping failed"); return false; } VLOGTRACE("offset = %#x", arg.offset_pages); *offset = arg.offset_pages; return true; }
bool DisplayPlane::assignToDevice(int disp) { RETURN_FALSE_IF_NOT_INIT(); ALOGTRACE("disp = %d", disp); mDevice = disp; Drm *drm = Hwcomposer::getInstance().getDrm(); if (!drm->getModeInfo(mDevice, mModeInfo)) { ELOGTRACE("failed to get mode info"); } mPanelOrientation = drm->getPanelOrientation(mDevice); mForceScaling = DisplayQuery::forceFbScaling(disp); drm->getDisplayResolution(disp, mDisplayWidth, mDisplayHeight); if (mForceScaling) { mModeInfo.hdisplay = mDisplayWidth; mModeInfo.vdisplay = mDisplayHeight; mPosition.x = 0; mPosition.y = 0; mPosition.w = mDisplayWidth; mPosition.h = mDisplayHeight; } mDisplayCrop.x = 0; mDisplayCrop.y = 0; mDisplayCrop.w = mDisplayWidth; mDisplayCrop.h = mDisplayHeight; return true; }
int Drm::getPanelOrientation(int device) { int outputIndex = getOutputIndex(device); if (outputIndex < 0) { ELOGTRACE("invalid device"); return PANEL_ORIENTATION_0; } DrmOutput *output= &mOutputs[outputIndex]; if (output->connected == false) { ELOGTRACE("device is not connected"); return PANEL_ORIENTATION_0; } return output->panelOrientation; }
BufferMapper* BufferManager::map(DataBuffer& buffer) { bool ret; BufferMapper* mapper; CTRACE(); Mutex::Autolock _l(mLock); //try to get mapper from pool mapper = mBufferPool->getMapper(buffer.getKey()); if (mapper) { // increase mapper ref count mapper->incRef(); return mapper; } // create a new buffer mapper and add it to pool do { VLOGTRACE("new buffer, will add it"); mapper = createBufferMapper(buffer); if (!mapper) { ELOGTRACE("failed to allocate mapper"); break; } ret = mapper->map(); if (!ret) { ELOGTRACE("failed to map"); delete mapper; mapper = NULL; break; } ret = mBufferPool->addMapper(buffer.getKey(), mapper); if (!ret) { ELOGTRACE("failed to add mapper"); break; } // increase mapper ref count mapper->incRef(); return mapper; } while (0); // error handling if (mapper) { mapper->unmap(); delete mapper; } return NULL; }
bool Hwcomposer::setActiveConfig(int disp, int index) { RETURN_FALSE_IF_NOT_INIT(); if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) { ELOGTRACE("invalid disp %d", disp); return false; } IDisplayDevice *device = mDisplayDevices.itemAt(disp); if (!device) { ELOGTRACE("no device found"); return false; } return device->setActiveConfig(index); }
int Hwcomposer::getActiveConfig(int disp) { RETURN_NULL_IF_NOT_INIT(); if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) { ELOGTRACE("invalid disp %d", disp); return -1; } IDisplayDevice *device = mDisplayDevices.itemAt(disp); if (!device) { ELOGTRACE("no device found"); return -1; } return device->getActiveConfig(); }
bool Drm::setRefreshRate(int device, int hz) { RETURN_FALSE_IF_NOT_INIT(); Mutex::Autolock _l(mLock); if (device != IDisplayDevice::DEVICE_EXTERNAL) { WLOGTRACE("Setting mode on invalid device %d", device); return false; } int outputIndex = getOutputIndex(device); if (outputIndex < 0 ) { ELOGTRACE("invalid device"); return false; } DrmOutput *output= &mOutputs[outputIndex]; if (!output->connected) { ELOGTRACE("device is not connected"); return false; } if (output->connector->count_modes <= 0) { ELOGTRACE("invalid count of modes"); return false; } drmModeModeInfoPtr mode; int index = 0; for (int i = 0; i < output->connector->count_modes; i++) { mode = &output->connector->modes[i]; if (mode->type & DRM_MODE_TYPE_PREFERRED) { index = i; } if (mode->hdisplay == output->mode.hdisplay && mode->vdisplay == output->mode.vdisplay && mode->vrefresh == (uint32_t)hz) { index = i; break; } } mode = &output->connector->modes[index]; return setDrmMode(outputIndex, mode); }
bool Wsbm::wrapTTMBuffer(uint32_t handle, void **buf) { int ret = psbWsbmWrapTTMBuffer(handle, buf); if (ret) { ELOGTRACE("failed to wrap buffer"); return false; } return true; }
bool Wsbm::destroyTTMBuffer(void * buf) { int ret = psbWsbmDestroyTTMBuffer(buf); if (ret) { ELOGTRACE("failed to destroy buffer"); return false; } return true; }
bool Wsbm::allocateTTMBufferUB(uint32_t size, uint32_t align, void ** buf, void *user_pt) { int ret = psbWsbmAllocateFromUB(size, align, buf, user_pt); if (ret) { ELOGTRACE("failed to allocate UB buffer"); return false; } return true; }
bool Wsbm::allocateTTMBuffer(uint32_t size, uint32_t align, void ** buf) { int ret = psbWsbmAllocateTTMBuffer(size, align, buf); if (ret) { ELOGTRACE("failed to allocate buffer"); return false; } return true; }
bool Wsbm::waitIdleTTMBuffer(void *buf) { int ret = psbWsbmWaitIdle(buf); if (ret) { ELOGTRACE("failed to wait ttm buffer for idle"); return false; } return true; }
bool Wsbm::unreferenceTTMBuffer(void *buf) { int ret = psbWsbmUnReference(buf); if (ret) { ELOGTRACE("failed to unreference buffer"); return false; } return true; }
void TngGrallocBufferMapper::putFbHandle() { int err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule, (buffer_handle_t)getHandle()); if (err) { ELOGTRACE("failed to unmap. err = %d", err); } return; }
void BufferManager::unmap(BufferMapper *mapper) { Mutex::Autolock _l(mLock); if (!mapper) { ELOGTRACE("invalid mapper"); return; } // unmap & remove this mapper from buffer when refCount = 0 int refCount = mapper->decRef(); if (refCount < 0) { ELOGTRACE("invalid ref count"); } else if (!refCount) { // remove mapper from buffer pool mBufferPool->removeMapper(mapper); mapper->unmap(); delete mapper; } }
bool Hwcomposer::blank(int disp, int blank) { RETURN_FALSE_IF_NOT_INIT(); ALOGTRACE("disp = %d, blank = %d", disp, blank); if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) { ELOGTRACE("invalid disp %d", disp); return false; } if (disp >= (int) mDisplayDevices.size()) { return false; } IDisplayDevice *device = mDisplayDevices.itemAt(disp); if (!device) { ELOGTRACE("no device found"); return false; } return device->blank(blank ? true : false); }
bool Hwcomposer::vsyncControl(int disp, int enabled) { RETURN_FALSE_IF_NOT_INIT(); ALOGTRACE("disp = %d, enabled = %d", disp, enabled); if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) { ELOGTRACE("invalid disp %d", disp); return false; } if (disp >= (int) mDisplayDevices.size()) { return false; } IDisplayDevice *device = mDisplayDevices.itemAt(disp); if (!device) { ELOGTRACE("no device found"); return false; } return device->vsyncControl(enabled ? true : false); }
bool Hwcomposer::setCursorPositionAsync(int disp, int x, int y) { RETURN_FALSE_IF_NOT_INIT(); if (disp != HWC_DISPLAY_PRIMARY && disp != HWC_DISPLAY_EXTERNAL) { ELOGTRACE("invalid disp %d", disp); return false; } return mDisplayContext->setCursorPosition(disp, x, y); }
bool TngGrallocBufferMapper::map() { void *vaddr[SUB_BUFFER_MAX]; uint32_t size[SUB_BUFFER_MAX]; int gttOffsetInPage = 0; bool ret; int err; int i; CTRACE(); // get virtual address err = mIMGGrallocModule.getCpuAddress(&mIMGGrallocModule, (buffer_handle_t)getHandle(), vaddr, size); if (err) { ELOGTRACE("failed to map. err = %d", err); return false; } for (i = 0; i < SUB_BUFFER_MAX; i++) { // skip gtt mapping for empty sub buffers if (!vaddr[i] || !size[i]) continue; // map to gtt ret = gttMap(vaddr[i], size[i], 0, >tOffsetInPage); if (!ret) { VLOGTRACE("failed to map %d into gtt", i); break; } mCpuAddress[i] = vaddr[i]; mSize[i] = size[i]; mGttOffsetInPage[i] = gttOffsetInPage; // TODO: set kernel handle mKHandle[i] = 0; } if (i == SUB_BUFFER_MAX) { return true; } // error handling for (i = 0; i < SUB_BUFFER_MAX; i++) { if (mCpuAddress[i]) { gttUnmap(mCpuAddress[i]); } } err = mIMGGrallocModule.putCpuAddress(&mIMGGrallocModule, (buffer_handle_t)getHandle()); return false; }
bool Hwcomposer::setActiveConfig(int disp, int index) { RETURN_FALSE_IF_NOT_INIT(); if (disp != 0) { ELOGTRACE("invalid disp %d", disp); // return false; } // return device->setActiveConfig(index); return true; }
int Hwcomposer::getActiveConfig(int disp) { RETURN_NULL_IF_NOT_INIT(); if (disp != 0) { ELOGTRACE("invalid disp %d", disp); return -1; } // return device->getActiveConfig(); return 0; }
bool Hwcomposer::setPowerMode(int disp, int mode) { RETURN_FALSE_IF_NOT_INIT(); if (disp != 0) { ELOGTRACE("invalid disp %d", disp); // return false; } // return device->setPowerMode(mode); return true; }
bool TngGrallocBufferMapper::mapKhandle() { // TODO: this is a complete hack and temporary workaround // need support from DDK to map khandle void *wsbmBufferObject = 0; int ret = psbWsbmWrapTTMBuffer2(mHandle, &wsbmBufferObject); if (ret != 0) { ELOGTRACE("Wrap ttm buffer failed!"); return false; } ret = psbWsbmCreateFromUB(wsbmBufferObject, mWidth * mHeight, mCpuAddress[0]); if (ret != 0) { ELOGTRACE("Create from UB failed!"); return false; } mKHandle[0] = psbWsbmGetKBufHandle(wsbmBufferObject); psbWsbmUnReference(wsbmBufferObject); return true; }