ebiten/graphics/opengl/texture.go

139 lines
3.4 KiB
Go
Raw Normal View History

2013-06-19 01:49:54 +02:00
package opengl
2013-06-15 10:07:14 +02:00
// #cgo LDFLAGS: -framework OpenGL
//
// #include <OpenGL/gl.h>
import "C"
import (
2013-06-19 03:31:44 +02:00
"image"
2013-10-20 17:17:05 +02:00
"image/draw"
2013-06-15 10:07:14 +02:00
"unsafe"
)
2013-10-18 20:15:25 +02:00
func nextPowerOf2(x uint64) uint64 {
2013-06-15 10:07:14 +02:00
x -= 1
x |= (x >> 1)
x |= (x >> 2)
x |= (x >> 4)
x |= (x >> 8)
x |= (x >> 16)
x |= (x >> 32)
return x + 1
}
type Texture struct {
2013-10-19 11:47:34 +02:00
native C.GLuint
2013-06-19 16:51:41 +02:00
width int
height int
textureWidth int
2013-06-19 01:49:54 +02:00
textureHeight int
2013-07-12 18:36:01 +02:00
}
2013-10-19 11:47:34 +02:00
type RenderTarget struct {
texture *Texture
framebuffer C.GLuint
2013-07-12 18:36:01 +02:00
}
2013-10-20 17:17:05 +02:00
func createNativeTexture(textureWidth, textureHeight int, pixels unsafe.Pointer) C.GLuint {
2013-10-19 11:47:34 +02:00
nativeTexture := C.GLuint(0)
2013-10-20 17:17:05 +02:00
2013-10-19 11:47:34 +02:00
C.glGenTextures(1, (*C.GLuint)(&nativeTexture))
if nativeTexture < 0 {
2013-06-19 03:31:44 +02:00
panic("glGenTexture failed")
}
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
2013-10-19 11:47:34 +02:00
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(nativeTexture))
2013-06-19 16:51:41 +02:00
2013-06-19 03:31:44 +02:00
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
2013-10-20 17:17:05 +02:00
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, pixels)
2013-06-15 10:07:14 +02:00
2013-06-19 03:31:44 +02:00
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
C.glBindTexture(C.GL_TEXTURE_2D, 0)
2013-06-15 10:07:14 +02:00
2013-10-20 17:17:05 +02:00
return nativeTexture
}
func createTexture(width, height int) *Texture {
textureWidth := int(nextPowerOf2(uint64(width)))
textureHeight := int(nextPowerOf2(uint64(height)))
return &Texture{
width: width,
height: height,
textureWidth: textureWidth,
textureHeight: textureHeight,
native: createNativeTexture(textureWidth, textureHeight, nil),
}
}
2013-10-20 18:13:09 +02:00
func newRenderTarget(width, height int) (*RenderTarget, error) {
texture := createTexture(width, height)
framebuffer := createFramebuffer(texture.native)
return &RenderTarget{
texture: texture,
framebuffer: framebuffer,
}, nil
}
func newTextureFromImage(img image.Image) (*Texture, error) {
2013-10-20 17:17:05 +02:00
size := img.Bounds().Size()
width, height := size.X, size.Y
textureWidth := int(nextPowerOf2(uint64(width)))
textureHeight := int(nextPowerOf2(uint64(height)))
adjustedImageBound := image.Rectangle{
image.ZP,
image.Point{textureWidth, textureHeight},
}
adjustedImage := image.NewNRGBA(adjustedImageBound)
dstBound := image.Rectangle{
image.ZP,
img.Bounds().Size(),
}
draw.Draw(adjustedImage, dstBound, img, image.ZP, draw.Src)
pixelsPtr := unsafe.Pointer(&adjustedImage.Pix[0])
nativeTexture := createNativeTexture(textureWidth, textureHeight, pixelsPtr)
2013-10-19 11:47:34 +02:00
2013-10-20 17:17:05 +02:00
return &Texture{
width: width,
height: height,
textureWidth: textureWidth,
textureHeight: textureHeight,
native: nativeTexture,
2013-10-20 18:13:09 +02:00
}, nil
2013-06-15 10:07:14 +02:00
}
2013-07-12 18:36:01 +02:00
2013-10-11 18:29:19 +02:00
func newRenderTargetWithFramebuffer(width, height int,
2013-10-19 11:47:34 +02:00
framebuffer C.GLuint) *RenderTarget {
texture := &Texture{
2013-07-12 18:36:01 +02:00
width: width,
height: height,
2013-10-18 20:15:25 +02:00
textureWidth: int(nextPowerOf2(uint64(width))),
textureHeight: int(nextPowerOf2(uint64(height))),
2013-10-19 11:47:34 +02:00
}
return &RenderTarget{
texture: texture,
framebuffer: framebuffer,
2013-07-12 18:36:01 +02:00
}
2013-10-11 18:29:19 +02:00
}
2013-10-17 04:21:57 +02:00
2013-10-19 11:47:34 +02:00
func createFramebuffer(nativeTexture C.GLuint) C.GLuint {
2013-10-17 04:21:57 +02:00
framebuffer := C.GLuint(0)
C.glGenFramebuffers(1, &framebuffer)
origFramebuffer := C.GLint(0)
C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &origFramebuffer)
C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer)
C.glFramebufferTexture2D(C.GL_FRAMEBUFFER, C.GL_COLOR_ATTACHMENT0,
2013-10-19 11:47:34 +02:00
C.GL_TEXTURE_2D, nativeTexture, 0)
2013-10-17 04:21:57 +02:00
C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer))
if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) !=
C.GL_FRAMEBUFFER_COMPLETE {
panic("creating framebuffer failed")
}
return framebuffer
}