mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 17:39:40 +01:00
JBR-5405: implementation of direct raster loading for VolatileImage
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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")
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
18
src/jetbrains.api/src/com/jetbrains/NativeRasterLoader.java
Normal file
18
src/jetbrains.api/src/com/jetbrains/NativeRasterLoader.java
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user