Skip to content

Commit

Permalink
Fix rendering not working on 32-bit devices
Browse files Browse the repository at this point in the history
Replace all usages of GLES20 with GLES30
  • Loading branch information
rafaelvcaetano committed Feb 6, 2025
1 parent b35140e commit 1803252
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 64 deletions.
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

<uses-feature android:glEsVersion="0x00030000" android:required="true" />
<uses-feature android:glEsVersion="0x00030002" android:required="false" />

<application
Expand Down Expand Up @@ -129,6 +130,7 @@
</activity>
<activity
android:name=".ui.backgrounds.BackgroundsActivity"
android:theme="@style/AppTheme.NoToolbar"
android:label="@string/backgrounds">
</activity>
<activity
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/AndroidFrameRenderedCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ void AndroidFrameRenderedCallback::onFrameRendered(long syncFence, int textureId

jclass listenerClass = env->GetObjectClass(this->androidFrameRenderedListener);
jmethodID onFrameRenderedMethod = env->GetMethodID(listenerClass, "onFrameRendered", "(JI)V");
env->CallVoidMethod(this->androidFrameRenderedListener, onFrameRenderedMethod, syncFence, textureId);
env->CallVoidMethod(this->androidFrameRenderedListener, onFrameRenderedMethod, (jlong) syncFence, textureId);
}
22 changes: 11 additions & 11 deletions app/src/main/java/me/magnum/melonds/common/opengl/Shader.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package me.magnum.melonds.common.opengl

import android.opengl.GLES20
import android.opengl.GLES30

class Shader(
private val programId: Int,
Expand All @@ -12,21 +12,21 @@ class Shader(
val uniformTex: Int

init {
GLES20.glUseProgram(programId)
uniformMvp = GLES20.glGetUniformLocation(programId, "MVP")
attribUv = GLES20.glGetAttribLocation(programId, "vUV")
attribPos = GLES20.glGetAttribLocation(programId, "vPos")
uniformTex = GLES20.glGetUniformLocation(programId, "tex")
GLES20.glUseProgram(0)
GLES30.glUseProgram(programId)
uniformMvp = GLES30.glGetUniformLocation(programId, "MVP")
attribUv = GLES30.glGetAttribLocation(programId, "vUV")
attribPos = GLES30.glGetAttribLocation(programId, "vPos")
uniformTex = GLES30.glGetUniformLocation(programId, "tex")
GLES30.glUseProgram(0)
}

fun use() {
GLES20.glUseProgram(programId)
GLES20.glEnableVertexAttribArray(attribUv)
GLES20.glEnableVertexAttribArray(attribPos)
GLES30.glUseProgram(programId)
GLES30.glEnableVertexAttribArray(attribUv)
GLES30.glEnableVertexAttribArray(attribPos)
}

fun delete() {
GLES20.glDeleteProgram(programId)
GLES30.glDeleteProgram(programId)
}
}
33 changes: 17 additions & 16 deletions app/src/main/java/me/magnum/melonds/common/opengl/ShaderFactory.kt
Original file line number Diff line number Diff line change
@@ -1,42 +1,43 @@
package me.magnum.melonds.common.opengl

import android.opengl.GLES20
import android.opengl.GLES30
import android.util.Log

object ShaderFactory {
fun createShaderProgram(source: ShaderProgramSource): Shader {
val shaderProgram = createShaderProgram(source.vertexShaderSource, source.fragmentShaderSource)
val textureFilter = when (source.textureFiltering) {
ShaderProgramSource.TextureFiltering.NEAREST -> GLES20.GL_NEAREST
ShaderProgramSource.TextureFiltering.LINEAR -> GLES20.GL_LINEAR
ShaderProgramSource.TextureFiltering.NEAREST -> GLES30.GL_NEAREST
ShaderProgramSource.TextureFiltering.LINEAR -> GLES30.GL_LINEAR
}

return Shader(shaderProgram, textureFilter)
}

private fun createShaderProgram(vertexShader: String, fragmentShader: String): Int {
val program = GLES20.glCreateProgram()
GLES20.glAttachShader(program, createShader(GLES20.GL_VERTEX_SHADER, vertexShader))
GLES20.glAttachShader(program, createShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader))
GLES20.glLinkProgram(program)
val program = GLES30.glCreateProgram()
GLES30.glAttachShader(program, createShader(GLES30.GL_VERTEX_SHADER, vertexShader))
GLES30.glAttachShader(program, createShader(GLES30.GL_FRAGMENT_SHADER, fragmentShader))
GLES30.glLinkProgram(program)
val result = IntArray(1)
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, result, 0)
GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, result, 0)

if (result[0] == GLES20.GL_FALSE) {
System.err.println(GLES20.glGetProgramInfoLog(program))
if (result[0] == GLES30.GL_FALSE) {
Log.e("ShaderFactory", GLES30.glGetProgramInfoLog(program))
}

return program
}

private fun createShader(shaderType: Int, code: String): Int {
val shader = GLES20.glCreateShader(shaderType)
GLES20.glShaderSource(shader, code)
GLES20.glCompileShader(shader)
val shader = GLES30.glCreateShader(shaderType)
GLES30.glShaderSource(shader, code)
GLES30.glCompileShader(shader)
val result = IntArray(1)
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, result, 0)
GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, result, 0)

