static void psb_xrandr_hdmi_property(VADriverContextP ctx) { INIT_DRIVER_DATA; Atom *props; Atom actual_type; XRRPropertyInfo *propinfo; int i, nprop, actual_format; unsigned long nitems, bytes_after; char* prop_name; unsigned char* prop; /* Check HDMI properties */ props = XRRListOutputProperties(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, &nprop); if (!props) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: XRRListOutputProperties failed\n", psb_xrandr_info->extend_output->output_id); return; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: extend output %08x has %d properties\n", psb_xrandr_info->extend_output->output_id, nprop); for (i = 0; i < nprop; i++) { XRRGetOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i], 0, 100, False, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); propinfo = XRRQueryOutputProperty(psb_xrandr_info->dpy, psb_xrandr_info->extend_output->output_id, props[i]); if (!propinfo) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Xrandr: get output %08x prop %08x failed\n", psb_xrandr_info->extend_output->output_id, props[i]); return; } prop_name = XGetAtomName(psb_xrandr_info->dpy, props[i]); /* Currently all properties are XA_INTEGER, 32 */ if (!strcmp(prop_name, "ExtVideoMode")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode); } else if (!strcmp(prop_name, "ExtVideoMode_Xres")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_XRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_XRes); } else if (!strcmp(prop_name, "ExtVideoMode_Yres")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_YRes (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_YRes); } else if (!strcmp(prop_name, "ExtVideoMode_X_Offset")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_X_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_X_Offset); } else if (!strcmp(prop_name, "ExtVideoMode_Y_Offset")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Y_Offset (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Y_Offset); } else if (!strcmp(prop_name, "ExtVideoMode_Center")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_Center (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_Center); } else if (!strcmp(prop_name, "ExtVideoMode_SubTitle")) { psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtVideoMode_SubTitle (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtVideoMode_SubTitle); } else if (!strcmp(prop_name, "ExtDesktopMode")) { if ((psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode != EXTENDEDVIDEO) && ((int)((INT32*)prop)[0] == EXTENDEDVIDEO)) { driver_data->xrandr_dirty |= PSB_NEW_EXTVIDEO; } psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: ExtDesktopMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->ExtDesktopMode); } else if (!strcmp(prop_name, "OverscanMode")) { psb_xrandr_info->hdmi_extvideo_prop->OverscanMode = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: OverscanMode (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->OverscanMode); } else if (!strcmp(prop_name, "PANELFITTING")) { psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING = (int)((INT32*)prop)[0]; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Xrandr: PANELFITTING (%08x)\n", psb_xrandr_info->hdmi_extvideo_prop->PANELFITTING); } } }
OutputConfiguration getOutputConfiguration(Display* display,int screen,const char* outputName) { /* Use the display's default screen if the given screen index is invalid: */ bool matchScreen=screen>=0; if(screen<0) screen=DefaultScreen(display); /* Create a default output configuration by assuming the entire root window goes to a single output: */ OutputConfiguration result; result.screen=screen; result.sizeMm[0]=DisplayWidthMM(display,screen); result.sizeMm[1]=DisplayHeightMM(display,screen); result.domainOrigin[0]=0; result.domainOrigin[1]=0; result.domainSize[0]=DisplayWidth(display,screen); result.domainSize[1]=DisplayHeight(display,screen); result.frameInterval=0U; // Unknown frame rate #if VRUI_INTERNAL_CONFIG_HAVE_XRANDR /* Check if the X server on the other end of the display connection understands XRANDR version >= 1.2: */ int xrandrEventBase,xrandrErrorBase; if(!XRRQueryExtension(display,&xrandrEventBase,&xrandrErrorBase)) return result; int xrandrMajor,xrandrMinor; if(!XRRQueryVersion(display,&xrandrMajor,&xrandrMinor)||xrandrMajor<1||(xrandrMajor==1&&xrandrMinor<2)) return result; /* Query the display name if in verbose mode: */ std::string displayName; if(vruiVerbose) { displayName=DisplayString(display); bool haveColon=false; std::string::iterator dotIt=displayName.end(); for(std::string::iterator dnIt=displayName.begin();dnIt!=displayName.end();++dnIt) if(*dnIt==':') haveColon=true; else if(haveColon&&*dnIt=='.') dotIt=dnIt; displayName.erase(dotIt,displayName.end()); } /* Iterate through all X screens belonging to the X display connection: */ bool firstOutput=true; bool haveMatch=false; for(int testScreen=0;testScreen<XScreenCount(display)&&(!haveMatch||vruiVerbose);++testScreen) if(!matchScreen||testScreen==screen) { /* Get the screen's resources: */ XRRScreenResources* screenResources=XRRGetScreenResources(display,RootWindow(display,testScreen)); if(screenResources!=0) { /* Find the first CRT controller that has an output of the given name: */ for(int crtcIndex=0;crtcIndex<screenResources->ncrtc&&(!haveMatch||vruiVerbose);++crtcIndex) { /* Get the CRT controller's information structure: */ XRRCrtcInfo* crtcInfo=XRRGetCrtcInfo(display,screenResources,screenResources->crtcs[crtcIndex]); if(crtcInfo!=0) { /* Find the specification of the CRT controller's current mode: */ unsigned int frameInterval=0U; for(int modeIndex=0;modeIndex<screenResources->nmode;++modeIndex) { XRRModeInfo& mode=screenResources->modes[modeIndex]; if(mode.id==crtcInfo->mode) { #if 0 /* Dump full modeline of detected CRT controller: */ std::cout<<"\tModeline: "<<mode.dotClock<<' '<<mode.width<<' '<<mode.hSyncStart<<' '<<mode.hSyncEnd<<' '<<mode.hTotal<<' '<<mode.hSkew; std::cout<<' '<<mode.height<<' '<<mode.vSyncStart<<' '<<mode.vSyncEnd<<' '<<mode.vTotal<<std::endl; #endif /* Calculate CRT controller's frame interval: */ frameInterval=(unsigned int)(((unsigned long)(mode.hTotal*mode.vTotal)*1000000000UL+mode.dotClock/2)/mode.dotClock); } } /* Try all outputs driven by the CRT controller: */ for(int outputIndex=0;outputIndex<crtcInfo->noutput&&(!haveMatch||vruiVerbose);++outputIndex) { /* Get the output's information structure: */ XRROutputInfo* outputInfo=XRRGetOutputInfo(display,screenResources,crtcInfo->outputs[outputIndex]); if(vruiVerbose&&outputName!=0&&outputName[0]!='\0') { std::cout<<"\tFound output "<<outputInfo->name<<" on display "<<displayName<<'.'<<testScreen; std::cout<<" at "<<crtcInfo->width<<'x'<<crtcInfo->height<<'+'<<crtcInfo->x<<'+'<<crtcInfo->y; std::cout<<" @ "<<1000000000.0/double(frameInterval)<<"Hz ("<<frameInterval<<")"<<std::endl; } /* Check if this output matches the search parameter: */ bool matchesName=strcmp(outputInfo->name,outputName)==0; if(!matchesName||vruiVerbose) { /* Check if the output has an associated EDID property: */ int numProperties; Atom* properties=XRRListOutputProperties(display,crtcInfo->outputs[outputIndex],&numProperties); for(int propertyIndex=0;propertyIndex<numProperties;++propertyIndex) { char* propertyName=XGetAtomName(display,properties[propertyIndex]); if(strcasecmp(propertyName,"EDID")==0) { Atom propertyType; int propertyFormat; unsigned long numItems; unsigned long bytes_after; unsigned char* propertyValue; XRRGetOutputProperty(display,crtcInfo->outputs[outputIndex],properties[propertyIndex],0,100,False,False,AnyPropertyType,&propertyType,&propertyFormat,&numItems,&bytes_after,&propertyValue); if(propertyType==XA_INTEGER&&propertyFormat==8) { /* Check the EDID's checksum and header ID: */ unsigned char checksum=0; for(unsigned long i=0;i<numItems;++i) checksum+=propertyValue[i]; unsigned char edidHeaderId[8]={0x00U,0xffU,0xffU,0xffU,0xffU,0xffU,0xffU,0x00U}; bool headerOk=true; for(int i=0;i<8&&headerOk;++i) headerOk=propertyValue[i]==edidHeaderId[i]; if(checksum==0&&headerOk) { /* Find the monitor name among the extension blocks: */ unsigned char* blockPtr=propertyValue+0x36; for(int i=0;i<4&&(!haveMatch||vruiVerbose);++i,blockPtr+=18) if(blockPtr[0]==0x00U&&blockPtr[1]==0x00U&&blockPtr[2]==0x00U&&blockPtr[3]==0xfcU) { /* Extract the monitor name: */ char monitorName[14]; char* mnPtr=monitorName; for(unsigned char* namePtr=blockPtr+5;namePtr<blockPtr+18&&*namePtr!='\n';++namePtr,++mnPtr) *mnPtr=char(*namePtr); *mnPtr='\0'; if(vruiVerbose&&outputName!=0&&outputName[0]!='\0') { std::cout<<"\tFound monitor "<<monitorName<<" on output "<<outputInfo->name<<" on display "<<displayName<<'.'<<testScreen; std::cout<<" at "<<crtcInfo->width<<'x'<<crtcInfo->height<<'+'<<crtcInfo->x<<'+'<<crtcInfo->y; std::cout<<" @ "<<1000000000.0/double(frameInterval)<<"Hz"<<std::endl; } matchesName=matchesName||strcmp(monitorName,outputName)==0; } } } XFree(propertyValue); } XFree(propertyName); } XFree(properties); } if(firstOutput||matchesName) { /* Remember the output's configuration: */ result.screen=testScreen; result.sizeMm[0]=outputInfo->mm_width; result.sizeMm[1]=outputInfo->mm_height; result.domainOrigin[0]=crtcInfo->x; result.domainOrigin[1]=crtcInfo->y; result.domainSize[0]=crtcInfo->width; result.domainSize[1]=crtcInfo->height; result.frameInterval=frameInterval; firstOutput=false; haveMatch=matchesName||outputName==0||outputName[0]=='\0'; } XRRFreeOutputInfo(outputInfo); } XRRFreeCrtcInfo(crtcInfo); } } XRRFreeScreenResources(screenResources); } } if(!haveMatch&&outputName!=0&&outputName[0]!='\0') std::cerr<<"\tOutput \""<<outputName<<"\" not found on display "<<DisplayString(display)<<std::endl; #endif /* Check the result configuration for sanity: */ if(result.sizeMm[0]==0||result.sizeMm[1]==0) { /* Assign a default display size based on a fixed and uniform resolution: */ int dpi=96; // Seems to be a reasonable number if(vruiVerbose) std::cout<<"\tSelected output advertises zero physical size; using default resolution of "<<dpi<<" dpi"<<std::endl; for(int i=0;i<2;++i) result.sizeMm[i]=(254*result.domainSize[i]+dpi*5)/(dpi*10); } return result; }