All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.shaders.ProgramBuilderImpl.kt Maven / Gradle / Ivy

/*
 * Copyright 2020-2021 Slawomir Czerwinski
 *
 * 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.
 *
 */

package graphics.glimpse.shaders

import graphics.glimpse.GlimpseAdapter
import graphics.glimpse.logging.GlimpseLogger

internal class ProgramBuilderImpl(private val gl: GlimpseAdapter) : Program.Builder {

    private val logger: GlimpseLogger = GlimpseLogger.create(this)

    private var vertexShaderHandle: Int = 0
    private var fragmentShaderHandle: Int = 0

    override fun withVertexShader(vertexShader: Shader): Program.Builder {
        vertexShaderHandle = vertexShader.handle
        return this
    }

    override fun withFragmentShader(fragmentShader: Shader): Program.Builder {
        fragmentShaderHandle = fragmentShader.handle
        return this
    }

    override fun build(): Program {
        check(value = vertexShaderHandle != 0) { "Vertex shader not set" }
        check(value = fragmentShaderHandle != 0) { "Fragment shader not set" }

        logger.debug(
            message = """
                |Linking program with:
                | - vertex shader $vertexShaderHandle
                | - fragment shader $fragmentShaderHandle
            """.trimMargin()
        )

        val handle = gl.glCreateProgram()

        gl.glAttachShader(handle, vertexShaderHandle)
        gl.glAttachShader(handle, fragmentShaderHandle)

        linkProgram(handle)
        validateProgram(handle)

        return ProgramImpl(handle, vertexShaderHandle, fragmentShaderHandle)
    }

    private fun linkProgram(handle: Int) {
        gl.glLinkProgram(handle)

        if (!gl.glGetProgramLinkStatus(handle)) {
            val programInfoLog = gl.glGetProgramInfoLog(handle)
            logger.error(message = "Program linking failed:\n$programInfoLog\nCleaning up")

            cleanUpAfterError(handle)

            throw IllegalStateException("Program linking failed:\n$programInfoLog")
        }
    }

    private fun validateProgram(handle: Int) {
        gl.glValidateProgram(handle)

        if (!gl.glGetProgramValidateStatus(handle)) {
            val programInfoLog = gl.glGetProgramInfoLog(handle)
            logger.error(message = "Program validation failed:\n$programInfoLog\nCleaning up")

            cleanUpAfterError(handle)

            throw IllegalStateException("Program validation failed:\n$programInfoLog")
        }
    }

    private fun cleanUpAfterError(handle: Int) {
        gl.glDeleteProgram(handle)
        gl.glDeleteShader(vertexShaderHandle)
        gl.glDeleteShader(fragmentShaderHandle)
    }

    private data class ProgramImpl(
        override val handle: Int,
        private val vertexShaderHandle: Int,
        private val fragmentShaderHandle: Int
    ) : Program {

        private val logger: GlimpseLogger = GlimpseLogger.create(this)

        override fun use(gl: GlimpseAdapter) {
            gl.glUseProgram(handle)
        }

        override fun dispose(gl: GlimpseAdapter) {
            gl.glDeleteProgram(handle)

            gl.glDeleteShader(vertexShaderHandle)
            gl.glDeleteShader(fragmentShaderHandle)

            if (!gl.glGetProgramDeleteStatus(handle)) {
                val shaderInfoLog = gl.glGetProgramInfoLog(handle)
                logger.error(message = "Program deletion failed:\n$shaderInfoLog")

                throw IllegalStateException("Program deletion failed:\n$shaderInfoLog")
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy