Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/com/jetbrains/Extensions.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,9 @@ public enum Extensions {
/**
* Opts-in {@link com.jetbrains.SystemUtils#shrinkingGC}
*/
SHRINKING_GC
SHRINKING_GC,
/**
* Extends SharedTextures service with OpenGL support
*/
SHARED_TEXTURES_OPENGL,
}
62 changes: 58 additions & 4 deletions src/com/jetbrains/SharedTextures.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

/**
* The service provides functionality for working with shared textures in JetBrainsRuntime.
* <p>
* This service is experemental and could be replaced with another service or deprecated.
*/
@Service
@Provided
Expand All @@ -30,10 +32,29 @@ public interface SharedTextures {
public final static int METAL_TEXTURE_TYPE = 1;

/**
* Returns the texture type supported by the current rendering pipeling.
* OpenGL textures are supported
*/
public final static int OPENGL_TEXTURE_TYPE = 2;


/**
* Returns the texture type supported by the graphics configuration.
*
* @param gc the GraphicsConfiguration
* @return the type of shared texture supported.
*/
@Extension(Extensions.SHARED_TEXTURES_OPENGL)
int getTextureType(GraphicsConfiguration gc);

/**
* Returns the texture type supported by the default graphics configuration
* of the default graphics device.
*
* @return the type of shared texture supported.
* @deprecated The graphics environment may contain configurations of different types.
* Use {@link #getTextureType(GraphicsConfiguration)} instead.
*/
@Deprecated
int getTextureType();

/**
Expand All @@ -50,10 +71,11 @@ public interface SharedTextures {
* <li>Client code is responsible for ensuring proper synchronization. All operations involving
* the texture must have been completed before the resulting image is used within the JBR rendering
* pipeline.</li>
* <li>Texture liftime:
* <li>Texture lifespan:
* <ul>
* <li>Metal: This texture is retained for the wrapping image lifetime and will be released
* <li>Metal: This texture is retained for the wrapping image lifespan and will be released
* after the image has been disposed.</li>
* <li>OpenGL: The wrapping image doesn't take owernship over the texute.</li>
* </ul>
* </li>
* </ul>
Expand All @@ -62,11 +84,43 @@ public interface SharedTextures {
* @param texture the texture to be wrapped.
* <p>Platform-specific:</p>
* <ul>
* <li>macOS (with the Metal rendering pipeline): a pointer to an {@code MTLTexture} object</li>
* <li>Metal: an {@code MTLTexture} object pointer</li>
* <li>OpenGL: a texture id({@code GLuint})</li>
* </ul>
* @return a wrapping image compatible with the specified {@code GraphicsConfiguration}.
* @throws UnsupportedOperationException if the current pipeline is not supported.
* @throws IllegalArgumentException if the texture cannot be wrapped. The details are logged in {@code J2D_TRACE_ERROR}.
*/
Image wrapTexture(GraphicsConfiguration gc, long texture);

/**
* Provides information needed for using shared OpenGL context.
*
* @param gc the target {@link GraphicsConfiguration}.
*
* @return an array of
* <ul>
* <li>2 elements(Windows):
* <ul>
* <li>0 - handle to an OpenGL Rendering Context ({@code HGLRC})</li>
* <li>1 - pixel format index (see Win32 {@code SetPixelFormat})</li>
* </ul>
* </li>
* <li>3 elements(Linux):
* <ul>
* <li>0 - shared context handle ({@code GLXContext})</li>
* <li>1 - Xlib connection pointer ({@code Display*})</li>
* <li>2 - GLX frame buffer configuration ({@code GLXFBConfig})</li>
* </ul>
* </li>
* <li>2 elements(macOS):
* <ul>
* <li>0 - shared context ({@code CGLContextObj})</li>
* <li>1 - pixel format ({@code CGLPixelFormatObj})</li>
* </ul>
* </li>
* </ul>
*/
@Extension(Extensions.SHARED_TEXTURES_OPENGL)
long[] getOpenGLContextInfo(GraphicsConfiguration gc) throws UnsupportedOperationException;
}
105 changes: 105 additions & 0 deletions tests/SharedTexturesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2000-2025 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @test
*
* @summary Checks SharedTexture service presence on Linux
* @requires (os.family == "linux")
*
* @run main/othervm -Dsun.java2d.opengl=True -DsharedTexturesSupported=True SharedTexturesTest
*/

/**
* @test
*
* @summary Checks SharedTexture service presence on Windows
* @requires (os.family == "windows")
*
* @run main/othervm -Dsun.java2d.opengl=True -DsharedTexturesSupported=True SharedTexturesTest
*/

/**
* @test
*
* @summary Checks SharedTexture service presence on Windows
* @requires (os.family == "mac")
*
* @run main/othervm -Dsun.java2d.opengl=True -DsharedTexturesSupported=True SharedTexturesTest
* @run main/othervm -Dsun.java2d.metal=True -DsharedTexturesSupported=True SharedTexturesTest
*/


import com.jetbrains.Extensions;
import com.jetbrains.JBR;
import com.jetbrains.SharedTextures;

import java.awt.*;

public class SharedTexturesTest {
final static GraphicsConfiguration gc = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration();

public static void main(String[] args) {
if (!JBR.isSharedTexturesSupported()) {
throw new RuntimeException("SharedTextures are not supported");
}

SharedTextures sharedTexturesService = JBR.getSharedTextures(Extensions.SHARED_TEXTURES_OPENGL);
if (sharedTexturesService == null) {
throw new RuntimeException("Extensions.SHARED_TEXTURES_OPENGL is not available");
}

int expectedTextureType = getExpectedTextureType();
int actualTextureType = sharedTexturesService.getTextureType(gc);

if (actualTextureType != expectedTextureType) {
throw new RuntimeException("Expected texture type: " + expectedTextureType + ", actual: " + actualTextureType);
}

if (actualTextureType == SharedTextures.OPENGL_TEXTURE_TYPE) {
int sharedContextSize = System.getProperty("os.name").toLowerCase().contains("linux") ? 3 : 2;
long[] sharedOpenGLContext = sharedTexturesService.getOpenGLContextInfo(gc);
if (sharedOpenGLContext.length != sharedContextSize) {
throw new RuntimeException("getSharedOpenGLContext: Expected " + sharedContextSize + " elements, actual: " + sharedOpenGLContext.length);
}
}

{
boolean illegalArgumentExceptionThrown = false;
try {
sharedTexturesService.wrapTexture(gc, 0);
} catch (IllegalArgumentException e) {
illegalArgumentExceptionThrown = true;
}
if (!illegalArgumentExceptionThrown) {
throw new RuntimeException("Expected IllegalArgumentException");
}
}
}

public static int getExpectedTextureType() {
if ("true".equalsIgnoreCase(System.getProperty("sun.java2d.opengl"))) {
return SharedTextures.OPENGL_TEXTURE_TYPE;
} else if ("true".equalsIgnoreCase(System.getProperty("sun.java2d.metal"))) {
return SharedTextures.METAL_TEXTURE_TYPE;
}

throw new InternalError("Unexpected rendering pipeline. The default graphics config: " + gc.toString());
}
}