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; }
// 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::isConnected(int device) { Mutex::Autolock _l(mLock); int output = getOutputIndex(device); if (output < 0 ) { return false; } return mOutputs[output].connected; }
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; }
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; }
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 Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height) { 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; } width = output->connector->mmWidth; height = output->connector->mmHeight; return true; }
bool Drm::getDisplayResolution(int device, uint32_t& width, uint32_t& height) { 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; } width = output->mode.hdisplay; height = output->mode.vdisplay; if (!width || !height) { ELOGTRACE("invalid width or height"); return false; } return true; }
glong indic_ot_reorder(const gunichar *chars, const glong *utf8_offsets, glong char_count, const IndicOTClassTable *class_table, gunichar *out_chars, glong *char_indices, gulong *char_tags, MPreFixups **outMPreFixups) { MPreFixups *mpreFixups = NULL; Output output; glong i, prev = 0; gboolean last_in_word = FALSE; if (outMPreFixups && (class_table->scriptFlags & SF_MPRE_FIXUP)) { mpreFixups = indic_mprefixups_new (char_count); } initOutput(&output, utf8_offsets, out_chars, char_indices, char_tags, mpreFixups); while (prev < char_count) { glong syllable = indic_ot_find_syllable(class_table, chars, prev, char_count); glong matra, vmabove, vmpost = syllable; while (vmpost > prev && indic_ot_is_vm_post(class_table, chars[vmpost - 1])) { vmpost -= 1; } vmabove = vmpost; while (vmabove > prev && indic_ot_is_vm_above(class_table, chars[vmabove - 1])) { vmabove -= 1; } matra = vmabove - 1; initMatra(&output, prev, blwf_p, !last_in_word); while (noteMatra(&output, class_table, chars[matra]) && matra != prev) matra--; last_in_word = TRUE; switch (indic_ot_get_char_class(class_table, chars[prev]) & CF_CLASS_MASK) { case CC_RESERVED: last_in_word = FALSE; /* Fall through */ case CC_INDEPENDENT_VOWEL: case CC_ZERO_WIDTH_MARK: for (i = prev; i < syllable; i += 1) { writeChar(&output, chars[i], /*i*/ prev, blwf_p); } break; case CC_MODIFYING_MARK_ABOVE: case CC_MODIFYING_MARK_POST: case CC_NUKTA: case CC_VIRAMA: /* patch for rendering fix for Malayalam SAMVRUTHOKARA by suresh */ if (chars[prev - 1] == 0x0D41) { writeChar(&output, chars[prev], prev, blwf_p); break; } /* end patch */ case CC_AL_LAKUNA: writeChar(&output, C_DOTTED_CIRCLE, prev, blwf_p); writeChar(&output, chars[prev], prev, blwf_p); break; case CC_DEPENDENT_VOWEL: writeMpre(&output); writeChar(&output, C_DOTTED_CIRCLE, prev, blwf_p); writeMbelow(&output); writeMabove(&output); writeMpost(&output); writeLengthMark(&output); writeAlLakuna(&output); break; case CC_CONSONANT: case CC_CONSONANT_WITH_NUKTA: { guint32 length = vmabove - prev; glong lastConsonant = vmabove - 1; glong baseLimit = prev; glong baseConsonant, postBase, postBaseLimit; gboolean seenVattu, seenBelowBaseForm, supressVattu; glong bcSpan; /* Check for REPH at front of syllable */ if (length > 2 && indic_ot_is_reph(class_table, chars[prev]) && indic_ot_is_virama(class_table, chars[prev + 1])) { baseLimit += 2; /* Check for eyelash RA, if the script supports it */ if ((class_table->scriptFlags & SF_EYELASH_RA) != 0 && chars[baseLimit] == C_SIGN_ZWJ) { if (length > 3) { baseLimit += 1; } else { baseLimit -= 2; } } } while (lastConsonant > baseLimit && !indic_ot_is_consonant(class_table, chars[lastConsonant])) { lastConsonant -= 1; } baseConsonant = lastConsonant; postBase = lastConsonant + 1; postBaseLimit = class_table->scriptFlags & SF_POST_BASE_LIMIT_MASK; seenVattu = false; seenBelowBaseForm = false; supressVattu = true; while (baseConsonant > baseLimit) { IndicOTCharClass charClass = indic_ot_get_char_class(class_table, chars[baseConsonant]); if (IS_CONSONANT(charClass)) { if (postBaseLimit == 0 || seenVattu || (baseConsonant > baseLimit && !indic_ot_is_virama(class_table, chars[baseConsonant - 1])) || !HAS_POST_OR_BELOW_BASE_FORM(charClass)) { break; } seenVattu = IS_VATTU(charClass); if (HAS_POST_BASE_FORM(charClass)) { if (seenBelowBaseForm) { break; } postBase = baseConsonant; } else if (HAS_BELOW_BASE_FORM(charClass)) { seenBelowBaseForm = true; } postBaseLimit -= 1; } baseConsonant -= 1; } /* Write Mpre */ writeMpre(&output); /* Write eyelash RA */ /* NOTE: baseLimit == prev + 3 iff eyelash RA present... */ if (baseLimit == prev + 3) { writeChar(&output, chars[prev], prev, half_p); writeChar(&output, chars[prev + 1], prev /*+ 1*/, half_p); writeChar(&output, chars[prev + 2], prev /*+ 2*/, half_p); } /* write any pre-base consonants */ supressVattu = true; for (i = baseLimit; i < baseConsonant; i += 1) { gunichar ch = chars[i]; /* Applying blwf to the first consonant doesn't makes sense * since the below-form follows the consonant that it is * put under */ gulong tag = (i == baseLimit) ? half_p : blwf_p; IndicOTCharClass charClass = indic_ot_get_char_class(class_table, ch); if (IS_CONSONANT(charClass)) { if (IS_VATTU(charClass) && supressVattu) { tag = nukt_p; } else if ((i + 2 < baseConsonant) && (chars[i + 2] == C_SIGN_ZWNJ)) { tag = nukt_p; } supressVattu = IS_VATTU(charClass); } else if (IS_VIRAMA(charClass) && chars[i + 1] == C_SIGN_ZWNJ) { tag = nukt_p; } writeChar(&output, ch, /*i*/ prev, tag); } bcSpan = baseConsonant + 1; if (bcSpan < vmabove && indic_ot_is_nukta(class_table, chars[bcSpan])) { bcSpan += 1; } if (baseConsonant == lastConsonant && bcSpan < vmabove && indic_ot_is_virama(class_table, chars[bcSpan])) { bcSpan += 1; if (bcSpan < vmabove && chars[bcSpan] == C_SIGN_ZWNJ) { bcSpan += 1; } } /* note the base consonant for post-GSUB fixups */ noteBaseConsonant(&output); /* write base consonant */ for (i = baseConsonant; i < bcSpan; i += 1) { writeChar(&output, chars[i], /*i*/ prev, nukt_p); } if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) != 0) { gboolean is_for_0C48 = FALSE; if (output.fOutChars != NULL) { /*for 0x0C48 of Telugu*/ int t; for (t = prev; t < syllable; t++) { if (chars[t] == 0x0C48) { writeMabove(&output); writeMbelow(&output); writeMpost(&output); is_for_0C48 = TRUE; break; } } } if (!is_for_0C48) { writeMbelow(&output); writeMabove(&output); writeMpost(&output); } } /* write below-base consonants */ if (baseConsonant != lastConsonant) { for (i = bcSpan + 1; i < postBase; i += 1) { writeChar(&output, chars[i], /*i*/ prev, blwf_p); } if (postBase > lastConsonant) { /* write halant that was after base consonant */ writeChar(&output, chars[bcSpan], /*bcSpan*/ prev, blwf_p); } } /* write Mbelow, Mabove */ if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) == 0) { writeMbelow(&output); writeMabove(&output); } if ((class_table->scriptFlags & SF_REPH_AFTER_BELOW) != 0) { if (baseLimit == prev + 2) { writeChar(&output, chars[prev], prev, rphf_p); writeChar(&output, chars[prev + 1], prev /*+ 1*/, rphf_p); } /* write VMabove */ for (i = vmabove; i < vmpost; i += 1) { writeChar(&output, chars[i], /*i*/ prev, blwf_p); } } /* write post-base consonants */ if (baseConsonant != lastConsonant) { if (postBase <= lastConsonant) { for (i = postBase; i <= lastConsonant; i += 1) { writeChar(&output, chars[i], /*i*/ prev, pstf_p); } /* write halant that was after base consonant */ writeChar(&output, chars[bcSpan], /*bcSpan*/ prev, blwf_p); } /* write the training halant, if there is one */ if (lastConsonant < matra && indic_ot_is_virama(class_table, chars[matra])) { writeChar(&output, chars[matra], /*matra*/ prev, nukt_p); } } /* write Mpost */ if ((class_table->scriptFlags & SF_MATRAS_AFTER_BASE) == 0) { writeMpost(&output); } writeLengthMark(&output); writeAlLakuna(&output); /* write reph */ if ((class_table->scriptFlags & SF_REPH_AFTER_BELOW) == 0) { if (baseLimit == prev + 2) { writeChar(&output, chars[prev], prev, rphf_p); writeChar(&output, chars[prev + 1], prev /*+ 1*/, rphf_p); } /* write VMabove */ for (i = vmabove; i < vmpost; i += 1) { writeChar(&output, chars[i], /*i*/ prev, blwf_p); } } /* write VMpost */ for (i = vmpost; i < syllable; i += 1) { writeChar(&output, chars[i], /*i*/ prev, blwf_p); } break; } default: break; } prev = syllable; } if (outMPreFixups) { *outMPreFixups = mpreFixups; } return getOutputIndex(&output); }
bool Drm::detect(int device) { RETURN_FALSE_IF_NOT_INIT(); Mutex::Autolock _l(mLock); int outputIndex = getOutputIndex(device); if (outputIndex < 0 ) { return false; } resetOutput(outputIndex); // get drm resources drmModeResPtr resources = drmModeGetResources(mDrmFd); if (!resources) { ELOGTRACE("fail to get drm resources, error: %s", strerror(errno)); return false; } drmModeConnectorPtr connector = NULL; DrmOutput *output = &mOutputs[outputIndex]; bool ret = false; // find connector for the given device for (int i = 0; i < resources->count_connectors; i++) { if (!resources->connectors || !resources->connectors[i]) { ELOGTRACE("fail to get drm resources connectors, error: %s", strerror(errno)); continue; } connector = drmModeGetConnector(mDrmFd, resources->connectors[i]); if (!connector) { ELOGTRACE("drmModeGetConnector failed"); continue; } if (connector->connector_type != DrmConfig::getDrmConnector(device)) { drmModeFreeConnector(connector); continue; } if (connector->connection != DRM_MODE_CONNECTED) { ILOGTRACE("device %d is not connected", device); drmModeFreeConnector(connector); ret = true; break; } output->connector = connector; output->connected = true; // get proper encoder for the given connector if (connector->encoder_id) { ILOGTRACE("Drm connector has encoder attached on device %d", device); output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id); if (!output->encoder) { ELOGTRACE("failed to get encoder from a known encoder id"); // fall through to get an encoder } } if (!output->encoder) { ILOGTRACE("getting encoder for device %d", device); drmModeEncoderPtr encoder; for (int j = 0; j < resources->count_encoders; j++) { if (!resources->encoders || !resources->encoders[j]) { ELOGTRACE("fail to get drm resources encoders, error: %s", strerror(errno)); continue; } encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]); if (!encoder) { ELOGTRACE("drmModeGetEncoder failed"); continue; } if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) { output->encoder = encoder; break; } drmModeFreeEncoder(encoder); encoder = NULL; } } if (!output->encoder) { ELOGTRACE("failed to get drm encoder"); break; } // get an attached crtc or spare crtc if (output->encoder->crtc_id) { ILOGTRACE("Drm encoder has crtc attached on device %d", device); output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id); if (!output->crtc) { ELOGTRACE("failed to get crtc from a known crtc id"); // fall through to get a spare crtc } } if (!output->crtc) { ILOGTRACE("getting crtc for device %d", device); drmModeCrtcPtr crtc; for (int j = 0; j < resources->count_crtcs; j++) { if (!resources->crtcs || !resources->crtcs[j]) { ELOGTRACE("fail to get drm resources crtcs, error: %s", strerror(errno)); continue; } crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]); if (!crtc) { ELOGTRACE("drmModeGetCrtc failed"); continue; } // check if legal crtc to the encoder if (output->encoder->possible_crtcs & (1<<j)) { if (crtc->buffer_id == 0) { output->crtc = crtc; break; } } drmModeFreeCrtc(crtc); } } if (!output->crtc) { ELOGTRACE("failed to get drm crtc"); break; } // current mode if (output->crtc->mode_valid) { ILOGTRACE("mode is valid, kernel mode settings"); memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo)); //output->fbId = output->crtc->buffer_id; ret = true; } else { ELOGTRACE("mode is invalid. Kernel mode setting is not completed"); ret = false; } if (outputIndex == OUTPUT_PRIMARY) { if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) { ELOGTRACE("failed to get device %d orientation", device); output->panelOrientation = PANEL_ORIENTATION_0; } } else { output->panelOrientation = PANEL_ORIENTATION_0; } break; } if (!ret) { if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) { // a fatal failure on primary device // non fatal on secondary device WLOGTRACE("device %d is disabled?", device); ret = true; } resetOutput(outputIndex); } else if (output->connected) { ILOGTRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh); } drmModeFreeResources(resources); return ret; }