#include "GLDraw.h" namespace Upp { void GLTexture::Clear() { if(data && --data->refcount == 0) { glDeleteTextures(1, &data->textureid); delete data; } data = NULL; } void GLTexture::Set(GLuint id, Size sz, Point hotspot) { Clear(); data = new Data; data->sz = sz; data->hotspot = hotspot; data->textureid = id; } void GLTexture::Set(const Image& img, dword flags) { Set(CreateGLTexture(img, flags), img.GetSize(), img.GetHotSpot()); } extern int sTextureCounter; void GLTexture::Bind(int ii) const { if(data) { glActiveTexture(GL_TEXTURE0 + ii); glBindTexture(GL_TEXTURE_2D, data->textureid); sTextureCounter++; } } GLTexture::GLTexture(const GLTexture& src) { data = src.data; if(data) data->refcount++; } GLTexture& GLTexture::operator=(const GLTexture& src) { Clear(); data = src.data; if(data) data->refcount++; return *this; } void GLBind(int ii, const Image& img, dword style) { extern int sTextureCounter; glActiveTexture(GL_TEXTURE0 + ii); glBindTexture(GL_TEXTURE_2D, GetTextureForImage(style, img)); sTextureCounter++; } void GLBind(const Image& img, dword style) { GLBind(0, img, style); } const GLVertexData& GLRectMesh() { static GLVertexData mesh; ONCELOCK { static const float box[] = { 0, 0, // 0 0, 1, // 1 1, 0, // 2 1, 1, // 3 }; static const int ndx[] = { 0, 1, 2, 1, 2, 3 }; mesh.Add(box, 2, 4).Index(ndx, 6); } return mesh; } void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, int textureid, Size tsz, const Rect& src) { static GLCode program(R"( // #version 330 core uniform vec2 offset; uniform vec2 scale; uniform vec2 toffset; uniform vec2 tscale; attribute vec2 aPos; varying vec2 tPos; void main() { gl_Position = vec4(scale * aPos + offset, 0, 1); tPos = tscale * aPos + toffset; } )", R"( // #version 330 core varying vec2 tPos; uniform float alpha; uniform sampler2D s_texture; void main() { vec4 v = texture2D(s_texture, tPos); gl_FragColor = alpha * clamp(v, vec4(0, 0, 0, 0), v.aaaa); // clamp fixes non-premultiplied textures } )"); if(tsz.cx * tsz.cy == 0) return; static int ioffset = program["offset"]; static int iscale = program["scale"]; static int ialpha = program["alpha"]; static int itscale = program["tscale"]; static int itoffset = program["toffset"]; glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, textureid); sTextureCounter++; GLRectMesh().Draw( program(ioffset, dd.vs * rect.TopLeft() + dd.off) (iscale, dd.vs * rect.GetSize()) (ialpha, dd.alpha) (itoffset, Sizef((float)src.left / tsz.cx, (float)src.top / tsz.cy)) (itscale, Sizef((float)src.GetWidth() / tsz.cx, (float)src.GetHeight() / tsz.cy)) ); } void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, const GLTexture& img, const Rect& src) { GLDrawTexture(dd, rect, img.GetID(), img.GetSize(), src); } void GLDrawImage(const GLContext2D& dd, const Rectf& rect, const Image& img, const Rect& src) { GLDrawTexture(dd, rect, GetTextureForImage(img), img.GetSize(), src); } void GLDrawTexture(const GLContext2D& dd, const Rectf& rect, const GLTexture& img) { GLDrawTexture(dd, rect, img, img.GetSize()); } void GLDrawImage(const GLContext2D& dd, const Rectf& rect, const Image& img) { GLDrawTexture(dd, rect, img, img.GetSize()); } };