static gboolean output_initialize (MateRROutput *output, XRRScreenResources *res, GError **error) { XRROutputInfo *info = XRRGetOutputInfo ( DISPLAY (output), res, output->id); GPtrArray *a; int i; #if 0 g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp); #endif if (!info || !output->info) { /* FIXME: see the comment in crtc_initialize() */ /* Translators: here, an "output" is a video output */ g_set_error (error, MATE_RR_ERROR, MATE_RR_ERROR_RANDR_ERROR, _("could not get information about output %d"), (int) output->id); return FALSE; } output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */ output->current_crtc = crtc_by_id (output->info, info->crtc); output->width_mm = info->mm_width; output->height_mm = info->mm_height; output->connected = (info->connection == RR_Connected); output->connector_type = get_connector_type_string (output); /* Possible crtcs */ a = g_ptr_array_new (); for (i = 0; i < info->ncrtc; ++i) { MateRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]); if (crtc) g_ptr_array_add (a, crtc); } g_ptr_array_add (a, NULL); output->possible_crtcs = (MateRRCrtc **)g_ptr_array_free (a, FALSE); /* Clones */ a = g_ptr_array_new (); for (i = 0; i < info->nclone; ++i) { MateRROutput *mate_rr_output = mate_rr_output_by_id (output->info, info->clones[i]); if (mate_rr_output) g_ptr_array_add (a, mate_rr_output); } g_ptr_array_add (a, NULL); output->clones = (MateRROutput **)g_ptr_array_free (a, FALSE); /* Modes */ a = g_ptr_array_new (); for (i = 0; i < info->nmode; ++i) { MateRRMode *mode = mode_by_id (output->info, info->modes[i]); if (mode) g_ptr_array_add (a, mode); } g_ptr_array_add (a, NULL); output->modes = (MateRRMode **)g_ptr_array_free (a, FALSE); output->n_preferred = info->npreferred; /* Edid data */ output->edid_data = read_edid_data (output); XRRFreeOutputInfo (info); return TRUE; }
static int discoverExtendedRifts(OVR::DisplayDesc* descriptorArray, int inputArraySize, bool /*edidInfo*/) { int result = 0; if (X11Display == NULL) { OVR::LogError("[Linux Display] Unable to open X Display!"); return 0; } Atom EDIDAtom = XInternAtom(X11Display, RR_PROPERTY_RANDR_EDID, False); int numScreens = XScreenCount(X11Display); for (int i = 0; i < numScreens; ++i) { Window sr = XRootWindow(X11Display, i); XRRScreenResources* screen = XRRGetScreenResources(X11Display, sr); for (int ii = 0; ii < screen->ncrtc; ++ii) { XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(X11Display, screen, screen->crtcs[ii]); if (0 == crtcInfo->noutput) { XRRFreeCrtcInfo(crtcInfo); continue; } bool foundOutput = false; RROutput output = crtcInfo->outputs[0]; for (int k = 0; k < crtcInfo->noutput; ++k) { XRROutputInfo* outputInfo = XRRGetOutputInfo(X11Display, screen, crtcInfo->outputs[k]); for (int kk = 0; kk < outputInfo->nmode; ++kk) { if (outputInfo->modes[kk] == crtcInfo->mode) { output = crtcInfo->outputs[k]; foundOutput = true; break; } } XRRFreeOutputInfo(outputInfo); if (foundOutput) { break; } } if (!foundOutput) { XRRFreeCrtcInfo(crtcInfo); continue; } XRROutputInfo* outputInfo = XRRGetOutputInfo(X11Display, screen, output); if (RR_Connected != outputInfo->connection) { XRRFreeOutputInfo(outputInfo); XRRFreeCrtcInfo(crtcInfo); continue; } // Read EDID associated with crtc. uint8_t* data = NULL; int dataLen = 0; if (getXRRProperty(X11Display, output, EDIDAtom, &data, &dataLen) != 0) { // Identify rifts based on EDID. Linux::DisplayEDID edid; parseEdid(data, edid); XFree(data); data = NULL; // TODO: Remove either this 3rdParty call to read EDID data // or remove our own parsing of the EDID. Probably opt // to remove our parsing. MonitorInfo* mi = read_edid_data(X11Display, output); if (mi == NULL) { XRRFreeOutputInfo(outputInfo); XRRFreeCrtcInfo(crtcInfo); continue; } if (edid.VendorName == "OVR") { if( result >= inputArraySize ) { delete mi; XRRFreeOutputInfo(outputInfo); XRRFreeCrtcInfo(crtcInfo); return result; } XRRModeInfo* modeInfo = findModeByXID(screen, crtcInfo->mode); int width = modeInfo->width; int height = modeInfo->height; int x = crtcInfo->x; int y = crtcInfo->y; // Generate a device ID string similar Windows does it char device_id[32]; OVR_sprintf(device_id, 32, "%s%04d-%d", mi->manufacturer_code, mi->product_code, screen->crtcs[ii]); OVR::DisplayDesc& desc = descriptorArray[result++]; desc.ResolutionInPixels = Sizei(width, height); desc.DesktopDisplayOffset = Vector2i(x, y); strncpy(desc.DisplayID, device_id, sizeof(desc.DisplayID)-1); desc.DisplayID[sizeof(desc.DisplayID)-1] = 0; strncpy(desc.ModelName, edid.MonitorName, sizeof(desc.ModelName)-1); desc.ModelName[sizeof(desc.ModelName)-1] = 0; strncpy(desc.EdidSerialNumber, edid.SerialNumber, sizeof(desc.EdidSerialNumber)-1); desc.EdidSerialNumber[sizeof(desc.EdidSerialNumber)-1] = 0; bool tallScreen = (height > width); switch (crtcInfo->rotation) { default: desc.Rotation = tallScreen ? 270 : 0; break; case RR_Rotate_90: desc.Rotation = tallScreen ? 0 : 90; break; case RR_Rotate_180: desc.Rotation = tallScreen ? 90 : 180; break; case RR_Rotate_270: desc.Rotation = tallScreen ? 180 : 270; break; } switch (mi->product_code) { case 3: desc.DeviceTypeGuess = HmdType_DK2; break; case 2: desc.DeviceTypeGuess = HmdType_DKHDProto; break; case 1: desc.DeviceTypeGuess = HmdType_DK1; break; default: case 0: desc.DeviceTypeGuess = HmdType_Unknown; break; } // Hard-coded defaults in case the device doesn't have the // data itself. DK2 prototypes (0003) or DK HD Prototypes (0002). if ( desc.DeviceTypeGuess == HmdType_DK2 || desc.DeviceTypeGuess == HmdType_DKHDProto) { desc.ResolutionInPixels = Sizei(1920, 1080); } else { desc.ResolutionInPixels = Sizei(width, height); } } delete mi; mi = NULL; } else { XFree(data); } XRRFreeOutputInfo(outputInfo); XRRFreeCrtcInfo(crtcInfo); } XRRFreeScreenResources(screen); } return result; }