JBR-5405: implementation of direct raster loading for VolatileImage

This commit is contained in:
Artem Bochkarev
2023-10-04 10:05:41 +04:00
parent 49b53da483
commit 95ada30c3f
17 changed files with 602 additions and 2 deletions

View File

@@ -640,4 +640,30 @@ public abstract class MTLSurfaceData extends SurfaceData
rq.unlock();
}
}
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
@Override
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
MTLRenderQueue rq = MTLRenderQueue.getInstance();
rq.lock();
try {
MTLContext.setScratchSurface(getMTLGraphicsConfig());
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
} finally {
rq.unlock();
}
markDirty();
}
private static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
}

View File

@@ -240,6 +240,23 @@ replaceTextureRegion(MTLContext *mtlc, id<MTLTexture> dest, const SurfaceDataRas
}
}
void replaceTexture(MTLContext *mtlc, id<MTLTexture> dest, void* pRaster, int width, int height, int dx1, int dy1, int dx2, int dy2) {
MTLRasterFormatInfo rfi = RasterFormatInfos[0];
SurfaceDataRasInfo srcInfo;
memset(&srcInfo, 0, sizeof(SurfaceDataRasInfo));
srcInfo.bounds.x1 = dx1;
srcInfo.bounds.y1 = dy1;
srcInfo.bounds.x2 = dx2;
srcInfo.bounds.y2 = dy2;
srcInfo.scanStride = width*4;
srcInfo.pixelStride = 4;
srcInfo.rasBase = pRaster;
srcInfo.pixelBitOffset = 0;
replaceTextureRegion(mtlc, dest, &srcInfo, &rfi, dx1, dy1, dx2, dy2);
}
/**
* Inner loop used for copying a source system memory ("Sw") surface to a
* destination MTL "Surface". This method is invoked from

View File

@@ -348,6 +348,8 @@ Java_sun_java2d_metal_MTLSurfaceData_initOps
}
}
extern void replaceTexture(MTLContext *mtlc, id<MTLTexture> dest, void* pRaster, int width, int height, int dx1, int dy1, int dx2, int dy2);
JNIEXPORT void JNICALL
Java_sun_java2d_metal_MTLSurfaceData_clearWindow
(JNIEnv *env, jobject mtlsd)
@@ -362,6 +364,43 @@ Java_sun_java2d_metal_MTLSurfaceData_clearWindow
mtlsdo->layer = NULL;
}
JNIEXPORT jboolean JNICALL
Java_sun_java2d_metal_MTLSurfaceData_loadNativeRasterWithRects
(JNIEnv *env, jclass clazz,
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
{
BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(sdops);
if (dstOps == NULL || pRaster == 0) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_loadNativeRasterWithRects: params are null");
return JNI_FALSE;
}
id<MTLTexture> dest = dstOps->pTexture;
if (dest == NULL) {
J2dTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_loadNativeRasterWithRects: dest is null");
return JNI_FALSE;
}
MTLSDOps *dstMTLOps = (MTLSDOps *)dstOps->privOps;
MTLContext *ctx = dstMTLOps->configInfo->context;
if (pRects == 0 || rectsCount < 1) {
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLSurfaceData_loadNativeRasterWithRects: do full copy of raster:");
replaceTexture(ctx, dest, (void*)pRaster, (int)width, (int)height, 0, 0, (int)width, (int)height);
} else {
int32_t *pr = (int32_t *) pRects;
for (int c = 0; c < rectsCount; ++c) {
int32_t x = *(pr++);
int32_t y = *(pr++);
int32_t w = *(pr++);
int32_t h = *(pr++);
//fprintf(stderr, "MTLSurfaceData_loadNativeRasterWithRects: process rect %d %d %d %d\n", x, y, w, h);
replaceTexture(ctx, dest, (void*)pRaster, (int)width, (int)height, x, y, x + w, y + h);
}
}
return JNI_TRUE;
}
NSString * getSurfaceDescription(const BMTLSDOps * bmtlsdOps) {
if (bmtlsdOps == NULL)
return @"NULL";

View File

@@ -63,6 +63,9 @@ public class JBRApiModule {
.withStatic("getFeaturesAsString", "getFeaturesAsString", "com.jetbrains.desktop.FontExtensions")
.clientProxy("java.awt.Font$Features", "com.jetbrains.FontExtensions$Features")
.service("com.jetbrains.WindowMove", "java.awt.Window$WindowMoveService")
.service("com.jetbrains.NativeRasterLoader")
.withStatic("loadNativeRaster", "loadNativeRaster", "com.jetbrains.desktop.NativeRasterLoader")
;
}
}

View File

@@ -0,0 +1,28 @@
package com.jetbrains.desktop;
import sun.awt.image.SunVolatileImage;
import java.awt.image.VolatileImage;
class NativeRasterLoader {
/**
* Loads native image raster into VolatileImage
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
static void loadNativeRaster(VolatileImage vi, long pRaster, int width, int height, long pRects, int rectsCount) {
if (!(vi instanceof SunVolatileImage)) {
System.err.printf("Unsupported type of VolatileImage: %s\n", vi);
return;
}
SunVolatileImage svi = (SunVolatileImage)vi;
sun.java2d.NativeRasterLoader.loadNativeRaster(svi.getDestSurface(), pRaster, width, height, pRects, rectsCount);
}
}

View File

@@ -0,0 +1,21 @@
package sun.java2d;
public class NativeRasterLoader {
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
public static void loadNativeRaster(Surface surface, long pRaster, int width, int height, long pRects, int rectsCount) {
if (surface instanceof SurfaceData) {
SurfaceData sd = (SurfaceData)surface;
sd.loadNativeRaster(pRaster, width, height, pRects, rectsCount);
}
}
}

View File

@@ -1091,4 +1091,19 @@ public abstract class SurfaceData
public double getDefaultScaleY() {
return 1;
}
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
System.err.println("ERROR: loadNativeRaster must be overriden.");
}
}

View File

@@ -654,4 +654,30 @@ public abstract class OGLSurfaceData extends SurfaceData
boolean isOnScreen() {
return getType() == WINDOW;
}
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
@Override
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock();
try {
OGLContext.setScratchSurface(getOGLGraphicsConfig());
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
} finally {
rq.unlock();
}
markDirty();
}
private static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
}

View File

@@ -238,6 +238,44 @@ OGLBlitSwToSurface(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
}
}
void OGLBlitRasterToSurface(OGLSDOps *dstOps, jlong pRaster, jint width, jint height,
OGLPixelFormat *pf,
jint sx1, jint sy1, jint sx2, jint sy2,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) {
SurfaceDataRasInfo srcInfo;
memset(&srcInfo, 0, sizeof(SurfaceDataRasInfo));
srcInfo.bounds.x1 = 0;
srcInfo.bounds.y1 = 0;
srcInfo.bounds.x2 = width;
srcInfo.bounds.y2 = height;
srcInfo.scanStride = width*4;
srcInfo.pixelStride = 4;
srcInfo.rasBase = (void*)pRaster;
srcInfo.pixelBitOffset = 0;
unsigned char * r = (unsigned char *)pRaster;
//fprintf(stderr, "OGLBlitRasterToSurface:%d,%d,%d,%d,%d,%d,%d,%d....\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
if (dstOps->drawableType == OGLSD_FBOBJECT) {
// Note that we unbind the currently bound texture first; this is
// recommended procedure when binding an fbobject
j2d_glBindTexture(dstOps->textureTarget, 0);
j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
} else {
J2dRlsTraceLn1(J2D_TRACE_ERROR, "Unsupported drawable type %d.", dstOps->drawableType);
}
j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, srcInfo.scanStride / srcInfo.pixelStride);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, pf->alignment);
OGLBlitSwToSurface(OGLRenderQueue_GetCurrentContext(), &srcInfo, pf, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
/**
* Inner loop used for copying a source system memory ("Sw") surface or
* OpenGL "Surface" to a destination OpenGL "Surface", using an OpenGL texture

View File

@@ -41,6 +41,10 @@ extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo);
extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo);
void OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
extern void OGLBlitRasterToSurface(OGLSDOps *dstOps, jlong pRaster, jint width, jint height,
OGLPixelFormat *pf,
jint sx1, jint sy1, jint sx2, jint sy2,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2);
/**
* This table contains the "pixel formats" for all system memory surfaces
@@ -526,6 +530,74 @@ Java_sun_java2d_opengl_OGLSurfaceData_getTextureID
return (jint)oglsdo->textureID;
}
JNIEXPORT jboolean JNICALL
Java_sun_java2d_opengl_OGLSurfaceData_loadNativeRasterWithRects
(JNIEnv *env, jclass clazz,
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
{
OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(sdops);
if (oglsdo == NULL || pRaster == 0) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_loadNativeRasterWithRects: params are null");
return JNI_FALSE;
}
//fprintf(stderr, "OGLSurfaceData_loadNativeRasterWithRects: ops=%p r=%p rCount=%d tt=%d texId=%d\n", (void*)sdops, (void*)pRaster, rectsCount, oglsdo->textureTarget, oglsdo->textureID);
// Set state.
OGLPixelFormat pf = PixelFormats[1];
const int viaTexSubImage = oglsdo->drawableType != OGLSD_FBOBJECT;
// NOTE: both types works correctly under OSX (probably need to choose the fastest one)
if (viaTexSubImage) {
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: via glTexSubImage2D");
j2d_glEnable(GL_TEXTURE_2D);
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
j2d_glBindTexture(GL_TEXTURE_2D, oglsdo->textureID);
} else {
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: via glDrawPix (i.e. OGLBlitSwToSurface)");
}
// Render.
if (pRects == 0 || rectsCount < 1) {
J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSurfaceData_loadNativeRasterWithRects: do full copy of raster:");
//unsigned char * r = (unsigned char *)pRaster;
//fprintf(stderr, "\t %d,%d,%d,%d,%d,%d,%d,%d....\n", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]);
if (viaTexSubImage) {
j2d_glTexSubImage2D(oglsdo->textureTarget, 0,
0, 0, width, height,
pf.format, pf.type, (GLvoid*)pRaster);
} else {
OGLBlitRasterToSurface(oglsdo, pRaster, width, height, &pf,
0, 0, width, height,
0, 0, width, height); }
} else {
int32_t *pr = (int32_t *) pRects;
for (int c = 0; c < rectsCount; ++c) {
int32_t x = *(pr++);
int32_t y = *(pr++);
int32_t w = *(pr++);
int32_t h = *(pr++);
if (viaTexSubImage) {
const GLvoid *srcBytes = (char *)pRaster + y*width*4 + x*4;
//fprintf(stderr, "\t[%d, %d, %d, %d] %d\n", x, y, w, h, (int)((char*)srcBytes - (char*)pRaster));
j2d_glTexSubImage2D(oglsdo->textureTarget, 0,
x, y, w, h,
pf.format, pf.type, srcBytes);
} else {
OGLBlitRasterToSurface(oglsdo, pRaster, width, height, &pf,
x, y, x + w, y + h,
x, y, x + w, y + h);
}
}
}
// Restore state.
if (viaTexSubImage) {
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
return JNI_TRUE;
}
/**
* Initializes nativeWidth/Height fields of the surfaceData object with
* passed arguments.

View File

@@ -61,4 +61,17 @@ public abstract class XSurfaceData extends SurfaceData {
protected native void setInvalid();
protected static native void XSetGraphicsExposures(long xgc, boolean needExposures);
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
protected static native boolean loadNativeRasterWithRects(long sdops, long pRaster, int width, int height, long pRects, int rectsCount);
}

View File

@@ -761,4 +761,20 @@ public abstract class XRSurfaceData extends XSurfaceData {
public void setStaticSrcTx(AffineTransform staticSrcTx) {
this.staticSrcTx = staticSrcTx;
}
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
@Override
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount);
}
}

View File

@@ -1703,3 +1703,90 @@ Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures
XSetGraphicsExposures(awt_display, (GC) xgc, needExposures ? True : False);
#endif /* !HEADLESS */
}
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: loadNativeRasterWithRects
* Signature:
*/
JNIEXPORT jboolean JNICALL
Java_sun_java2d_x11_XSurfaceData_loadNativeRasterWithRects
(JNIEnv *env, jclass clazz,
jlong sdops, jlong pRaster, jint width, jint height, jlong pRects, jint rectsCount)
{
SurfaceDataOps *dstOps = (SurfaceDataOps *)sdops;
if (dstOps == NULL || pRaster == 0) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: params are null");
return JNI_FALSE;
}
if (pRects == 0 || rectsCount < 1) {
SurfaceDataRasInfo dstInfo;
memset(&dstInfo, 0, sizeof(SurfaceDataRasInfo));
dstInfo.bounds.x1 = 0;
dstInfo.bounds.y1 = 0;
dstInfo.bounds.x2 = width;
dstInfo.bounds.y2 = height;
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't lock dest.");
return JNI_FALSE;
}
dstOps->GetRasInfo(env, dstOps, &dstInfo);
if (dstInfo.rasBase) {
J2dTraceLn(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy whole memory.");
memcpy(dstInfo.rasBase, (void *) pRaster, width * height * 4);
} else {
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't get pointer of dest raster.");
}
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
} else {
int32_t *pr = (int32_t *) pRects;
for (int c = 0; c < rectsCount; ++c) {
int32_t x = *(pr++);
int32_t y = *(pr++);
int32_t w = *(pr++);
int32_t h = *(pr++);
SurfaceDataRasInfo dstInfo;
memset(&dstInfo, 0, sizeof(SurfaceDataRasInfo));
dstInfo.bounds.x1 = x;
dstInfo.bounds.y1 = y;
dstInfo.bounds.x2 = x + w;
dstInfo.bounds.y2 = y + h;
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't lock dest rect.");
return JNI_FALSE;
}
dstOps->GetRasInfo(env, dstOps, &dstInfo);
if (dstInfo.rasBase) {
char* pSrc = (char*)PtrCoord(pRaster, x, 4, y, width*4);
char* pDst = (char*)PtrCoord(dstInfo.rasBase, x, dstInfo.pixelStride, y, dstInfo.scanStride);
if (dstInfo.scanStride == width*4) {
J2dTraceLn4(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy rect %d,%d - %d,%d [FAST]", x, y, w, h);
memcpy(pDst, pSrc, width*h*4);
} else {
J2dTraceLn4(J2D_TRACE_VERBOSE, "XSurfaceData_loadNativeRasterWithRects: copy rect %d,%d - %d,%d [line by line]", x, y, w, h);
for (int line = 0; line < h; ++line) {
memcpy(pDst, pSrc, w*4);
pSrc += width*4;
pDst += dstInfo.scanStride;
}
}
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
} else {
J2dRlsTraceLn(J2D_TRACE_ERROR, "XSurfaceData_loadNativeRasterWithRects: can't get pointer of dest raster (rect).");
}
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
}
}
return JNI_TRUE;
}

