< prev index next >

src/java.desktop/windows/native/libawt/java2d/windows/GDIBlitLoops.cpp

Print this page




  25 
  26 #include "awt.h"
  27 #include <sun_java2d_windows_GDIBlitLoops.h>
  28 #include "gdefs.h"
  29 #include "Trace.h"
  30 #include "GDIWindowSurfaceData.h"
  31 
  32 static RGBQUAD *byteGrayPalette = NULL;
  33 
  34 extern "C" {
  35 
  36 typedef struct tagBitmapheader  {
  37     BITMAPINFOHEADER bmiHeader;
  38     union {
  39         DWORD           dwMasks[3];
  40         RGBQUAD         palette[256];
  41     } colors;
  42 } BmiType;
  43 
  44 /*






























































  45  * Class:     sun_java2d_windows_GDIBlitLoops
  46  * Method:    nativeBlit
  47  * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;IIIIIIZ)V
  48  */
  49 JNIEXPORT void JNICALL
  50 Java_sun_java2d_windows_GDIBlitLoops_nativeBlit
  51     (JNIEnv *env, jobject joSelf,
  52      jobject srcData, jobject dstData,
  53      jobject clip,
  54      jint srcx, jint srcy,
  55      jint dstx, jint dsty,
  56      jint width, jint height,
  57      jint rmask, jint gmask, jint bmask,
  58      jboolean needLut)
  59 {
  60     J2dTraceLn(J2D_TRACE_INFO, "GDIBlitLoops_nativeBlit");
  61 
  62     SurfaceDataRasInfo srcInfo;
  63     SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcData);
  64     GDIWinSDOps *dstOps = GDIWindowSurfaceData_GetOps(env, dstData);


 110         // GetRasInfo implicitly calls GetPrimitiveArrayCritical
 111         // and since GetDC uses JNI it needs to be called first.
 112         HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0);
 113         if (hDC == NULL) {
 114             SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 115             return;
 116         }
 117         srcOps->GetRasInfo(env, srcOps, &srcInfo);
 118         if (srcInfo.rasBase == NULL) {
 119             dstOps->ReleaseDC(env, dstOps, hDC);
 120             SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 121             return;
 122         }
 123         void *rasBase = ((char *)srcInfo.rasBase) + srcInfo.scanStride * srcy +
 124                         srcInfo.pixelStride * srcx;
 125 
 126         // If scanlines are DWORD-aligned (scanStride is a multiple of 4),
 127         // then we can do the work much faster.  This is due to a constraint
 128         // in the way DIBs are structured and parsed by GDI
 129         jboolean fastBlt = ((srcInfo.scanStride & 0x03) == 0);
 130 
 131         bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
 132         bmi.bmiHeader.biWidth = srcInfo.scanStride/srcInfo.pixelStride;
 133         // fastBlt copies whole image in one call; else copy line-by-line
 134         LONG dwHeight = srcInfo.bounds.y2 - srcInfo.bounds.y1;
 135         bmi.bmiHeader.biHeight = (fastBlt) ? -dwHeight : -1;
 136         bmi.bmiHeader.biPlanes = 1;
 137         bmi.bmiHeader.biBitCount = (WORD)srcInfo.pixelStride * 8;
 138         // 1,3,4 byte use BI_RGB, 2 byte use BI_BITFIELD...
 139         // 4 byte _can_ use BI_BITFIELD, but this seems to cause a performance
 140         // penalty.  Since we only ever have one format (xrgb) for 32-bit
 141         // images that enter this function, just use BI_RGB.
 142         // Could do BI_RGB for 2-byte 555 format, but no perceived
 143         // performance benefit.
 144         bmi.bmiHeader.biCompression = (srcInfo.pixelStride != 2)
 145                 ? BI_RGB : BI_BITFIELDS;
 146         bmi.bmiHeader.biSizeImage = (bmi.bmiHeader.biWidth * dwHeight *
 147                                      srcInfo.pixelStride);
 148         bmi.bmiHeader.biXPelsPerMeter = 0;
 149         bmi.bmiHeader.biYPelsPerMeter = 0;
 150         bmi.bmiHeader.biClrUsed = 0;


 173                         byteGrayPalette[i].rgbGreen = i;
 174                         byteGrayPalette[i].rgbBlue = i;
 175                     }
 176                 }
 177                 memcpy(bmi.colors.palette, byteGrayPalette, 256 * sizeof(RGBQUAD));
 178             }
 179         } else if (srcInfo.pixelStride == 2) {
 180             // For 16-bit case, init the masks for the pixel depth
 181             bmi.colors.dwMasks[0] = rmask;
 182             bmi.colors.dwMasks[1] = gmask;
 183             bmi.colors.dwMasks[2] = bmask;
 184         }
 185 
 186         if (fastBlt) {
 187             // Window could go away at any time, leaving bits on the screen
 188             // from this GDI call, so make sure window still exists
 189             if (::IsWindowVisible(dstOps->window)) {
 190                 // Could also call StretchDIBits.  Testing showed slight
 191                 // performance advantage of SetDIBits instead, so since we
 192                 // have no need of scaling, might as well use SetDIBits.
 193                 SetDIBitsToDevice(hDC, dstx, dsty, width, height,
 194                     0, 0, 0, height, rasBase,
 195                     (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
 196             }
 197         } else {
 198             // Source scanlines not DWORD-aligned - copy each scanline individually
 199             for (int i = 0; i < height; i += 1) {
 200                 if (::IsWindowVisible(dstOps->window)) {
 201                     SetDIBitsToDevice(hDC, dstx, dsty+i, width, 1,
 202                         0, 0, 0, 1, rasBase,
 203                         (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
 204                     rasBase = (void*)((char*)rasBase + srcInfo.scanStride);
 205                 } else {
 206                     break;
 207                 }
 208             }
 209         }
 210         dstOps->ReleaseDC(env, dstOps, hDC);
 211         SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
 212     }
 213     SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 214 
 215     return;
 216 }
 217 
 218 } // extern "C"


  25 
  26 #include "awt.h"
  27 #include <sun_java2d_windows_GDIBlitLoops.h>
  28 #include "gdefs.h"
  29 #include "Trace.h"
  30 #include "GDIWindowSurfaceData.h"
  31 
  32 static RGBQUAD *byteGrayPalette = NULL;
  33 
  34 extern "C" {
  35 
  36 typedef struct tagBitmapheader  {
  37     BITMAPINFOHEADER bmiHeader;
  38     union {
  39         DWORD           dwMasks[3];
  40         RGBQUAD         palette[256];
  41     } colors;
  42 } BmiType;
  43 
  44 /*
  45  * Some GDI functions functions will fail if they operate on memory which spans
  46  * virtual allocations as used by modern garbage collectors (ie ZGC).
  47  * So if the call to SetDIBitsToDevice fails, we will re-try it on malloced
  48  * memory rather than the pinned Java heap memory.
  49  * Once Microsoft fix the GDI bug, the small performance penalty of this retry
  50  * will be gone.
  51  */
  52 static void retryingSetDIBitsToDevice(
  53     HDC              hdc,
  54     int              xDest,
  55     int              yDest,
  56     DWORD            w,
  57     DWORD            h,
  58     int              xSrc,
  59     int              ySrc,
  60     UINT             StartScan,
  61     UINT             cLines,
  62     const VOID       *lpvBits,
  63     BITMAPINFO       *lpbmi,
  64     UINT             ColorUse) {
  65 
  66 #ifdef DEBUG_PERF
  67     LARGE_INTEGER    ts1, ts2;
  68     QueryPerformanceCounter(&ts1);
  69 #endif
  70 
  71     int ret =
  72         SetDIBitsToDevice(hdc, xDest, yDest, w, h,
  73                           xSrc, ySrc, StartScan, cLines, lpvBits,
  74                           lpbmi, ColorUse);
  75 
  76     if (ret != 0 || h == 0) {
  77 #ifdef DEBUG_PERF
  78          QueryPerformanceCounter(&ts2);
  79          printf("success time: %zd\n", (ts2.QuadPart-ts1.QuadPart));
  80 #endif
  81         return;
  82     }
  83 
  84     size_t size = lpbmi->bmiHeader.biSizeImage;
  85     void* imageData = NULL;
  86     try {
  87         imageData = safe_Malloc(size);
  88     } catch (std::bad_alloc&) {
  89     }
  90     if (imageData == NULL) {
  91         return;
  92     }
  93     memcpy(imageData, lpvBits, size); // this is the most expensive part.
  94     SetDIBitsToDevice(hdc, xDest, yDest, w, h,
  95                       xSrc, ySrc, StartScan, cLines, imageData,
  96                       lpbmi, ColorUse);
  97     free(imageData);
  98 
  99 #ifdef DEBUG_PERF
 100     QueryPerformanceCounter(&ts2);
 101     printf("with retry time: %zd\n", (ts2.QuadPart-ts1.QuadPart));
 102 #endif
 103 
 104 };
 105 
 106 /*
 107  * Class:     sun_java2d_windows_GDIBlitLoops
 108  * Method:    nativeBlit
 109  * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;IIIIIIZ)V
 110  */
 111 JNIEXPORT void JNICALL
 112 Java_sun_java2d_windows_GDIBlitLoops_nativeBlit
 113     (JNIEnv *env, jobject joSelf,
 114      jobject srcData, jobject dstData,
 115      jobject clip,
 116      jint srcx, jint srcy,
 117      jint dstx, jint dsty,
 118      jint width, jint height,
 119      jint rmask, jint gmask, jint bmask,
 120      jboolean needLut)
 121 {
 122     J2dTraceLn(J2D_TRACE_INFO, "GDIBlitLoops_nativeBlit");
 123 
 124     SurfaceDataRasInfo srcInfo;
 125     SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcData);
 126     GDIWinSDOps *dstOps = GDIWindowSurfaceData_GetOps(env, dstData);


 172         // GetRasInfo implicitly calls GetPrimitiveArrayCritical
 173         // and since GetDC uses JNI it needs to be called first.
 174         HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0);
 175         if (hDC == NULL) {
 176             SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 177             return;
 178         }
 179         srcOps->GetRasInfo(env, srcOps, &srcInfo);
 180         if (srcInfo.rasBase == NULL) {
 181             dstOps->ReleaseDC(env, dstOps, hDC);
 182             SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 183             return;
 184         }
 185         void *rasBase = ((char *)srcInfo.rasBase) + srcInfo.scanStride * srcy +
 186                         srcInfo.pixelStride * srcx;
 187 
 188         // If scanlines are DWORD-aligned (scanStride is a multiple of 4),
 189         // then we can do the work much faster.  This is due to a constraint
 190         // in the way DIBs are structured and parsed by GDI
 191         jboolean fastBlt = ((srcInfo.scanStride & 0x03) == 0);

 192         bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
 193         bmi.bmiHeader.biWidth = srcInfo.scanStride/srcInfo.pixelStride;
 194         // fastBlt copies whole image in one call; else copy line-by-line
 195         LONG dwHeight = srcInfo.bounds.y2 - srcInfo.bounds.y1;
 196         bmi.bmiHeader.biHeight = (fastBlt) ? -dwHeight : -1;
 197         bmi.bmiHeader.biPlanes = 1;
 198         bmi.bmiHeader.biBitCount = (WORD)srcInfo.pixelStride * 8;
 199         // 1,3,4 byte use BI_RGB, 2 byte use BI_BITFIELD...
 200         // 4 byte _can_ use BI_BITFIELD, but this seems to cause a performance
 201         // penalty.  Since we only ever have one format (xrgb) for 32-bit
 202         // images that enter this function, just use BI_RGB.
 203         // Could do BI_RGB for 2-byte 555 format, but no perceived
 204         // performance benefit.
 205         bmi.bmiHeader.biCompression = (srcInfo.pixelStride != 2)
 206                 ? BI_RGB : BI_BITFIELDS;
 207         bmi.bmiHeader.biSizeImage = (bmi.bmiHeader.biWidth * dwHeight *
 208                                      srcInfo.pixelStride);
 209         bmi.bmiHeader.biXPelsPerMeter = 0;
 210         bmi.bmiHeader.biYPelsPerMeter = 0;
 211         bmi.bmiHeader.biClrUsed = 0;


 234                         byteGrayPalette[i].rgbGreen = i;
 235                         byteGrayPalette[i].rgbBlue = i;
 236                     }
 237                 }
 238                 memcpy(bmi.colors.palette, byteGrayPalette, 256 * sizeof(RGBQUAD));
 239             }
 240         } else if (srcInfo.pixelStride == 2) {
 241             // For 16-bit case, init the masks for the pixel depth
 242             bmi.colors.dwMasks[0] = rmask;
 243             bmi.colors.dwMasks[1] = gmask;
 244             bmi.colors.dwMasks[2] = bmask;
 245         }
 246 
 247         if (fastBlt) {
 248             // Window could go away at any time, leaving bits on the screen
 249             // from this GDI call, so make sure window still exists
 250             if (::IsWindowVisible(dstOps->window)) {
 251                 // Could also call StretchDIBits.  Testing showed slight
 252                 // performance advantage of SetDIBits instead, so since we
 253                 // have no need of scaling, might as well use SetDIBits.
 254                 retryingSetDIBitsToDevice(hDC, dstx, dsty, width, height,
 255                     0, 0, 0, height, rasBase,
 256                     (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
 257             }
 258         } else {
 259             // Source scanlines not DWORD-aligned - copy each scanline individually
 260             for (int i = 0; i < height; i += 1) {
 261                 if (::IsWindowVisible(dstOps->window)) {
 262                     retryingSetDIBitsToDevice(hDC, dstx, dsty+i, width, 1,
 263                         0, 0, 0, 1, rasBase,
 264                         (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
 265                     rasBase = (void*)((char*)rasBase + srcInfo.scanStride);
 266                 } else {
 267                     break;
 268                 }
 269             }
 270         }
 271         dstOps->ReleaseDC(env, dstOps, hDC);
 272         SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
 273     }
 274     SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
 275 
 276     return;
 277 }
 278 
 279 } // extern "C"
< prev index next >