src/share/native/sun/java2d/opengl/OGLBlitLoops.c
Print this page
@@ -1,7 +1,7 @@
/*
- * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -32,10 +32,13 @@
#include "OGLBlitLoops.h"
#include "OGLRenderQueue.h"
#include "OGLSurfaceData.h"
#include "GraphicsPrimitiveMgr.h"
+#include <stdlib.h> // malloc
+#include <string.h> // memcpy
+
extern OGLPixelFormat PixelFormats[];
/**
* Inner loop used for copying a source OpenGL "Surface" (window, pbuffer,
* etc.) to a destination OpenGL "Surface". Note that the same surface can
@@ -748,19 +751,23 @@
srcInfo.bounds.y2 > srcInfo.bounds.y1)
{
dstOps->GetRasInfo(env, dstOps, &dstInfo);
if (dstInfo.rasBase) {
void *pDst = dstInfo.rasBase;
+ void* tempRow;
+ jint clippedStride;
srcx = srcInfo.bounds.x1;
srcy = srcInfo.bounds.y1;
dstx = dstInfo.bounds.x1;
dsty = dstInfo.bounds.y1;
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_SKIP_PIXELS, 0);
+ j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
j2d_glPixelStorei(GL_PACK_ROW_LENGTH,
dstInfo.scanStride / dstInfo.pixelStride);
j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment);
#ifdef MACOSX
if (srcOps->isOpaque) {
@@ -779,29 +786,49 @@
// this accounts for lower-left origin of the source region
srcx = srcOps->xOffset + srcx;
srcy = srcOps->yOffset + srcOps->height - (srcy + 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);
+ 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--;
}
+ j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+ }
#ifdef MACOSX
if (srcOps->isOpaque) {
j2d_glPixelTransferf(GL_ALPHA_BIAS, 0.0);
}
#endif
- j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
- j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4);
}
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
}