1 /*
2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include "jni_util.h"
27 #include "awt_p.h"
28 #include "awt.h"
29 #include "color.h"
30 #include <java_awt_DisplayMode.h>
31 #include <sun_awt_X11GraphicsEnvironment.h>
32 #include <sun_awt_X11GraphicsDevice.h>
33 #include <sun_awt_X11GraphicsConfig.h>
34 #ifndef HEADLESS
35 #include <X11/extensions/Xdbe.h>
36 #include <X11/XKBlib.h>
37 #ifndef _AIX
38 #include <X11/extensions/Xrandr.h>
39 #endif
40 #include "GLXGraphicsConfig.h"
41 #endif /* !HEADLESS */
42 
43 #include <jni.h>
44 #include <jni_util.h>
45 #include <jvm.h>
46 #include <jvm_md.h>
47 #include <jlong.h>
48 #include "systemScale.h"
49 #include <stdlib.h>
50 
51 #include "awt_GraphicsEnv.h"
52 #include "awt_util.h"
53 #include "gdefs.h"
54 #include <dlfcn.h>
55 #include "Trace.h"
56 
57 #ifdef NETSCAPE
58 #include <signal.h>
59 extern int awt_init_xt;
60 #endif
61 
62 #ifndef HEADLESS
63 
64 int awt_numScreens;     /* Xinerama-aware number of screens */
65 
66 AwtScreenDataPtr x11Screens;
67 
68 /*
69  * Set in initDisplay() to indicate whether we should attempt to initialize
70  * GLX for the default configuration.
71  */
72 static jboolean glxRequested = JNI_FALSE;
73 
74 #endif /* !HEADLESS */
75 
76 #ifdef HEADLESS
77 #define Display void
78 #endif /* HEADLESS */
79 
80 Display *awt_display;
81 
82 jclass tkClass = NULL;
83 jmethodID awtLockMID = NULL;
84 jmethodID awtUnlockMID = NULL;
85 jmethodID awtWaitMID = NULL;
86 jmethodID awtNotifyMID = NULL;
87 jmethodID awtNotifyAllMID = NULL;
88 jboolean awtLockInited = JNI_FALSE;
89 
90 /** Convenience macro for loading the lock-related method IDs. */
91 #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
92     do { \
93         method_id = (*env)->GetStaticMethodID(env, klass, \
94                                               method_name, method_sig); \
95         if (method_id == NULL) return NULL; \
96     } while (0)
97 
98 struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
99 struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs;
100 
101 #ifndef HEADLESS
102 int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata);
103 #endif /* HEADLESS */
104 
105 static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig";
106 
107 /* AWT and Xinerama
108  *
109  * As of fix 4356756, AWT is Xinerama-aware.  X11GraphicsDevices are created for
110  * each screen of a Xinerama setup, though X11 itself still only sees a single
111  * display.
112  * In many places where we talk to X11, a xinawareScreen variable is used to
113  * pass the correct Display value, depending on the circumstances (a single
114  * X display, multiple X displays, or a single X display with multiple
115  * Xinerama screens).
116  *
117  * Solaris and Linux differ in the functions used to access Xinerama-related
118  * data.  This is in part because at this time, the X consortium has not
119  * finalized the "official" Xinerama API.  Once this spec is available, and
120  * both OSes are conformant, one code base should be sufficient for Xinerama
121  * operation on both OSes.  Until then, some of the Xinerama-related code
122  * is ifdef'd appropriately.  -bchristi, 7/12/01
123  */
124 
125 #define MAXFRAMEBUFFERS 16
126 #if defined(__solaris__)
127 typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
128          XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
129          int* num_framebuffers);
130 typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number,
131                                          int* x, int* y);
132 
133 XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL;
134 #else /* Linux, Mac, AIX */
135 typedef struct {
136    int   screen_number;
137    short x_org;
138    short y_org;
139    short width;
140    short height;
141 } XineramaScreenInfo;
142 
143 typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
144 #endif
145 
146 Bool usingXinerama = False;
147 XRectangle fbrects[MAXFRAMEBUFFERS];
148 
149 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_initIDs(JNIEnv * env,jclass cls)150 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
151 {
152     x11GraphicsConfigIDs.aData = NULL;
153     x11GraphicsConfigIDs.bitsPerPixel = NULL;
154     x11GraphicsConfigIDs.screen = NULL;
155 
156     x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");
157     CHECK_NULL(x11GraphicsConfigIDs.aData);
158     x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");
159     CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel);
160     x11GraphicsConfigIDs.screen = (*env)->GetFieldID (env, cls, "screen", "Lsun/awt/X11GraphicsDevice;");
161     CHECK_NULL(x11GraphicsConfigIDs.screen);
162 
163     if (x11GraphicsConfigIDs.aData == NULL ||
164             x11GraphicsConfigIDs.bitsPerPixel == NULL ||
165         x11GraphicsConfigIDs.screen == NULL) {
166 
167             JNU_ThrowNoSuchFieldError(env, "Can't find a field");
168             return;
169         }
170 }
171 
172 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_initIDs(JNIEnv * env,jclass cls)173 Java_sun_awt_X11GraphicsDevice_initIDs (JNIEnv *env, jclass cls)
174 {
175     x11GraphicsDeviceIDs.screen = NULL;
176     x11GraphicsDeviceIDs.screen = (*env)->GetFieldID (env, cls, "screen", "I");
177     DASSERT(x11GraphicsDeviceIDs.screen);
178 }
179 
180 #ifndef HEADLESS
181 
182 /*
183  * XIOErrorHandler
184  */
xioerror_handler(Display * disp)185 static int xioerror_handler(Display *disp)
186 {
187     if (awtLockInited) {
188         if (errno == EPIPE) {
189             jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));
190         }
191         /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */
192     }
193     return 0;
194 }
195 
196 static AwtGraphicsConfigDataPtr
findWithTemplate(XVisualInfo * vinfo,long mask)197 findWithTemplate(XVisualInfo *vinfo,
198                  long mask)
199 {
200 
201     XVisualInfo *visualList;
202     XColor color;
203     AwtGraphicsConfigDataPtr defaultConfig;
204     int visualsMatched, i;
205 
206     visualList = XGetVisualInfo(awt_display,
207                                 mask, vinfo, &visualsMatched);
208     if (visualList) {
209         int id = -1;
210         VisualID defaultVisual = XVisualIDFromVisual(DefaultVisual(awt_display, vinfo->screen));
211         defaultConfig = ZALLOC(_AwtGraphicsConfigData);
212         if (defaultConfig == NULL) {
213             XFree(visualList);
214             return NULL;
215         }
216         for (i = 0; i < visualsMatched; i++) {
217             memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo));
218             defaultConfig->awt_depth = visualList[i].depth;
219 
220             /* we can't use awtJNI_CreateColorData here, because it'll pull,
221                SystemColor, which in turn will cause toolkit to be reinitialized */
222             if (awtCreateX11Colormap(defaultConfig)) {
223                 if (visualList[i].visualid == defaultVisual) {
224                     id = i;
225                     break;
226                 } else if (-1 == id) {
227                     // Keep 1st match for fallback
228                     id = i;
229                 }
230             }
231         }
232         if (-1 != id) {
233             memcpy(&defaultConfig->awt_visInfo, &visualList[id], sizeof(XVisualInfo));
234             defaultConfig->awt_depth = visualList[id].depth;
235             /* Allocate white and black pixels for this visual */
236             color.flags = DoRed | DoGreen | DoBlue;
237             color.red = color.green = color.blue = 0x0000;
238             XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
239             x11Screens[visualList[id].screen].blackpixel = color.pixel;
240             color.flags = DoRed | DoGreen | DoBlue;
241             color.red = color.green = color.blue = 0xffff;
242             XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
243             x11Screens[visualList[id].screen].whitepixel = color.pixel;
244 
245             XFree(visualList);
246             return defaultConfig;
247         }
248         XFree(visualList);
249         free((void *)defaultConfig);
250     }
251     return NULL;
252 }
253 
254 /* default config is based on X11 screen.  All Xinerama screens of that X11
255    screen will have the same default config */
256 /* Need more notes about which fields of the structure are based on the X
257    screen, and which are based on the Xinerama screen */
258 static AwtGraphicsConfigDataPtr
makeDefaultConfig(JNIEnv * env,int screen)259 makeDefaultConfig(JNIEnv *env, int screen) {
260 
261     AwtGraphicsConfigDataPtr defaultConfig;
262     int xinawareScreen = 0;
263     VisualID forcedVisualID = 0, defaultVisualID;
264     char *forcedVisualStr;
265     XVisualInfo vinfo;
266     long mask;
267 
268     xinawareScreen = usingXinerama ? 0 : screen;
269     defaultVisualID =
270         XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen));
271 
272     memset(&vinfo, 0, sizeof(XVisualInfo));
273     vinfo.screen = xinawareScreen;
274 
275     if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {
276         mask = VisualIDMask | VisualScreenMask;
277         if (sscanf(forcedVisualStr, "%lx", &forcedVisualID) > 0 &&
278             forcedVisualID > 0)
279         {
280             vinfo.visualid = forcedVisualID;
281         } else {
282             vinfo.visualid = defaultVisualID;
283         }
284     } else {
285         VisualID bestGLXVisualID;
286         if (glxRequested &&
287             (bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0)
288         {
289             /* we've found the best visual for use with GLX, so use it */
290             vinfo.visualid = bestGLXVisualID;
291             mask = VisualIDMask | VisualScreenMask;
292         } else {
293             /* otherwise, continue looking for the best X11 visual */
294             vinfo.depth = 24;
295             vinfo.class = TrueColor;
296             mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
297         }
298     }
299 
300     /* try the best, or forced visual */
301     defaultConfig = findWithTemplate(&vinfo, mask);
302     if (defaultConfig) {
303         return defaultConfig;
304     }
305 
306     /* try the default visual */
307     vinfo.visualid = defaultVisualID;
308     mask = VisualIDMask | VisualScreenMask;
309     defaultConfig = findWithTemplate(&vinfo, mask);
310     if (defaultConfig) {
311         return defaultConfig;
312     }
313 
314     /* try any TrueColor */
315     vinfo.class = TrueColor;
316     mask = VisualScreenMask | VisualClassMask;
317     defaultConfig = findWithTemplate(&vinfo, mask);
318     if (defaultConfig) {
319         return defaultConfig;
320     }
321 
322     /* try 8-bit PseudoColor */
323     vinfo.depth = 8;
324     vinfo.class = PseudoColor;
325     mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
326     defaultConfig = findWithTemplate(&vinfo, mask);
327     if (defaultConfig) {
328         return defaultConfig;
329     }
330 
331     /* try any 8-bit */
332     vinfo.depth = 8;
333     mask = VisualDepthMask | VisualScreenMask;
334     defaultConfig = findWithTemplate(&vinfo, mask);
335     if (defaultConfig) {
336         return defaultConfig;
337     }
338 
339     /* we tried everything, give up */
340     JNU_ThrowInternalError(env, "Can't find supported visual");
341     XCloseDisplay(awt_display);
342     awt_display = NULL;
343     return NULL;
344 }
345 
346 static void
getAllConfigs(JNIEnv * env,int screen,AwtScreenDataPtr screenDataPtr)347 getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
348 
349     int i;
350     int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0;
351     int nConfig;
352     XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs,
353                 *pVI8sg, *pVI1sg = NULL, viTmp;
354     AwtGraphicsConfigDataPtr *graphicsConfigs;
355     AwtGraphicsConfigDataPtr defaultConfig;
356     int ind;
357     char errmsg[128];
358     int xinawareScreen;
359     void* xrenderLibHandle = NULL;
360     XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL;
361     int major_opcode, first_event, first_error;
362 
363     if (usingXinerama) {
364         xinawareScreen = 0;
365     }
366     else {
367         xinawareScreen = screen;
368     }
369 
370     AWT_LOCK ();
371 
372     viTmp.screen = xinawareScreen;
373 
374     viTmp.depth = 8;
375     viTmp.class = PseudoColor;
376     viTmp.colormap_size = 256;
377     pVI8p = XGetVisualInfo (awt_display,
378                             VisualDepthMask | VisualClassMask |
379                             VisualColormapSizeMask | VisualScreenMask,
380                             &viTmp, &n8p);
381 
382     viTmp.depth = 12;
383     viTmp.class = PseudoColor;
384     viTmp.colormap_size = 4096;
385     pVI12p = XGetVisualInfo (awt_display,
386                              VisualDepthMask | VisualClassMask |
387                              VisualColormapSizeMask | VisualScreenMask,
388                              &viTmp, &n12p);
389 
390     viTmp.class = TrueColor;
391     pVITrue = XGetVisualInfo (awt_display,
392                               VisualClassMask |
393                               VisualScreenMask,
394                               &viTmp, &nTrue);
395 
396     viTmp.depth = 8;
397     viTmp.class = StaticColor;
398     pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask |
399                             VisualScreenMask, &viTmp, &n8s);
400 
401     viTmp.depth = 8;
402     viTmp.class = GrayScale;
403     viTmp.colormap_size = 256;
404     pVI8gs = XGetVisualInfo (awt_display,
405                              VisualDepthMask | VisualClassMask |
406                              VisualColormapSizeMask | VisualScreenMask,
407                              &viTmp, &n8gs);
408     viTmp.depth = 8;
409     viTmp.class = StaticGray;
410     viTmp.colormap_size = 256;
411     pVI8sg = XGetVisualInfo (awt_display,
412                              VisualDepthMask | VisualClassMask |
413                              VisualColormapSizeMask | VisualScreenMask,
414                              &viTmp, &n8sg);
415 
416 /* REMIND.. remove when we have support for the color classes below */
417 /*     viTmp.depth = 1; */
418 /*     viTmp.class = StaticGray; */
419 /*     pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */
420 /*                              viTmp, &n1sg); */
421 
422     nConfig = n8p + n12p + n8s + n8gs + n8sg  + n1sg + nTrue + 1;
423     graphicsConfigs = (AwtGraphicsConfigDataPtr *)
424         calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr));
425     if (graphicsConfigs == NULL) {
426         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
427                                   NULL);
428         AWT_UNLOCK();
429         return;
430     }
431 
432     if (screenDataPtr->defaultConfig == NULL) {
433         /*
434          * After a display change event, the default config field will have
435          * been reset, so we need to recreate the default config here.
436          */
437         screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);
438     }
439 
440     defaultConfig = screenDataPtr->defaultConfig;
441     graphicsConfigs[0] = defaultConfig;
442     nConfig = 1; /* reserve index 0 for default config */
443 
444     // Only use the RENDER extension if it is available on the X server
445     if (XQueryExtension(awt_display, "RENDER",
446                         &major_opcode, &first_event, &first_error))
447     {
448         DTRACE_PRINTLN("RENDER extension available");
449         xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
450 
451 #ifdef MACOSX
452 #define XRENDER_LIB "/usr/X11/lib/libXrender.dylib"
453 #else
454 #define XRENDER_LIB "libXrender.so"
455 #endif
456 
457         if (xrenderLibHandle == NULL) {
458             xrenderLibHandle = dlopen(XRENDER_LIB,
459                                       RTLD_LAZY | RTLD_GLOBAL);
460         }
461 
462 #if defined(__solaris__)
463         if (xrenderLibHandle == NULL) {
464             xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
465                                       RTLD_LAZY | RTLD_GLOBAL);
466         }
467 #elif defined(_AIX)
468         if (xrenderLibHandle == NULL) {
469             xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
470                                       RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
471         }
472 #endif
473         if (xrenderLibHandle != NULL) {
474             DTRACE_PRINTLN("Loaded libXrender");
475             xrenderFindVisualFormat =
476                 (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
477                                                     "XRenderFindVisualFormat");
478             if (xrenderFindVisualFormat == NULL) {
479                 DTRACE_PRINTLN1("Can't find 'XRenderFindVisualFormat' in libXrender (%s)", dlerror());
480             }
481         } else {
482             DTRACE_PRINTLN1("Can't load libXrender (%s)", dlerror());
483         }
484     } else {
485         DTRACE_PRINTLN("RENDER extension NOT available");
486     }
487 
488     for (i = 0; i < nTrue; i++) {
489         if (XVisualIDFromVisual(pVITrue[i].visual) ==
490             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
491             pVITrue[i].depth == 12) {
492             /* Skip the non-supported 12-bit TrueColor visual */
493             continue;
494         } else {
495             ind = nConfig++;
496         }
497         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
498         if (graphicsConfigs[ind] == NULL) {
499             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
500             goto cleanup;
501         }
502         graphicsConfigs[ind]->awt_depth = pVITrue [i].depth;
503         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
504                 sizeof (XVisualInfo));
505         if (xrenderFindVisualFormat != NULL) {
506             XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,
507                                                                  pVITrue [i].visual);
508             if (format &&
509                 format->type == PictTypeDirect &&
510                 format->direct.alphaMask)
511             {
512                 DTRACE_PRINTLN1("GraphicsConfig[%d] supports Translucency", ind);
513                 graphicsConfigs [ind]->isTranslucencySupported = 1;
514                 memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
515                         sizeof(*format));
516             } else {
517                 DTRACE_PRINTLN1(format ?
518                                 "GraphicsConfig[%d] has no Translucency support" :
519                                 "Error calling 'XRenderFindVisualFormat'", ind);
520             }
521        }
522     }
523 
524     if (xrenderLibHandle != NULL) {
525         dlclose(xrenderLibHandle);
526         xrenderLibHandle = NULL;
527     }
528 
529     for (i = 0; i < n8p; i++) {
530         if (XVisualIDFromVisual(pVI8p[i].visual) ==
531             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
532             continue;
533         } else {
534             ind = nConfig++;
535         }
536         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
537         if (graphicsConfigs[ind] == NULL) {
538             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
539             goto cleanup;
540         }
541         graphicsConfigs[ind]->awt_depth = pVI8p [i].depth;
542         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
543                 sizeof (XVisualInfo));
544     }
545 
546     for (i = 0; i < n12p; i++) {
547         if (XVisualIDFromVisual(pVI12p[i].visual) ==
548             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
549             continue;
550         } else {
551             ind = nConfig++;
552         }
553         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
554         if (graphicsConfigs[ind] == NULL) {
555             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
556             goto cleanup;
557         }
558         graphicsConfigs[ind]->awt_depth = pVI12p [i].depth;
559         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i],
560                 sizeof (XVisualInfo));
561     }
562 
563     for (i = 0; i < n8s; i++) {
564         if (XVisualIDFromVisual(pVI8s[i].visual) ==
565             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
566             continue;
567         } else {
568             ind = nConfig++;
569         }
570         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
571         if (graphicsConfigs[ind] == NULL) {
572             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
573             goto cleanup;
574         }
575         graphicsConfigs[ind]->awt_depth = pVI8s [i].depth;
576         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i],
577                 sizeof (XVisualInfo));
578     }
579 
580     for (i = 0; i < n8gs; i++) {
581         if (XVisualIDFromVisual(pVI8gs[i].visual) ==
582             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
583             continue;
584         } else {
585             ind = nConfig++;
586         }
587         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
588         if (graphicsConfigs[ind] == NULL) {
589             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
590             goto cleanup;
591         }
592         graphicsConfigs[ind]->awt_depth = pVI8gs [i].depth;
593         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i],
594                 sizeof (XVisualInfo));
595     }
596 
597     for (i = 0; i < n8sg; i++) {
598         if (XVisualIDFromVisual(pVI8sg[i].visual) ==
599             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
600             continue;
601         } else {
602             ind = nConfig++;
603         }
604         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
605         if (graphicsConfigs[ind] == NULL) {
606             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
607             goto cleanup;
608         }
609         graphicsConfigs[ind]->awt_depth = pVI8sg [i].depth;
610         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i],
611                 sizeof (XVisualInfo));
612     }
613 
614     for (i = 0; i < n1sg; i++) {
615         if (XVisualIDFromVisual(pVI1sg[i].visual) ==
616             XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
617             continue;
618         } else {
619             ind = nConfig++;
620         }
621         graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
622         if (graphicsConfigs[ind] == NULL) {
623             JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
624             goto cleanup;
625         }
626         graphicsConfigs[ind]->awt_depth = pVI1sg [i].depth;
627         memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i],
628                 sizeof (XVisualInfo));
629     }
630 
631     screenDataPtr->numConfigs = nConfig;
632     screenDataPtr->configs = graphicsConfigs;
633 
634 cleanup:
635     if (n8p != 0)
636        XFree (pVI8p);
637     if (n12p != 0)
638        XFree (pVI12p);
639     if (n8s != 0)
640        XFree (pVI8s);
641     if (n8gs != 0)
642        XFree (pVI8gs);
643     if (n8sg != 0)
644        XFree (pVI8sg);
645     if (n1sg != 0)
646        XFree (pVI1sg);
647 
648     AWT_UNLOCK ();
649 }
650 
651 #ifndef HEADLESS
652 #if defined(__linux__) || defined(MACOSX) || defined(_AIX) || defined(_ALLBSD_SOURCE)
xinerama_init_linux()653 static void xinerama_init_linux()
654 {
655     void* libHandle = NULL;
656     int32_t locNumScr = 0;
657     XineramaScreenInfo *xinInfo;
658     char* XineramaQueryScreensName = "XineramaQueryScreens";
659     XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
660 
661     /* load library */
662     libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),
663                        RTLD_LAZY | RTLD_GLOBAL);
664     if (libHandle == NULL) {
665 #if defined(_AIX)
666         libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
667 #else
668         libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);
669 #endif
670     }
671     if (libHandle != NULL) {
672         XineramaQueryScreens = (XineramaQueryScreensFunc*)
673             dlsym(libHandle, XineramaQueryScreensName);
674 
675         if (XineramaQueryScreens != NULL) {
676             DTRACE_PRINTLN("calling XineramaQueryScreens func");
677             xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
678             if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
679                 int32_t idx;
680                 DTRACE_PRINTLN("Enabling Xinerama support");
681                 usingXinerama = True;
682                 /* set global number of screens */
683                 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
684                 awt_numScreens = locNumScr;
685 
686                 /* stuff values into fbrects */
687                 for (idx = 0; idx < awt_numScreens; idx++) {
688                     DASSERT(xinInfo[idx].screen_number == idx);
689 
690                     fbrects[idx].width = xinInfo[idx].width;
691                     fbrects[idx].height = xinInfo[idx].height;
692                     fbrects[idx].x = xinInfo[idx].x_org;
693                     fbrects[idx].y = xinInfo[idx].y_org;
694                 }
695             } else {
696                 DTRACE_PRINTLN((xinInfo == NULL) ?
697                                "calling XineramaQueryScreens didn't work" :
698                                "XineramaQueryScreens <= XScreenCount"
699                                );
700             }
701         } else {
702             DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
703         }
704         dlclose(libHandle);
705     } else {
706         DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
707     }
708 }
709 #elif defined(__solaris__)
xinerama_init_solaris()710 static void xinerama_init_solaris()
711 {
712     void* libHandle = NULL;
713     unsigned char fbhints[MAXFRAMEBUFFERS];
714     int32_t locNumScr = 0;
715     /* load and run XineramaGetInfo */
716     char* XineramaGetInfoName = "XineramaGetInfo";
717     char* XineramaGetCenterHintName = "XineramaGetCenterHint";
718     XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
719 
720     /* load library */
721     libHandle = dlopen(JNI_LIB_NAME("Xext"), RTLD_LAZY | RTLD_GLOBAL);
722     if (libHandle != NULL) {
723         XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
724         XineramaSolarisCenterFunc =
725             (XineramaGetCenterHintFunc*)dlsym(libHandle, XineramaGetCenterHintName);
726 
727         if (XineramaSolarisFunc != NULL) {
728             DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
729             if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
730                                        &fbhints[0], &locNumScr) != 0 &&
731                 locNumScr > XScreenCount(awt_display))
732             {
733                 DTRACE_PRINTLN("Enabling Xinerama support");
734                 usingXinerama = True;
735                 /* set global number of screens */
736                 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
737                 awt_numScreens = locNumScr;
738             } else {
739                 DTRACE_PRINTLN("calling XineramaGetInfo didn't work");
740             }
741         } else {
742             DTRACE_PRINTLN("couldn't load XineramaGetInfo symbol");
743         }
744         dlclose(libHandle);
745     } else {
746         DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
747     }
748 }
749 #endif
750 
751 /*
752  * Checks if Xinerama is running and perform Xinerama-related
753  * platform dependent initialization.
754  */
xineramaInit(void)755 static void xineramaInit(void) {
756     char* XinExtName = "XINERAMA";
757     int32_t major_opcode, first_event, first_error;
758     Bool gotXinExt = False;
759 
760     gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
761                                 &first_event, &first_error);
762 
763     if (!gotXinExt) {
764         DTRACE_PRINTLN("Xinerama extension is not available");
765         return;
766     }
767 
768     DTRACE_PRINTLN("Xinerama extension is available");
769 #if defined(__solaris__)
770     xinerama_init_solaris();
771 #else /* Linux, Mac, AIX */
772     xinerama_init_linux();
773 #endif
774 }
775 #endif /* HEADLESS */
776 
777 Display *
awt_init_Display(JNIEnv * env,jobject this)778 awt_init_Display(JNIEnv *env, jobject this)
779 {
780     jclass klass;
781     Display *dpy;
782     char errmsg[128];
783     int i;
784 #ifdef NETSCAPE
785     sigset_t alarm_set, oldset;
786 #endif
787 
788     if (awt_display) {
789         return awt_display;
790     }
791 
792 #ifdef NETSCAPE
793     /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select
794        code: some unix systems don't implement SA_RESTART properly and
795        because of this, select returns with EINTR. Most implementations of
796        gethostbyname don't cope with EINTR properly and as a result we get
797        stuck (forever) in the gethostbyname code
798     */
799     sigemptyset(&alarm_set);
800     sigaddset(&alarm_set, SIGALRM);
801     sigprocmask(SIG_BLOCK, &alarm_set, &oldset);
802 #endif
803 
804     /* Load AWT lock-related methods in SunToolkit */
805     klass = (*env)->FindClass(env, "sun/awt/SunToolkit");
806     if (klass == NULL) return NULL;
807     GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V");
808     GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V");
809     GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V");
810     GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V");
811     GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V");
812     tkClass = (*env)->NewGlobalRef(env, klass);
813     awtLockInited = JNI_TRUE;
814 
815     if (getenv("_AWT_IGNORE_XKB") != NULL &&
816         strlen(getenv("_AWT_IGNORE_XKB")) > 0) {
817         if (XkbIgnoreExtension(True)) {
818             printf("Ignoring XKB.\n");
819         }
820     }
821 
822     dpy = awt_display = XOpenDisplay(NULL);
823 #ifdef NETSCAPE
824     sigprocmask(SIG_SETMASK, &oldset, NULL);
825 #endif
826     if (!dpy) {
827         jio_snprintf(errmsg,
828                      sizeof(errmsg),
829                      "Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.",
830                      (getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY"));
831         JNU_ThrowByName(env, "java/awt/AWTError", errmsg);
832         return NULL;
833     }
834 
835     XSetIOErrorHandler(xioerror_handler);
836     JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",
837         ptr_to_jlong(awt_display));
838     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
839 
840     /* set awt_numScreens, and whether or not we're using Xinerama */
841     xineramaInit();
842 
843     if (!usingXinerama) {
844         awt_numScreens =  XScreenCount(awt_display);
845     }
846 
847     DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens);
848     /* Allocate screen data structure array */
849     x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData));
850     if (x11Screens == NULL) {
851         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
852                                   NULL);
853         return NULL;
854     }
855 
856     for (i = 0; i < awt_numScreens; i++) {
857         if (usingXinerama) {
858             /* All Xinerama screens use the same X11 root for now */
859             x11Screens[i].root = RootWindow(awt_display, 0);
860         }
861         else {
862             x11Screens[i].root = RootWindow(awt_display, i);
863         }
864         x11Screens[i].defaultConfig = makeDefaultConfig(env, i);
865         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
866     }
867 
868     return dpy;
869 }
870 #endif /* !HEADLESS */
871 
872 /*
873  * Class:     sun_awt_X11GraphicsEnvironment
874  * Method:    getDefaultScreenNum
875  * Signature: ()I
876  */
877 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(JNIEnv * env,jobject this)878 Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(
879 JNIEnv *env, jobject this)
880 {
881 #ifdef HEADLESS
882     return (jint)0;
883 #else
884     return DefaultScreen(awt_display);
885 #endif /* !HEADLESS */
886 }
887 
888 #ifndef HEADLESS
ensureConfigsInited(JNIEnv * env,int screen)889 static void ensureConfigsInited(JNIEnv* env, int screen) {
890    if (x11Screens[screen].numConfigs == 0) {
891        if (env == NULL) {
892            env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
893        }
894        getAllConfigs (env, screen, &(x11Screens[screen]));
895     }
896 }
897 #endif
898 
899 #ifdef HEADLESS
getDefaultConfig(int screen)900 void* getDefaultConfig(int screen) {
901     return NULL;
902 }
903 #else
904 AwtGraphicsConfigDataPtr
getDefaultConfig(int screen)905 getDefaultConfig(int screen) {
906     ensureConfigsInited(NULL, screen);
907     return x11Screens[screen].defaultConfig;
908 }
909 
910 AwtScreenDataPtr
getScreenData(int screen)911 getScreenData(int screen) {
912     return &(x11Screens[screen]);
913 }
914 #endif /* !HEADLESS */
915 
916 /*
917  * Class:     sun_awt_X11GraphicsEnvironment
918  * Method:    initDisplay
919  * Signature: (Z)V
920  */
921 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv * env,jobject this,jboolean glxReq)922 Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this,
923                                                 jboolean glxReq)
924 {
925 #ifndef HEADLESS
926     glxRequested = glxReq;
927     (void) awt_init_Display(env, this);
928 #endif /* !HEADLESS */
929 }
930 
931 /*
932  * Class:     sun_awt_X11GraphicsEnvironment
933  * Method:    initGLX
934  * Signature: ()Z
935  */
936 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv * env,jclass x11ge)937 Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge)
938 {
939 #ifndef HEADLESS
940     jboolean glxAvailable;
941 
942     AWT_LOCK();
943     glxAvailable = GLXGC_IsGLXAvailable();
944     AWT_UNLOCK();
945 
946     return glxAvailable;
947 #else
948     return JNI_FALSE;
949 #endif /* !HEADLESS */
950 }
951 
952 /*
953  * Class:     sun_awt_X11GraphicsEnvironment
954  * Method:    getNumScreens
955  * Signature: ()I
956  */
957 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv * env,jobject this)958 Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this)
959 {
960 #ifdef HEADLESS
961     return (jint)0;
962 #else
963     return awt_numScreens;
964 #endif /* !HEADLESS */
965 }
966 
967 /*
968  * Class:     sun_awt_X11GraphicsDevice
969  * Method:    getDisplay
970  * Signature: ()J
971  */
972 JNIEXPORT jlong JNICALL
Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv * env,jobject this)973 Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)
974 {
975 #ifdef HEADLESS
976     return NULL;
977 #else
978     return ptr_to_jlong(awt_display);
979 #endif /* !HEADLESS */
980 }
981 
982 #ifdef MITSHM
983 
984 static jint canUseShmExt = UNSET_MITSHM;
985 static jint canUseShmExtPixmaps = UNSET_MITSHM;
986 static jboolean xshmAttachFailed = JNI_FALSE;
987 
XShmAttachXErrHandler(Display * display,XErrorEvent * xerr)988 int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr) {
989     if (xerr->minor_code == X_ShmAttach) {
990         xshmAttachFailed = JNI_TRUE;
991     }
992     return 0;
993 }
isXShmAttachFailed()994 jboolean isXShmAttachFailed() {
995     return xshmAttachFailed;
996 }
resetXShmAttachFailed()997 void resetXShmAttachFailed() {
998     xshmAttachFailed = JNI_FALSE;
999 }
1000 
1001 extern int mitShmPermissionMask;
1002 
TryInitMITShm(JNIEnv * env,jint * shmExt,jint * shmPixmaps)1003 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
1004     XShmSegmentInfo shminfo;
1005     int XShmMajor, XShmMinor;
1006     int a, b, c;
1007 
1008     AWT_LOCK();
1009     if (canUseShmExt != UNSET_MITSHM) {
1010         *shmExt = canUseShmExt;
1011         *shmPixmaps = canUseShmExtPixmaps;
1012         AWT_UNLOCK();
1013         return;
1014     }
1015 
1016     *shmExt = canUseShmExt = CANT_USE_MITSHM;
1017     *shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM;
1018 
1019     if (awt_display == (Display *)NULL) {
1020         AWT_NOFLUSH_UNLOCK();
1021         return;
1022     }
1023 
1024     /**
1025      * XShmQueryExtension returns False in remote server case.
1026      * Unfortunately it also returns True in ssh case, so
1027      * we need to test that we can actually do XShmAttach.
1028      */
1029     if (XShmQueryExtension(awt_display)) {
1030         shminfo.shmid = shmget(IPC_PRIVATE, 0x10000,
1031                                IPC_CREAT|mitShmPermissionMask);
1032         if (shminfo.shmid < 0) {
1033             AWT_UNLOCK();
1034             J2dRlsTraceLn1(J2D_TRACE_ERROR,
1035                            "TryInitMITShm: shmget has failed: %s",
1036                            strerror(errno));
1037             return;
1038         }
1039         shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0);
1040         if (shminfo.shmaddr == ((char *) -1)) {
1041             shmctl(shminfo.shmid, IPC_RMID, 0);
1042             AWT_UNLOCK();
1043             J2dRlsTraceLn1(J2D_TRACE_ERROR,
1044                            "TryInitMITShm: shmat has failed: %s",
1045                            strerror(errno));
1046             return;
1047         }
1048         shminfo.readOnly = True;
1049 
1050         resetXShmAttachFailed();
1051         /**
1052          * The J2DXErrHandler handler will set xshmAttachFailed
1053          * to JNI_TRUE if any Shm error has occured.
1054          */
1055         EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler,
1056                                  XShmAttach(awt_display, &shminfo));
1057 
1058         /**
1059          * Get rid of the id now to reduce chances of leaking
1060          * system resources.
1061          */
1062         shmctl(shminfo.shmid, IPC_RMID, 0);
1063 
1064         if (isXShmAttachFailed() == JNI_FALSE) {
1065             canUseShmExt = CAN_USE_MITSHM;
1066             /* check if we can use shared pixmaps */
1067             XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
1068                              (Bool*)&canUseShmExtPixmaps);
1069             canUseShmExtPixmaps = canUseShmExtPixmaps &&
1070                 (XShmPixmapFormat(awt_display) == ZPixmap);
1071             XShmDetach(awt_display, &shminfo);
1072         }
1073         shmdt(shminfo.shmaddr);
1074         *shmExt = canUseShmExt;
1075         *shmPixmaps = canUseShmExtPixmaps;
1076     }
1077     AWT_UNLOCK();
1078 }
1079 #endif /* MITSHM */
1080 
1081 /*
1082  * Class:     sun_awt_X11GraphicsEnvironment
1083  * Method:    checkShmExt
1084  * Signature: ()I
1085  */
1086 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv * env,jobject this)1087 Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this)
1088 {
1089 
1090     int shmExt = NOEXT_MITSHM, shmPixmaps;
1091 #ifdef MITSHM
1092     TryInitMITShm(env, &shmExt, &shmPixmaps);
1093 #endif
1094     return shmExt;
1095 }
1096 
1097 /*
1098  * Class:     sun_awt_X11GraphicsEnvironment
1099  * Method:    getDisplayString
1100  * Signature: ()Ljava/lang/String
1101  */
1102 JNIEXPORT jstring JNICALL
Java_sun_awt_X11GraphicsEnvironment_getDisplayString(JNIEnv * env,jobject this)1103 Java_sun_awt_X11GraphicsEnvironment_getDisplayString
1104   (JNIEnv *env, jobject this)
1105 {
1106 #ifdef HEADLESS
1107     return (jstring)NULL;
1108 #else
1109     return (*env)->NewStringUTF(env, DisplayString(awt_display));
1110 #endif /* HEADLESS */
1111 }
1112 
1113 
1114 /*
1115  * Class:     sun_awt_X11GraphicsDevice
1116  * Method:    getNumConfigs
1117  * Signature: ()I
1118  */
1119 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getNumConfigs(JNIEnv * env,jobject this,jint screen)1120 Java_sun_awt_X11GraphicsDevice_getNumConfigs(
1121 JNIEnv *env, jobject this, jint screen)
1122 {
1123 #ifdef HEADLESS
1124     return (jint)0;
1125 #else
1126     ensureConfigsInited(env, screen);
1127     return x11Screens[screen].numConfigs;
1128 #endif /* !HEADLESS */
1129 }
1130 
1131 /*
1132  * Class:     sun_awt_X11GraphicsDevice
1133  * Method:    getConfigVisualId
1134  * Signature: (I)I
1135  */
1136 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigVisualId(JNIEnv * env,jobject this,jint index,jint screen)1137 Java_sun_awt_X11GraphicsDevice_getConfigVisualId(
1138 JNIEnv *env, jobject this, jint index, jint screen)
1139 {
1140 #ifdef HEADLESS
1141     return (jint)0;
1142 #else
1143     int visNum;
1144 
1145     ensureConfigsInited(env, screen);
1146     if (index == 0) {
1147         return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.visualid);
1148     } else {
1149         return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid);
1150     }
1151 #endif /* !HEADLESS */
1152 }
1153 
1154 /*
1155  * Class:     sun_awt_X11GraphicsDevice
1156  * Method:    getConfigDepth
1157  * Signature: (I)I
1158  */
1159 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigDepth(JNIEnv * env,jobject this,jint index,jint screen)1160 Java_sun_awt_X11GraphicsDevice_getConfigDepth(
1161 JNIEnv *env, jobject this, jint index, jint screen)
1162 {
1163 #ifdef HEADLESS
1164     return (jint)0;
1165 #else
1166     int visNum;
1167 
1168     ensureConfigsInited(env, screen);
1169     if (index == 0) {
1170         return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.depth);
1171     } else {
1172         return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth);
1173     }
1174 #endif /* !HEADLESS */
1175 }
1176 
1177 /*
1178  * Class:     sun_awt_X11GraphicsDevice
1179  * Method:    getConfigColormap
1180  * Signature: (I)I
1181  */
1182 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigColormap(JNIEnv * env,jobject this,jint index,jint screen)1183 Java_sun_awt_X11GraphicsDevice_getConfigColormap(
1184 JNIEnv *env, jobject this, jint index, jint screen)
1185 {
1186 #ifdef HEADLESS
1187     return (jint)0;
1188 #else
1189     int visNum;
1190 
1191     ensureConfigsInited(env, screen);
1192     if (index == 0) {
1193         return ((jint)x11Screens[screen].defaultConfig->awt_cmap);
1194     } else {
1195         return ((jint)x11Screens[screen].configs[index]->awt_cmap);
1196     }
1197 #endif /* !HEADLESS */
1198 }
1199 
1200 /*
1201  * Class:     sun_awt_X11GraphicsDevice
1202  * Method:    resetNativeData
1203  * Signature: (I)V
1204  */
1205 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_resetNativeData(JNIEnv * env,jclass x11gd,jint screen)1206 Java_sun_awt_X11GraphicsDevice_resetNativeData
1207     (JNIEnv *env, jclass x11gd, jint screen)
1208 {
1209 #ifndef HEADLESS
1210     /*
1211      * Reset references to the various configs; the actual native config data
1212      * will be free'd later by the Disposer mechanism when the Java-level
1213      * X11GraphicsConfig objects go away.  By setting these values to NULL,
1214      * we ensure that they will be reinitialized as necessary (for example,
1215      * see the getNumConfigs() method).
1216      */
1217     if (x11Screens[screen].configs) {
1218         free(x11Screens[screen].configs);
1219         x11Screens[screen].configs = NULL;
1220     }
1221     x11Screens[screen].defaultConfig = NULL;
1222     x11Screens[screen].numConfigs = 0;
1223 #endif /* !HEADLESS */
1224 }
1225 
1226 /*
1227  * Class:     sun_awt_X11GraphicsConfig
1228  * Method:    dispose
1229  * Signature: (J)V
1230  */
1231 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_dispose(JNIEnv * env,jclass x11gc,jlong configData)1232 Java_sun_awt_X11GraphicsConfig_dispose
1233     (JNIEnv *env, jclass x11gc, jlong configData)
1234 {
1235 #ifndef HEADLESS
1236     AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)
1237         jlong_to_ptr(configData);
1238 
1239     if (aData == NULL) {
1240         return;
1241     }
1242 
1243     AWT_LOCK();
1244     if (aData->awt_cmap) {
1245         XFreeColormap(awt_display, aData->awt_cmap);
1246     }
1247     if (aData->awtImage) {
1248         free(aData->awtImage);
1249     }
1250     if (aData->monoImage) {
1251         XFree(aData->monoImage);
1252     }
1253     if (aData->monoPixmap) {
1254         XFreePixmap(awt_display, aData->monoPixmap);
1255     }
1256     if (aData->monoPixmapGC) {
1257         XFreeGC(awt_display, aData->monoPixmapGC);
1258     }
1259     if (aData->color_data) {
1260         free(aData->color_data);
1261     }
1262     AWT_UNLOCK();
1263 
1264     if (aData->glxInfo) {
1265         /*
1266          * The native GLXGraphicsConfig data needs to be disposed separately
1267          * on the OGL queue flushing thread (should not be called while
1268          * the AWT lock is held).
1269          */
1270         JNU_CallStaticMethodByName(env, NULL,
1271                                    "sun/java2d/opengl/OGLRenderQueue",
1272                                    "disposeGraphicsConfig", "(J)V",
1273                                    ptr_to_jlong(aData->glxInfo));
1274     }
1275 
1276     free(aData);
1277 #endif /* !HEADLESS */
1278 }
1279 
1280 /*
1281  * Class:     sun_awt_X11GraphicsConfig
1282  * Method:    getXResolution
1283  * Signature: ()I
1284  */
1285 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsConfig_getXResolution(JNIEnv * env,jobject this,jint screen)1286 Java_sun_awt_X11GraphicsConfig_getXResolution(
1287 JNIEnv *env, jobject this, jint screen)
1288 {
1289 #ifdef HEADLESS
1290     return (jdouble)0;
1291 #else
1292     return ((DisplayWidth(awt_display, screen) * 25.4) /
1293             DisplayWidthMM(awt_display, screen));
1294 #endif /* !HEADLESS */
1295 }
1296 
1297 /*
1298  * Class:     sun_awt_X11GraphicsConfig
1299  * Method:    getYResolution
1300  * Signature: ()I
1301  */
1302 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsConfig_getYResolution(JNIEnv * env,jobject this,jint screen)1303 Java_sun_awt_X11GraphicsConfig_getYResolution(
1304 JNIEnv *env, jobject this, jint screen)
1305 {
1306 #ifdef HEADLESS
1307     return (jdouble)0;
1308 #else
1309     return ((DisplayHeight(awt_display, screen) * 25.4) /
1310             DisplayHeightMM(awt_display, screen));
1311 #endif /* !HEADLESS */
1312 }
1313 
1314 
1315 /*
1316  * Class:     sun_awt_X11GraphicsConfig
1317  * Method:    getNumColors
1318  * Signature: ()I
1319  */
1320 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsConfig_getNumColors(JNIEnv * env,jobject this)1321 Java_sun_awt_X11GraphicsConfig_getNumColors(
1322 JNIEnv *env, jobject this)
1323 {
1324 #ifdef HEADLESS
1325     return (jint)0;
1326 #else
1327     AwtGraphicsConfigData *adata;
1328 
1329     adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1330                                               x11GraphicsConfigIDs.aData);
1331 
1332     return adata->awt_num_colors;
1333 #endif /* !HEADLESS */
1334 }
1335 
1336 /*
1337  * Class:     sun_awt_X11GraphicsConfig
1338  * Method:    init
1339  * Signature: (I)V
1340  */
1341 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_init(JNIEnv * env,jobject this,jint visualNum,jint screen)1342 Java_sun_awt_X11GraphicsConfig_init(
1343 JNIEnv *env, jobject this, jint visualNum, jint screen)
1344 {
1345 #ifndef HEADLESS
1346     AwtGraphicsConfigData *adata = NULL;
1347     AwtScreenData asd = x11Screens[screen];
1348     int i, n;
1349     int depth;
1350     XImage * tempImage;
1351 
1352     /* If haven't gotten all of the configs yet, do it now. */
1353     if (asd.numConfigs == 0) {
1354         getAllConfigs (env, screen, &asd);
1355     }
1356 
1357     /* Check the graphicsConfig for this visual */
1358     for (i = 0; i < asd.numConfigs; i++) {
1359         AwtGraphicsConfigDataPtr agcPtr = asd.configs[i];
1360         if ((jint)agcPtr->awt_visInfo.visualid == visualNum) {
1361            adata = agcPtr;
1362            break;
1363         }
1364     }
1365 
1366     /* If didn't find the visual, throw an exception... */
1367     if (adata == (AwtGraphicsConfigData *) NULL) {
1368         JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified");
1369         return;
1370     }
1371 
1372     /*  adata->awt_cmap initialization has been deferred to
1373      *  makeColorModel call
1374      */
1375 
1376     JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata);
1377 
1378     depth = adata->awt_visInfo.depth;
1379     tempImage = XCreateImage(awt_display,
1380                              adata->awt_visInfo.visual,
1381                              depth, ZPixmap, 0, NULL, 1, 1, 32, 0);
1382     adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8;
1383     (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel,
1384                         (jint)tempImage->bits_per_pixel);
1385     XDestroyImage(tempImage);
1386 #endif /* !HEADLESS */
1387 }
1388 
1389 
1390 
1391 /*
1392  * Class:     sun_awt_X11GraphicsConfig
1393  * Method:    makeColorModel
1394  * Signature: ()Ljava/awt/image/ColorModel
1395  */
1396 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsConfig_makeColorModel(JNIEnv * env,jobject this)1397 Java_sun_awt_X11GraphicsConfig_makeColorModel(
1398 JNIEnv *env, jobject this)
1399 {
1400 #ifdef HEADLESS
1401     return NULL;
1402 #else
1403     AwtGraphicsConfigData *adata;
1404     jobject colorModel;
1405 
1406     /*
1407      * If awt is not locked yet, return null since the toolkit is not
1408      * initialized yet.
1409      */
1410     if (!awtLockInited) {
1411         return NULL;
1412     }
1413 
1414     AWT_LOCK ();
1415 
1416     adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1417                                               x11GraphicsConfigIDs.aData);
1418 
1419     /* If colormap entry of adata is NULL, need to create it now */
1420     if (adata->awt_cmap == (Colormap) NULL) {
1421         awtJNI_CreateColorData (env, adata, 1);
1422     }
1423 
1424     /* Make Color Model object for this GraphicsConfiguration */
1425     colorModel = (*env)->ExceptionCheck(env)
1426                  ? NULL : awtJNI_GetColorModel (env, adata);
1427 
1428     AWT_UNLOCK ();
1429 
1430     return colorModel;
1431 #endif /* !HEADLESS */
1432 }
1433 
1434 
1435 /*
1436  * Class:     sun_awt_X11GraphicsConfig
1437  * Method:    getBounds
1438  * Signature: ()Ljava/awt/Rectangle
1439  */
1440 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv * env,jobject this,jint screen)1441 Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen)
1442 {
1443 #ifdef HEADLESS
1444     return NULL;
1445 #else
1446     jclass clazz;
1447     jmethodID mid;
1448     jobject bounds = NULL;
1449     AwtGraphicsConfigDataPtr adata;
1450 
1451     adata = (AwtGraphicsConfigDataPtr)
1452         JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData);
1453 
1454     clazz = (*env)->FindClass(env, "java/awt/Rectangle");
1455     CHECK_NULL_RETURN(clazz, NULL);
1456     mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
1457     if (mid != NULL) {
1458         if (usingXinerama) {
1459             if (0 <= screen && screen < awt_numScreens) {
1460                 bounds = (*env)->NewObject(env, clazz, mid, fbrects[screen].x,
1461                                                             fbrects[screen].y,
1462                                                             fbrects[screen].width,
1463                                                             fbrects[screen].height);
1464             } else {
1465                 jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
1466                 if (exceptionClass != NULL) {
1467                     (*env)->ThrowNew(env, exceptionClass, "Illegal screen index");
1468                 }
1469             }
1470         } else {
1471             XWindowAttributes xwa;
1472             memset(&xwa, 0, sizeof(xwa));
1473 
1474             AWT_LOCK ();
1475             XGetWindowAttributes(awt_display,
1476                     RootWindow(awt_display, adata->awt_visInfo.screen),
1477                     &xwa);
1478             AWT_UNLOCK ();
1479 
1480             bounds = (*env)->NewObject(env, clazz, mid, 0, 0,
1481                     xwa.width, xwa.height);
1482         }
1483 
1484         if ((*env)->ExceptionOccurred(env)) {
1485             return NULL;
1486         }
1487     }
1488     return bounds;
1489 #endif /* !HEADLESS */
1490 }
1491 
1492 /*
1493  * Class:     sun_awt_X11GraphicsConfig
1494  * Method:    createBackBuffer
1495  * Signature: (JI)J
1496  */
1497 JNIEXPORT jlong JNICALL
Java_sun_awt_X11GraphicsConfig_createBackBuffer(JNIEnv * env,jobject this,jlong window,jint swapAction)1498 Java_sun_awt_X11GraphicsConfig_createBackBuffer
1499     (JNIEnv *env, jobject this, jlong window, jint swapAction)
1500 {
1501     int32_t v1, v2;
1502     XdbeBackBuffer ret = (unsigned long) 0;
1503     Window w = (Window)window;
1504     AWT_LOCK();
1505     if (!XdbeQueryExtension(awt_display, &v1, &v2)) {
1506         JNU_ThrowByName(env, "java/lang/Exception",
1507                         "Could not query double-buffer extension");
1508         AWT_UNLOCK();
1509         return (jlong)0;
1510     }
1511     ret = XdbeAllocateBackBufferName(awt_display, w,
1512                                      (XdbeSwapAction)swapAction);
1513     AWT_FLUSH_UNLOCK();
1514     return (jlong)ret;
1515 }
1516 
1517 /*
1518  * Class:     sun_awt_X11GraphicsConfig
1519  * Method:    destroyBackBuffer
1520  * Signature: (J)V
1521  */
1522 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_destroyBackBuffer(JNIEnv * env,jobject this,jlong backBuffer)1523 Java_sun_awt_X11GraphicsConfig_destroyBackBuffer
1524     (JNIEnv *env, jobject this, jlong backBuffer)
1525 {
1526     AWT_LOCK();
1527     XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer);
1528     AWT_FLUSH_UNLOCK();
1529 }
1530 
1531 /*
1532  * Class:     sun_awt_X11GraphicsConfig
1533  * Method:    swapBuffers
1534  * Signature: (JI)V
1535  */
1536 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_swapBuffers(JNIEnv * env,jobject this,jlong window,jint swapAction)1537 Java_sun_awt_X11GraphicsConfig_swapBuffers
1538     (JNIEnv *env, jobject this,
1539      jlong window, jint swapAction)
1540 {
1541     XdbeSwapInfo swapInfo;
1542 
1543     AWT_LOCK();
1544 
1545     XdbeBeginIdiom(awt_display);
1546     swapInfo.swap_window = (Window)window;
1547     swapInfo.swap_action = (XdbeSwapAction)swapAction;
1548     if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) {
1549         JNU_ThrowInternalError(env, "Could not swap buffers");
1550     }
1551     XdbeEndIdiom(awt_display);
1552 
1553     AWT_FLUSH_UNLOCK();
1554 }
1555 
1556 /*
1557  * Class:     sun_awt_X11GraphicsConfig
1558  * Method:    isTranslucencyCapable
1559  * Signature: (J)V
1560  */
1561 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable(JNIEnv * env,jobject this,jlong configData)1562 Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable
1563     (JNIEnv *env, jobject this, jlong configData)
1564 {
1565 #ifdef HEADLESS
1566     return JNI_FALSE;
1567 #else
1568     AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData);
1569     if (aData == NULL) {
1570         return JNI_FALSE;
1571     }
1572     return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE;
1573 #endif
1574 }
1575 
1576 /*
1577  * Class:     sun_awt_X11GraphicsDevice
1578  * Method:    isDBESupported
1579  * Signature: ()Z
1580  */
1581 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv * env,jobject this)1582 Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this)
1583 {
1584 #ifdef HEADLESS
1585     return JNI_FALSE;
1586 #else
1587     int opcode = 0, firstEvent = 0, firstError = 0;
1588     jboolean ret;
1589 
1590     AWT_LOCK();
1591     ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER",
1592                                     &opcode, &firstEvent, &firstError);
1593     AWT_FLUSH_UNLOCK();
1594     return ret;
1595 #endif /* !HEADLESS */
1596 }
1597 
1598 /*
1599  * Class:     sun_awt_X11GraphicsDevice
1600  * Method:    getDoubleBufferVisuals
1601  * Signature: (I)V
1602  */
1603 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv * env,jobject this,jint screen)1604 Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,
1605     jobject this, jint screen)
1606 {
1607 #ifndef HEADLESS
1608     jclass clazz;
1609     jmethodID midAddVisual;
1610     Window rootWindow;
1611     int i, n = 1;
1612     XdbeScreenVisualInfo* visScreenInfo;
1613     int xinawareScreen;
1614 
1615     if (usingXinerama) {
1616         xinawareScreen = 0;
1617     }
1618     else {
1619         xinawareScreen = screen;
1620     }
1621 
1622     clazz = (*env)->GetObjectClass(env, this);
1623     midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual",
1624         "(I)V");
1625     CHECK_NULL(midAddVisual);
1626     AWT_LOCK();
1627     rootWindow = RootWindow(awt_display, xinawareScreen);
1628     visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n);
1629     if (visScreenInfo == NULL) {
1630         JNU_ThrowInternalError(env, "Could not get visual info");
1631         AWT_UNLOCK();
1632         return;
1633     }
1634     AWT_FLUSH_UNLOCK();
1635     for (i = 0; i < visScreenInfo->count; i++) {
1636         XdbeVisualInfo* visInfo = visScreenInfo->visinfo;
1637         (*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual);
1638         if ((*env)->ExceptionCheck(env)) {
1639             break;
1640         }
1641     }
1642 #endif /* !HEADLESS */
1643 }
1644 
1645 /*
1646  * Class:     sun_awt_X11GraphicsEnvironment
1647  * Method:    pRunningXinerama
1648  * Signature: ()Z
1649  */
1650 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv * env,jobject this)1651 Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env,
1652     jobject this)
1653 {
1654 #ifdef HEADLESS
1655     return JNI_FALSE;
1656 #else
1657     return usingXinerama ? JNI_TRUE : JNI_FALSE;
1658 #endif /* HEADLESS */
1659 }
1660 
1661 /*
1662  * Can return NULL.
1663  *
1664  * Class:     sun_awt_X11GraphicsEnvironment
1665  * Method:    getXineramaCenterPoint
1666  * Signature: ()Ljava/awt/Point
1667  */
1668 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv * env,jobject this)1669 Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env,
1670     jobject this)
1671 {
1672     jobject point = NULL;
1673 #ifndef HEADLESS    /* return NULL in HEADLESS, Linux */
1674 #if defined(__solaris__)
1675     int x,y;
1676 
1677     AWT_LOCK();
1678     DASSERT(usingXinerama);
1679     if (XineramaSolarisCenterFunc != NULL) {
1680         (XineramaSolarisCenterFunc)(awt_display, 0, &x, &y);
1681         point = JNU_NewObjectByName(env, "java/awt/Point","(II)V", x, y);
1682         DASSERT(point);
1683     } else {
1684         DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null");
1685     }
1686     AWT_FLUSH_UNLOCK();
1687 #endif /* __solaris__ */
1688 #endif /* HEADLESS */
1689     return point;
1690 }
1691 
1692 
1693 /**
1694  * Begin DisplayMode/FullScreen support
1695  */
1696 
1697 #ifndef HEADLESS
1698 
1699 #ifndef _AIX
1700 
1701 #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI
1702 #define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN
1703 
1704 typedef Status
1705     (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);
1706 typedef XRRScreenConfiguration*
1707     (*XRRGetScreenInfoType)(Display *dpy, Drawable root);
1708 typedef void
1709     (*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config);
1710 typedef short*
1711     (*XRRConfigRatesType)(XRRScreenConfiguration *config,
1712                           int sizeID, int *nrates);
1713 typedef short
1714     (*XRRConfigCurrentRateType)(XRRScreenConfiguration *config);
1715 typedef XRRScreenSize*
1716     (*XRRConfigSizesType)(XRRScreenConfiguration *config,
1717                           int *nsizes);
1718 typedef SizeID
1719     (*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config,
1720                                          Rotation *rotation);
1721 typedef Status
1722     (*XRRSetScreenConfigAndRateType)(Display *dpy,
1723                                      XRRScreenConfiguration *config,
1724                                      Drawable draw,
1725                                      int size_index,
1726                                      Rotation rotation,
1727                                      short rate,
1728                                      Time timestamp);
1729 typedef Rotation
1730     (*XRRConfigRotationsType)(XRRScreenConfiguration *config,
1731                               Rotation *current_rotation);
1732 
1733 typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy,
1734                                                                  Window window);
1735 
1736 typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources);
1737 
1738 typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy,
1739                                 XRRScreenResources *resources, RROutput output);
1740 
1741 typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
1742 
1743 typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
1744                                     XRRScreenResources *resources, RRCrtc crtc);
1745 
1746 typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
1747 
1748 static XRRQueryVersionType               awt_XRRQueryVersion;
1749 static XRRGetScreenInfoType              awt_XRRGetScreenInfo;
1750 static XRRFreeScreenConfigInfoType       awt_XRRFreeScreenConfigInfo;
1751 static XRRConfigRatesType                awt_XRRConfigRates;
1752 static XRRConfigCurrentRateType          awt_XRRConfigCurrentRate;
1753 static XRRConfigSizesType                awt_XRRConfigSizes;
1754 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;
1755 static XRRSetScreenConfigAndRateType     awt_XRRSetScreenConfigAndRate;
1756 static XRRConfigRotationsType            awt_XRRConfigRotations;
1757 static XRRGetScreenResourcesType         awt_XRRGetScreenResources;
1758 static XRRFreeScreenResourcesType        awt_XRRFreeScreenResources;
1759 static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
1760 static XRRFreeOutputInfoType             awt_XRRFreeOutputInfo;
1761 static XRRGetCrtcInfoType                awt_XRRGetCrtcInfo;
1762 static XRRFreeCrtcInfoType               awt_XRRFreeCrtcInfo;
1763 
1764 #define LOAD_XRANDR_FUNC(f) \
1765     do { \
1766         awt_##f = (f##Type)dlsym(pLibRandR, #f); \
1767         if (awt_##f == NULL) { \
1768             J2dRlsTraceLn1(J2D_TRACE_ERROR, \
1769                            "X11GD_InitXrandrFuncs: Could not load %s", #f); \
1770             dlclose(pLibRandR); \
1771             return JNI_FALSE; \
1772         } \
1773     } while (0)
1774 
1775 static jboolean
X11GD_InitXrandrFuncs(JNIEnv * env)1776 X11GD_InitXrandrFuncs(JNIEnv *env)
1777 {
1778     int rr_maj_ver = 0, rr_min_ver = 0;
1779 
1780     void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"),
1781                              RTLD_LAZY | RTLD_LOCAL);
1782     if (pLibRandR == NULL) {
1783         pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL);
1784     }
1785     if (pLibRandR == NULL) {
1786         J2dRlsTraceLn(J2D_TRACE_ERROR,
1787                       "X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");
1788         return JNI_FALSE;
1789     }
1790 
1791     LOAD_XRANDR_FUNC(XRRQueryVersion);
1792 
1793     if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {
1794         J2dRlsTraceLn(J2D_TRACE_ERROR,
1795                       "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");
1796         dlclose(pLibRandR);
1797         return JNI_FALSE;
1798     }
1799 
1800     if (usingXinerama) {
1801         /*
1802          * We can proceed as long as this is RANDR 1.2 or above.
1803          * As of Xorg server 1.3 onwards the Xinerama backend may actually be
1804          * a fake one provided by RANDR itself. See Java bug 6636469 for info.
1805          */
1806         if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {
1807             J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1808                            "Xinerama is active and Xrandr version is %d.%d",
1809                            rr_maj_ver, rr_min_ver);
1810             dlclose(pLibRandR);
1811             return JNI_FALSE;
1812         }
1813 
1814         /*
1815          * REMIND: Fullscreen mode doesn't work quite right with multi-monitor
1816          * setups and RANDR 1.2.
1817          */
1818         if ((rr_maj_ver == 1 && rr_min_ver <= 2) && awt_numScreens > 1) {
1819             J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1820                           "Multiple screens in use");
1821             dlclose(pLibRandR);
1822             return JNI_FALSE;
1823         }
1824     }
1825 
1826     LOAD_XRANDR_FUNC(XRRGetScreenInfo);
1827     LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);
1828     LOAD_XRANDR_FUNC(XRRConfigRates);
1829     LOAD_XRANDR_FUNC(XRRConfigCurrentRate);
1830     LOAD_XRANDR_FUNC(XRRConfigSizes);
1831     LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);
1832     LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);
1833     LOAD_XRANDR_FUNC(XRRConfigRotations);
1834     LOAD_XRANDR_FUNC(XRRGetScreenResources);
1835     LOAD_XRANDR_FUNC(XRRFreeScreenResources);
1836     LOAD_XRANDR_FUNC(XRRGetOutputInfo);
1837     LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
1838     LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
1839     LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
1840 
1841     return JNI_TRUE;
1842 }
1843 
1844 static jobject
X11GD_CreateDisplayMode(JNIEnv * env,jint width,jint height,jint bitDepth,jint refreshRate)1845 X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height,
1846                         jint bitDepth, jint refreshRate)
1847 {
1848     jclass displayModeClass;
1849     jmethodID cid;
1850     jint validRefreshRate = refreshRate;
1851 
1852     displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");
1853     CHECK_NULL_RETURN(displayModeClass, NULL);
1854     if (JNU_IsNull(env, displayModeClass)) {
1855         JNU_ThrowInternalError(env,
1856                                "Could not get display mode class");
1857         return NULL;
1858     }
1859 
1860     cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V");
1861     CHECK_NULL_RETURN(cid, NULL);
1862     if (cid == NULL) {
1863         JNU_ThrowInternalError(env,
1864                                "Could not get display mode constructor");
1865         return NULL;
1866     }
1867 
1868     // early versions of xrandr may report "empty" rates (6880694)
1869     if (validRefreshRate <= 0) {
1870         validRefreshRate = REFRESH_RATE_UNKNOWN;
1871     }
1872 
1873     return (*env)->NewObject(env, displayModeClass, cid,
1874                              width, height, bitDepth, validRefreshRate);
1875 }
1876 
1877 static void
X11GD_AddDisplayMode(JNIEnv * env,jobject arrayList,jint width,jint height,jint bitDepth,jint refreshRate)1878 X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList,
1879                      jint width, jint height,
1880                      jint bitDepth, jint refreshRate)
1881 {
1882     jobject displayMode = X11GD_CreateDisplayMode(env, width, height,
1883                                                   bitDepth, refreshRate);
1884     if (!JNU_IsNull(env, displayMode)) {
1885         jclass arrayListClass;
1886         jmethodID mid;
1887         arrayListClass = (*env)->GetObjectClass(env, arrayList);
1888         if (JNU_IsNull(env, arrayListClass)) {
1889             JNU_ThrowInternalError(env,
1890                                    "Could not get class java.util.ArrayList");
1891             return;
1892         }
1893         mid = (*env)->GetMethodID(env, arrayListClass, "add",
1894                                   "(Ljava/lang/Object;)Z");
1895         CHECK_NULL(mid);
1896         if (mid == NULL) {
1897             JNU_ThrowInternalError(env,
1898                 "Could not get method java.util.ArrayList.add()");
1899             return;
1900         }
1901         (*env)->CallObjectMethod(env, arrayList, mid, displayMode);
1902         (*env)->DeleteLocalRef(env, displayMode);
1903     }
1904 }
1905 
1906 #endif /* !_AIX */
1907 
1908 static void
X11GD_SetFullscreenMode(Window win,jboolean enabled)1909 X11GD_SetFullscreenMode(Window win, jboolean enabled)
1910 {
1911     Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False);
1912     Atom wmStateFs = XInternAtom(awt_display,
1913                                  "_NET_WM_STATE_FULLSCREEN", False);
1914     XWindowAttributes attr;
1915     XEvent event;
1916 
1917     if (wmState == None || wmStateFs == None
1918             || !XGetWindowAttributes(awt_display, win, &attr)) {
1919         return;
1920     }
1921 
1922     memset(&event, 0, sizeof(event));
1923     event.xclient.type = ClientMessage;
1924     event.xclient.message_type = wmState;
1925     event.xclient.display = awt_display;
1926     event.xclient.window = win;
1927     event.xclient.format = 32;
1928     event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove
1929     event.xclient.data.l[1] = wmStateFs;
1930 
1931     XSendEvent(awt_display, attr.root, False,
1932                SubstructureRedirectMask | SubstructureNotifyMask,
1933                &event);
1934     XSync(awt_display, False);
1935 }
1936 #endif /* !HEADLESS */
1937 
1938 /*
1939  * Class:     sun_awt_X11GraphicsDevice
1940  * Method:    initXrandrExtension
1941  * Signature: ()Z
1942  */
1943 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsDevice_initXrandrExtension(JNIEnv * env,jclass x11gd)1944 Java_sun_awt_X11GraphicsDevice_initXrandrExtension
1945     (JNIEnv *env, jclass x11gd)
1946 {
1947 #if defined(HEADLESS) || defined(_AIX)
1948     return JNI_FALSE;
1949 #else
1950     int opcode = 0, firstEvent = 0, firstError = 0;
1951     jboolean ret;
1952 
1953     AWT_LOCK();
1954     ret = (jboolean)XQueryExtension(awt_display, "RANDR",
1955                                     &opcode, &firstEvent, &firstError);
1956     if (ret) {
1957         ret = X11GD_InitXrandrFuncs(env);
1958     }
1959     AWT_FLUSH_UNLOCK();
1960 
1961     return ret;
1962 #endif /* HEADLESS */
1963 }
1964 
1965 /*
1966  * Class:     sun_awt_X11GraphicsDevice
1967  * Method:    getCurrentDisplayMode
1968  * Signature: (I)Ljava/awt/DisplayMode;
1969  */
1970 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode(JNIEnv * env,jclass x11gd,jint screen)1971 Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
1972     (JNIEnv* env, jclass x11gd, jint screen)
1973 {
1974 #if defined(HEADLESS) || defined(_AIX)
1975     return NULL;
1976 #else
1977     XRRScreenConfiguration *config;
1978     jobject displayMode = NULL;
1979 
1980     AWT_LOCK();
1981 
1982     if (usingXinerama && XScreenCount(awt_display) > 0) {
1983         XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
1984                                                     RootWindow(awt_display, 0));
1985         if (res) {
1986             if (res->noutput > screen) {
1987                 XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
1988                                                      res, res->outputs[screen]);
1989                 if (output_info) {
1990                     if (output_info->crtc) {
1991                         XRRCrtcInfo *crtc_info =
1992                                     awt_XRRGetCrtcInfo (awt_display, res,
1993                                                         output_info->crtc);
1994                         if (crtc_info) {
1995                             if (crtc_info->mode) {
1996                                 int i;
1997                                 for (i = 0; i < res->nmode; i++) {
1998                                     XRRModeInfo *mode = &res->modes[i];
1999                                     if (mode->id == crtc_info->mode) {
2000                                         float rate = 0;
2001                                         if (mode->hTotal && mode->vTotal) {
2002                                              rate = ((float)mode->dotClock /
2003                                                     ((float)mode->hTotal *
2004                                                     (float)mode->vTotal));
2005                                         }
2006                                         displayMode = X11GD_CreateDisplayMode(
2007                                                            env,
2008                                                            mode->width,
2009                                                            mode->height,
2010                                                            BIT_DEPTH_MULTI,
2011                                                            (int)(rate +.2));
2012                                         break;
2013                                     }
2014                                 }
2015                             }
2016                             awt_XRRFreeCrtcInfo(crtc_info);
2017                         }
2018                     }
2019                     awt_XRRFreeOutputInfo(output_info);
2020                 }
2021             }
2022             awt_XRRFreeScreenResources(res);
2023         }
2024     } else {
2025 
2026         config = awt_XRRGetScreenInfo(awt_display,
2027                                       RootWindow(awt_display, screen));
2028         if (config != NULL) {
2029             Rotation rotation;
2030             short curRate;
2031             SizeID curSizeIndex;
2032             XRRScreenSize *sizes;
2033             int nsizes;
2034 
2035             curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);
2036             sizes = awt_XRRConfigSizes(config, &nsizes);
2037             curRate = awt_XRRConfigCurrentRate(config);
2038 
2039             if ((sizes != NULL) &&
2040                 (curSizeIndex < nsizes))
2041             {
2042                 XRRScreenSize curSize = sizes[curSizeIndex];
2043                 displayMode = X11GD_CreateDisplayMode(env,
2044                                                       curSize.width,
2045                                                       curSize.height,
2046                                                       BIT_DEPTH_MULTI,
2047                                                       curRate);
2048             }
2049 
2050             awt_XRRFreeScreenConfigInfo(config);
2051         }
2052     }
2053 
2054     AWT_FLUSH_UNLOCK();
2055 
2056     return displayMode;
2057 #endif /* HEADLESS */
2058 }
2059 
2060 /*
2061  * Class:     sun_awt_X11GraphicsDevice
2062  * Method:    enumDisplayModes
2063  * Signature: (ILjava/util/ArrayList;)V
2064  */
2065 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_enumDisplayModes(JNIEnv * env,jclass x11gd,jint screen,jobject arrayList)2066 Java_sun_awt_X11GraphicsDevice_enumDisplayModes
2067     (JNIEnv* env, jclass x11gd,
2068      jint screen, jobject arrayList)
2069 {
2070 #if !defined(HEADLESS) && !defined(_AIX)
2071 
2072     AWT_LOCK();
2073 
2074     if (usingXinerama && XScreenCount(awt_display) > 0) {
2075         XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
2076                                                     RootWindow(awt_display, 0));
2077         if (res) {
2078            if (res->noutput > screen) {
2079                 XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
2080                                                      res, res->outputs[screen]);
2081                 if (output_info) {
2082                     int i;
2083                     for (i = 0; i < output_info->nmode; i++) {
2084                         RRMode m = output_info->modes[i];
2085                         int j;
2086                         XRRModeInfo *mode;
2087                         for (j = 0; j < res->nmode; j++) {
2088                             mode = &res->modes[j];
2089                             if (mode->id == m) {
2090                                  float rate = 0;
2091                                  if (mode->hTotal && mode->vTotal) {
2092                                      rate = ((float)mode->dotClock /
2093                                                    ((float)mode->hTotal *
2094                                                           (float)mode->vTotal));
2095                                  }
2096                                  X11GD_AddDisplayMode(env, arrayList,
2097                                         mode->width, mode->height,
2098                                               BIT_DEPTH_MULTI, (int)(rate +.2));
2099                                  if ((*env)->ExceptionCheck(env)) {
2100                                      goto ret0;
2101                                  }
2102                                  break;
2103                             }
2104                         }
2105                     }
2106 ret0:
2107                     awt_XRRFreeOutputInfo(output_info);
2108                 }
2109             }
2110             awt_XRRFreeScreenResources(res);
2111         }
2112     } else {
2113         XRRScreenConfiguration *config;
2114 
2115         config = awt_XRRGetScreenInfo(awt_display,
2116                                       RootWindow(awt_display, screen));
2117         if (config != NULL) {
2118             int nsizes, i, j;
2119             XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
2120 
2121             if (sizes != NULL) {
2122                 for (i = 0; i < nsizes; i++) {
2123                     int nrates;
2124                     XRRScreenSize size = sizes[i];
2125                     short *rates = awt_XRRConfigRates(config, i, &nrates);
2126 
2127                     for (j = 0; j < nrates; j++) {
2128                         X11GD_AddDisplayMode(env, arrayList,
2129                                              size.width,
2130                                              size.height,
2131                                              BIT_DEPTH_MULTI,
2132                                              rates[j]);
2133                         if ((*env)->ExceptionCheck(env)) {
2134                             goto ret1;
2135                         }
2136                     }
2137                 }
2138             }
2139 ret1:
2140             awt_XRRFreeScreenConfigInfo(config);
2141         }
2142     }
2143 
2144     AWT_FLUSH_UNLOCK();
2145 #endif /* !HEADLESS */
2146 }
2147 
2148 /*
2149  * Class:     sun_awt_X11GraphicsDevice
2150  * Method:    configDisplayMode
2151  * Signature: (IIII)V
2152  */
2153 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_configDisplayMode(JNIEnv * env,jclass x11gd,jint screen,jint width,jint height,jint refreshRate)2154 Java_sun_awt_X11GraphicsDevice_configDisplayMode
2155     (JNIEnv* env, jclass x11gd,
2156      jint screen, jint width, jint height, jint refreshRate)
2157 {
2158 #if !defined(HEADLESS) && !defined(_AIX)
2159     jboolean success = JNI_FALSE;
2160     XRRScreenConfiguration *config;
2161     Drawable root;
2162     Rotation currentRotation = RR_Rotate_0;
2163 
2164     AWT_LOCK();
2165 
2166     root = RootWindow(awt_display, screen);
2167     config = awt_XRRGetScreenInfo(awt_display, root);
2168     if (config != NULL) {
2169         jboolean foundConfig = JNI_FALSE;
2170         int chosenSizeIndex = -1;
2171         short chosenRate = -1;
2172         int nsizes;
2173         XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
2174         awt_XRRConfigRotations(config, &currentRotation);
2175 
2176         if (sizes != NULL) {
2177             int i, j;
2178 
2179             /* find the size index that matches the requested dimensions */
2180             for (i = 0; i < nsizes; i++) {
2181                 XRRScreenSize size = sizes[i];
2182 
2183                 if ((size.width == width) && (size.height == height)) {
2184                     /* we've found our size index... */
2185                     int nrates;
2186                     short *rates = awt_XRRConfigRates(config, i, &nrates);
2187 
2188                     /* now find rate that matches requested refresh rate */
2189                     for (j = 0; j < nrates; j++) {
2190                         if (rates[j] == refreshRate) {
2191                             /* we've found our rate; break out of the loop */
2192                             chosenSizeIndex = i;
2193                             chosenRate = rates[j];
2194                             foundConfig = JNI_TRUE;
2195                             break;
2196                         }
2197                     }
2198 
2199                     break;
2200                 }
2201             }
2202         }
2203 
2204         if (foundConfig) {
2205             Status status =
2206                 awt_XRRSetScreenConfigAndRate(awt_display, config, root,
2207                                               chosenSizeIndex,
2208                                               currentRotation,
2209                                               chosenRate,
2210                                               CurrentTime);
2211 
2212             /* issue XSync to ensure immediate mode change */
2213             XSync(awt_display, False);
2214 
2215             if (status == RRSetConfigSuccess) {
2216                 success = JNI_TRUE;
2217             }
2218         }
2219 
2220         awt_XRRFreeScreenConfigInfo(config);
2221     }
2222 
2223     AWT_FLUSH_UNLOCK();
2224 
2225     if (!success && !(*env)->ExceptionCheck(env)) {
2226         JNU_ThrowInternalError(env, "Could not set display mode");
2227     }
2228 #endif /* !HEADLESS */
2229 }
2230 
2231 /*
2232  * Class:     sun_awt_X11GraphicsDevice
2233  * Method:    enterFullScreenExclusive
2234  * Signature: (J)V
2235  */
2236 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive(JNIEnv * env,jclass x11gd,jlong window)2237 Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive
2238     (JNIEnv* env, jclass x11gd,
2239      jlong window)
2240 {
2241 #ifndef HEADLESS
2242     Window win = (Window)window;
2243 
2244     AWT_LOCK();
2245     XSync(awt_display, False); /* ensures window is visible first */
2246     X11GD_SetFullscreenMode(win, JNI_TRUE);
2247     AWT_UNLOCK();
2248 #endif /* !HEADLESS */
2249 }
2250 
2251 /*
2252  * Class:     sun_awt_X11GraphicsDevice
2253  * Method:    exitFullScreenExclusive
2254  * Signature: (J)V
2255  */
2256 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive(JNIEnv * env,jclass x11gd,jlong window)2257 Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive
2258     (JNIEnv* env, jclass x11gd,
2259      jlong window)
2260 {
2261 #ifndef HEADLESS
2262     Window win = (Window)window;
2263 
2264     AWT_LOCK();
2265     X11GD_SetFullscreenMode(win, JNI_FALSE);
2266     AWT_UNLOCK();
2267 #endif /* !HEADLESS */
2268 }
2269 
2270 /**
2271  * End DisplayMode/FullScreen support
2272  */
2273 
get_output_screen_name(JNIEnv * env,int screen)2274 static char *get_output_screen_name(JNIEnv *env, int screen) {
2275 #ifdef _AIX
2276     return NULL;
2277 #else
2278     if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) {
2279         return NULL;
2280     }
2281     char *name = NULL;
2282     AWT_LOCK();
2283     int scr = 0, out = 0;
2284     if (usingXinerama && XScreenCount(awt_display) > 0) {
2285         out = screen;
2286     } else {
2287         scr = screen;
2288     }
2289 
2290     XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
2291                                                   RootWindow(awt_display, scr));
2292     if (res) {
2293        if (res->noutput > out) {
2294             XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
2295                                                         res, res->outputs[out]);
2296             if (output_info) {
2297                 if (output_info->name) {
2298                     name = strdup(output_info->name);
2299                 }
2300                 awt_XRRFreeOutputInfo(output_info);
2301             }
2302         }
2303         awt_XRRFreeScreenResources(res);
2304     }
2305     AWT_UNLOCK();
2306     return name;
2307 #endif /* _AIX */
2308 }
2309 
2310 /*
2311  * Class:     sun_awt_X11GraphicsDevice
2312  * Method:    getNativeScaleFactor
2313  * Signature: (I)D
2314  */
2315 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor(JNIEnv * env,jobject this,jint screen)2316 Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
2317     (JNIEnv *env, jobject this, jint screen) {
2318     // in case of Xinerama individual screen scales are not supported
2319     char *name = get_output_screen_name(env, usingXinerama ? 0 : screen);
2320     double scale = getNativeScaleFactor(name);
2321     if (name) {
2322         free(name);
2323     }
2324     return scale;
2325 }
2326