View File

@@ -1023,4 +1023,32 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
*/
public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
int w, int h);
/**
* Loads native image raster into surface.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
@Override
protected void loadNativeRaster(long pRaster, int width, int height, long pRects, int rectsCount) {
D3DRenderQueue rq = D3DRenderQueue.getInstance();
rq.lock();
try {
// make sure we have a current context before uploading
// the sysmem data to the texture object
D3DContext.setScratchSurface(getContext());
rq.flushAndInvokeNow(() -> loadNativeRasterWithRects(getNativeOps(), pRaster, width, height, pRects, rectsCount));
} finally {
rq.unlock();
}
markDirty();
}
private static native boolean loadNativeRasterWithRects(long pData, long pRaster, int width, int height, long pRects, int rectsCount);
}

View File

@@ -25,6 +25,7 @@
#include "D3DPipeline.h"
#include <jlong.h>
#include <cstdint>
#include "D3DSurfaceData.h"
#include "D3DPipelineManager.h"
#include "Trace.h"
@@ -32,7 +33,18 @@
#include "awt_Window.h"
#include "awt_BitmapUtil.h"
#include "D3DRenderQueue.h"
#include "D3DBlitLoops.h"
#include "GraphicsPrimitiveMgr.h"
#include "IntArgb.h"
#include "IntArgbPre.h"
#include "IntRgb.h"
#include "IntBgr.h"
extern "C" BlitFunc IntArgbToIntArgbPreConvert;
extern "C" BlitFunc IntArgbPreToIntArgbConvert;
extern "C" BlitFunc IntArgbBmToIntArgbConvert;
extern "C" BlitFunc IntRgbToIntArgbConvert;
// REMIND: move to awt_Component.h
extern "C" HWND AwtComponent_GetHWnd(JNIEnv *env, jlong pData);
@@ -163,6 +175,134 @@ D3DSD_Unlock(JNIEnv *env,
JNU_ThrowInternalError(env, "D3DSD_Unlock not implemented!");
}
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
jboolean loadNativeRasterWithRectsImpl(
D3DSDOps * d3dsdo, jlong pRaster, jint width, jint height,
jlong pRects, jint rectsCount
) {
D3DPipelineManager * pMgr = D3DPipelineManager::GetInstance();
if (d3dsdo == NULL || d3dsdo->pResource == NULL || pMgr == NULL || pRaster == NULL) {
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: null param.");
return JNI_FALSE;
}
J2dTraceLn3(J2D_TRACE_VERBOSE, "D3DSurfaceData_loadNativeRasterWithRects: ops=%p r=%p rCount=%d\n", (void*)d3dsdo, (void*)pRaster, rectsCount);
HRESULT res;
D3DContext *pCtx;
if (FAILED(res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx))) {
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed GetD3DContext.");
return JNI_FALSE;
}
//
// Blit via tiles
//
D3DResource *pBlitTextureRes = NULL;
res = pCtx->GetResourceManager()->GetBlitTexture(&pBlitTextureRes);
if (FAILED(res)) {
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed GetBlitTexture.");
return JNI_FALSE;
}
IDirect3DSurface9 *pBlitSurface = pBlitTextureRes->GetSurface();
IDirect3DTexture9 *pBlitTexture = pBlitTextureRes->GetTexture();
D3DSURFACE_DESC *pBlitDesc = pBlitTextureRes->GetDesc();
res = pCtx->BeginScene(STATE_TEXTUREOP);
if (FAILED(res)) {
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed BeginScene.");
return JNI_FALSE;
}
res = pCtx->SetTexture(pBlitTexture);
if (FAILED(res)) {
J2dTraceLn(J2D_TRACE_ERROR, "D3DSurfaceData_loadNativeRasterWithRects: failed SetTexture.");
return JNI_FALSE;
}
IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice();
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
SurfaceDataRasInfo srcInfo;
ZeroMemory(&srcInfo, sizeof(SurfaceDataRasInfo));
srcInfo.bounds.x1 = 0;
srcInfo.bounds.y1 = 0;
srcInfo.bounds.x2 = width;
srcInfo.bounds.y2 = height;
srcInfo.scanStride = width*4;
srcInfo.pixelStride = 4;
srcInfo.rasBase = (void*)pRaster;
srcInfo.pixelBitOffset = 0;
const jint tw = pBlitDesc->Width;
const jint th = pBlitDesc->Height;
jint sy, dy;
jint sx, dx;
for (sy = 0, dy = 0; sy < height; sy += th, dy += th) {
jint sh = ((sy + th) > height) ? (height - sy) : th;
jint dh = ((dy + th) > height) ? (height - dy) : th;
for (sx = 0, dx = 0; sx < width; sx += tw, dx += tw) {
jint sw = ((sx + tw) > width) ? (width - sx) : tw;
jint dw = ((dx + tw) > width) ? (width - dx) : tw;
if (pRects == 0 || rectsCount < 1) {
//fprintf(stderr, "D3D_loadNativeRasterWithRects: do full copy of tile\n");
D3DBL_CopyImageToIntXrgbSurface(&srcInfo, ST_INT_ARGB, pBlitTextureRes, sx, sy, sw, sh, 0, 0);
const double tx1 = ((double)sw) / tw;
const double ty1 = ((double)sh) / th;
res = pCtx->pVCacher->DrawTexture((float)dx, (float)dy, (float)(dx+dw), (float)(dy+dh),
0.0f, 0.0f, (float)tx1, (float)ty1);
} else {
int32_t *pr = (int32_t *) pRects;
for (int c = 0; c < rectsCount; ++c) {
const int32_t rx = *(pr++);
const int32_t ry = *(pr++);
const int32_t rw = *(pr++);
const int32_t rh = *(pr++);
// Check intersection with tile.
if (sx + sw <= rx || sy + sh <= ry || rx + rw <= sx || rx + rw <= sx)
continue;
// Calc intersection rect.
const int32_t rcX0 = MAX(sx, rx);
const int32_t rcY0 = MAX(sy, ry);
const int32_t rcX1 = MIN(sx + sw, rx + rw);
const int32_t rcY1 = MIN(sy + sh, ry + rh);
const int32_t rectW = rcX1 - rcX0;
const int32_t rectH = rcY1 - rcY0;
const int32_t relX0 = rcX0 - sx;
const int32_t relY0 = rcY0 - sy;
const int32_t relX1 = rcX1 - sx;
const int32_t relY1 = rcY1 - sy;
// Blit.
D3DBL_CopyImageToIntXrgbSurface(&srcInfo, ST_INT_ARGB, pBlitTextureRes, rcX0, rcY0, rectW, rectH, relX0, relY0);
// Render.
const double tx0 = ((double)relX0) / tw;
const double ty0 = ((double)relY0) / th;
const double tx1 = ((double)relX1) / tw;
const double ty1 = ((double)relY1) / th;
res = pCtx->pVCacher->DrawTexture(
(float)dx + relX0, (float)dy + relY0, (float)(dx + relX1), (float)(dy + relY1),
(float)tx0, (float)ty0, (float)tx1, (float)ty1);
}
}
res = pCtx->pVCacher->Render();
}
}
return JNI_TRUE;
}
// ------------ D3DSurfaceData's JNI methods ----------------
@@ -636,4 +776,17 @@ JNICALL Java_sun_java2d_d3d_D3DSurfaceData_updateWindowAccelImpl
return JNI_TRUE;
}
/*
* Class: sun_java2d_d3d_D3DSurfaceData
* Method: loadNativeRasterWithRects
* Signature:
*/
JNIEXPORT
jboolean JNICALL Java_sun_java2d_d3d_D3DSurfaceData_loadNativeRasterWithRects
(JNIEnv *env, jclass clazz, jlong pData, jlong pRaster, jint width, jint height, jlong pRects,
jint rectsCount) {
return loadNativeRasterWithRectsImpl((D3DSDOps *) jlong_to_ptr(pData), pRaster, width, height, pRects, rectsCount);
}
} // namespace extern C

