1 | /* |
2 | * Copyright (c) 2000, 2007, 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 <stdlib.h> |
27 | #include <jni.h> |
28 | #include <jlong.h> |
29 | #include "X11SurfaceData.h" |
30 | #include "Region.h" |
31 | |
32 | JNIEXPORT void JNICALL |
33 | Java_sun_java2d_x11_X11PMBlitLoops_nativeBlit |
34 | (JNIEnv *env, jobject joSelf, |
35 | jlong srcData, jlong dstData, |
36 | jlong gc, jobject clip, |
37 | jint srcx, jint srcy, |
38 | jint dstx, jint dsty, |
39 | jint width, jint height) |
40 | { |
41 | #ifndef HEADLESS |
42 | X11SDOps *srcXsdo, *dstXsdo; |
43 | SurfaceDataBounds span, srcBounds; |
44 | RegionData clipInfo; |
45 | GC xgc; |
46 | |
47 | if (width <= 0 || height <= 0) { |
48 | return; |
49 | } |
50 | |
51 | srcXsdo = (X11SDOps *)jlong_to_ptr(srcData); |
52 | if (srcXsdo == NULL) { |
53 | return; |
54 | } |
55 | dstXsdo = (X11SDOps *)jlong_to_ptr(dstData); |
56 | if (dstXsdo == NULL) { |
57 | return; |
58 | } |
59 | if (Region_GetInfo(env, clip, &clipInfo)) { |
60 | return; |
61 | } |
62 | |
63 | xgc = (GC)gc; |
64 | if (xgc == NULL) { |
65 | return; |
66 | } |
67 | |
68 | #ifdef MITSHM |
69 | if (srcXsdo->isPixmap) { |
70 | X11SD_UnPuntPixmap(srcXsdo); |
71 | } |
72 | #endif /* MITSHM */ |
73 | |
74 | /* clip the source rect to the source pixmap's dimensions */ |
75 | srcBounds.x1 = srcx; |
76 | srcBounds.y1 = srcy; |
77 | srcBounds.x2 = srcx + width; |
78 | srcBounds.y2 = srcy + height; |
79 | SurfaceData_IntersectBoundsXYXY(&srcBounds, |
80 | 0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight); |
81 | span.x1 = dstx; |
82 | span.y1 = dsty; |
83 | span.x2 = dstx + width; |
84 | span.y2 = dsty + height; |
85 | |
86 | /* intersect the source and dest rects */ |
87 | SurfaceData_IntersectBlitBounds(&srcBounds, &span, |
88 | dstx - srcx, dsty - srcy); |
89 | srcx = srcBounds.x1; |
90 | srcy = srcBounds.y1; |
91 | dstx = span.x1; |
92 | dsty = span.y1; |
93 | |
94 | if (srcXsdo->bitmask != 0) { |
95 | XSetClipOrigin(awt_display, xgc, dstx - srcx, dsty - srcy); |
96 | XSetClipMask(awt_display, xgc, srcXsdo->bitmask); |
97 | } |
98 | |
99 | Region_IntersectBounds(&clipInfo, &span); |
100 | if (!Region_IsEmpty(&clipInfo)) { |
101 | Region_StartIteration(env, &clipInfo); |
102 | srcx -= dstx; |
103 | srcy -= dsty; |
104 | while (Region_NextIteration(&clipInfo, &span)) { |
105 | XCopyArea(awt_display, srcXsdo->drawable, dstXsdo->drawable, xgc, |
106 | srcx + span.x1, srcy + span.y1, |
107 | span.x2 - span.x1, span.y2 - span.y1, |
108 | span.x1, span.y1); |
109 | } |
110 | Region_EndIteration(env, &clipInfo); |
111 | } |
112 | |
113 | if (srcXsdo->bitmask != 0) { |
114 | XSetClipMask(awt_display, xgc, None); |
115 | } |
116 | |
117 | #ifdef MITSHM |
118 | if (srcXsdo->shmPMData.usingShmPixmap) { |
119 | srcXsdo->shmPMData.xRequestSent = JNI_TRUE; |
120 | } |
121 | #endif /* MITSHM */ |
122 | X11SD_DirectRenderNotify(env, dstXsdo); |
123 | #endif /* !HEADLESS */ |
124 | } |
125 | |
126 | JNIEXPORT void JNICALL |
127 | Java_sun_java2d_x11_X11PMBlitBgLoops_nativeBlitBg |
128 | (JNIEnv *env, jobject joSelf, |
129 | jlong srcData, jlong dstData, |
130 | jlong xgc, jint pixel, |
131 | jint srcx, jint srcy, |
132 | jint dstx, jint dsty, |
133 | jint width, jint height) |
134 | { |
135 | #ifndef HEADLESS |
136 | X11SDOps *srcXsdo, *dstXsdo; |
137 | GC dstGC; |
138 | SurfaceDataBounds dstBounds, srcBounds; |
139 | Drawable srcDrawable; |
140 | |
141 | if (width <= 0 || height <= 0) { |
142 | return; |
143 | } |
144 | |
145 | srcXsdo = (X11SDOps *)jlong_to_ptr(srcData); |
146 | if (srcXsdo == NULL) { |
147 | return; |
148 | } |
149 | dstXsdo = (X11SDOps *)jlong_to_ptr(dstData); |
150 | if (dstXsdo == NULL) { |
151 | return; |
152 | } |
153 | |
154 | dstGC = (GC)xgc; |
155 | if (dstGC == NULL) { |
156 | return; |
157 | } |
158 | |
159 | #ifdef MITSHM |
160 | if (srcXsdo->isPixmap) { |
161 | X11SD_UnPuntPixmap(srcXsdo); |
162 | } |
163 | #endif /* MITSHM */ |
164 | |
165 | srcDrawable = srcXsdo->GetPixmapWithBg(env, srcXsdo, pixel); |
166 | if (srcDrawable == 0) { |
167 | return; |
168 | } |
169 | |
170 | /* clip the source rect to the source pixmap's dimensions */ |
171 | srcBounds.x1 = srcx; |
172 | srcBounds.y1 = srcy; |
173 | srcBounds.x2 = srcx + width; |
174 | srcBounds.y2 = srcy + height; |
175 | SurfaceData_IntersectBoundsXYXY(&srcBounds, |
176 | 0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight); |
177 | dstBounds.x1 = dstx; |
178 | dstBounds.y1 = dsty; |
179 | dstBounds.x2 = dstx + width; |
180 | dstBounds.y2 = dsty + height; |
181 | |
182 | /* intersect the source and dest rects */ |
183 | SurfaceData_IntersectBlitBounds(&srcBounds, &dstBounds, |
184 | dstx - srcx, dsty - srcy); |
185 | srcx = srcBounds.x1; |
186 | srcy = srcBounds.y1; |
187 | dstx = dstBounds.x1; |
188 | dsty = dstBounds.y1; |
189 | width = srcBounds.x2 - srcBounds.x1; |
190 | height = srcBounds.y2 - srcBounds.y1; |
191 | |
192 | /* do an unmasked copy as we've already filled transparent |
193 | pixels of the source image with the desired color */ |
194 | XCopyArea(awt_display, srcDrawable, dstXsdo->drawable, dstGC, |
195 | srcx, srcy, width, height, dstx, dsty); |
196 | |
197 | srcXsdo->ReleasePixmapWithBg(env, srcXsdo); |
198 | X11SD_DirectRenderNotify(env, dstXsdo); |
199 | #endif /* !HEADLESS */ |
200 | } |
201 | |
202 | /* |
203 | * Class: sun_java2d_x11_X11PMBlitLoops |
204 | * Method: updateBitmask |
205 | * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;)V |
206 | */ |
207 | JNIEXPORT void JNICALL |
208 | Java_sun_java2d_x11_X11PMBlitLoops_updateBitmask |
209 | (JNIEnv *env, jclass xpmbl, jobject srcsd, jobject dstsd, jboolean isICM) |
210 | { |
211 | #ifndef HEADLESS |
212 | SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcsd); |
213 | X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, dstsd); |
214 | SurfaceDataRasInfo srcInfo; |
215 | |
216 | int flags; |
217 | int screen; |
218 | int width; |
219 | int height; |
220 | jint srcScan, dstScan; |
221 | int rowCount; |
222 | unsigned char *pDst; |
223 | XImage *image; |
224 | GC xgc; |
225 | |
226 | if (srcOps == NULL || xsdo == NULL) { |
227 | JNU_ThrowNullPointerException(env, "Null BISD in updateMaskRegion" ); |
228 | return; |
229 | } |
230 | |
231 | AWT_LOCK(); |
232 | |
233 | screen = xsdo->configData->awt_visInfo.screen; |
234 | width = xsdo->pmWidth; |
235 | height = xsdo->pmHeight; |
236 | |
237 | if (xsdo->bitmask == 0) { |
238 | /* create the bitmask if it is not yet created */ |
239 | xsdo->bitmask = XCreatePixmap(awt_display, |
240 | RootWindow(awt_display, screen), |
241 | width, height, 1); |
242 | if (xsdo->bitmask == 0) { |
243 | AWT_UNLOCK(); |
244 | if (!(*env)->ExceptionCheck(env)) |
245 | { |
246 | JNU_ThrowOutOfMemoryError(env, |
247 | "Cannot create bitmask for " |
248 | "offscreen surface" ); |
249 | } |
250 | return; |
251 | } |
252 | } |
253 | |
254 | /* Create a bitmask image and then blit it to the pixmap. */ |
255 | image = XCreateImage(awt_display, DefaultVisual(awt_display, screen), |
256 | 1, XYBitmap, 0, NULL, width, height, 32, 0); |
257 | if (image == NULL) { |
258 | AWT_UNLOCK(); |
259 | if (!(*env)->ExceptionCheck(env)) |
260 | { |
261 | JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask" ); |
262 | } |
263 | return; |
264 | } |
265 | dstScan = image->bytes_per_line; |
266 | image->data = malloc(dstScan * height); |
267 | if (image->data == NULL) { |
268 | XFree(image); |
269 | AWT_UNLOCK(); |
270 | if (!(*env)->ExceptionCheck(env)) |
271 | { |
272 | JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask" ); |
273 | } |
274 | return; |
275 | } |
276 | pDst = (unsigned char *)image->data; |
277 | |
278 | srcInfo.bounds.x1 = 0; |
279 | srcInfo.bounds.y1 = 0; |
280 | srcInfo.bounds.x2 = width; |
281 | srcInfo.bounds.y2 = height; |
282 | |
283 | flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ); |
284 | if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) { |
285 | XDestroyImage(image); |
286 | AWT_UNLOCK(); |
287 | return; |
288 | } |
289 | srcOps->GetRasInfo(env, srcOps, &srcInfo); |
290 | |
291 | rowCount = height; |
292 | if (isICM) { |
293 | unsigned char *pSrc; |
294 | jint *srcLut; |
295 | |
296 | srcScan = srcInfo.scanStride; |
297 | srcLut = srcInfo.lutBase; |
298 | pSrc = (unsigned char *)srcInfo.rasBase; |
299 | |
300 | if (image->bitmap_bit_order == MSBFirst) { |
301 | do { |
302 | int x = 0, bx = 0; |
303 | unsigned int pix = 0; |
304 | unsigned int bit = 0x80; |
305 | unsigned char *srcPixel = pSrc; |
306 | do { |
307 | if (bit == 0) { |
308 | pDst[bx++] = (unsigned char)pix; |
309 | pix = 0; |
310 | bit = 0x80; |
311 | } |
312 | pix |= bit & (srcLut[*srcPixel++] >> 31); |
313 | bit >>= 1; |
314 | } while (++x < width); |
315 | pDst[bx] = (unsigned char)pix; |
316 | pDst += dstScan; |
317 | pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan); |
318 | } while (--rowCount > 0); |
319 | } else { |
320 | do { |
321 | int x = 0, bx = 0; |
322 | unsigned int pix = 0; |
323 | unsigned int bit = 1; |
324 | unsigned char *srcPixel = pSrc; |
325 | do { |
326 | if ((bit >> 8) != 0) { |
327 | pDst[bx++] = (unsigned char) pix; |
328 | pix = 0; |
329 | bit = 1; |
330 | } |
331 | pix |= bit & (srcLut[*srcPixel++] >> 31); |
332 | bit <<= 1; |
333 | } while (++x < width); |
334 | pDst[bx] = (unsigned char) pix; |
335 | pDst += dstScan; |
336 | pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan); |
337 | } while (--rowCount > 0); |
338 | } |
339 | } else /*DCM with ARGB*/ { |
340 | unsigned int *pSrc; |
341 | |
342 | /* this is a number of pixels in a row, not number of bytes */ |
343 | srcScan = srcInfo.scanStride; |
344 | pSrc = (unsigned int *)srcInfo.rasBase; |
345 | |
346 | if (image->bitmap_bit_order == MSBFirst) { |
347 | do { |
348 | int x = 0, bx = 0; |
349 | unsigned int pix = 0; |
350 | unsigned int bit = 0x80; |
351 | int *srcPixel = (int *) pSrc; |
352 | do { |
353 | if (bit == 0) { |
354 | /* next word */ |
355 | pDst[bx++] = (unsigned char)pix; |
356 | pix = 0; |
357 | bit = 0x80; |
358 | } |
359 | if (*srcPixel++ & 0xff000000) { |
360 | /* if src pixel is opaque, set the bit in the bitmap */ |
361 | pix |= bit; |
362 | } |
363 | bit >>= 1; |
364 | } while (++x < width); |
365 | /* last pixels in a row */ |
366 | pDst[bx] = (unsigned char)pix; |
367 | |
368 | pDst += dstScan; |
369 | pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan); |
370 | } while (--rowCount > 0); |
371 | } else { |
372 | do { |
373 | int x = 0, bx = 0; |
374 | unsigned int pix = 0; |
375 | unsigned int bit = 1; |
376 | int *srcPixel = (int *) pSrc; |
377 | do { |
378 | if ((bit >> 8) != 0) { |
379 | pDst[bx++] = (unsigned char)pix; |
380 | pix = 0; |
381 | bit = 1; |
382 | } |
383 | if (*srcPixel++ & 0xff000000) { |
384 | /* if src pixel is opaque, set the bit in the bitmap */ |
385 | pix |= bit; |
386 | } |
387 | bit <<= 1; |
388 | } while (++x < width); |
389 | pDst[bx] = (unsigned char)pix; |
390 | pDst += dstScan; |
391 | pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan); |
392 | } while (--rowCount > 0); |
393 | } |
394 | } |
395 | SurfaceData_InvokeRelease(env, srcOps, &srcInfo); |
396 | SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); |
397 | |
398 | xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL); |
399 | XSetForeground(awt_display, xgc, 1); |
400 | XSetBackground(awt_display, xgc, 0); |
401 | XPutImage(awt_display, xsdo->bitmask, xgc, |
402 | image, 0, 0, 0, 0, width, height); |
403 | |
404 | XFreeGC(awt_display, xgc); |
405 | XDestroyImage(image); |
406 | |
407 | AWT_UNLOCK(); |
408 | #endif /* !HEADLESS */ |
409 | } |
410 | |