< prev index next >
src/java.desktop/windows/native/libawt/java2d/windows/GDIBlitLoops.cpp
Print this page
@@ -40,10 +40,72 @@
RGBQUAD palette[256];
} colors;
} BmiType;
/*
+ * Some GDI functions functions will fail if they operate on memory which spans
+ * virtual allocations as used by modern garbage collectors (ie ZGC).
+ * So if the call to SetDIBitsToDevice fails, we will re-try it on malloced
+ * memory rather than the pinned Java heap memory.
+ * Once Microsoft fix the GDI bug, the small performance penalty of this retry
+ * will be gone.
+ */
+static void retryingSetDIBitsToDevice(
+ HDC hdc,
+ int xDest,
+ int yDest,
+ DWORD w,
+ DWORD h,
+ int xSrc,
+ int ySrc,
+ UINT StartScan,
+ UINT cLines,
+ const VOID *lpvBits,
+ BITMAPINFO *lpbmi,
+ UINT ColorUse) {
+
+#ifdef DEBUG_PERF
+ LARGE_INTEGER ts1, ts2;
+ QueryPerformanceCounter(&ts1);
+#endif
+
+ int ret =
+ SetDIBitsToDevice(hdc, xDest, yDest, w, h,
+ xSrc, ySrc, StartScan, cLines, lpvBits,
+ lpbmi, ColorUse);
+
+ if (ret != 0 || h == 0) {
+#ifdef DEBUG_PERF
+ QueryPerformanceCounter(&ts2);
+ printf("success time: %zd\n", (ts2.QuadPart-ts1.QuadPart));
+#endif
+ return;
+ }
+
+ size_t size = lpbmi->bmiHeader.biSizeImage;
+ void* imageData = NULL;
+ try {
+ imageData = safe_Malloc(size);
+ } catch (std::bad_alloc&) {
+ }
+ if (imageData == NULL) {
+ return;
+ }
+ memcpy(imageData, lpvBits, size); // this is the most expensive part.
+ SetDIBitsToDevice(hdc, xDest, yDest, w, h,
+ xSrc, ySrc, StartScan, cLines, imageData,
+ lpbmi, ColorUse);
+ free(imageData);
+
+#ifdef DEBUG_PERF
+ QueryPerformanceCounter(&ts2);
+ printf("with retry time: %zd\n", (ts2.QuadPart-ts1.QuadPart));
+#endif
+
+};
+
+/*
* Class: sun_java2d_windows_GDIBlitLoops
* Method: nativeBlit
* Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;IIIIIIZ)V
*/
JNIEXPORT void JNICALL
@@ -125,11 +187,10 @@
// If scanlines are DWORD-aligned (scanStride is a multiple of 4),
// then we can do the work much faster. This is due to a constraint
// in the way DIBs are structured and parsed by GDI
jboolean fastBlt = ((srcInfo.scanStride & 0x03) == 0);
-
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = srcInfo.scanStride/srcInfo.pixelStride;
// fastBlt copies whole image in one call; else copy line-by-line
LONG dwHeight = srcInfo.bounds.y2 - srcInfo.bounds.y1;
bmi.bmiHeader.biHeight = (fastBlt) ? -dwHeight : -1;
@@ -188,19 +249,19 @@
// from this GDI call, so make sure window still exists
if (::IsWindowVisible(dstOps->window)) {
// Could also call StretchDIBits. Testing showed slight
// performance advantage of SetDIBits instead, so since we
// have no need of scaling, might as well use SetDIBits.
- SetDIBitsToDevice(hDC, dstx, dsty, width, height,
+ retryingSetDIBitsToDevice(hDC, dstx, dsty, width, height,
0, 0, 0, height, rasBase,
(BITMAPINFO*)&bmi, DIB_RGB_COLORS);
}
} else {
// Source scanlines not DWORD-aligned - copy each scanline individually
for (int i = 0; i < height; i += 1) {
if (::IsWindowVisible(dstOps->window)) {
- SetDIBitsToDevice(hDC, dstx, dsty+i, width, 1,
+ retryingSetDIBitsToDevice(hDC, dstx, dsty+i, width, 1,
0, 0, 0, 1, rasBase,
(BITMAPINFO*)&bmi, DIB_RGB_COLORS);
rasBase = (void*)((char*)rasBase + srcInfo.scanStride);
} else {
break;
< prev index next >