--- old/src/share/native/sun/java2d/opengl/OGLBlitLoops.c 2014-04-24 00:01:28.810066400 +0400 +++ new/src/share/native/sun/java2d/opengl/OGLBlitLoops.c 2014-04-24 00:01:28.665459000 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,9 @@ #include "OGLSurfaceData.h" #include "GraphicsPrimitiveMgr.h" +#include // malloc +#include // memcpy + extern OGLPixelFormat PixelFormats[]; /** @@ -750,6 +753,8 @@ dstOps->GetRasInfo(env, dstOps, &dstInfo); if (dstInfo.rasBase) { void *pDst = dstInfo.rasBase; + void* tempRow; + jint clippedStride; srcx = srcInfo.bounds.x1; srcy = srcInfo.bounds.y1; @@ -758,7 +763,7 @@ width = srcInfo.bounds.x2 - srcInfo.bounds.x1; height = srcInfo.bounds.y2 - srcInfo.bounds.y1; - j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, dstx); + pDst = PtrAddBytes(pDst, dstx * dstInfo.pixelStride); j2d_glPixelStorei(GL_PACK_ROW_LENGTH, dstInfo.scanStride / dstInfo.pixelStride); j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment); @@ -780,16 +785,37 @@ // this accounts for lower-left origin of the source region srcx = srcOps->xOffset + srcx; srcy = srcOps->yOffset + srcOps->height - (srcy + 1); - - // we must read one scanline at a time because there is no way - // to read starting at the top-left corner of the source region - while (height > 0) { - j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty); - j2d_glReadPixels(srcx, srcy, width, 1, + + // Note that glReadPixels() is extremely slow! + // So we try to call it only once and flip the image using memcpy. + clippedStride = dstInfo.pixelStride * width; + if (tempRow = malloc(clippedStride)) { + // fast path + jint i; + srcy = srcy - height + 1; + pDst = PtrAddBytes(pDst, dsty * dstInfo.scanStride); + j2d_glReadPixels(srcx, srcy, width, height, pf.format, pf.type, pDst); - srcy--; - dsty++; - height--; + for (i = 0; i < height / 2; ++i) { + void * row1 = PtrAddBytes(pDst, (i * dstInfo.scanStride)); + void * row2 = PtrAddBytes(pDst,(height - i - 1) * dstInfo.scanStride); + memcpy(tempRow, row1, clippedStride); + memcpy(row1, row2, clippedStride); + memcpy(row2, tempRow, clippedStride); + } + free(tempRow); + } else { + // slow path + // we must read one scanline at a time because there is no way + // to read starting at the top-left corner of the source region + while (height > 0) { + j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty); + j2d_glReadPixels(srcx, srcy, width, 1, + pf.format, pf.type, pDst); + srcy--; + dsty++; + height--; + } } #ifdef MACOSX