Create Skia Context from GLSurfaceView

290 views
Skip to first unread message

mrousavy

unread,
Aug 9, 2023, 1:07:28 PM8/9/23
to skia-discuss
I'm trying to create a Skia Context inside my `GLSurfaceView` to draw to an OpengL Texture using Skia.

This is my code:

Java/Kotlin part:

```java
class SkiaPreviewView(context: Context): GLSurfaceView(context), GLSurfaceView.Renderer {
  init {
    setEGLContextClientVersion(2)
    setRenderer(this)
  }

  override fun onSurfaceCreated(gl: GL10, config: EGLConfig?) {
    val textures = IntBuffer.allocate(1)
    gl.glGenTextures(1, textures)
    val textureId = textures[0]

    val surfaceTexture = SurfaceTexture(textureId)
    surfaceTexture.setDefaultBufferSize(1280, 720)
    surfaceTexture.setOnFrameAvailableListener { s ->
      // TODO: Draw here, not sure if I need updateTexImage?
    }
    val surface = Surface(surfaceTexture)
    // TODO: Set up Camera here which will stream Frames into surface

    nativeOnSurfaceCreated(textureId, 1280, 720) // <-- C++
  }

  override fun onDrawFrame(gl: GL10) {
    nativeOnDrawFrame()
  }
}
```

NDK/C++ part:

```
sk_sp<SkSurface> onSurfaceCreated(int textureId, int width, int height) {
  // Create the Skia backend context
  auto backendInterface = GrGLMakeNativeInterface();
  auto grContext = GrDirectContext::MakeGL(backendInterface);
  if (grContext == nullptr) throw OpenGLError("Failed to create Skia Context!");

  GrGLFramebufferInfo fbInfo;
  fbInfo.fFBOID = 0; // <-- TODO: should this be 0? Or textureId?
  fbInfo.fFormat = GR_GL_RGBA8;

  auto renderTarget = GrBackendRenderTarget(width, height, 0, 8, fbInfo);

  this.surface = SkSurfaces::WrapBackendRenderTarget(
      grContext.get(), renderTarget, kBottomLeft_GrSurfaceOrigin,
      kRGBA_8888_SkColorType, nullptr, nullptr,
      nullptr,
      nullptr);
}

void onDrawFrame() {
  // TODO: Do I make the Texture current or does GLSurfaceView do that?

  auto canvas = this.surface->getCanvas();

  auto rect = SkRect::MakeXYWH(50, 150, 30, 50);
  auto paint = SkPaint();
  paint.setColor(SkColors::kRed);
  canvas->drawRect(rect, paint);

  canvas->flush();

  // TODO: Do I need to do an eglSwapBuffers here or does GLSurfaceView do that?
}
```

But this just crashes in `nativeOnDrawFrame()`:

```
EGL_emulation    E  eglQueryContext 32c0  EGL_BAD_ATTRIBUTE
EGL_emulation    E  tid 9441: eglQueryContext(2122): error 0x3004 (EGL_BAD_ATTRIBUTE)
```


I'm assuming this is because `GLSurfaceView` manages it's own OpenGL context - maybe it's better to use a plain `SurfaceView` and then set up OpenGL myself?

William Candillon

unread,
Aug 10, 2023, 1:20:27 AM8/10/23
to skia-discuss
A good example of such Android/JNI integration is the SkottieView: https://github.com/google/skia/blob/main/platform_tools/android/apps/skottie/skottielib/src/main/java/org/skia/skottie/SkottieView.java

Kind regards,

William

Reply all
Reply to author
Forward
0 new messages