if (result[0] == GLES20.GL_FALSE) {
System.err.println(GLES20.glGetShaderInfoLog(shader))
if (result[0] == GLES30.GL_FALSE) {
Log.e("ShaderFactory", GLES30.glGetShaderInfoLog(shader))
}

return shader
Expand Down
69 changes: 35 additions & 34 deletions app/src/main/java/me/magnum/melonds/ui/emulator/DSRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package me.magnum.melonds.ui.emulator
import android.content.Context
import android.graphics.BitmapFactory
import android.opengl.EGL14
import android.opengl.GLES20
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import me.magnum.melonds.common.opengl.Shader
import me.magnum.melonds.common.opengl.ShaderFactory
import me.magnum.melonds.common.opengl.ShaderProgramSource
Expand All @@ -25,6 +25,7 @@ import java.util.LinkedList
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.roundToInt
import kotlin.random.Random

class DSRenderer(
private val context: Context,
Expand Down Expand Up @@ -116,20 +117,20 @@ class DSRenderer(
}

override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
GLES20.glClearColor(0f, 0f, 0f, 1f)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
GLES20.glDisable(GLES20.GL_CULL_FACE)
GLES30.glClearColor(0f, 0f, 0f, 1f)
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)
GLES30.glDisable(GLES30.GL_CULL_FACE)

// Setup textures
val textures = IntArray(1)
GLES20.glGenTextures(1, textures, 0)
GLES30.glGenTextures(1, textures, 0)
backgroundTexture = textures[0]

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundTexture)
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, backgroundTexture)
GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE.toFloat())
GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE.toFloat())
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)

// Create background shader
backgroundShader = ShaderFactory.createShaderProgram(ShaderProgramSource.BackgroundShader)
Expand Down Expand Up @@ -268,7 +269,7 @@ class DSRenderer(
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
this.width = width.toFloat()
this.height = height.toFloat()
GLES20.glViewport(0, 0, width, height)
GLES30.glViewport(0, 0, width, height)
mustUpdateConfiguration = true

synchronized(backgroundLock) {
Expand Down Expand Up @@ -296,7 +297,7 @@ class DSRenderer(
}
}

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)

posBuffer.position(0)
uvBuffer.position(0)
Expand All @@ -305,21 +306,21 @@ class DSRenderer(
screenShader?.let { shader ->
shader.use()

GLES30.glWaitSync(currentGlFenceSync, GLES30.GL_SYNC_FLUSH_COMMANDS_BIT, 100_000_000)
GLES30.glWaitSync(currentGlFenceSync, 0, GLES30.GL_TIMEOUT_IGNORED)
GLES30.glDeleteSync(currentGlFenceSync)

GLES20.glEnable(GLES20.GL_DEPTH_TEST)
GLES20.glDepthFunc(GLES20.GL_NOTEQUAL)
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, currentTextureId)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, shader.textureFiltering)
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, shader.textureFiltering)

GLES20.glUniformMatrix4fv(shader.uniformMvp, 1, false, mvpMatrix, 0)
GLES20.glVertexAttribPointer(shader.attribPos, 2, GLES20.GL_FLOAT, false, 0, posBuffer)
GLES20.glVertexAttribPointer(shader.attribUv, 2, GLES20.GL_FLOAT, false, 0, uvBuffer)
GLES20.glUniform1i(shader.uniformTex, 0)
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, indices)
GLES30.glEnable(GLES30.GL_DEPTH_TEST)
GLES30.glDepthFunc(GLES30.GL_NOTEQUAL)
GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, currentTextureId)
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, shader.textureFiltering)
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, shader.textureFiltering)

GLES30.glUniformMatrix4fv(shader.uniformMvp, 1, false, mvpMatrix, 0)
GLES30.glVertexAttribPointer(shader.attribPos, 2, GLES30.GL_FLOAT, false, 0, posBuffer)
GLES30.glVertexAttribPointer(shader.attribUv, 2, GLES30.GL_FLOAT, false, 0, uvBuffer)
GLES30.glUniform1i(shader.uniformTex, 0)
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, indices)
}

synchronized(backgroundLock) {
Expand All @@ -346,13 +347,13 @@ class DSRenderer(

val indices = backgroundPosBuffer.capacity() / 2
backgroundShader.use()
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundTexture)
GLES20.glUniformMatrix4fv(backgroundShader.uniformMvp, 1, false, mvpMatrix, 0)
GLES20.glVertexAttribPointer(backgroundShader.attribPos, 2, GLES20.GL_FLOAT, false, 0, backgroundPosBuffer)
GLES20.glVertexAttribPointer(backgroundShader.attribUv, 2, GLES20.GL_FLOAT, false, 0, backgroundUvBuffer)
GLES20.glUniform1i(backgroundShader.uniformTex, 0)
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, indices)
GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, backgroundTexture)
GLES30.glUniformMatrix4fv(backgroundShader.uniformMvp, 1, false, mvpMatrix, 0)
GLES30.glVertexAttribPointer(backgroundShader.attribPos, 2, GLES30.GL_FLOAT, false, 0, backgroundPosBuffer)
GLES30.glVertexAttribPointer(backgroundShader.attribUv, 2, GLES30.GL_FLOAT, false, 0, backgroundUvBuffer)
GLES30.glUniform1i(backgroundShader.uniformTex, 0)
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, indices)
}

private fun loadBackground() {
Expand All @@ -373,8 +374,8 @@ class DSRenderer(

val bitmap = bitmapResult.getOrNull() ?: return

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundTexture)
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0)
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, backgroundTexture)
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0)
bitmap.recycle()

backgroundWidth = bitmap.width
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class EmulatorActivity : AppCompatActivity() {
}
)
binding.surfaceMain.apply {
setEGLContextClientVersion(2)
setEGLContextClientVersion(3)
preserveEGLContextOnPause = true
setRenderer(dsRenderer)
renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
Expand Down
2 changes: 1 addition & 1 deletion melonDS-android-lib

0 comments on commit 1803252

Please sign in to comment.