View File

@@ -0,0 +1,18 @@
package com.jetbrains;
import java.awt.image.VolatileImage;
public interface NativeRasterLoader {
/**
* Loads native image raster into VolatileImage.
*
* @param pRaster native pointer image raster with 8-bit RGBA color components packed into integer pixels.
* Note: The color data in this image is considered to be premultiplied with alpha.
* @param width width of image in pixels
* @param height height of image in pixels
* @param pRects native pointer to array of "dirty" rects, each rect is a sequence of four 32-bit integers: x, y, width, heigth
* Note: can be null (then whole image used)
* @param rectsCount count of "dirty" rects (if 0 then whole image used)
*/
void loadNativeRaster(VolatileImage vi, long pRaster, int width, int height, long pRects, int rectsCount);
}

View File

@@ -6,9 +6,9 @@
# 2. When only new API is added, or some existing API was @Deprecated - increment MINOR, reset PATCH to 0
# 3. For major backwards incompatible API changes - increment MAJOR, reset MINOR and PATCH to 0
VERSION = 1.9.0
VERSION = 1.10.0
# Hash is used to track changes to jetbrains.api, so you would not forget to update version when needed.
# When you make any changes, "make jbr-api" will fail and ask you to update hash and version number here.
HASH = 34E293D39C67B301086DDAD59EB9426
HASH = 825E9B6832D82F59A0FFEAA4DA6F4A2