Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c
41159 views
1
/*
2
* Copyright (c) 1999, 2013, 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 "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
static int X11SD_GetBitmapPad(int pixelStride);
78
79
extern jfieldID validID;
80
81
static int nativeByteOrder;
82
static jclass xorCompClass;
83
84
jint useMitShmExt = CANT_USE_MITSHM;
85
jint useMitShmPixmaps = CANT_USE_MITSHM;
86
jint forceSharedPixmaps = JNI_FALSE;
87
88
#ifdef MITSHM
89
int mitShmPermissionMask = MITSHM_PERM_OWNER;
90
#endif
91
92
/* Cached shared image, one for all surface datas. */
93
static XImage * cachedXImage;
94
95
#endif /* !HEADLESS */
96
97
jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
98
{
99
#ifndef HEADLESS
100
union {
101
char c[4];
102
int i;
103
} endian;
104
105
endian.i = 0xff000000;
106
nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
107
108
cachedXImage = NULL;
109
110
if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
111
JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
112
return JNI_FALSE;
113
}
114
115
#ifdef MITSHM
116
if (getenv("NO_AWT_MITSHM") == NULL &&
117
getenv("NO_J2D_MITSHM") == NULL) {
118
char * force;
119
char * permission = getenv("J2D_MITSHM_PERMISSION");
120
if (permission != NULL) {
121
if (strcmp(permission, "common") == 0) {
122
mitShmPermissionMask = MITSHM_PERM_COMMON;
123
}
124
}
125
126
TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
127
128
if(allowShmPixmaps) {
129
useMitShmPixmaps = (useMitShmPixmaps == CAN_USE_MITSHM);
130
force = getenv("J2D_PIXMAPS");
131
if (force != NULL) {
132
if (useMitShmPixmaps && (strcmp(force, "shared") == 0)) {
133
forceSharedPixmaps = JNI_TRUE;
134
} else if (strcmp(force, "server") == 0) {
135
useMitShmPixmaps = JNI_FALSE;
136
}
137
}
138
}else {
139
useMitShmPixmaps = JNI_FALSE;
140
}
141
}
142
#endif /* MITSHM */
143
144
#endif /* !HEADLESS */
145
146
return JNI_TRUE;
147
}
148
149
150
/*
151
* Class: sun_java2d_x11_X11SurfaceData
152
* Method: initIDs
153
* Signature: (Ljava/lang/Class;Z)V
154
*/
155
JNIEXPORT void JNICALL
156
Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
157
jclass XORComp)
158
{
159
#ifndef HEADLESS
160
if(XShared_initIDs(env, JNI_TRUE))
161
{
162
xorCompClass = (*env)->NewGlobalRef(env, XORComp);
163
}
164
#endif /* !HEADLESS */
165
}
166
167
/*
168
* Class: sun_java2d_x11_X11SurfaceData
169
* Method: isDrawableValid
170
* Signature: ()Z
171
*/
172
JNIEXPORT jboolean JNICALL
173
Java_sun_java2d_x11_XSurfaceData_isDrawableValid(JNIEnv *env, jobject this)
174
{
175
jboolean ret = JNI_FALSE;
176
177
#ifndef HEADLESS
178
X11SDOps *xsdo = X11SurfaceData_GetOps(env, this);
179
180
AWT_LOCK();
181
if (xsdo->drawable != 0 || X11SD_InitWindow(env, xsdo) == SD_SUCCESS) {
182
ret = JNI_TRUE;
183
}
184
AWT_UNLOCK();
185
#endif /* !HEADLESS */
186
187
return ret;
188
}
189
190
/*
191
* Class: sun_java2d_x11_X11SurfaceData
192
* Method: isShmPMAvailable
193
* Signature: ()Z
194
*/
195
JNIEXPORT jboolean JNICALL
196
Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
197
{
198
#if defined(HEADLESS) || !defined(MITSHM)
199
return JNI_FALSE;
200
#else
201
return (jboolean)useMitShmPixmaps;
202
#endif /* HEADLESS, MITSHM */
203
}
204
205
/*
206
* Class: sun_java2d_x11_X11SurfaceData
207
* Method: initOps
208
* Signature: (Ljava/lang/Object;I)V
209
*/
210
JNIEXPORT void JNICALL
211
Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd,
212
jobject peer,
213
jobject graphicsConfig, jint depth)
214
{
215
#ifndef HEADLESS
216
X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps));
217
jboolean hasException;
218
if (xsdo == NULL) {
219
JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
220
return;
221
}
222
xsdo->sdOps.Lock = X11SD_Lock;
223
xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo;
224
xsdo->sdOps.Unlock = X11SD_Unlock;
225
xsdo->sdOps.Dispose = X11SD_Dispose;
226
xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg;
227
xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg;
228
if (peer != NULL) {
229
xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j;
230
if (hasException) {
231
return;
232
}
233
} else {
234
xsdo->drawable = 0;
235
}
236
xsdo->depth = depth;
237
xsdo->isPixmap = JNI_FALSE;
238
xsdo->bitmask = 0;
239
xsdo->bgPixel = 0;
240
xsdo->isBgInitialized = JNI_FALSE;
241
#ifdef MITSHM
242
xsdo->shmPMData.shmSegInfo = NULL;
243
xsdo->shmPMData.xRequestSent = JNI_FALSE;
244
xsdo->shmPMData.pmSize = 0;
245
xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
246
xsdo->shmPMData.pixmap = 0;
247
xsdo->shmPMData.shmPixmap = 0;
248
xsdo->shmPMData.numBltsSinceRead = 0;
249
xsdo->shmPMData.pixelsReadSinceBlt = 0;
250
xsdo->shmPMData.numBltsThreshold = 2;
251
#endif /* MITSHM */
252
253
xsdo->configData = (AwtGraphicsConfigDataPtr)
254
JNU_GetLongFieldAsPtr(env,
255
graphicsConfig,
256
x11GraphicsConfigIDs.aData);
257
if (xsdo->configData == NULL) {
258
JNU_ThrowNullPointerException(env,
259
"Native GraphicsConfig data block missing");
260
return;
261
}
262
if (depth > 12) {
263
xsdo->pixelmask = (xsdo->configData->awt_visInfo.red_mask |
264
xsdo->configData->awt_visInfo.green_mask |
265
xsdo->configData->awt_visInfo.blue_mask);
266
} else if (depth == 12) {
267
xsdo->pixelmask = 0xfff;
268
} else {
269
xsdo->pixelmask = 0xff;
270
}
271
272
xsdo->xrPic = None;
273
#endif /* !HEADLESS */
274
}
275
276
/*
277
* Class: sun_java2d_x11_X11SurfaceData
278
* Method: flushNativeSurface
279
* Signature: ()V
280
*/
281
JNIEXPORT void JNICALL
282
Java_sun_java2d_x11_XSurfaceData_flushNativeSurface(JNIEnv *env, jobject xsd)
283
{
284
#ifndef HEADLESS
285
SurfaceDataOps *ops = SurfaceData_GetOps(env, xsd);
286
287
if (ops != NULL) {
288
X11SD_Dispose(env, ops);
289
}
290
#endif /* !HEADLESS */
291
}
292
293
294
JNIEXPORT X11SDOps * JNICALL
295
X11SurfaceData_GetOps(JNIEnv *env, jobject sData)
296
{
297
#ifdef HEADLESS
298
return NULL;
299
#else
300
SurfaceDataOps *ops = SurfaceData_GetOps(env, sData);
301
if (ops != NULL && ops->Lock != X11SD_Lock) {
302
SurfaceData_ThrowInvalidPipeException(env, "not an X11 SurfaceData");
303
ops = NULL;
304
}
305
return (X11SDOps *) ops;
306
#endif /* !HEADLESS */
307
}
308
309
/*
310
* Method for disposing X11SD-specific data
311
*/
312
static void
313
X11SD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
314
{
315
#ifndef HEADLESS
316
/* ops is assumed non-null as it is checked in SurfaceData_DisposeOps */
317
X11SDOps * xsdo = (X11SDOps*)ops;
318
319
AWT_LOCK();
320
321
xsdo->invalid = JNI_TRUE;
322
323
if (xsdo->xrPic != None) {
324
XRenderFreePicture(awt_display, xsdo->xrPic);
325
xsdo->xrPic = None;
326
}
327
328
if (xsdo->isPixmap == JNI_TRUE && xsdo->drawable != 0) {
329
#ifdef MITSHM
330
if (xsdo->shmPMData.shmSegInfo != NULL) {
331
X11SD_DropSharedSegment(xsdo->shmPMData.shmSegInfo);
332
xsdo->shmPMData.shmSegInfo = NULL;
333
}
334
if (xsdo->shmPMData.pixmap) {
335
XFreePixmap(awt_display, xsdo->shmPMData.pixmap);
336
xsdo->shmPMData.pixmap = 0;
337
}
338
if (xsdo->shmPMData.shmPixmap) {
339
XFreePixmap(awt_display, xsdo->shmPMData.shmPixmap);
340
xsdo->shmPMData.shmPixmap = 0;
341
}
342
#else
343
XFreePixmap(awt_display, xsdo->drawable);
344
#endif /* MITSHM */
345
xsdo->drawable = 0;
346
}
347
if (xsdo->bitmask != 0) {
348
XFreePixmap(awt_display, xsdo->bitmask);
349
xsdo->bitmask = 0;
350
}
351
if (xsdo->javaGC != NULL) {
352
XFreeGC(awt_display, xsdo->javaGC);
353
xsdo->javaGC = NULL;
354
}
355
if (xsdo->cachedGC != NULL) {
356
XFreeGC(awt_display, xsdo->cachedGC);
357
xsdo->cachedGC = NULL;
358
}
359
360
if(xsdo->xrPic != None) {
361
XRenderFreePicture(awt_display, xsdo->xrPic);
362
}
363
364
AWT_UNLOCK();
365
#endif /* !HEADLESS */
366
}
367
/*
368
* Class: sun_java2d_x11_X11SurfaceData
369
* Method: setInvalid
370
* Signature: ()V
371
*/
372
JNIEXPORT void JNICALL
373
Java_sun_java2d_x11_XSurfaceData_setInvalid(JNIEnv *env, jobject xsd)
374
{
375
#ifndef HEADLESS
376
X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, xsd);
377
378
if (xsdo != NULL) {
379
xsdo->invalid = JNI_TRUE;
380
}
381
#endif /* !HEADLESS */
382
}
383
384
385
jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable)
386
{
387
#ifndef HEADLESS
388
389
if (drawable != (jlong)0) {
390
/* Double-buffering */
391
xsdo->drawable = drawable;
392
xsdo->isPixmap = JNI_FALSE;
393
} else {
394
jboolean sizeIsInvalid = JNI_FALSE;
395
jlong scan = 0;
396
397
/*
398
* width , height must be nonzero otherwise XCreatePixmap
399
* generates BadValue in error_handler
400
*/
401
if (width <= 0 || height <= 0 || width > 32767 || height > 32767) {
402
sizeIsInvalid = JNI_TRUE;
403
} else {
404
XImage* tmpImg = NULL;
405
406
AWT_LOCK();
407
tmpImg = XCreateImage(awt_display,
408
xsdo->configData->awt_visInfo.visual,
409
depth, ZPixmap, 0, NULL, width, height,
410
X11SD_GetBitmapPad(xsdo->configData->pixelStride), 0);
411
if (tmpImg) {
412
scan = (jlong) tmpImg->bytes_per_line;
413
XDestroyImage(tmpImg);
414
tmpImg = NULL;
415
}
416
AWT_UNLOCK();
417
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
418
}
419
420
if (sizeIsInvalid || (scan * height > 0x7FFFFFFFL)) {
421
JNU_ThrowOutOfMemoryError(env,
422
"Can't create offscreen surface");
423
return JNI_FALSE;
424
}
425
xsdo->isPixmap = JNI_TRUE;
426
427
xsdo->pmWidth = width;
428
xsdo->pmHeight = height;
429
430
#ifdef MITSHM
431
xsdo->shmPMData.pmSize = (jlong) width * height * depth;
432
xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
433
if (forceSharedPixmaps) {
434
AWT_LOCK();
435
xsdo->drawable = X11SD_CreateSharedPixmap(xsdo);
436
AWT_UNLOCK();
437
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
438
if (xsdo->drawable) {
439
xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
440
xsdo->shmPMData.shmPixmap = xsdo->drawable;
441
return JNI_TRUE;
442
}
443
}
444
#endif /* MITSHM */
445
446
AWT_LOCK();
447
xsdo->drawable =
448
XCreatePixmap(awt_display,
449
RootWindow(awt_display,
450
xsdo->configData->awt_visInfo.screen),
451
width, height, depth);
452
AWT_UNLOCK();
453
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
454
#ifdef MITSHM
455
xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
456
xsdo->shmPMData.pixmap = xsdo->drawable;
457
#endif /* MITSHM */
458
}
459
if (xsdo->drawable == 0) {
460
JNU_ThrowOutOfMemoryError(env,
461
"Can't create offscreen surface");
462
return JNI_FALSE;
463
}
464
465
#endif /* !HEADLESS */
466
return JNI_TRUE;
467
}
468
469
470
/*
471
* Class: sun_java2d_x11_X11SurfaceData
472
* Method: initSurface
473
* Signature: ()V
474
*/
475
JNIEXPORT void JNICALL
476
Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd,
477
jint depth,
478
jint width, jint height,
479
jlong drawable)
480
{
481
#ifndef HEADLESS
482
X11SDOps *xsdo = X11SurfaceData_GetOps(env, xsd);
483
if (xsdo == NULL) {
484
return;
485
}
486
487
if (xsdo->configData->awt_cmap == (Colormap)NULL) {
488
awtJNI_CreateColorData(env, xsdo->configData, 1);
489
JNU_CHECK_EXCEPTION(env);
490
}
491
/* color_data will be initialized in awtJNI_CreateColorData for
492
8-bit visuals */
493
xsdo->cData = xsdo->configData->color_data;
494
495
XShared_initSurface(env, xsdo, depth, width, height, drawable);
496
xsdo->xrPic = None;
497
#endif /* !HEADLESS */
498
}
499
500
#ifndef HEADLESS
501
502
#ifdef MITSHM
503
504
void X11SD_DropSharedSegment(XShmSegmentInfo *shminfo)
505
{
506
if (shminfo != NULL) {
507
XShmDetach(awt_display, shminfo);
508
shmdt(shminfo->shmaddr);
509
/* REMIND: we don't need shmctl(shminfo->shmid, IPC_RMID, 0); here. */
510
/* Check X11SD_CreateSharedImage() for the explanation */
511
}
512
}
513
514
XImage* X11SD_CreateSharedImage(X11SDOps *xsdo,
515
jint width, jint height)
516
{
517
XImage *img = NULL;
518
XShmSegmentInfo *shminfo;
519
520
shminfo = malloc(sizeof(XShmSegmentInfo));
521
if (shminfo == NULL) {
522
return NULL;
523
}
524
memset(shminfo, 0, sizeof(XShmSegmentInfo));
525
526
img = XShmCreateImage(awt_display, xsdo->configData->awt_visInfo.visual,
527
xsdo->depth, ZPixmap, NULL, shminfo,
528
width, height);
529
if (img == NULL) {
530
free((void *)shminfo);
531
return NULL;
532
}
533
shminfo->shmid =
534
shmget(IPC_PRIVATE, (size_t) height * img->bytes_per_line,
535
IPC_CREAT|mitShmPermissionMask);
536
if (shminfo->shmid < 0) {
537
J2dRlsTraceLn1(J2D_TRACE_ERROR,
538
"X11SD_SetupSharedSegment shmget has failed: %s",
539
strerror(errno));
540
free((void *)shminfo);
541
XDestroyImage(img);
542
return NULL;
543
}
544
545
shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
546
if (shminfo->shmaddr == ((char *) -1)) {
547
shmctl(shminfo->shmid, IPC_RMID, 0);
548
J2dRlsTraceLn1(J2D_TRACE_ERROR,
549
"X11SD_SetupSharedSegment shmat has failed: %s",
550
strerror(errno));
551
free((void *)shminfo);
552
XDestroyImage(img);
553
return NULL;
554
}
555
556
shminfo->readOnly = False;
557
558
resetXShmAttachFailed();
559
EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler,
560
XShmAttach(awt_display, shminfo));
561
562
/*
563
* Once the XSync round trip has finished then we
564
* can get rid of the id so that this segment does not stick
565
* around after we go away, holding system resources.
566
*/
567
shmctl(shminfo->shmid, IPC_RMID, 0);
568
569
if (isXShmAttachFailed() == JNI_TRUE) {
570
J2dRlsTraceLn1(J2D_TRACE_ERROR,
571
"X11SD_SetupSharedSegment XShmAttach has failed: %s",
572
strerror(errno));
573
shmdt(shminfo->shmaddr);
574
free((void *)shminfo);
575
XDestroyImage(img);
576
return NULL;
577
}
578
579
img->data = shminfo->shmaddr;
580
img->obdata = (char *)shminfo;
581
582
return img;
583
}
584
585
XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height,
586
jint maxWidth, jint maxHeight, jboolean readBits)
587
{
588
XImage * retImage = NULL;
589
if (cachedXImage != NULL &&
590
X11SD_CachedXImageFits(width, height, maxWidth, maxHeight,
591
xsdo->depth, readBits)) {
592
/* sync so previous data gets flushed */
593
XSync(awt_display, False);
594
retImage = cachedXImage;
595
cachedXImage = (XImage *)NULL;
596
} else if ((jlong) width * height * xsdo->depth > 0x10000) {
597
retImage = X11SD_CreateSharedImage(xsdo, width, height);
598
}
599
return retImage;
600
}
601
602
Drawable X11SD_CreateSharedPixmap(X11SDOps *xsdo)
603
{
604
XShmSegmentInfo *shminfo;
605
XImage *img = NULL;
606
Drawable pixmap;
607
int scan;
608
int width = xsdo->pmWidth;
609
int height = xsdo->pmHeight;
610
611
if (xsdo->shmPMData.pmSize < 0x10000) {
612
/* only use shared mem pixmaps for relatively big images */
613
return 0;
614
}
615
616
/* need to create shared(!) image to get bytes_per_line */
617
img = X11SD_CreateSharedImage(xsdo, width, height);
618
if (img == NULL) {
619
return 0;
620
}
621
scan = img->bytes_per_line;
622
shminfo = (XShmSegmentInfo*)img->obdata;
623
XFree(img);
624
625
pixmap =
626
XShmCreatePixmap(awt_display,
627
RootWindow(awt_display,
628
xsdo->configData->awt_visInfo.screen),
629
shminfo->shmaddr, shminfo,
630
width, height, xsdo->depth);
631
if (pixmap == 0) {
632
X11SD_DropSharedSegment(shminfo);
633
return 0;
634
}
635
636
xsdo->shmPMData.shmSegInfo = shminfo;
637
xsdo->shmPMData.bytesPerLine = scan;
638
return pixmap;
639
}
640
641
void X11SD_PuntPixmap(X11SDOps *xsdo, jint width, jint height)
642
{
643
644
if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) {
645
return;
646
}
647
648
/* we wouldn't be here if it's a shared pixmap, so no check
649
* for !usingShmPixmap.
650
*/
651
652
xsdo->shmPMData.numBltsSinceRead = 0;
653
654
xsdo->shmPMData.pixelsReadSinceBlt += width * height;
655
if (xsdo->shmPMData.pixelsReadSinceBlt >
656
xsdo->shmPMData.pixelsReadThreshold) {
657
if (!xsdo->shmPMData.shmPixmap) {
658
xsdo->shmPMData.shmPixmap =
659
X11SD_CreateSharedPixmap(xsdo);
660
}
661
if (xsdo->shmPMData.shmPixmap) {
662
GC xgc = XCreateGC(awt_display, xsdo->shmPMData.shmPixmap, 0L, NULL);
663
if (xgc != NULL) {
664
xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
665
xsdo->drawable = xsdo->shmPMData.shmPixmap;
666
XCopyArea(awt_display,
667
xsdo->shmPMData.pixmap, xsdo->drawable, xgc,
668
0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0);
669
XSync(awt_display, False);
670
xsdo->shmPMData.xRequestSent = JNI_FALSE;
671
XFreeGC(awt_display, xgc);
672
}
673
}
674
}
675
}
676
677
void X11SD_UnPuntPixmap(X11SDOps *xsdo)
678
{
679
if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) {
680
return;
681
}
682
xsdo->shmPMData.pixelsReadSinceBlt = 0;
683
if (xsdo->shmPMData.numBltsSinceRead >=
684
xsdo->shmPMData.numBltsThreshold)
685
{
686
if (xsdo->shmPMData.usingShmPixmap) {
687
if (!xsdo->shmPMData.pixmap) {
688
xsdo->shmPMData.pixmap =
689
XCreatePixmap(awt_display,
690
RootWindow(awt_display,
691
xsdo->configData->awt_visInfo.screen),
692
xsdo->pmWidth, xsdo->pmHeight, xsdo->depth);
693
}
694
if (xsdo->shmPMData.pixmap) {
695
GC xgc = XCreateGC(awt_display, xsdo->shmPMData.pixmap, 0L, NULL);
696
if (xgc != NULL) {
697
xsdo->drawable = xsdo->shmPMData.pixmap;
698
XCopyArea(awt_display,
699
xsdo->shmPMData.shmPixmap, xsdo->drawable, xgc,
700
0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0);
701
XSync(awt_display, False);
702
XFreeGC(awt_display, xgc);
703
xsdo->shmPMData.xRequestSent = JNI_FALSE;
704
xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
705
xsdo->shmPMData.numBltsThreshold *= 2;
706
}
707
}
708
}
709
} else {
710
xsdo->shmPMData.numBltsSinceRead++;
711
}
712
}
713
714
/**
715
* Determines if the cached image can be used for current operation.
716
* If the image is to be used to be read into by XShmGetImage,
717
* it must be close enough to avoid excessive reading from the screen;
718
* otherwise it should just be at least the size requested.
719
*/
720
jboolean X11SD_CachedXImageFits(jint width, jint height, jint maxWidth,
721
jint maxHeight, jint depth, jboolean readBits)
722
{
723
/* we assume here that the cached image exists */
724
jint imgWidth = cachedXImage->width;
725
jint imgHeight = cachedXImage->height;
726
727
if (imgWidth < width || imgHeight < height || depth != cachedXImage->depth) {
728
/* doesn't fit if any of the cached image dimensions is smaller
729
or the depths are different */
730
return JNI_FALSE;
731
}
732
733
if (!readBits) {
734
/* Not reading from this image, so any image at least of the
735
size requested will do */
736
return JNI_TRUE;
737
}
738
739
if ((imgWidth < width + 64) && (imgHeight < height + 64)
740
&& imgWidth <= maxWidth && imgHeight <= maxHeight)
741
{
742
/* Cached image's width/height shouldn't be more than 64 pixels
743
* larger than requested, because the region in XShmGetImage
744
* can't be specified and we don't want to read too much.
745
* Furthermore it has to be smaller than maxWidth/Height
746
* so drawables are not read out of bounds.
747
*/
748
return JNI_TRUE;
749
}
750
751
return JNI_FALSE;
752
}
753
#endif /* MITSHM */
754
755
jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo)
756
{
757
if (xsdo->isPixmap == JNI_TRUE) {
758
return SD_FAILURE;
759
}
760
xsdo->cData = xsdo->configData->color_data;
761
762
return SD_SUCCESS;
763
}
764
765
static jint X11SD_Lock(JNIEnv *env,
766
SurfaceDataOps *ops,
767
SurfaceDataRasInfo *pRasInfo,
768
jint lockflags)
769
{
770
X11SDOps *xsdo = (X11SDOps *) ops;
771
X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
772
int ret = SD_SUCCESS;
773
774
AWT_LOCK();
775
776
if (xsdo->invalid) {
777
AWT_UNLOCK();
778
SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
779
return SD_FAILURE;
780
}
781
xsdo->cData = xsdo->configData->color_data;
782
if (xsdo->drawable == 0 && X11SD_InitWindow(env, xsdo) == SD_FAILURE) {
783
AWT_UNLOCK();
784
return SD_FAILURE;
785
}
786
if ((lockflags & SD_LOCK_LUT) != 0 &&
787
(xsdo->cData == NULL ||
788
xsdo->cData->awt_icmLUT == NULL))
789
{
790
AWT_UNLOCK();
791
if (!(*env)->ExceptionCheck(env))
792
{
793
JNU_ThrowNullPointerException(env, "colormap lookup table");
794
}
795
return SD_FAILURE;
796
}
797
if ((lockflags & SD_LOCK_INVCOLOR) != 0 &&
798
(xsdo->cData == NULL ||
799
xsdo->cData->img_clr_tbl == NULL ||
800
xsdo->cData->img_oda_red == NULL ||
801
xsdo->cData->img_oda_green == NULL ||
802
xsdo->cData->img_oda_blue == NULL))
803
{
804
AWT_UNLOCK();
805
if (!(*env)->ExceptionCheck(env))
806
{
807
JNU_ThrowNullPointerException(env, "inverse colormap lookup table");
808
}
809
return SD_FAILURE;
810
}
811
if ((lockflags & SD_LOCK_INVGRAY) != 0 &&
812
(xsdo->cData == NULL ||
813
xsdo->cData->pGrayInverseLutData == NULL))
814
{
815
AWT_UNLOCK();
816
if (!(*env)->ExceptionCheck(env))
817
{
818
JNU_ThrowNullPointerException(env, "inverse gray lookup table");
819
}
820
return SD_FAILURE;
821
}
822
if (lockflags & SD_LOCK_RD_WR) {
823
if (lockflags & SD_LOCK_FASTEST) {
824
ret = SD_SLOWLOCK;
825
}
826
xpriv->lockType = X11SD_LOCK_BY_XIMAGE;
827
if (xsdo->isPixmap) {
828
#ifdef MITSHM
829
if (xsdo->shmPMData.usingShmPixmap) {
830
xpriv->lockType = X11SD_LOCK_BY_SHMEM;
831
}
832
#endif /* MITSHM */
833
if (pRasInfo->bounds.x1 < 0) {
834
pRasInfo->bounds.x1 = 0;
835
}
836
if (pRasInfo->bounds.y1 < 0) {
837
pRasInfo->bounds.y1 = 0;
838
}
839
if (pRasInfo->bounds.x2 > xsdo->pmWidth) {
840
pRasInfo->bounds.x2 = xsdo->pmWidth;
841
}
842
if (pRasInfo->bounds.y2 > xsdo->pmHeight) {
843
pRasInfo->bounds.y2 = xsdo->pmHeight;
844
}
845
}
846
} else {
847
/* They didn't lock for anything - we won't give them anything */
848
xpriv->lockType = X11SD_LOCK_BY_NULL;
849
}
850
xpriv->lockFlags = lockflags;
851
xpriv->img = NULL;
852
853
return ret;
854
/* AWT_UNLOCK() called in Unlock */
855
}
856
857
static void X11SD_GetRasInfo(JNIEnv *env,
858
SurfaceDataOps *ops,
859
SurfaceDataRasInfo *pRasInfo)
860
{
861
X11SDOps *xsdo = (X11SDOps *) ops;
862
X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
863
jint lockFlags = xpriv->lockFlags;
864
jint depth = xsdo->depth;
865
int mult = xsdo->configData->pixelStride;
866
867
868
#ifdef MITSHM
869
if (xpriv->lockType == X11SD_LOCK_BY_SHMEM) {
870
if (xsdo->shmPMData.xRequestSent == JNI_TRUE) {
871
/* need to sync before using shared mem pixmap
872
if any x calls were issued for this pixmap */
873
XSync(awt_display, False);
874
xsdo->shmPMData.xRequestSent = JNI_FALSE;
875
}
876
xpriv->x = pRasInfo->bounds.x1;
877
xpriv->y = pRasInfo->bounds.y1;
878
pRasInfo->rasBase = xsdo->shmPMData.shmSegInfo->shmaddr;
879
pRasInfo->pixelStride = mult;
880
pRasInfo->pixelBitOffset = 0;
881
pRasInfo->scanStride = xsdo->shmPMData.bytesPerLine;
882
} else
883
#endif /* MITSHM */
884
if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) {
885
int x, y, w, h;
886
x = pRasInfo->bounds.x1;
887
y = pRasInfo->bounds.y1;
888
w = pRasInfo->bounds.x2 - x;
889
h = pRasInfo->bounds.y2 - y;
890
891
xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags);
892
if (xpriv->img) {
893
int scan = xpriv->img->bytes_per_line;
894
xpriv->x = x;
895
xpriv->y = y;
896
pRasInfo->rasBase = xpriv->img->data - x * mult - (intptr_t) y * scan;
897
pRasInfo->pixelStride = mult;
898
pRasInfo->pixelBitOffset = 0;
899
pRasInfo->scanStride = scan;
900
} else {
901
pRasInfo->rasBase = NULL;
902
pRasInfo->pixelStride = 0;
903
pRasInfo->pixelBitOffset = 0;
904
pRasInfo->scanStride = 0;
905
}
906
} else {
907
/* They didn't lock for anything - we won't give them anything */
908
pRasInfo->rasBase = NULL;
909
pRasInfo->pixelStride = 0;
910
pRasInfo->pixelBitOffset = 0;
911
pRasInfo->scanStride = 0;
912
}
913
if (lockFlags & SD_LOCK_LUT) {
914
pRasInfo->lutBase = (jint *) xsdo->cData->awt_icmLUT;
915
pRasInfo->lutSize = xsdo->cData->awt_numICMcolors;
916
} else {
917
pRasInfo->lutBase = NULL;
918
pRasInfo->lutSize = 0;
919
}
920
if (lockFlags & SD_LOCK_INVCOLOR) {
921
pRasInfo->invColorTable = xsdo->cData->img_clr_tbl;
922
pRasInfo->redErrTable = xsdo->cData->img_oda_red;
923
pRasInfo->grnErrTable = xsdo->cData->img_oda_green;
924
pRasInfo->bluErrTable = xsdo->cData->img_oda_blue;
925
} else {
926
pRasInfo->invColorTable = NULL;
927
pRasInfo->redErrTable = NULL;
928
pRasInfo->grnErrTable = NULL;
929
pRasInfo->bluErrTable = NULL;
930
}
931
if (lockFlags & SD_LOCK_INVGRAY) {
932
pRasInfo->invGrayTable = xsdo->cData->pGrayInverseLutData;
933
} else {
934
pRasInfo->invGrayTable = NULL;
935
}
936
}
937
938
static void X11SD_Unlock(JNIEnv *env,
939
SurfaceDataOps *ops,
940
SurfaceDataRasInfo *pRasInfo)
941
{
942
X11SDOps *xsdo = (X11SDOps *) ops;
943
X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv);
944
945
if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE &&
946
xpriv->img != NULL)
947
{
948
if (xpriv->lockFlags & SD_LOCK_WRITE) {
949
int x = xpriv->x;
950
int y = xpriv->y;
951
int w = pRasInfo->bounds.x2 - x;
952
int h = pRasInfo->bounds.y2 - y;
953
Drawable drawable = xsdo->drawable;
954
GC xgc = xsdo->cachedGC;
955
if (xgc == NULL) {
956
xsdo->cachedGC = xgc =
957
XCreateGC(awt_display, drawable, 0L, NULL);
958
}
959
960
if (xpriv->img->byte_order != nativeByteOrder) {
961
/* switching bytes back in 24 and 32 bpp cases. */
962
/* For 16 bit XLib will switch for us. */
963
if (xsdo->depth > 16) {
964
X11SD_SwapBytes(xsdo, xpriv->img, xsdo->depth,
965
xsdo->configData->awtImage->wsImageFormat.bits_per_pixel);
966
}
967
}
968
969
#ifdef MITSHM
970
if (xpriv->img->obdata != NULL) {
971
XShmPutImage(awt_display, drawable, xgc,
972
xpriv->img, 0, 0, x, y, w, h, False);
973
XFlush(awt_display);
974
} else {
975
XPutImage(awt_display, drawable, xgc,
976
xpriv->img, 0, 0, x, y, w, h);
977
}
978
if (xsdo->shmPMData.usingShmPixmap) {
979
xsdo->shmPMData.xRequestSent = JNI_TRUE;
980
}
981
#else
982
XPutImage(awt_display, drawable, xgc,
983
xpriv->img, 0, 0, x, y, w, h);
984
#endif /* MITSHM */
985
986
}
987
X11SD_DisposeOrCacheXImage(xpriv->img);
988
xpriv->img = (XImage *)NULL;
989
}
990
/* the background pixel is not valid anymore */
991
if (xpriv->lockFlags & SD_LOCK_WRITE) {
992
xsdo->isBgInitialized = JNI_FALSE;
993
}
994
xpriv->lockType = X11SD_LOCK_UNLOCKED;
995
AWT_UNLOCK();
996
}
997
998
static int
999
X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
1000
X11SDOps *xsdo)
1001
{
1002
short x1=0, y1=0, x2=0, y2=0;
1003
int tmpx, tmpy;
1004
Window tmpchild;
1005
1006
Window window = (Window)(xsdo->drawable); /* is always a Window */
1007
XWindowAttributes winAttr;
1008
1009
Status status = XGetWindowAttributes(awt_display, window, &winAttr);
1010
if (status == 0) {
1011
/* Failure, X window no longer valid. */
1012
return FALSE;
1013
}
1014
if (!XTranslateCoordinates(awt_display, window,
1015
RootWindowOfScreen(winAttr.screen),
1016
0, 0, &tmpx, &tmpy, &tmpchild)) {
1017
return FALSE;
1018
}
1019
1020
x1 = -(x1 + tmpx);
1021
y1 = -(y1 + tmpy);
1022
1023
x2 = x1 + DisplayWidth(awt_display, xsdo->configData->awt_visInfo.screen);
1024
y2 = y1 + DisplayHeight(awt_display, xsdo->configData->awt_visInfo.screen);
1025
1026
x1 = XSD_MAX(bounds->x1, x1);
1027
y1 = XSD_MAX(bounds->y1, y1);
1028
x2 = XSD_MIN(bounds->x2, x2);
1029
y2 = XSD_MIN(bounds->y2, y2);
1030
if ((x1 >= x2) || (y1 >= y2)) {
1031
return FALSE;
1032
}
1033
b->x1 = x1;
1034
b->y1 = y1;
1035
b->x2 = x2;
1036
b->y2 = y2;
1037
1038
return TRUE;
1039
}
1040
1041
/*
1042
* x1, y1, x2, y2 - our rectangle in the coord system of
1043
* the widget
1044
* px1, xy1, px2, py2 - current parent rect coords in the
1045
* same system
1046
*/
1047
static int
1048
X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds, X11SDOps *xsdo)
1049
{
1050
return TRUE;
1051
}
1052
1053
static void
1054
X11SD_SwapBytes(X11SDOps *xsdo, XImage * img, int depth, int bpp) {
1055
jlong lengthInBytes = (jlong) img->height * img->bytes_per_line;
1056
jlong i;
1057
1058
switch (depth) {
1059
case 12:
1060
case 15:
1061
case 16:
1062
{
1063
/* AB -> BA */
1064
unsigned short *d = (unsigned short *)img->data;
1065
unsigned short t;
1066
for (i = 0; i < lengthInBytes/2; i++) {
1067
t = *d;
1068
*d++ = (t >> 8) | (t << 8);
1069
}
1070
img->byte_order = nativeByteOrder;
1071
img->bitmap_bit_order = nativeByteOrder;
1072
break;
1073
}
1074
case 24:
1075
{
1076
/* ABC -> CBA */
1077
if (bpp == 24) {
1078
// 4517321: Only swap if we have a "real" ThreeByteBgr
1079
// visual (denoted by a red_mask of 0xff). Due to ambiguity
1080
// in the X11 spec, it appears that the swap is not required
1081
// on Linux configurations that use 24 bits per pixel (denoted
1082
// by a red_mask of 0xff0000).
1083
if (xsdo->configData->awt_visInfo.red_mask == 0xff) {
1084
int scan = img->bytes_per_line;
1085
unsigned char *d = (unsigned char *) img->data;
1086
unsigned char *d1;
1087
unsigned int t;
1088
int j;
1089
1090
for (i = 0; i < img->height; i++, d += scan) {
1091
d1 = d;
1092
for (j = 0; j < img->width; j++, d1 += 3) {
1093
/* not obvious opt from XLib src */
1094
t = d1[0]; d1[0] = d1[2]; d1[2] = t;
1095
}
1096
}
1097
}
1098
break;
1099
}
1100
}
1101
/* FALL THROUGH for 32-bit case */
1102
case 32:
1103
{
1104
/* ABCD -> DCBA */
1105
unsigned int *d = (unsigned int *) img->data;
1106
unsigned int t;
1107
for (i = 0; i < lengthInBytes/4; i++) {
1108
t = *d;
1109
*d++ = ((t >> 24) |
1110
((t >> 8) & 0xff00) |
1111
((t & 0xff00) << 8) |
1112
(t << 24));
1113
}
1114
break;
1115
}
1116
}
1117
}
1118
1119
static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
1120
SurfaceDataBounds *bounds,
1121
jint lockFlags)
1122
{
1123
int x, y, w, h, maxWidth, maxHeight;
1124
int scan;
1125
XImage * img = NULL;
1126
Drawable drawable;
1127
int depth = xsdo->depth;
1128
int mult = xsdo->configData->pixelStride;
1129
int pad = X11SD_GetBitmapPad(mult);
1130
jboolean readBits = lockFlags & SD_LOCK_NEED_PIXELS;
1131
1132
x = bounds->x1;
1133
y = bounds->y1;
1134
w = bounds->x2 - x;
1135
h = bounds->y2 - y;
1136
1137
#ifdef MITSHM
1138
if (useMitShmExt == CAN_USE_MITSHM) {
1139
if (xsdo->isPixmap) {
1140
if (readBits) {
1141
X11SD_PuntPixmap(xsdo, w, h);
1142
}
1143
maxWidth = xsdo->pmWidth;
1144
maxHeight = xsdo->pmHeight;
1145
} else {
1146
XWindowAttributes winAttr;
1147
if (XGetWindowAttributes(awt_display,
1148
(Window) xsdo->drawable, &winAttr) != 0) {
1149
maxWidth = winAttr.width;
1150
maxHeight = winAttr.height;
1151
} else {
1152
/* XGWA failed which isn't a good thing. Defaulting to using
1153
* x,y means that after the subtraction of these we will use
1154
* w=0, h=0 which is a reasonable default on such a failure.
1155
*/
1156
maxWidth = x;
1157
maxHeight = y;
1158
}
1159
}
1160
maxWidth -= x;
1161
maxHeight -= y;
1162
1163
img = X11SD_GetSharedImage(xsdo, w, h, maxWidth, maxHeight, readBits);
1164
}
1165
#endif /* MITSHM */
1166
drawable = xsdo->drawable;
1167
1168
if (readBits) {
1169
#ifdef MITSHM
1170
if (img != NULL) {
1171
if (!XShmGetImage(awt_display, drawable, img, x, y, -1)) {
1172
X11SD_DisposeOrCacheXImage(img);
1173
img = NULL;
1174
}
1175
}
1176
if (img == NULL) {
1177
img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap);
1178
if (img != NULL) {
1179
img->obdata = NULL;
1180
}
1181
}
1182
#else
1183
img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap);
1184
#endif /* MITSHM */
1185
if (img == NULL) {
1186
SurfaceDataBounds temp;
1187
img = XCreateImage(awt_display,
1188
xsdo->configData->awt_visInfo.visual,
1189
depth, ZPixmap, 0, NULL, w, h, pad, 0);
1190
if (img == NULL) {
1191
return NULL;
1192
}
1193
1194
scan = img->bytes_per_line;
1195
img->data = malloc((size_t) h * scan);
1196
if (img->data == NULL) {
1197
XFree(img);
1198
return NULL;
1199
}
1200
1201
if (xsdo->isPixmap == JNI_FALSE &&
1202
X11SD_ClipToRoot(&temp, bounds, xsdo)) {
1203
1204
XImage * temp_image;
1205
temp_image = XGetImage(awt_display, drawable,
1206
temp.x1, temp.y1,
1207
temp.x2 - temp.x1,
1208
temp.y2 - temp.y1,
1209
-1, ZPixmap);
1210
if (temp_image == NULL) {
1211
XGrabServer(awt_display);
1212
if (X11SD_FindClip(&temp, bounds, xsdo)) {
1213
temp_image =
1214
XGetImage(awt_display, drawable,
1215
temp.x1, temp.y1,
1216
temp.x2 - temp.x1,
1217
temp.y2 - temp.y1,
1218
-1, ZPixmap);
1219
}
1220
XUngrabServer(awt_display);
1221
/* Workaround for bug 5039226 */
1222
XSync(awt_display, False);
1223
}
1224
if (temp_image != NULL) {
1225
int temp_scan, bytes_to_copy;
1226
char * img_addr, * temp_addr;
1227
int i;
1228
1229
img_addr = img->data +
1230
(intptr_t) (temp.y1 - y) * scan + (temp.x1 - x) * mult;
1231
temp_scan = temp_image->bytes_per_line;
1232
temp_addr = temp_image->data;
1233
bytes_to_copy = (temp.x2 - temp.x1) * mult;
1234
for (i = temp.y1; i < temp.y2; i++) {
1235
memcpy(img_addr, temp_addr, bytes_to_copy);
1236
img_addr += scan;
1237
temp_addr += temp_scan;
1238
}
1239
XDestroyImage(temp_image);
1240
}
1241
}
1242
img->obdata = NULL;
1243
}
1244
if (depth > 8 && img->byte_order != nativeByteOrder) {
1245
X11SD_SwapBytes(xsdo, img, depth,
1246
xsdo->configData->awtImage->wsImageFormat.bits_per_pixel);
1247
}
1248
} else {
1249
/*
1250
* REMIND: This might be better to move to the Lock function
1251
* to avoid lengthy I/O pauses inside what may be a critical
1252
* section. This will be more critical when SD_LOCK_READ is
1253
* implemented. Another solution is to cache the pixels
1254
* to avoid reading for every operation.
1255
*/
1256
if (img == NULL) {
1257
img = XCreateImage(awt_display,
1258
xsdo->configData->awt_visInfo.visual,
1259
depth, ZPixmap, 0, NULL, w, h, pad, 0);
1260
if (img == NULL) {
1261
return NULL;
1262
}
1263
1264
img->data = malloc((size_t) h * img->bytes_per_line);
1265
if (img->data == NULL) {
1266
XFree(img);
1267
return NULL;
1268
}
1269
1270
img->obdata = NULL;
1271
1272
if (img->byte_order != nativeByteOrder &&
1273
(depth == 15 || depth == 16 || depth == 12)) {
1274
/* bytes will be swapped by XLib. */
1275
img->byte_order = nativeByteOrder;
1276
img->bitmap_bit_order = nativeByteOrder;
1277
}
1278
}
1279
}
1280
return img;
1281
}
1282
1283
void X11SD_DisposeOrCacheXImage(XImage * image) {
1284
/* REMIND: might want to check if the new image worth caching. */
1285
/* Cache only shared images. Passed image is assumed to be non-null. */
1286
if (image->obdata != NULL) {
1287
if (cachedXImage != NULL) {
1288
X11SD_DisposeXImage(cachedXImage);
1289
}
1290
cachedXImage = image;
1291
} else {
1292
X11SD_DisposeXImage(image);
1293
}
1294
}
1295
1296
void X11SD_DisposeXImage(XImage * image) {
1297
if (image != NULL) {
1298
#ifdef MITSHM
1299
if (image->obdata != NULL) {
1300
X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata);
1301
image->obdata = NULL;
1302
}
1303
#endif /* MITSHM */
1304
XDestroyImage(image);
1305
}
1306
}
1307
1308
void
1309
X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo)
1310
{
1311
#ifdef MITSHM
1312
if (xsdo->shmPMData.usingShmPixmap) {
1313
xsdo->shmPMData.xRequestSent = JNI_TRUE;
1314
}
1315
#endif /* MITSHM */
1316
awt_output_flush();
1317
}
1318
1319
/*
1320
* Sets transparent pixels in the pixmap to
1321
* the specified solid background color and returns it.
1322
* Doesn't update source pixmap unless the color of the
1323
* transparent pixels is different from the specified color.
1324
*
1325
* Note: The AWT lock must be held by the current thread
1326
* while calling into this method.
1327
*/
1328
static Drawable
1329
X11SD_GetPixmapWithBg(JNIEnv *env, X11SDOps *xsdo, jint pixel)
1330
{
1331
/* assert AWT_CHECK_HAVE_LOCK(); */
1332
1333
if (xsdo->invalid) {
1334
AWT_UNLOCK();
1335
SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
1336
return 0;
1337
}
1338
1339
/* the image doesn't have transparency, just return it */
1340
if (xsdo->bitmask == 0) {
1341
/* don't need to unlock here, the caller will unlock through
1342
the release call */
1343
return xsdo->drawable;
1344
}
1345
1346
/* Check if current color of the transparent pixels is different
1347
from the specified one */
1348
if (xsdo->isBgInitialized == JNI_FALSE || xsdo->bgPixel != pixel) {
1349
GC srcGC;
1350
GC bmGC;
1351
1352
if (xsdo->drawable == 0) {
1353
AWT_UNLOCK();
1354
return 0;
1355
}
1356
1357
bmGC = XCreateGC(awt_display, xsdo->bitmask, 0, NULL);
1358
if (bmGC == NULL) {
1359
AWT_UNLOCK();
1360
return 0;
1361
}
1362
1363
/* invert the bitmask */
1364
XSetFunction(awt_display, bmGC, GXxor);
1365
XSetForeground(awt_display, bmGC, 1);
1366
XFillRectangle(awt_display, xsdo->bitmask, bmGC,
1367
0, 0, xsdo->pmWidth, xsdo->pmHeight);
1368
1369
srcGC = XCreateGC(awt_display, xsdo->drawable, 0L, NULL);
1370
if (srcGC == NULL) {
1371
XFreeGC(awt_display, bmGC);
1372
AWT_UNLOCK();
1373
return 0;
1374
}
1375
1376
/* set transparent pixels in the source pm to the bg color */
1377
XSetClipMask(awt_display, srcGC, xsdo->bitmask);
1378
XSetForeground(awt_display, srcGC, pixel);
1379
XFillRectangle(awt_display, xsdo->drawable, srcGC,
1380
0, 0, xsdo->pmWidth, xsdo->pmHeight);
1381
1382
/* invert the mask back */
1383
XFillRectangle(awt_display, xsdo->bitmask, bmGC,
1384
0, 0, xsdo->pmWidth, xsdo->pmHeight);
1385
1386
XFreeGC(awt_display, bmGC);
1387
XFreeGC(awt_display, srcGC);
1388
xsdo->bgPixel = pixel;
1389
xsdo->isBgInitialized = JNI_TRUE;
1390
}
1391
1392
return xsdo->drawable;
1393
}
1394
1395
static void
1396
X11SD_ReleasePixmapWithBg(JNIEnv *env, X11SDOps *xsdo)
1397
{
1398
#ifdef MITSHM
1399
if (xsdo->shmPMData.usingShmPixmap) {
1400
xsdo->shmPMData.xRequestSent = JNI_TRUE;
1401
}
1402
#endif /* MITSHM */
1403
}
1404
1405
static int X11SD_GetBitmapPad(int pixelStride) {
1406
// pad must be 8, 16, or 32
1407
return (pixelStride == 3) ? 32 : pixelStride * 8;
1408
}
1409
1410
#endif /* !HEADLESS */
1411
1412
/*
1413
* Class: sun_java2d_x11_X11SurfaceData
1414
* Method: XCreateGC
1415
* Signature: (I)J
1416
*/
1417
JNIEXPORT jlong JNICALL
1418
Java_sun_java2d_x11_XSurfaceData_XCreateGC
1419
(JNIEnv *env, jclass xsd, jlong pXSData)
1420
{
1421
jlong ret;
1422
1423
#ifndef HEADLESS
1424
X11SDOps *xsdo;
1425
1426
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XCreateGC");
1427
1428
xsdo = (X11SDOps *) pXSData;
1429
if (xsdo == NULL) {
1430
return 0L;
1431
}
1432
1433
xsdo->javaGC = XCreateGC(awt_display, xsdo->drawable, 0, NULL);
1434
ret = (jlong) xsdo->javaGC;
1435
#else /* !HEADLESS */
1436
ret = 0L;
1437
#endif /* !HEADLESS */
1438
1439
return ret;
1440
}
1441
1442
/*
1443
* Class: sun_java2d_x11_X11SurfaceData
1444
* Method: XResetClip
1445
* Signature: (JIIIILsun/java2d/pipe/Region;)V
1446
*/
1447
JNIEXPORT void JNICALL
1448
Java_sun_java2d_x11_XSurfaceData_XResetClip
1449
(JNIEnv *env, jclass xsd, jlong xgc)
1450
{
1451
#ifndef HEADLESS
1452
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XResetClip");
1453
XSetClipMask(awt_display, (GC) xgc, None);
1454
#endif /* !HEADLESS */
1455
}
1456
1457
/*
1458
* Class: sun_java2d_x11_X11SurfaceData
1459
* Method: XSetClip
1460
* Signature: (JIIIILsun/java2d/pipe/Region;)V
1461
*/
1462
JNIEXPORT void JNICALL
1463
Java_sun_java2d_x11_XSurfaceData_XSetClip
1464
(JNIEnv *env, jclass xsd, jlong xgc,
1465
jint x1, jint y1, jint x2, jint y2,
1466
jobject complexclip)
1467
{
1468
#ifndef HEADLESS
1469
int numrects;
1470
XRectangle rects[256];
1471
XRectangle *pRect = rects;
1472
1473
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetClip");
1474
1475
numrects = RegionToYXBandedRectangles(env,
1476
x1, y1, x2, y2, complexclip,
1477
&pRect, 256);
1478
1479
XSetClipRectangles(awt_display, (GC) xgc, 0, 0, pRect, numrects, YXBanded);
1480
1481
if (pRect != rects) {
1482
free(pRect);
1483
}
1484
#endif /* !HEADLESS */
1485
}
1486
1487
/*
1488
* Class: sun_java2d_x11_X11SurfaceData
1489
* Method: XSetCopyMode
1490
* Signature: (J)V
1491
*/
1492
JNIEXPORT void JNICALL
1493
Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode
1494
(JNIEnv *env, jclass xsd, jlong xgc)
1495
{
1496
#ifndef HEADLESS
1497
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetCopyMode");
1498
XSetFunction(awt_display, (GC) xgc, GXcopy);
1499
#endif /* !HEADLESS */
1500
}
1501
1502
/*
1503
* Class: sun_java2d_x11_X11SurfaceData
1504
* Method: XSetXorMode
1505
* Signature: (J)V
1506
*/
1507
JNIEXPORT void JNICALL
1508
Java_sun_java2d_x11_X11SurfaceData_XSetXorMode
1509
(JNIEnv *env, jclass xr, jlong xgc)
1510
{
1511
#ifndef HEADLESS
1512
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetXorMode");
1513
XSetFunction(awt_display, (GC) xgc, GXxor);
1514
#endif /* !HEADLESS */
1515
}
1516
1517
/*
1518
* Class: sun_java2d_x11_X11SurfaceData
1519
* Method: XSetForeground
1520
* Signature: (JI)V
1521
*/
1522
JNIEXPORT void JNICALL
1523
Java_sun_java2d_x11_X11SurfaceData_XSetForeground
1524
(JNIEnv *env, jclass xsd, jlong xgc, jint pixel)
1525
{
1526
#ifndef HEADLESS
1527
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetForeground");
1528
XSetForeground(awt_display, (GC) xgc, pixel);
1529
#endif /* !HEADLESS */
1530
}
1531
1532
/*
1533
* Class: sun_java2d_x11_X11SurfaceData
1534
* Method: XSetGraphicsExposures
1535
* Signature: (JZ)V
1536
*/
1537
JNIEXPORT void JNICALL
1538
Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures
1539
(JNIEnv *env, jclass xsd, jlong xgc, jboolean needExposures)
1540
{
1541
#ifndef HEADLESS
1542
J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetGraphicsExposures");
1543
XSetGraphicsExposures(awt_display, (GC) xgc, needExposures ? True : False);
1544
#endif /* !HEADLESS */
1545
}
1546
1547