|
@@ -818,15 +818,16 @@ void la_PerfDraw(){
|
|
|
}
|
|
|
|
|
|
laScreen* la_EnsureScreen(char* Name, int mmw, int mmh, int x, int y, int w, int h,int dpi){ if(!Name || !Name[0]) return 0;
|
|
|
+ laScreen* uses=0;
|
|
|
for(laScreen* s=MAIN.Screens.pFirst;s;s=s->Item.pNext){
|
|
|
- if(strSame(SSTR(s->Name),Name)){ s->x=x;s->y=y;s->w=w;s->h=h; return s; }
|
|
|
+ if(strSame(SSTR(s->Name),Name)){ s->x=x;s->y=y;s->w=w;s->h=h; uses=s; break; }
|
|
|
}
|
|
|
- laScreen* s=memAcquire(sizeof(laScreen)); lstAppendItem(&MAIN.Screens,s);
|
|
|
- strSafeSet(&s->Name,Name);
|
|
|
- strSafePrint(&s->Description,"%dmm x %dmm with %dx%d ~%ddpi",mmw,mmh,w,h,dpi); s->RoughDPI=dpi;
|
|
|
- s->x=x;s->y=y;s->w=w;s->h=h;
|
|
|
+ if(!uses){ uses=memAcquire(sizeof(laScreen)); lstAppendItem(&MAIN.Screens,uses); }
|
|
|
+ strSafeSet(&uses->Name,Name); strSafeDestroy(&uses->Description);
|
|
|
+ strSafePrint(&uses->Description,"%dmm x %dmm with %dx%d ~%ddpi",mmw,mmh,w,h,dpi); uses->RoughDPI=dpi;
|
|
|
+ uses->x=x;uses->y=y;uses->w=w;uses->h=h;
|
|
|
laNotifyUsers("la.user_preferences.screens");
|
|
|
- return s;
|
|
|
+ return uses;
|
|
|
}
|
|
|
void la_RemoveScreen(laScreen*s){
|
|
|
strSafeDestroy(&s->Description); strSafeDestroy(&s->Name);
|
|
@@ -852,7 +853,84 @@ laScreen* laGetWindowScreen(laWindow* w){
|
|
|
return maxs;
|
|
|
}
|
|
|
|
|
|
+void la_EnsureScreenColorMatrix(laScreen* s){
|
|
|
+ real* usemat; tnsMatrix44d mat,matinv;
|
|
|
+ if(s->whitepoint[0]==0.0f || s->primaries[0]==0.0f || s->gamma==0.0f){
|
|
|
+ logPrint(" Fallback to sRGB configurations\n");
|
|
|
+ s->gamma=2.2;
|
|
|
+ static const tnsMatrix44d srgbmat={3.2404542,-1.5371385,-0.4985314,
|
|
|
+ -0.9692660,1.8760108,0.0415560,
|
|
|
+ 0.0556434,-0.2040259,1.0572252};
|
|
|
+ usemat=srgbmat;
|
|
|
+ }else{
|
|
|
+ tnsComputeMatrixRGB2XYZ(mat,&s->primaries[0],&s->primaries[2],&s->primaries[4],s->whitepoint);
|
|
|
+ tnsInverse33d(matinv,mat); usemat=matinv;
|
|
|
+ }
|
|
|
+ for(int i=0;i<9;i++){ s->xyz2rgb[i]=usemat[i]; }
|
|
|
+}
|
|
|
+void la_UseWindowColorCorrection(laWindow* w){
|
|
|
+ if(w->OutputColorSpace==255){
|
|
|
+ if(!w->WhichScreen){ memAssignRef(w,&w->WhichScreen,laGetWindowScreen(w)); }
|
|
|
+ if(w->WhichScreen){
|
|
|
+ tnsUniformOutputColorCorrection(T->immShader,w->WhichScreen->gamma, w->WhichScreen->xyz2rgb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#define EDID_MAX_SIZE 256
|
|
|
#ifdef LA_LINUX
|
|
|
+void la_TryGettingEDIDColors(XRROutputInfo* output, laScreen* s){
|
|
|
+ if(s->gamma!=0){ return; }
|
|
|
+ Atom edid_atom = XInternAtom(MAIN.dpy, "EDID", True);
|
|
|
+ if (edid_atom != None) {
|
|
|
+ unsigned char *edid_data = NULL;
|
|
|
+ Atom actual_type;
|
|
|
+ int actual_format;
|
|
|
+ unsigned long nitems, bytes_after;
|
|
|
+
|
|
|
+ if (XRRGetOutputProperty(MAIN.dpy, output, edid_atom, 0, EDID_MAX_SIZE,
|
|
|
+ False, False, AnyPropertyType, &actual_type, &actual_format,
|
|
|
+ &nitems, &bytes_after, &edid_data) == Success &&
|
|
|
+ edid_data && nitems > 0) {
|
|
|
+ logPrint(" %d bytes of EDID data is available\n",nitems);
|
|
|
+ real gamma = edid_data[23]==255?0.0f:((real)(edid_data[23]+100))/100.0f;
|
|
|
+ uint8_t rx_low = (edid_data[0x19] >> 6) & 0x03;
|
|
|
+ uint8_t ry_low = (edid_data[0x19] >> 4) & 0x03;
|
|
|
+ uint8_t gx_low = (edid_data[0x19] >> 2) & 0x03;
|
|
|
+ uint8_t gy_low = edid_data[0x19] & 0x03;
|
|
|
+ uint8_t bx_low = (edid_data[0x1A] >> 6) & 0x03;
|
|
|
+ uint8_t by_low = (edid_data[0x1A] >> 4) & 0x03;
|
|
|
+ uint8_t wx_low = (edid_data[0x1A] >> 2) & 0x03;
|
|
|
+ uint8_t wy_low = edid_data[0x1A] & 0x03;
|
|
|
+ double red_x = ((edid_data[0x1B] << 2) | rx_low) / 1024.0;
|
|
|
+ double red_y = ((edid_data[0x1C] << 2) | ry_low) / 1024.0;
|
|
|
+ double green_x = ((edid_data[0x1D] << 2) | gx_low) / 1024.0;
|
|
|
+ double green_y = ((edid_data[0x1E] << 2) | gy_low) / 1024.0;
|
|
|
+ double blue_x = ((edid_data[0x1F] << 2) | bx_low) / 1024.0;
|
|
|
+ double blue_y = ((edid_data[0x20] << 2) | by_low) / 1024.0;
|
|
|
+ double white_x = ((edid_data[0x21] << 2) | wx_low) / 1024.0;
|
|
|
+ double white_y = ((edid_data[0x22] << 2) | wy_low) / 1024.0;
|
|
|
+ s->gamma=gamma;
|
|
|
+ s->primaries[0]=red_x; s->primaries[1]=red_y;
|
|
|
+ s->primaries[2]=green_x; s->primaries[3]=green_y;
|
|
|
+ s->primaries[4]=blue_x; s->primaries[5]=blue_y;
|
|
|
+ s->whitepoint[0]=white_x; s->whitepoint[1]=white_y;
|
|
|
+ laSafeString* additional=0; strSafePrint(&additional,"\n"
|
|
|
+ " Gamma: %0.4f\n"
|
|
|
+ " Primaries:\n"
|
|
|
+ " (%04lf, %04lf)\n"
|
|
|
+ " (%04lf, %04lf)\n"
|
|
|
+ " (%04lf, %04lf)\n"
|
|
|
+ " White point:\n"
|
|
|
+ " (%04lf, %04lf)\n", gamma, LA_COLOR3(s->primaries),LA_COLOR3(&s->primaries[3]),s->whitepoint[0],s->whitepoint[1]);
|
|
|
+ //strSafeAppend(&s->Description,SSTR(additional));
|
|
|
+ logPrint("Color calibration info:%s",SSTR(additional));
|
|
|
+ strSafeDestroy(&additional);
|
|
|
+ XFree(edid_data);
|
|
|
+ la_EnsureScreenColorMatrix(s); if(!s->ColorSpace)s->ColorSpace=255;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
int la_GetDPI(Window* root_win){
|
|
|
XRRScreenResources *screen;
|
|
|
XRROutputInfo *info;
|
|
@@ -863,12 +941,13 @@ int la_GetDPI(Window* root_win){
|
|
|
screen=XRRGetScreenResources(MAIN.dpy, root_win);
|
|
|
for(iscres=0;iscres<screen->noutput;iscres++){
|
|
|
info=XRRGetOutputInfo(MAIN.dpy,screen,screen->outputs[iscres]);
|
|
|
- if(!info->mm_width || !info->mm_height){ continue; }
|
|
|
- logPrint(" Xrandr reported output size: %dmm x %dmm\n",info->mm_width,info->mm_height);
|
|
|
+ if(!info->mm_width || !info->mm_height || info->connection!=RR_Connected){ continue; }
|
|
|
+ logPrint(" Output size: %dmm x %dmm\n",info->mm_width,info->mm_height);
|
|
|
crtc=XRRGetCrtcInfo(MAIN.dpy,screen,info->crtc);
|
|
|
dpi=(real)crtc->width/(real)info->mm_width*25.4;
|
|
|
logPrint(" CRTC: %d x %d, around %ddpi\n",crtc->width,crtc->height,dpi);
|
|
|
laScreen* s=la_EnsureScreen(info->name,info->mm_width,info->mm_height,crtc->x,crtc->y,crtc->width,crtc->height,dpi);
|
|
|
+ la_TryGettingEDIDColors(screen->outputs[iscres],s);
|
|
|
XRRFreeCrtcInfo(crtc);
|
|
|
//if(info->connection==RR_Connected){
|
|
|
// for (icrtc=0;icrtc<info->ncrtc;icrtc++) {
|
|
@@ -878,6 +957,12 @@ int la_GetDPI(Window* root_win){
|
|
|
// }
|
|
|
//}
|
|
|
XRRFreeOutputInfo(info);
|
|
|
+
|
|
|
+ //real primaries[6]={0.64, 0.33, 0.3, 0.6, 0.15, 0.06};
|
|
|
+ //real white[2]={0.3127, 0.3290};
|
|
|
+ //tnsMatrix44d mat;
|
|
|
+ //tnsComputeMatrixRGB2XYZ(mat,&primaries[0],&primaries[2],&primaries[4],white);
|
|
|
+ //for(int i=0;i<9;i++){ printf("%lf ",mat[i]); } printf("\n");
|
|
|
}
|
|
|
XRRFreeScreenResources(screen);
|
|
|
return dpi;
|
|
@@ -1974,9 +2059,9 @@ void la_CommandResizeWindow(SYSWINDOW hwnd, int x, int y, int w, int h){
|
|
|
window->W = rcw.right - rcw.left;
|
|
|
window->H = rcw.bottom - rcw.top;
|
|
|
window->X = rcw.left; window->Y = rcw.top;
|
|
|
- if (MAIN.AutoSwitchColorSpace) {
|
|
|
- laScreen* s = laGetWindowScreen(window);
|
|
|
- if (s) { window->OutputColorSpace = s->ColorSpace; }
|
|
|
+ if (MAIN.AutoSwitchColorSpace || window->OutputColorSpace==255) {
|
|
|
+ memAssignRef(window,&window->WhichScreen, laGetWindowScreen(window));
|
|
|
+ if (window->WhichScreen && MAIN.AutoSwitchColorSpace) { window->OutputColorSpace = window->WhichScreen->ColorSpace; }
|
|
|
}
|
|
|
#endif
|
|
|
#ifdef LA_LINUX
|
|
@@ -1985,9 +2070,9 @@ void la_CommandResizeWindow(SYSWINDOW hwnd, int x, int y, int w, int h){
|
|
|
window->CW = w; window->CH = h;
|
|
|
window->W = w; window->H = h;
|
|
|
window->X = x; window->Y = y;
|
|
|
- if(MAIN.AutoSwitchColorSpace){
|
|
|
- laScreen* s = laGetWindowScreen(window);
|
|
|
- if(s){ window->OutputColorSpace = s->ColorSpace; }
|
|
|
+ if(MAIN.AutoSwitchColorSpace || window->OutputColorSpace==255){
|
|
|
+ memAssignRef(window,&window->WhichScreen, laGetWindowScreen(window));
|
|
|
+ if(window->WhichScreen && MAIN.AutoSwitchColorSpace){ window->OutputColorSpace = window->WhichScreen->ColorSpace; }
|
|
|
}
|
|
|
#endif
|
|
|
la_UpdateUiPlacement(window);
|
|
@@ -2688,6 +2773,7 @@ void la_PanelDrawToWindow(laPanel *p, laWindow *w){
|
|
|
tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);
|
|
|
tnsUniformShowColorOverflowStripes(T->immShader,w->OutputShowStripes);
|
|
|
tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint,w->OutputProofing);
|
|
|
+ la_UseWindowColorCorrection(w);
|
|
|
}else{
|
|
|
tnsUniformOutputColorSpace(T->immShader,0);
|
|
|
tnsUniformShowColorOverflowStripes(T->immShader,0);
|
|
@@ -3089,6 +3175,7 @@ void la_BlockDefDrawSelf(laBlock *b, int CH){
|
|
|
laWindow* w=MAIN.CurrentWindow;
|
|
|
tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);
|
|
|
tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint,w->OutputProofing);
|
|
|
+ la_UseWindowColorCorrection(w);
|
|
|
}else{
|
|
|
tnsUniformOutputColorSpace(T->immShader,0);
|
|
|
tnsUniformColorComposing(T->immShader,0,0,0,0);
|
|
@@ -3150,6 +3237,7 @@ void la_BlockDefDrawSelfEmpty(laBlock *b, int CH){
|
|
|
laWindow* w=MAIN.CurrentWindow;
|
|
|
tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);
|
|
|
tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint,w->OutputProofing);
|
|
|
+ la_UseWindowColorCorrection(w);
|
|
|
}else{
|
|
|
tnsUniformOutputColorSpace(T->immShader,0);
|
|
|
tnsUniformColorComposing(T->immShader,0,0,0,0);
|
|
@@ -3304,6 +3392,7 @@ void la_WindowDefDraw(laWindow *w, laBoxedTheme *bt){
|
|
|
if(MAIN.EnableColorManagement){
|
|
|
tnsUniformOutputColorSpace(T->immShader,w->OutputColorSpace);
|
|
|
tnsUniformColorComposing(T->immShader,w->UseComposing,w->ComposingGamma,w->ComposingBlackpoint,w->OutputProofing);
|
|
|
+ la_UseWindowColorCorrection(w);
|
|
|
}else{
|
|
|
tnsUniformOutputColorSpace(T->immShader,0);
|
|
|
tnsUniformColorComposing(T->immShader,0,0,0,0);
|