func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { var texture Texture if err := c.runOnContextThread(func() error { var t uint32 gl.GenTextures(1, &t) // TODO: Use gl.IsTexture if t <= 0 { return errors.New("opengl: creating texture failed") } gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4) texture = Texture(t) return nil }); err != nil { return 0, err } if err := c.BindTexture(texture); err != nil { return 0, err } if err := c.runOnContextThread(func() error { gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int32(filter)) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int32(filter)) var p interface{} if pixels != nil { p = pixels } gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p)) return nil }); err != nil { return 0, err } return texture, nil }
func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { var t uint32 gl.GenTextures(1, &t) if t < 0 { return 0, errors.New("glGenTexture failed") } gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4) gl.BindTexture(gl.TEXTURE_2D, t) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int32(filter)) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int32(filter)) var p interface{} if pixels != nil { p = pixels } gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(p)) return Texture(t), nil }
// PixelStorei sets pixel storage parameters. // // http://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml func PixelStorei(pname Enum, param int32) { gl.PixelStorei(uint32(pname), param) }
func (stash *Stash) GetGlyph(fnt *Font, codepoint int, isize int16) *Glyph { size := float64(isize) / 10 // Find code point and size. h := hashint(uint(codepoint)) & (HASH_LUT_SIZE - 1) for i := fnt.lut[h]; i != -1; i = fnt.glyphs[i].next { if fnt.glyphs[i].codepoint == codepoint && (fnt.fType == BMFONT || fnt.glyphs[i].size == isize) { return fnt.glyphs[i] } } // Could not find glyph. // For bitmap fonts: ignore this glyph. if fnt.fType == BMFONT { return nil } // For truetype fonts: create this glyph. scale := fnt.font.ScaleForPixelHeight(size) g := fnt.font.FindGlyphIndex(codepoint) if g == 0 { // glyph not found return nil } advance, _ := fnt.font.GetGlyphHMetrics(g) x0, y0, x1, y1 := fnt.font.GetGlyphBitmapBox(g, scale, scale) gw := x1 - x0 gh := y1 - y0 // Check if glyph is larger than maximum texture size if gw >= stash.tw || gh >= stash.th { return nil } // Find texture and row where the glyph can be fit. rh := (int16(gh) + 7) & ^7 var tt int texture := stash.ttTextures[tt] var br *Row for br == nil { for i := range texture.rows { if texture.rows[i].h == rh && int(texture.rows[i].x)+gw+1 <= stash.tw { br = texture.rows[i] } } // If no row is found, there are 3 possibilities: // - add new row // - try next texture // - create new texture if br == nil { var py int16 // Check that there is enough space. if len(texture.rows) > 0 { py = texture.rows[len(texture.rows)-1].y + texture.rows[len(texture.rows)-1].h + 1 if int(py+rh) > stash.th { if tt < len(stash.ttTextures)-1 { tt++ texture = stash.ttTextures[tt] } else { // Create new texture gl.Enable(gl.TEXTURE_2D) texture = &Texture{} gl.GenTextures(1, &texture.id) gl.BindTexture(gl.TEXTURE_2D, texture.id) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, int32(stash.tw), int32(stash.th), 0, gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&stash.emptyData[0])) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.Disable(gl.TEXTURE_2D) stash.ttTextures = append(stash.ttTextures, texture) } continue } } // Init and add row br = &Row{ x: 0, y: py, h: rh, } texture.rows = append(texture.rows, br) } } // Init glyph. glyph := &Glyph{ codepoint: codepoint, size: isize, texture: texture, x0: int(br.x), y0: int(br.y), x1: int(br.x) + gw, y1: int(br.y) + gh, xadv: scale * float64(advance), xoff: float64(x0), yoff: float64(y0), next: 0, } fnt.glyphs = append(fnt.glyphs, glyph) // Advance row location. br.x += int16(gw) + 1 // Insert char to hash lookup. glyph.next = fnt.lut[h] fnt.lut[h] = len(fnt.glyphs) - 1 // Rasterize bmp := make([]byte, gw*gh) bmp = fnt.font.MakeGlyphBitmap(bmp, gw, gh, gw, scale, scale, g) if len(bmp) > 0 { gl.Enable(gl.TEXTURE_2D) // Update texture gl.BindTexture(gl.TEXTURE_2D, texture.id) gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1) gl.TexSubImage2D(gl.TEXTURE_2D, 0, int32(glyph.x0), int32(glyph.y0), int32(gw), int32(gh), gl.ALPHA, gl.UNSIGNED_BYTE, unsafe.Pointer(&bmp[0])) gl.Disable(gl.TEXTURE_2D) } return glyph }