internal/graphicsdriver/opengl/program.go
func (d *Driver) useProgram(mode graphics.CompositeMode, colorM *affine.ColorM, filter graphics.Filter, address graphics.Address) error {
	destination := d.state.destination
	if destination == nil {
		panic("destination image is not set")
	}
	source := d.state.source
	if source == nil {
		panic("source image is not set")
	}

	if err := destination.setViewport(); err != nil {
		return err
	}
	dstW := destination.width
	srcW, srcH := source.width, source.height

	d.context.blendFunc(mode)

	program := d.state.programs[programKey{
		useColorM: colorM != nil,
		filter:    filter,
		address:   address,
	}]
	if d.state.lastProgram != program {
		d.context.useProgram(program)
		if d.state.lastProgram == zeroProgram {
			theArrayBufferLayout.enable(&d.context, program)
			d.context.bindBuffer(arrayBuffer, d.state.arrayBuffer)
			d.context.bindBuffer(elementArrayBuffer, d.state.elementArrayBuffer)
			d.context.uniformInt(program, "texture", 0)
		}

		d.state.lastProgram = program
		d.state.lastViewportWidth = 0
		d.state.lastViewportHeight = 0
		d.state.lastColorMatrix = nil
		d.state.lastColorMatrixTranslation = nil
		d.state.lastSourceWidth = 0
		d.state.lastSourceHeight = 0
	}

	vw := destination.framebuffer.width
	vh := destination.framebuffer.height
	if d.state.lastViewportWidth != vw || d.state.lastViewportHeight != vh {
		d.context.uniformFloats(program, "viewport_size", []float32{float32(vw), float32(vh)})
		d.state.lastViewportWidth = vw
		d.state.lastViewportHeight = vh
	}

	if colorM != nil {
		esBody, esTranslate := colorM.UnsafeElements()
		if !areSameFloat32Array(d.state.lastColorMatrix, esBody) {
			d.context.uniformFloats(program, "color_matrix_body", esBody)
			// ColorM's elements are immutable. It's OK to hold the reference without copying.
			d.state.lastColorMatrix = esBody
		}
		if !areSameFloat32Array(d.state.lastColorMatrixTranslation, esTranslate) {
			d.context.uniformFloats(program, "color_matrix_translation", esTranslate)
			// ColorM's elements are immutable. It's OK to hold the reference without copying.
			d.state.lastColorMatrixTranslation = esTranslate
		}
	}

	if filter != graphics.FilterNearest {
		sw := graphics.InternalImageSize(srcW)
		sh := graphics.InternalImageSize(srcH)
		if d.state.lastSourceWidth != sw || d.state.lastSourceHeight != sh {
			d.context.uniformFloats(program, "source_size", []float32{float32(sw), float32(sh)})
			d.state.lastSourceWidth = sw
			d.state.lastSourceHeight = sh
		}
	}

	if filter == graphics.FilterScreen {
		scale := float32(dstW) / float32(srcW)
		d.context.uniformFloat(program, "scale", scale)
	}

	// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
	// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
	d.context.bindTexture(source.textureNative)

	d.state.source = nil
	d.state.destination = nil
	return nil
}
func (d *Driver) useProgram(mode graphics.CompositeMode, colorM *affine.ColorM, filter graphics.Filter, address graphics.Address) error {
	destination := d.state.destination
	if destination == nil {
		panic("destination image is not set")
	}
	source := d.state.source
	if source == nil {
		panic("source image is not set")
	}

	if err := destination.setViewport(); err != nil {
		return err
	}
	dstW := destination.width
	srcW, srcH := source.width, source.height

	d.context.blendFunc(mode)

	program := d.state.programs[programKey{
		useColorM: colorM != nil,
		filter:    filter,
		address:   address,
	}]
	if d.state.lastProgram != program {
		d.context.useProgram(program)
		if d.state.lastProgram == zeroProgram {
			theArrayBufferLayout.enable(&d.context, program)
			d.context.bindBuffer(arrayBuffer, d.state.arrayBuffer)
			d.context.bindBuffer(elementArrayBuffer, d.state.elementArrayBuffer)
			d.context.uniformInt(program, "texture", 0)
		}

		d.state.lastProgram = program
		d.state.lastViewportWidth = 0
		d.state.lastViewportHeight = 0
		d.state.lastColorMatrix = nil
		d.state.lastColorMatrixTranslation = nil
		d.state.lastSourceWidth = 0
		d.state.lastSourceHeight = 0
	}

	vw := destination.framebuffer.width
	vh := destination.framebuffer.height
	if d.state.lastViewportWidth != vw || d.state.lastViewportHeight != vh {
		d.context.uniformFloats(program, "viewport_size", []float32{float32(vw), float32(vh)})
		d.state.lastViewportWidth = vw
		d.state.lastViewportHeight = vh
	}

	if colorM != nil {
		esBody, esTranslate := colorM.UnsafeElements()
		if !areSameFloat32Array(d.state.lastColorMatrix, esBody) {
			d.context.uniformFloats(program, "color_matrix_body", esBody)
			// ColorM's elements are immutable. It's OK to hold the reference without copying.
			d.state.lastColorMatrix = esBody
		}
		if !areSameFloat32Array(d.state.lastColorMatrixTranslation, esTranslate) {
			d.context.uniformFloats(program, "color_matrix_translation", esTranslate)
			// ColorM's elements are immutable. It's OK to hold the reference without copying.
			d.state.lastColorMatrixTranslation = esTranslate
		}
	}

	if filter != graphics.FilterNearest {
		sw := graphics.InternalImageSize(srcW)
		sh := graphics.InternalImageSize(srcH)
		if d.state.lastSourceWidth != sw || d.state.lastSourceHeight != sh {
			d.context.uniformFloats(program, "source_size", []float32{float32(sw), float32(sh)})
			d.state.lastSourceWidth = sw
			d.state.lastSourceHeight = sh
		}
	}

	if filter == graphics.FilterScreen {
		scale := float32(dstW) / float32(srcW)
		d.context.uniformFloat(program, "scale", scale)
	}

	// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
	// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
	d.context.bindTexture(source.textureNative)

	d.state.source = nil
	d.state.destination = nil
	return nil
}
func ( d * Driver ) useProgram ( mode graphics . CompositeMode , colorM * affine . ColorM , filter graphics . Filter , address graphics . Address ) error { destination := d . state . destination if destination == nil { panic ( " " ) } source := d . state . source if source == nil { panic ( " " ) } if err := destination . setViewport ( ) ; err != nil { return err } dstW := destination . width srcW , srcH := source . width , source . height d . context . blendFunc ( mode ) program := d . state . programs [ programKey { useColorM : colorM != nil , filter : filter , address : address , } ] if d . state . lastProgram != program { d . context . useProgram ( program ) if d . state . lastProgram == zeroProgram { theArrayBufferLayout . enable ( & d . context , program ) d . context . bindBuffer ( arrayBuffer , d . state . arrayBuffer ) d . context . bindBuffer ( elementArrayBuffer , d . state . elementArrayBuffer ) d . context . uniformInt ( program , " " , 0 ) } d . state . lastProgram = program d . state . lastViewportWidth = 0 d . state . lastViewportHeight = 0 d . state . lastColorMatrix = nil d . state . lastColorMatrixTranslation = nil d . state . lastSourceWidth = 0 d . state . lastSourceHeight = 0 } vw := destination . framebuffer . width vh := destination . framebuffer . height if d . state . lastViewportWidth != vw || d . state . lastViewportHeight != vh { d . context . uniformFloats ( program , " " , [ ] float32 { float32 ( vw ) , float32 ( vh ) } ) d . state . lastViewportWidth = vw d . state . lastViewportHeight = vh } if colorM != nil { esBody , esTranslate := colorM . UnsafeElements ( ) if ! areSameFloat32Array ( d . state . lastColorMatrix , esBody ) { d . context . uniformFloats ( program , " " , esBody ) // ColorM's elements are immutable. It's OK to hold the reference without copying. d . state . lastColorMatrix = esBody } if ! areSameFloat32Array ( d . state . lastColorMatrixTranslation , esTranslate ) { d . context . uniformFloats ( program , " " , esTranslate ) // ColorM's elements are immutable. It's OK to hold the reference without copying. d . state . lastColorMatrixTranslation = esTranslate } } if filter != graphics . FilterNearest { sw := graphics . InternalImageSize ( srcW ) sh := graphics . InternalImageSize ( srcH ) if d . state . lastSourceWidth != sw || d . state . lastSourceHeight != sh { d . context . uniformFloats ( program , " " , [ ] float32 { float32 ( sw ) , float32 ( sh ) } ) d . state . lastSourceWidth = sw d . state . lastSourceHeight = sh } } if filter == graphics . FilterScreen { scale := float32 ( dstW ) / float32 ( srcW ) d . context . uniformFloat ( program , " " , scale ) } // We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture // See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml d . context . bindTexture ( source . textureNative ) d . state . source = nil d . state . destination = nil return nil }
// useProgram uses the program (programTexture).
useProgram uses the program ( programTexture ) .