From e4ab8de45e4d8d5ceb41840d5fda1f7d99cda422 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 27 Oct 2013 21:27:16 +0900 Subject: [PATCH] Remove texture.Texture.Native --- graphics/opengl/context.go | 57 ++++++++++--------- graphics/opengl/rendertarget/render_target.go | 20 +++++-- graphics/opengl/texture/texture.go | 36 +++++++++--- graphics/rendertarget/render_target.go | 9 ++- graphics/texture/texture.go | 21 ++++--- 5 files changed, 88 insertions(+), 55 deletions(-) diff --git a/graphics/opengl/context.go b/graphics/opengl/context.go index 021ca54b7..30bd2598a 100644 --- a/graphics/opengl/context.go +++ b/graphics/opengl/context.go @@ -49,24 +49,20 @@ func (context *Context) Init() { C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &mainFramebuffer) var err error - context.mainFramebufferTexture, err = rendertarget.NewRenderTargetWithFramebuffer( + context.mainFramebufferTexture, err = rendertarget.NewWithFramebuffer( context.screenWidth*context.screenScale, context.screenHeight*context.screenScale, - rendertarget.Framebuffer(mainFramebuffer)) + rendertarget.Framebuffer(mainFramebuffer), + texture.FilterLinear) if err != nil { panic("creating main framebuffer failed: " + err.Error()) } - context.screenId, err = context.NewRenderTarget( - context.screenWidth, context.screenHeight) + context.screenId, err = context.newRenderTarget( + context.screenWidth, context.screenHeight, texture.FilterNearest) if err != nil { panic("initializing the offscreen failed: " + err.Error()) } - screen := context.renderTargets[context.screenId] - C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(screen.Texture().Native().(texture.Native))) - C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_NEAREST) - C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_NEAREST) - C.glBindTexture(C.GL_TEXTURE_2D, 0) } func (context *Context) ToTexture(renderTargetId graphics.RenderTargetId) graphics.TextureId { @@ -127,24 +123,26 @@ func (context *Context) SetOffscreen(renderTargetId graphics.RenderTargetId) { func (context *Context) setOffscreen(renderTarget *grendertarget.RenderTarget) { C.glFlush() - framebuffer := C.GLuint(renderTarget.Framebuffer().(rendertarget.Framebuffer)) - C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer) - err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) - if err != C.GL_FRAMEBUFFER_COMPLETE { - panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) - } + renderTarget.SetAsOffscreen(func(framebuffer interface{}) { + f := framebuffer.(rendertarget.Framebuffer) + C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(f)) + err := C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) + if err != C.GL_FRAMEBUFFER_COMPLETE { + panic(fmt.Sprintf("glBindFramebuffer failed: %d", err)) + } - C.glEnable(C.GL_BLEND) - C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA, - C.GL_ZERO, C.GL_ONE) + C.glEnable(C.GL_BLEND) + C.glBlendFuncSeparate(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA, + C.GL_ZERO, C.GL_ONE) - isUsingMainFramebuffer := renderTarget == context.mainFramebufferTexture - setter := &viewportSetter{ - isUsingMainFramebuffer, - context.screenHeight * context.screenScale, - context, - } - renderTarget.SetAsViewport(setter.Set) + isUsingMainFramebuffer := renderTarget == context.mainFramebufferTexture + setter := &viewportSetter{ + isUsingMainFramebuffer, + context.screenHeight * context.screenScale, + context, + } + renderTarget.SetAsViewport(setter.Set) + }) } type viewportSetter struct { @@ -178,9 +176,9 @@ func (context *Context) flush() { C.glFlush() } -func (context *Context) NewRenderTarget(width, height int) ( +func (context *Context) newRenderTarget(width, height int, filter texture.Filter) ( graphics.RenderTargetId, error) { - renderTarget, err := rendertarget.NewRenderTarget(width, height) + renderTarget, err := rendertarget.New(width, height, filter) if err != nil { return 0, nil } @@ -198,6 +196,11 @@ func (context *Context) NewRenderTarget(width, height int) ( return renderTargetId, nil } +func (context *Context) NewRenderTarget(width, height int) ( + graphics.RenderTargetId, error) { + return context.newRenderTarget(width, height, texture.FilterLinear) +} + func (context *Context) NewTextureFromImage(img image.Image) ( graphics.TextureId, error) { texture, err := texture.NewFromImage(img) diff --git a/graphics/opengl/rendertarget/render_target.go b/graphics/opengl/rendertarget/render_target.go index 3b129f17e..c2a9f1d6c 100644 --- a/graphics/opengl/rendertarget/render_target.go +++ b/graphics/opengl/rendertarget/render_target.go @@ -17,10 +17,12 @@ func createFramebuffer(nativeTexture C.GLuint) C.GLuint { origFramebuffer := C.GLint(0) C.glGetIntegerv(C.GL_FRAMEBUFFER_BINDING, &origFramebuffer) + C.glBindFramebuffer(C.GL_FRAMEBUFFER, framebuffer) + defer C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer)) + C.glFramebufferTexture2D(C.GL_FRAMEBUFFER, C.GL_COLOR_ATTACHMENT0, C.GL_TEXTURE_2D, nativeTexture, 0) - C.glBindFramebuffer(C.GL_FRAMEBUFFER, C.GLuint(origFramebuffer)) if C.glCheckFramebufferStatus(C.GL_FRAMEBUFFER) != C.GL_FRAMEBUFFER_COMPLETE { panic("creating framebuffer failed") @@ -29,17 +31,23 @@ func createFramebuffer(nativeTexture C.GLuint) C.GLuint { return framebuffer } -func NewRenderTarget(width, height int) (*rendertarget.RenderTarget, error) { - tex, err := texture.New(width, height) +func New(width, height int, filter texture.Filter) ( + *rendertarget.RenderTarget, error) { + tex, err := texture.New(width, height, filter) if err != nil { return nil, err } - framebuffer := createFramebuffer(C.GLuint(tex.Native().(texture.Native))) + framebuffer := C.GLuint(0) + tex.CreateFramebuffer(func(native interface{}) { + framebuffer = + createFramebuffer(C.GLuint(native.(texture.Native))) + }) return rendertarget.NewWithFramebuffer(tex, Framebuffer(framebuffer)), nil } -func NewRenderTargetWithFramebuffer(width, height int, framebuffer Framebuffer) (*rendertarget.RenderTarget, error) { - tex, err := texture.New(width, height) +func NewWithFramebuffer(width, height int, framebuffer Framebuffer, + filter texture.Filter) (*rendertarget.RenderTarget, error) { + tex, err := texture.New(width, height, filter) if err != nil { return nil, err } diff --git a/graphics/opengl/texture/texture.go b/graphics/opengl/texture/texture.go index 6e5f67324..fcef9a7cf 100644 --- a/graphics/opengl/texture/texture.go +++ b/graphics/opengl/texture/texture.go @@ -12,7 +12,15 @@ import ( type Native C.GLuint -func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) Native { +type Filter int + +const ( + FilterLinear = iota + FilterNearest +) + +func createNativeTexture(textureWidth, textureHeight int, pixels []uint8, + filter Filter) Native { nativeTexture := C.GLuint(0) C.glGenTextures(1, (*C.GLuint)(&nativeTexture)) @@ -23,8 +31,17 @@ func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) Native C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(nativeTexture)) defer C.glBindTexture(C.GL_TEXTURE_2D, 0) - 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) + glFilter := C.GLint(0) + switch filter { + case FilterLinear: + glFilter = C.GL_LINEAR + case FilterNearest: + glFilter = C.GL_NEAREST + default: + panic("not reached") + } + C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, glFilter) + C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, glFilter) ptr := unsafe.Pointer(nil) if pixels != nil { @@ -37,17 +54,20 @@ func createNativeTexture(textureWidth, textureHeight int, pixels []uint8) Native return Native(nativeTexture) } -func create(textureWidth, textureHeight int) (interface{}, error) { - return createNativeTexture(textureWidth, textureHeight, nil), nil +func create(textureWidth, textureHeight int, filter Filter) (interface{}, error) { + return createNativeTexture(textureWidth, textureHeight, nil, filter), nil } func createFromImage(img *image.NRGBA) (interface{}, error) { size := img.Bounds().Size() - return createNativeTexture(size.X, size.Y, img.Pix), nil + return createNativeTexture(size.X, size.Y, img.Pix, FilterLinear), nil } -func New(width, height int) (*gtexture.Texture, error) { - return gtexture.New(width, height, create) +func New(width, height int, filter Filter) (*gtexture.Texture, error) { + f := func(textureWidth, textureHeight int) (interface{}, error) { + return create(textureWidth, textureHeight, filter) + } + return gtexture.New(width, height, f) } func NewFromImage(img image.Image) (*gtexture.Texture, error) { diff --git a/graphics/rendertarget/render_target.go b/graphics/rendertarget/render_target.go index d2dc897fb..f623604ad 100644 --- a/graphics/rendertarget/render_target.go +++ b/graphics/rendertarget/render_target.go @@ -21,11 +21,10 @@ func (renderTarget *RenderTarget) Texture() *texture.Texture { return renderTarget.texture } -// TODO: Remove this -func (renderTarget *RenderTarget) Framebuffer() interface{} { - return renderTarget.framebuffer -} - func (renderTarget *RenderTarget) SetAsViewport(setter func(x, y, width, height int)) { renderTarget.texture.SetAsViewport(setter) } + +func (renderTarget *RenderTarget) SetAsOffscreen(setter func(framebuffer interface{})) { + setter(renderTarget.framebuffer) +} diff --git a/graphics/texture/texture.go b/graphics/texture/texture.go index c2ca60952..058f14b07 100644 --- a/graphics/texture/texture.go +++ b/graphics/texture/texture.go @@ -23,20 +23,23 @@ type Texture struct { height int } -func New(width, height int, create func(textureWidth, textureHeight int) (interface{}, error)) (*Texture, error) { +func New(width, height int, create func(textureWidth, textureHeight int) ( + interface{}, error)) (*Texture, error) { texture := &Texture{ width: width, height: height, } var err error - texture.native, err = create(texture.textureWidth(), texture.textureHeight()) + texture.native, err = create(texture.textureWidth(), + texture.textureHeight()) if err != nil { return nil, err } return texture, nil } -func NewFromImage(img image.Image, create func(img *image.NRGBA) (interface{}, error)) (*Texture, error) { +func NewFromImage(img image.Image, create func(img *image.NRGBA) ( + interface{}, error)) (*Texture, error) { size := img.Bounds().Size() width, height := size.X, size.Y texture := &Texture{ @@ -69,11 +72,6 @@ func (texture *Texture) textureHeight() int { return int(nextPowerOf2(uint64(texture.height))) } -// TODO: Remove this -func (texture *Texture) Native() interface{} { - return texture.native -} - func (texture *Texture) u(x int) float32 { return float32(x) / float32(texture.textureWidth()) } @@ -110,7 +108,8 @@ func (texture *Texture) Draw(draw func(native interface{}, quads []Quad)) { draw(texture.native, []Quad{quad}) } -func (texture *Texture) DrawParts(parts []graphics.TexturePart, draw func(native interface{}, quads []Quad)) { +func (texture *Texture) DrawParts(parts []graphics.TexturePart, + draw func(native interface{}, quads []Quad)) { quads := []Quad{} for _, part := range parts { x1 := float32(part.LocationX) @@ -126,3 +125,7 @@ func (texture *Texture) DrawParts(parts []graphics.TexturePart, draw func(native } draw(texture.native, quads) } + +func (texture *Texture) CreateFramebuffer(create func(native interface{})) { + create(texture.native) +}