22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "X11SurfaceData.h"
27 #include "GraphicsPrimitiveMgr.h"
28 #include "Region.h"
29 #include "Trace.h"
30
31 /* Needed to define intptr_t */
32 #include "gdefs.h"
33
34 #include "jni_util.h"
35 #include "jvm_md.h"
36 #include "awt_Component.h"
37 #include "awt_GraphicsEnv.h"
38
39 #include <dlfcn.h>
40
41 #ifndef HEADLESS
42 static JDgaLibInfo DgaLibInfoStub;
43 static JDgaLibInfo theJDgaInfo;
44 static JDgaLibInfo *pJDgaInfo = &DgaLibInfoStub;
45
46
47 /**
48 * This file contains support code for loops using the SurfaceData
49 * interface to talk to an X11 drawable from native code.
50 */
51
52 typedef struct _X11RIPrivate {
53 jint lockType;
54 jint lockFlags;
55 XImage *img;
56 int x, y;
57 } X11RIPrivate;
58
59 #define XSD_MAX(a,b) ((a) > (b) ? (a) : (b))
60 #define XSD_MIN(a,b) ((a) < (b) ? (a) : (b))
61
62 static LockFunc X11SD_Lock;
63 static GetRasInfoFunc X11SD_GetRasInfo;
64 static UnlockFunc X11SD_Unlock;
65 static DisposeFunc X11SD_Dispose;
66 static GetPixmapBgFunc X11SD_GetPixmapWithBg;
67 static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg;
68 extern int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr);
69 extern AwtGraphicsConfigDataPtr
70 getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
71 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
72
73 static int X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
74 X11SDOps *xsdo);
75 static int X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
76 X11SDOps *xsdo);
77 static void X11SD_SwapBytes(X11SDOps *xsdo, XImage *img, int depth, int bpp);
78 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
79 SurfaceDataBounds *bounds,
80 jint lockFlags);
81
82 extern jfieldID validID;
83
84 static int nativeByteOrder;
85 static jboolean dgaAvailable = JNI_FALSE;
86 static jboolean useDGAWithPixmaps = JNI_FALSE;
87 static jclass xorCompClass;
88
89 jint useMitShmExt = CANT_USE_MITSHM;
90 jint useMitShmPixmaps = CANT_USE_MITSHM;
91 jint forceSharedPixmaps = JNI_FALSE;
92 int mitShmPermissionMask = MITSHM_PERM_OWNER;
93
94 /* Cached shared image, one for all surface datas. */
95 static XImage * cachedXImage;
96
97 #endif /* !HEADLESS */
98
99 jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
100 {
101 #ifndef HEADLESS
102 union {
103 char c[4];
104 int i;
105 } endian;
106
107 endian.i = 0xff000000;
108 nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
109
110 dgaAvailable = JNI_FALSE;
111
112 cachedXImage = NULL;
113
114 if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
115 JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
116 return JNI_FALSE;
117 }
118
119 #ifdef MITSHM
120 if (getenv("NO_AWT_MITSHM") == NULL &&
121 getenv("NO_J2D_MITSHM") == NULL) {
122 char * force;
123 char * permission = getenv("J2D_MITSHM_PERMISSION");
124 if (permission != NULL) {
125 if (strcmp(permission, "common") == 0) {
126 mitShmPermissionMask = MITSHM_PERM_COMMON;
127 }
128 }
129
130 TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
131
141 }
142 }else {
143 useMitShmPixmaps = JNI_FALSE;
144 }
145 }
146 #endif /* MITSHM */
147
148 #endif /* !HEADLESS */
149
150 return JNI_TRUE;
151 }
152
153
154 /*
155 * Class: sun_java2d_x11_X11SurfaceData
156 * Method: initIDs
157 * Signature: (Ljava/lang/Class;Z)V
158 */
159 JNIEXPORT void JNICALL
160 Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
161 jclass XORComp, jboolean tryDGA)
162 {
163 #ifndef HEADLESS
164 if(XShared_initIDs(env, JNI_TRUE))
165 {
166 void *lib = 0;
167
168 xorCompClass = (*env)->NewGlobalRef(env, XORComp);
169
170 if (tryDGA && (getenv("NO_J2D_DGA") == NULL)) {
171 /* we use RTLD_NOW because of bug 4032715 */
172 lib = dlopen(JNI_LIB_NAME("sunwjdga"), RTLD_NOW);
173 }
174
175 if (lib != NULL) {
176 JDgaStatus ret = JDGA_FAILED;
177 void *sym = dlsym(lib, "JDgaLibInit");
178 if (sym != NULL) {
179 theJDgaInfo.display = awt_display;
180 AWT_LOCK();
181 ret = (*(JDgaLibInitFunc *)sym)(env, &theJDgaInfo);
182 AWT_UNLOCK();
183 }
184 if (ret == JDGA_SUCCESS) {
185 pJDgaInfo = &theJDgaInfo;
186 dgaAvailable = JNI_TRUE;
187 useDGAWithPixmaps = (getenv("USE_DGA_PIXMAPS") != NULL);
188 } else {
189 dlclose(lib);
190 lib = NULL;
191 }
192 }
193 }
194 #endif /* !HEADLESS */
195 }
196
197 /*
198 * Class: sun_java2d_x11_X11SurfaceData
199 * Method: isDrawableValid
200 * Signature: ()Z
201 */
202 JNIEXPORT jboolean JNICALL
203 Java_sun_java2d_x11_XSurfaceData_isDrawableValid(JNIEnv *env, jobject this)
204 {
205 jboolean ret = JNI_FALSE;
206
207 #ifndef HEADLESS
208 X11SDOps *xsdo = X11SurfaceData_GetOps(env, this);
209
210 AWT_LOCK();
211 if (xsdo->drawable != 0 || X11SD_InitWindow(env, xsdo) == SD_SUCCESS) {
212 ret = JNI_TRUE;
217 return ret;
218 }
219
220 /*
221 * Class: sun_java2d_x11_X11SurfaceData
222 * Method: isShmPMAvailable
223 * Signature: ()Z
224 */
225 JNIEXPORT jboolean JNICALL
226 Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
227 {
228 #if defined(HEADLESS) || !defined(MITSHM)
229 return JNI_FALSE;
230 #else
231 return (jboolean)useMitShmPixmaps;
232 #endif /* HEADLESS, MITSHM */
233 }
234
235 /*
236 * Class: sun_java2d_x11_X11SurfaceData
237 * Method: isDgaAvailable
238 * Signature: ()Z
239 */
240 JNIEXPORT jboolean JNICALL
241 Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable(JNIEnv *env, jobject this)
242 {
243 #if defined(HEADLESS) || defined(__linux__)
244 return JNI_FALSE;
245 #else
246 return dgaAvailable;
247 #endif /* HEADLESS */
248 }
249
250 /*
251 * Class: sun_java2d_x11_X11SurfaceData
252 * Method: initOps
253 * Signature: (Ljava/lang/Object;I)V
254 */
255 JNIEXPORT void JNICALL
256 Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd,
257 jobject peer,
258 jobject graphicsConfig, jint depth)
259 {
260 #ifndef HEADLESS
261 X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps));
262 jboolean hasException;
263 if (xsdo == NULL) {
264 JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
265 return;
266 }
267 xsdo->sdOps.Lock = X11SD_Lock;
268 xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo;
269 xsdo->sdOps.Unlock = X11SD_Unlock;
270 xsdo->sdOps.Dispose = X11SD_Dispose;
271 xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg;
272 xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg;
273 if (peer != NULL) {
274 xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j;
275 if (hasException) {
276 return;
277 }
278 } else {
279 xsdo->drawable = 0;
280 }
281 xsdo->depth = depth;
282 xsdo->dgaAvailable = dgaAvailable;
283 xsdo->isPixmap = JNI_FALSE;
284 xsdo->bitmask = 0;
285 xsdo->bgPixel = 0;
286 xsdo->isBgInitialized = JNI_FALSE;
287 #ifdef MITSHM
288 xsdo->shmPMData.shmSegInfo = NULL;
289 xsdo->shmPMData.xRequestSent = JNI_FALSE;
290 xsdo->shmPMData.pmSize = 0;
291 xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
292 xsdo->shmPMData.pixmap = 0;
293 xsdo->shmPMData.shmPixmap = 0;
294 xsdo->shmPMData.numBltsSinceRead = 0;
295 xsdo->shmPMData.pixelsReadSinceBlt = 0;
296 xsdo->shmPMData.numBltsThreshold = 2;
297 #endif /* MITSHM */
298
299 xsdo->configData = (AwtGraphicsConfigDataPtr)
300 JNU_GetLongFieldAsPtr(env,
301 graphicsConfig,
302 x11GraphicsConfigIDs.aData);
430
431 jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable)
432 {
433 #ifndef HEADLESS
434
435 if (drawable != (jlong)0) {
436 /* Double-buffering */
437 xsdo->drawable = drawable;
438 xsdo->isPixmap = JNI_FALSE;
439 } else {
440 /*
441 * width , height must be nonzero otherwise XCreatePixmap
442 * generates BadValue in error_handler
443 */
444 if (width <= 0 || height <= 0 || width > 32767 || height > 32767) {
445 JNU_ThrowOutOfMemoryError(env,
446 "Can't create offscreen surface");
447 return JNI_FALSE;
448 }
449 xsdo->isPixmap = JNI_TRUE;
450 /* REMIND: workaround for bug 4420220 on pgx32 boards:
451 don't use DGA with pixmaps unless USE_DGA_PIXMAPS is set.
452 */
453 xsdo->dgaAvailable = useDGAWithPixmaps;
454
455 xsdo->pmWidth = width;
456 xsdo->pmHeight = height;
457
458 #ifdef MITSHM
459 xsdo->shmPMData.pmSize = width * height * depth;
460 xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
461 if (forceSharedPixmaps) {
462 AWT_LOCK();
463 xsdo->drawable = X11SD_CreateSharedPixmap(xsdo);
464 AWT_UNLOCK();
465 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
466 if (xsdo->drawable) {
467 xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
468 xsdo->shmPMData.shmPixmap = xsdo->drawable;
469 return JNI_TRUE;
470 }
471 }
472 #endif /* MITSHM */
473
830 xsdo->cData->img_oda_blue == NULL))
831 {
832 AWT_UNLOCK();
833 if (!(*env)->ExceptionCheck(env))
834 {
835 JNU_ThrowNullPointerException(env, "inverse colormap lookup table");
836 }
837 return SD_FAILURE;
838 }
839 if ((lockflags & SD_LOCK_INVGRAY) != 0 &&
840 (xsdo->cData == NULL ||
841 xsdo->cData->pGrayInverseLutData == NULL))
842 {
843 AWT_UNLOCK();
844 if (!(*env)->ExceptionCheck(env))
845 {
846 JNU_ThrowNullPointerException(env, "inverse gray lookup table");
847 }
848 return SD_FAILURE;
849 }
850 if (xsdo->dgaAvailable && (lockflags & (SD_LOCK_RD_WR))) {
851 int dgaret;
852
853 dgaret = (*pJDgaInfo->pGetLock)(env, awt_display, &xsdo->dgaDev,
854 xsdo->drawable, &xsdo->surfInfo,
855 pRasInfo->bounds.x1,
856 pRasInfo->bounds.y1,
857 pRasInfo->bounds.x2,
858 pRasInfo->bounds.y2);
859 if (dgaret == JDGA_SUCCESS) {
860 int wx = xsdo->surfInfo.window.lox;
861 int wy = xsdo->surfInfo.window.loy;
862 pRasInfo->bounds.x1 = xsdo->surfInfo.visible.lox - wx;
863 pRasInfo->bounds.y1 = xsdo->surfInfo.visible.loy - wy;
864 pRasInfo->bounds.x2 = xsdo->surfInfo.visible.hix - wx;
865 pRasInfo->bounds.y2 = xsdo->surfInfo.visible.hiy - wy;
866 xpriv->lockType = X11SD_LOCK_BY_DGA;
867 xpriv->lockFlags = lockflags;
868 return SD_SUCCESS;
869 } else if (dgaret == JDGA_UNAVAILABLE) {
870 xsdo->dgaAvailable = JNI_FALSE;
871 }
872 }
873 if (lockflags & SD_LOCK_RD_WR) {
874 if (lockflags & SD_LOCK_FASTEST) {
875 ret = SD_SLOWLOCK;
876 }
877 xpriv->lockType = X11SD_LOCK_BY_XIMAGE;
878 if (xsdo->isPixmap) {
879 #ifdef MITSHM
880 if (xsdo->shmPMData.usingShmPixmap) {
881 xpriv->lockType = X11SD_LOCK_BY_SHMEM;
882 }
883 #endif /* MITSHM */
884 if (pRasInfo->bounds.x1 < 0) {
885 pRasInfo->bounds.x1 = 0;
886 }
887 if (pRasInfo->bounds.y1 < 0) {
888 pRasInfo->bounds.y1 = 0;
889 }
890 if (pRasInfo->bounds.x2 > xsdo->pmWidth) {
891 pRasInfo->bounds.x2 = xsdo->pmWidth;
892 }
898 /* They didn't lock for anything - we won't give them anything */
899 xpriv->lockType = X11SD_LOCK_BY_NULL;
900 }
901 xpriv->lockFlags = lockflags;
902 xpriv->img = NULL;
903
904 return ret;
905 /* AWT_UNLOCK() called in Unlock */
906 }
907
908 static void X11SD_GetRasInfo(JNIEnv *env,
909 SurfaceDataOps *ops,
910 SurfaceDataRasInfo *pRasInfo)
911 {
912 X11SDOps *xsdo = (X11SDOps *) ops;
913 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
914 jint lockFlags = xpriv->lockFlags;
915 jint depth = xsdo->depth;
916 int mult = xsdo->configData->pixelStride;
917
918 if (xsdo->dgaAvailable &&
919 xpriv->lockType == X11SD_LOCK_BY_XIMAGE &&
920 (lockFlags & SD_LOCK_FASTEST))
921 {
922 /* Try one more time to use DGA (now with smaller bounds)... */
923 int dgaret;
924
925 dgaret = (*pJDgaInfo->pGetLock)(env, awt_display, &xsdo->dgaDev,
926 xsdo->drawable, &xsdo->surfInfo,
927 pRasInfo->bounds.x1,
928 pRasInfo->bounds.y1,
929 pRasInfo->bounds.x2,
930 pRasInfo->bounds.y2);
931 if (dgaret == JDGA_SUCCESS) {
932 int wx = xsdo->surfInfo.window.lox;
933 int wy = xsdo->surfInfo.window.loy;
934 pRasInfo->bounds.x1 = xsdo->surfInfo.visible.lox - wx;
935 pRasInfo->bounds.y1 = xsdo->surfInfo.visible.loy - wy;
936 pRasInfo->bounds.x2 = xsdo->surfInfo.visible.hix - wx;
937 pRasInfo->bounds.y2 = xsdo->surfInfo.visible.hiy - wy;
938 xpriv->lockType = X11SD_LOCK_BY_DGA;
939 } else if (dgaret == JDGA_UNAVAILABLE) {
940 xsdo->dgaAvailable = JNI_FALSE;
941 }
942 }
943
944 if (xpriv->lockType == X11SD_LOCK_BY_DGA) {
945 int scan = xsdo->surfInfo.surfaceScan;
946 int wx = xsdo->surfInfo.window.lox;
947 int wy = xsdo->surfInfo.window.loy;
948 pRasInfo->rasBase =
949 (void *)(((uintptr_t) xsdo->surfInfo.basePtr) + (scan*wy + wx) * mult);
950 pRasInfo->pixelStride = mult;
951 pRasInfo->pixelBitOffset = 0;
952 pRasInfo->scanStride = scan * mult;
953 #ifdef MITSHM
954 } else if (xpriv->lockType == X11SD_LOCK_BY_SHMEM) {
955 if (xsdo->shmPMData.xRequestSent == JNI_TRUE) {
956 /* need to sync before using shared mem pixmap
957 if any x calls were issued for this pixmap */
958 XSync(awt_display, False);
959 xsdo->shmPMData.xRequestSent = JNI_FALSE;
960 }
961 xpriv->x = pRasInfo->bounds.x1;
962 xpriv->y = pRasInfo->bounds.y1;
963 pRasInfo->rasBase = xsdo->shmPMData.shmSegInfo->shmaddr;
964 pRasInfo->pixelStride = mult;
965 pRasInfo->pixelBitOffset = 0;
966 pRasInfo->scanStride = xsdo->shmPMData.bytesPerLine;
967 #endif /* MITSHM */
968 } else if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) {
969 int x, y, w, h;
970 x = pRasInfo->bounds.x1;
971 y = pRasInfo->bounds.y1;
972 w = pRasInfo->bounds.x2 - x;
973 h = pRasInfo->bounds.y2 - y;
974
975 xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags);
976 if (xpriv->img) {
977 int scan = xpriv->img->bytes_per_line;
978 xpriv->x = x;
979 xpriv->y = y;
980 pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan;
981 pRasInfo->pixelStride = mult;
982 pRasInfo->pixelBitOffset = 0;
983 pRasInfo->scanStride = scan;
984 } else {
985 pRasInfo->rasBase = NULL;
986 pRasInfo->pixelStride = 0;
987 pRasInfo->pixelBitOffset = 0;
988 pRasInfo->scanStride = 0;
1009 } else {
1010 pRasInfo->invColorTable = NULL;
1011 pRasInfo->redErrTable = NULL;
1012 pRasInfo->grnErrTable = NULL;
1013 pRasInfo->bluErrTable = NULL;
1014 }
1015 if (lockFlags & SD_LOCK_INVGRAY) {
1016 pRasInfo->invGrayTable = xsdo->cData->pGrayInverseLutData;
1017 } else {
1018 pRasInfo->invGrayTable = NULL;
1019 }
1020 }
1021
1022 static void X11SD_Unlock(JNIEnv *env,
1023 SurfaceDataOps *ops,
1024 SurfaceDataRasInfo *pRasInfo)
1025 {
1026 X11SDOps *xsdo = (X11SDOps *) ops;
1027 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
1028
1029 if (xpriv->lockType == X11SD_LOCK_BY_DGA) {
1030 (*pJDgaInfo->pReleaseLock)(env, xsdo->dgaDev, xsdo->drawable);
1031 } else if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE &&
1032 xpriv->img != NULL)
1033 {
1034 if (xpriv->lockFlags & SD_LOCK_WRITE) {
1035 int x = xpriv->x;
1036 int y = xpriv->y;
1037 int w = pRasInfo->bounds.x2 - x;
1038 int h = pRasInfo->bounds.y2 - y;
1039 Drawable drawable = xsdo->drawable;
1040 GC xgc = xsdo->cachedGC;
1041 if (xgc == NULL) {
1042 xsdo->cachedGC = xgc =
1043 XCreateGC(awt_display, drawable, 0L, NULL);
1044 }
1045
1046 if (xpriv->img->byte_order != nativeByteOrder) {
1047 /* switching bytes back in 24 and 32 bpp cases. */
1048 /* For 16 bit XLib will switch for us. */
1049 if (xsdo->depth > 16) {
1050 X11SD_SwapBytes(xsdo, xpriv->img, xsdo->depth,
1051 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel);
1052 }
1053 }
1054
1055 #ifdef MITSHM
1056 if (xpriv->img->obdata != NULL) {
1057 XShmPutImage(awt_display, drawable, xgc,
1058 xpriv->img, 0, 0, x, y, w, h, False);
1059 XFlush(awt_display);
1060 } else {
1061 XPutImage(awt_display, drawable, xgc,
1062 xpriv->img, 0, 0, x, y, w, h);
1063 }
1064 if (xsdo->shmPMData.usingShmPixmap) {
1065 xsdo->shmPMData.xRequestSent = JNI_TRUE;
1066 }
1067 #else
1068 XPutImage(awt_display, drawable, xgc,
1069 xpriv->img, 0, 0, x, y, w, h);
1070 #endif /* MITSHM */
1071
1072 (*pJDgaInfo->pXRequestSent)(env, xsdo->dgaDev, drawable);
1073 }
1074 X11SD_DisposeOrCacheXImage(xpriv->img);
1075 xpriv->img = (XImage *)NULL;
1076 }
1077 /* the background pixel is not valid anymore */
1078 if (xpriv->lockFlags & SD_LOCK_WRITE) {
1079 xsdo->isBgInitialized = JNI_FALSE;
1080 }
1081 xpriv->lockType = X11SD_LOCK_UNLOCKED;
1082 AWT_UNLOCK();
1083 }
1084
1085 static int
1086 X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
1087 X11SDOps *xsdo)
1088 {
1089 short x1=0, y1=0, x2=0, y2=0;
1090 int tmpx, tmpy;
1091 Window tmpchild;
1092
1375 X11SD_DisposeXImage(cachedXImage);
1376 }
1377 cachedXImage = image;
1378 } else {
1379 X11SD_DisposeXImage(image);
1380 }
1381 }
1382
1383 void X11SD_DisposeXImage(XImage * image) {
1384 if (image != NULL) {
1385 #ifdef MITSHM
1386 if (image->obdata != NULL) {
1387 X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata);
1388 image->obdata = NULL;
1389 }
1390 #endif /* MITSHM */
1391 XDestroyImage(image);
1392 }
1393 }
1394
1395 static JDgaStatus
1396 GetLockStub(JNIEnv *env, Display *display, void **dgaDev,
1397 Drawable d, JDgaSurfaceInfo *pSurface,
1398 jint lox, jint loy, jint hix, jint hiy)
1399 {
1400 return JDGA_UNAVAILABLE;
1401 }
1402
1403 static JDgaStatus
1404 ReleaseLockStub(JNIEnv *env, void *dgaDev, Drawable d)
1405 {
1406 return JDGA_FAILED;
1407 }
1408
1409 static void
1410 XRequestSentStub(JNIEnv *env, void *dgaDev, Drawable d)
1411 {
1412 }
1413
1414 static void
1415 LibDisposeStub(JNIEnv *env)
1416 {
1417 }
1418
1419 static JDgaLibInfo DgaLibInfoStub = {
1420 NULL,
1421 GetLockStub,
1422 ReleaseLockStub,
1423 XRequestSentStub,
1424 LibDisposeStub,
1425 };
1426
1427 void X11SD_LibDispose(JNIEnv *env) {
1428 AWT_LOCK();
1429 if (pJDgaInfo != NULL) {
1430 pJDgaInfo->pLibDispose(env);
1431 pJDgaInfo = &DgaLibInfoStub;
1432 }
1433 AWT_UNLOCK();
1434 }
1435
1436 void
1437 X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo)
1438 {
1439 #ifdef MITSHM
1440 if (xsdo->shmPMData.usingShmPixmap) {
1441 xsdo->shmPMData.xRequestSent = JNI_TRUE;
1442 }
1443 #endif /* MITSHM */
1444 (*pJDgaInfo->pXRequestSent)(env, xsdo->dgaDev, xsdo->drawable);
1445 awt_output_flush();
1446 }
1447
1448 /*
1449 * Sets transparent pixels in the pixmap to
1450 * the specified solid background color and returns it.
1451 * Doesn't update source pixmap unless the color of the
1452 * transparent pixels is different from the specified color.
1453 *
1454 * Note: The AWT lock must be held by the current thread
1455 * while calling into this method.
1456 */
1457 static Drawable
1458 X11SD_GetPixmapWithBg(JNIEnv *env, X11SDOps *xsdo, jint pixel)
1459 {
1460 /* assert AWT_CHECK_HAVE_LOCK(); */
1461
1462 if (xsdo->invalid) {
1463 AWT_UNLOCK();
1464 SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
|
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "X11SurfaceData.h"
27 #include "GraphicsPrimitiveMgr.h"
28 #include "Region.h"
29 #include "Trace.h"
30
31 /* Needed to define intptr_t */
32 #include "gdefs.h"
33
34 #include "jni_util.h"
35 #include "jvm_md.h"
36 #include "awt_Component.h"
37 #include "awt_GraphicsEnv.h"
38
39 #include <dlfcn.h>
40
41 #ifndef HEADLESS
42
43 /**
44 * This file contains support code for loops using the SurfaceData
45 * interface to talk to an X11 drawable from native code.
46 */
47
48 typedef struct _X11RIPrivate {
49 jint lockType;
50 jint lockFlags;
51 XImage *img;
52 int x, y;
53 } X11RIPrivate;
54
55 #define XSD_MAX(a,b) ((a) > (b) ? (a) : (b))
56 #define XSD_MIN(a,b) ((a) < (b) ? (a) : (b))
57
58 static LockFunc X11SD_Lock;
59 static GetRasInfoFunc X11SD_GetRasInfo;
60 static UnlockFunc X11SD_Unlock;
61 static DisposeFunc X11SD_Dispose;
62 static GetPixmapBgFunc X11SD_GetPixmapWithBg;
63 static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg;
64 extern int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr);
65 extern AwtGraphicsConfigDataPtr
66 getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
67 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
68
69 static int X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
70 X11SDOps *xsdo);
71 static int X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
72 X11SDOps *xsdo);
73 static void X11SD_SwapBytes(X11SDOps *xsdo, XImage *img, int depth, int bpp);
74 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
75 SurfaceDataBounds *bounds,
76 jint lockFlags);
77
78 extern jfieldID validID;
79
80 static int nativeByteOrder;
81 static jclass xorCompClass;
82
83 jint useMitShmExt = CANT_USE_MITSHM;
84 jint useMitShmPixmaps = CANT_USE_MITSHM;
85 jint forceSharedPixmaps = JNI_FALSE;
86 int mitShmPermissionMask = MITSHM_PERM_OWNER;
87
88 /* Cached shared image, one for all surface datas. */
89 static XImage * cachedXImage;
90
91 #endif /* !HEADLESS */
92
93 jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
94 {
95 #ifndef HEADLESS
96 union {
97 char c[4];
98 int i;
99 } endian;
100
101 endian.i = 0xff000000;
102 nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
103
104 cachedXImage = NULL;
105
106 if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
107 JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
108 return JNI_FALSE;
109 }
110
111 #ifdef MITSHM
112 if (getenv("NO_AWT_MITSHM") == NULL &&
113 getenv("NO_J2D_MITSHM") == NULL) {
114 char * force;
115 char * permission = getenv("J2D_MITSHM_PERMISSION");
116 if (permission != NULL) {
117 if (strcmp(permission, "common") == 0) {
118 mitShmPermissionMask = MITSHM_PERM_COMMON;
119 }
120 }
121
122 TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
123
133 }
134 }else {
135 useMitShmPixmaps = JNI_FALSE;
136 }
137 }
138 #endif /* MITSHM */
139
140 #endif /* !HEADLESS */
141
142 return JNI_TRUE;
143 }
144
145
146 /*
147 * Class: sun_java2d_x11_X11SurfaceData
148 * Method: initIDs
149 * Signature: (Ljava/lang/Class;Z)V
150 */
151 JNIEXPORT void JNICALL
152 Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
153 jclass XORComp)
154 {
155 #ifndef HEADLESS
156 if(XShared_initIDs(env, JNI_TRUE))
157 {
158 xorCompClass = (*env)->NewGlobalRef(env, XORComp);
159 }
160 #endif /* !HEADLESS */
161 }
162
163 /*
164 * Class: sun_java2d_x11_X11SurfaceData
165 * Method: isDrawableValid
166 * Signature: ()Z
167 */
168 JNIEXPORT jboolean JNICALL
169 Java_sun_java2d_x11_XSurfaceData_isDrawableValid(JNIEnv *env, jobject this)
170 {
171 jboolean ret = JNI_FALSE;
172
173 #ifndef HEADLESS
174 X11SDOps *xsdo = X11SurfaceData_GetOps(env, this);
175
176 AWT_LOCK();
177 if (xsdo->drawable != 0 || X11SD_InitWindow(env, xsdo) == SD_SUCCESS) {
178 ret = JNI_TRUE;
183 return ret;
184 }
185
186 /*
187 * Class: sun_java2d_x11_X11SurfaceData
188 * Method: isShmPMAvailable
189 * Signature: ()Z
190 */
191 JNIEXPORT jboolean JNICALL
192 Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
193 {
194 #if defined(HEADLESS) || !defined(MITSHM)
195 return JNI_FALSE;
196 #else
197 return (jboolean)useMitShmPixmaps;
198 #endif /* HEADLESS, MITSHM */
199 }
200
201 /*
202 * Class: sun_java2d_x11_X11SurfaceData
203 * Method: initOps
204 * Signature: (Ljava/lang/Object;I)V
205 */
206 JNIEXPORT void JNICALL
207 Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd,
208 jobject peer,
209 jobject graphicsConfig, jint depth)
210 {
211 #ifndef HEADLESS
212 X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps));
213 jboolean hasException;
214 if (xsdo == NULL) {
215 JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
216 return;
217 }
218 xsdo->sdOps.Lock = X11SD_Lock;
219 xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo;
220 xsdo->sdOps.Unlock = X11SD_Unlock;
221 xsdo->sdOps.Dispose = X11SD_Dispose;
222 xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg;
223 xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg;
224 if (peer != NULL) {
225 xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j;
226 if (hasException) {
227 return;
228 }
229 } else {
230 xsdo->drawable = 0;
231 }
232 xsdo->depth = depth;
233 xsdo->isPixmap = JNI_FALSE;
234 xsdo->bitmask = 0;
235 xsdo->bgPixel = 0;
236 xsdo->isBgInitialized = JNI_FALSE;
237 #ifdef MITSHM
238 xsdo->shmPMData.shmSegInfo = NULL;
239 xsdo->shmPMData.xRequestSent = JNI_FALSE;
240 xsdo->shmPMData.pmSize = 0;
241 xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
242 xsdo->shmPMData.pixmap = 0;
243 xsdo->shmPMData.shmPixmap = 0;
244 xsdo->shmPMData.numBltsSinceRead = 0;
245 xsdo->shmPMData.pixelsReadSinceBlt = 0;
246 xsdo->shmPMData.numBltsThreshold = 2;
247 #endif /* MITSHM */
248
249 xsdo->configData = (AwtGraphicsConfigDataPtr)
250 JNU_GetLongFieldAsPtr(env,
251 graphicsConfig,
252 x11GraphicsConfigIDs.aData);
380
381 jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable)
382 {
383 #ifndef HEADLESS
384
385 if (drawable != (jlong)0) {
386 /* Double-buffering */
387 xsdo->drawable = drawable;
388 xsdo->isPixmap = JNI_FALSE;
389 } else {
390 /*
391 * width , height must be nonzero otherwise XCreatePixmap
392 * generates BadValue in error_handler
393 */
394 if (width <= 0 || height <= 0 || width > 32767 || height > 32767) {
395 JNU_ThrowOutOfMemoryError(env,
396 "Can't create offscreen surface");
397 return JNI_FALSE;
398 }
399 xsdo->isPixmap = JNI_TRUE;
400
401 xsdo->pmWidth = width;
402 xsdo->pmHeight = height;
403
404 #ifdef MITSHM
405 xsdo->shmPMData.pmSize = width * height * depth;
406 xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
407 if (forceSharedPixmaps) {
408 AWT_LOCK();
409 xsdo->drawable = X11SD_CreateSharedPixmap(xsdo);
410 AWT_UNLOCK();
411 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
412 if (xsdo->drawable) {
413 xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
414 xsdo->shmPMData.shmPixmap = xsdo->drawable;
415 return JNI_TRUE;
416 }
417 }
418 #endif /* MITSHM */
419
776 xsdo->cData->img_oda_blue == NULL))
777 {
778 AWT_UNLOCK();
779 if (!(*env)->ExceptionCheck(env))
780 {
781 JNU_ThrowNullPointerException(env, "inverse colormap lookup table");
782 }
783 return SD_FAILURE;
784 }
785 if ((lockflags & SD_LOCK_INVGRAY) != 0 &&
786 (xsdo->cData == NULL ||
787 xsdo->cData->pGrayInverseLutData == NULL))
788 {
789 AWT_UNLOCK();
790 if (!(*env)->ExceptionCheck(env))
791 {
792 JNU_ThrowNullPointerException(env, "inverse gray lookup table");
793 }
794 return SD_FAILURE;
795 }
796 if (lockflags & SD_LOCK_RD_WR) {
797 if (lockflags & SD_LOCK_FASTEST) {
798 ret = SD_SLOWLOCK;
799 }
800 xpriv->lockType = X11SD_LOCK_BY_XIMAGE;
801 if (xsdo->isPixmap) {
802 #ifdef MITSHM
803 if (xsdo->shmPMData.usingShmPixmap) {
804 xpriv->lockType = X11SD_LOCK_BY_SHMEM;
805 }
806 #endif /* MITSHM */
807 if (pRasInfo->bounds.x1 < 0) {
808 pRasInfo->bounds.x1 = 0;
809 }
810 if (pRasInfo->bounds.y1 < 0) {
811 pRasInfo->bounds.y1 = 0;
812 }
813 if (pRasInfo->bounds.x2 > xsdo->pmWidth) {
814 pRasInfo->bounds.x2 = xsdo->pmWidth;
815 }
821 /* They didn't lock for anything - we won't give them anything */
822 xpriv->lockType = X11SD_LOCK_BY_NULL;
823 }
824 xpriv->lockFlags = lockflags;
825 xpriv->img = NULL;
826
827 return ret;
828 /* AWT_UNLOCK() called in Unlock */
829 }
830
831 static void X11SD_GetRasInfo(JNIEnv *env,
832 SurfaceDataOps *ops,
833 SurfaceDataRasInfo *pRasInfo)
834 {
835 X11SDOps *xsdo = (X11SDOps *) ops;
836 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
837 jint lockFlags = xpriv->lockFlags;
838 jint depth = xsdo->depth;
839 int mult = xsdo->configData->pixelStride;
840
841
842 #ifdef MITSHM
843 if (xpriv->lockType == X11SD_LOCK_BY_SHMEM) {
844 if (xsdo->shmPMData.xRequestSent == JNI_TRUE) {
845 /* need to sync before using shared mem pixmap
846 if any x calls were issued for this pixmap */
847 XSync(awt_display, False);
848 xsdo->shmPMData.xRequestSent = JNI_FALSE;
849 }
850 xpriv->x = pRasInfo->bounds.x1;
851 xpriv->y = pRasInfo->bounds.y1;
852 pRasInfo->rasBase = xsdo->shmPMData.shmSegInfo->shmaddr;
853 pRasInfo->pixelStride = mult;
854 pRasInfo->pixelBitOffset = 0;
855 pRasInfo->scanStride = xsdo->shmPMData.bytesPerLine;
856 } else
857 #endif /* MITSHM */
858 if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) {
859 int x, y, w, h;
860 x = pRasInfo->bounds.x1;
861 y = pRasInfo->bounds.y1;
862 w = pRasInfo->bounds.x2 - x;
863 h = pRasInfo->bounds.y2 - y;
864
865 xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags);
866 if (xpriv->img) {
867 int scan = xpriv->img->bytes_per_line;
868 xpriv->x = x;
869 xpriv->y = y;
870 pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan;
871 pRasInfo->pixelStride = mult;
872 pRasInfo->pixelBitOffset = 0;
873 pRasInfo->scanStride = scan;
874 } else {
875 pRasInfo->rasBase = NULL;
876 pRasInfo->pixelStride = 0;
877 pRasInfo->pixelBitOffset = 0;
878 pRasInfo->scanStride = 0;
899 } else {
900 pRasInfo->invColorTable = NULL;
901 pRasInfo->redErrTable = NULL;
902 pRasInfo->grnErrTable = NULL;
903 pRasInfo->bluErrTable = NULL;
904 }
905 if (lockFlags & SD_LOCK_INVGRAY) {
906 pRasInfo->invGrayTable = xsdo->cData->pGrayInverseLutData;
907 } else {
908 pRasInfo->invGrayTable = NULL;
909 }
910 }
911
912 static void X11SD_Unlock(JNIEnv *env,
913 SurfaceDataOps *ops,
914 SurfaceDataRasInfo *pRasInfo)
915 {
916 X11SDOps *xsdo = (X11SDOps *) ops;
917 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
918
919 if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE &&
920 xpriv->img != NULL)
921 {
922 if (xpriv->lockFlags & SD_LOCK_WRITE) {
923 int x = xpriv->x;
924 int y = xpriv->y;
925 int w = pRasInfo->bounds.x2 - x;
926 int h = pRasInfo->bounds.y2 - y;
927 Drawable drawable = xsdo->drawable;
928 GC xgc = xsdo->cachedGC;
929 if (xgc == NULL) {
930 xsdo->cachedGC = xgc =
931 XCreateGC(awt_display, drawable, 0L, NULL);
932 }
933
934 if (xpriv->img->byte_order != nativeByteOrder) {
935 /* switching bytes back in 24 and 32 bpp cases. */
936 /* For 16 bit XLib will switch for us. */
937 if (xsdo->depth > 16) {
938 X11SD_SwapBytes(xsdo, xpriv->img, xsdo->depth,
939 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel);
940 }
941 }
942
943 #ifdef MITSHM
944 if (xpriv->img->obdata != NULL) {
945 XShmPutImage(awt_display, drawable, xgc,
946 xpriv->img, 0, 0, x, y, w, h, False);
947 XFlush(awt_display);
948 } else {
949 XPutImage(awt_display, drawable, xgc,
950 xpriv->img, 0, 0, x, y, w, h);
951 }
952 if (xsdo->shmPMData.usingShmPixmap) {
953 xsdo->shmPMData.xRequestSent = JNI_TRUE;
954 }
955 #else
956 XPutImage(awt_display, drawable, xgc,
957 xpriv->img, 0, 0, x, y, w, h);
958 #endif /* MITSHM */
959
960 }
961 X11SD_DisposeOrCacheXImage(xpriv->img);
962 xpriv->img = (XImage *)NULL;
963 }
964 /* the background pixel is not valid anymore */
965 if (xpriv->lockFlags & SD_LOCK_WRITE) {
966 xsdo->isBgInitialized = JNI_FALSE;
967 }
968 xpriv->lockType = X11SD_LOCK_UNLOCKED;
969 AWT_UNLOCK();
970 }
971
972 static int
973 X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
974 X11SDOps *xsdo)
975 {
976 short x1=0, y1=0, x2=0, y2=0;
977 int tmpx, tmpy;
978 Window tmpchild;
979
1262 X11SD_DisposeXImage(cachedXImage);
1263 }
1264 cachedXImage = image;
1265 } else {
1266 X11SD_DisposeXImage(image);
1267 }
1268 }
1269
1270 void X11SD_DisposeXImage(XImage * image) {
1271 if (image != NULL) {
1272 #ifdef MITSHM
1273 if (image->obdata != NULL) {
1274 X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata);
1275 image->obdata = NULL;
1276 }
1277 #endif /* MITSHM */
1278 XDestroyImage(image);
1279 }
1280 }
1281
1282 void
1283 X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo)
1284 {
1285 #ifdef MITSHM
1286 if (xsdo->shmPMData.usingShmPixmap) {
1287 xsdo->shmPMData.xRequestSent = JNI_TRUE;
1288 }
1289 #endif /* MITSHM */
1290 awt_output_flush();
1291 }
1292
1293 /*
1294 * Sets transparent pixels in the pixmap to
1295 * the specified solid background color and returns it.
1296 * Doesn't update source pixmap unless the color of the
1297 * transparent pixels is different from the specified color.
1298 *
1299 * Note: The AWT lock must be held by the current thread
1300 * while calling into this method.
1301 */
1302 static Drawable
1303 X11SD_GetPixmapWithBg(JNIEnv *env, X11SDOps *xsdo, jint pixel)
1304 {
1305 /* assert AWT_CHECK_HAVE_LOCK(); */
1306
1307 if (xsdo->invalid) {
1308 AWT_UNLOCK();
1309 SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
|