mirror of https://github.com/buggins/dlangui.git
cleartype for opengl, part 1; WARNING: openGL text rendering is broken - don't sync to this commit
This commit is contained in:
parent
b15478b8e5
commit
4e90c9b39e
|
@ -66,7 +66,7 @@
|
|||
<debuglevel>0</debuglevel>
|
||||
<debugids>DebugFocus</debugids>
|
||||
<versionlevel>0</versionlevel>
|
||||
<versionids>EmbedStandardResources Unicode USE_FREETYPE</versionids>
|
||||
<versionids>EmbedStandardResources Unicode USE_FREETYPE USE_OPENGL</versionids>
|
||||
<dump_source>0</dump_source>
|
||||
<mapverbosity>0</mapverbosity>
|
||||
<createImplib>1</createImplib>
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
<debuglevel>0</debuglevel>
|
||||
<debugids />
|
||||
<versionlevel>0</versionlevel>
|
||||
<versionids>Unicode USE_FREETYPE</versionids>
|
||||
<versionids>Unicode USE_FREETYPE USE_OPENGL</versionids>
|
||||
<dump_source>0</dump_source>
|
||||
<mapverbosity>3</mapverbosity>
|
||||
<createImplib>0</createImplib>
|
||||
|
|
|
@ -600,6 +600,35 @@ class ColorDrawBufBase : DrawBuf {
|
|||
}
|
||||
}
|
||||
|
||||
void drawGlyphToTexture(int x, int y, Glyph * glyph) {
|
||||
ubyte[] src = glyph.glyph;
|
||||
int srcdx = glyph.blackBoxX;
|
||||
int srcdy = glyph.blackBoxY;
|
||||
bool subpixel = glyph.subpixelMode != SubpixelRenderingMode.None;
|
||||
for (int yy = 0; yy < srcdy; yy++) {
|
||||
int liney = y + yy;
|
||||
uint * row = scanLine(liney);
|
||||
ubyte * srcrow = src.ptr + yy * srcdx;
|
||||
int increment = subpixel ? 3 : 1;
|
||||
for (int xx = 0; xx <= srcdx - increment; xx += increment) {
|
||||
int colx = x + (subpixel ? xx / 3 : xx);
|
||||
uint alpha1 = srcrow[xx] ^ 255;
|
||||
if (subpixel) {
|
||||
//int x0 = xx % 3;
|
||||
//ubyte * dst = cast(ubyte*)(row + colx);
|
||||
//ubyte * pcolor = cast(ubyte*)(&color);
|
||||
//blendSubpixel(dst, pcolor, alpha, x0, glyph.subpixelMode);
|
||||
} else {
|
||||
uint pixel = (alpha1 << 24) || 0xFFFFFF; //(alpha1 << 16) || (alpha1 << 8) || alpha1;
|
||||
row[colx] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
// for debugging
|
||||
fillRect(Rect(x,y,x+2, y+2), 0xFF8040C0);
|
||||
fillRect(Rect(x+2,y+2,x+4, y+4), 0x40408070);
|
||||
}
|
||||
|
||||
override void fillRect(Rect rc, uint color) {
|
||||
if (applyClipping(rc)) {
|
||||
for (int y = rc.top; y < rc.bottom; y++) {
|
||||
|
|
|
@ -537,9 +537,6 @@ private class TextureSceneItem : SceneItem {
|
|||
};
|
||||
|
||||
|
||||
/// by some reason ALPHA texture does not work as expected
|
||||
private immutable USE_RGBA_TEXTURE_FOR_GLYPHS = true;
|
||||
|
||||
private class GLGlyphCache {
|
||||
|
||||
static class GLGlyphCacheItem {
|
||||
|
@ -557,7 +554,7 @@ private class GLGlyphCache {
|
|||
private GLGlyphCache _cache;
|
||||
private int _tdx;
|
||||
private int _tdy;
|
||||
private GrayDrawBuf _drawbuf;
|
||||
private ColorDrawBuf _drawbuf;
|
||||
private int _currentLine;
|
||||
private int _nextLine;
|
||||
private int _x;
|
||||
|
@ -585,9 +582,6 @@ private class GLGlyphCache {
|
|||
}
|
||||
}
|
||||
|
||||
static if (USE_RGBA_TEXTURE_FOR_GLYPHS) {
|
||||
uint[] _rgbaBuffer;
|
||||
}
|
||||
void updateTexture() {
|
||||
if (_drawbuf is null)
|
||||
return; // no draw buffer!!!
|
||||
|
@ -598,23 +592,11 @@ private class GLGlyphCache {
|
|||
return;
|
||||
}
|
||||
//CRLog::debug("updateTexture - setting image %dx%d", _drawbuf.width, _drawbuf.height);
|
||||
ubyte * pixels = _drawbuf.scanLine(0);
|
||||
static if (USE_RGBA_TEXTURE_FOR_GLYPHS) {
|
||||
int len = _drawbuf.width * _drawbuf.height;
|
||||
_rgbaBuffer.length = len;
|
||||
for (int i = 0; i < len; i++)
|
||||
_rgbaBuffer[i] = ((cast(uint)pixels[i]) << 24) | 0x00FFFFFF;
|
||||
if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) {
|
||||
glSupport.deleteTexture(_textureId);
|
||||
_textureId = 0;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!setTextureImageAlpha(_textureId, _drawbuf.width, _drawbuf.height, pixels)) {
|
||||
deleteTexture(_textureId);
|
||||
_textureId = 0;
|
||||
return;
|
||||
}
|
||||
int len = _drawbuf.width * _drawbuf.height;
|
||||
if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte *)_drawbuf.scanLine(0))) {
|
||||
glSupport.deleteTexture(_textureId);
|
||||
_textureId = 0;
|
||||
return;
|
||||
}
|
||||
_needUpdateTexture = false;
|
||||
if (_closed) {
|
||||
|
@ -622,6 +604,7 @@ private class GLGlyphCache {
|
|||
_drawbuf = null;
|
||||
}
|
||||
}
|
||||
|
||||
GLGlyphCacheItem reserveSpace(uint objectId, int width, int height) {
|
||||
GLGlyphCacheItem cacheItem = new GLGlyphCacheItem(this, objectId);
|
||||
if (_closed)
|
||||
|
@ -643,10 +626,11 @@ private class GLGlyphCache {
|
|||
if (_nextLine < _currentLine + height + 2)
|
||||
_nextLine = _currentLine + height + 2;
|
||||
if (!_drawbuf) {
|
||||
_drawbuf = new GrayDrawBuf(_tdx, _tdy);
|
||||
_drawbuf = new ColorDrawBuf(_tdx, _tdy);
|
||||
//_drawbuf.SetBackgroundColor(0x000000);
|
||||
//_drawbuf.SetTextColor(0xFFFFFF);
|
||||
_drawbuf.fill(0x00000000);
|
||||
//_drawbuf.fill(0x00000000);
|
||||
_drawbuf.fill(0xFF000000);
|
||||
}
|
||||
_x += width + 1;
|
||||
_needUpdateTexture = true;
|
||||
|
@ -662,7 +646,8 @@ private class GLGlyphCache {
|
|||
GLGlyphCacheItem cacheItem = reserveSpace(glyph.id, glyph.correctedBlackBoxX, glyph.blackBoxY);
|
||||
if (cacheItem is null)
|
||||
return null;
|
||||
_drawbuf.drawGlyph(cacheItem._rc.left, cacheItem._rc.top, glyph, 0xFFFFFF);
|
||||
//_drawbuf.drawGlyph(cacheItem._rc.left, cacheItem._rc.top, glyph, 0xFFFFFF);
|
||||
_drawbuf.drawGlyphToTexture(cacheItem._rc.left, cacheItem._rc.top, glyph);
|
||||
_needUpdateTexture = true;
|
||||
return cacheItem;
|
||||
}
|
||||
|
@ -697,7 +682,8 @@ private class GLGlyphCache {
|
|||
}
|
||||
if (!dstrc.empty) {
|
||||
//Log.d("drawing glyph with color ", color);
|
||||
glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false);
|
||||
glSupport.drawColorAndTextureGlyphRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false);
|
||||
//glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -706,9 +692,6 @@ private class GLGlyphCache {
|
|||
_closed = true;
|
||||
if (_needUpdateTexture)
|
||||
updateTexture();
|
||||
static if (USE_RGBA_TEXTURE_FOR_GLYPHS) {
|
||||
_rgbaBuffer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -416,6 +416,116 @@ class TextureProgram : SolidFillProgram {
|
|||
}
|
||||
}
|
||||
|
||||
class FontProgram : SolidFillProgram {
|
||||
@property override string vertexSource() {
|
||||
return
|
||||
"attribute " ~ HIGHP ~ " vec4 vertex;\n"
|
||||
"attribute " ~ LOWP ~ " vec4 colAttr;\n"
|
||||
"attribute " ~ MEDIUMP ~ " vec4 texCoord;\n"
|
||||
"varying " ~ LOWP ~ " vec4 col;\n"
|
||||
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
|
||||
"uniform " ~ MEDIUMP ~ " mat4 matrix;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_Position = matrix * vertex;\n"
|
||||
" col = colAttr;\n"
|
||||
" texc = texCoord;\n"
|
||||
"}\n";
|
||||
|
||||
}
|
||||
@property override string fragmentSource() {
|
||||
return
|
||||
"uniform sampler2D texture;\n"
|
||||
"varying " ~ LOWP ~ " vec4 col;\n"
|
||||
"varying " ~ MEDIUMP ~ " vec4 texc;\n"
|
||||
"void main(void)\n"
|
||||
"{\n"
|
||||
" gl_FragColor = texture2D(texture, texc.st) * col;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
GLint texCoordLocation;
|
||||
override bool initLocations() {
|
||||
bool res = super.initLocations();
|
||||
texCoordLocation = glGetAttribLocation(program, "texCoord");
|
||||
return res && texCoordLocation >= 0;
|
||||
}
|
||||
|
||||
bool execute(float[] vertices, float[] texcoords, float[] colors, uint textureId, bool linear) {
|
||||
if (error)
|
||||
return false;
|
||||
if (!initialized)
|
||||
if (!compile())
|
||||
return false;
|
||||
beforeExecute();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
checkError("glActiveTexture GL_TEXTURE0");
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
checkError("glBindTexture");
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||
checkError("drawColorAndTextureRect - glTexParameteri");
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||
checkError("drawColorAndTextureRect - glTexParameteri");
|
||||
|
||||
GLuint vao;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLuint vbo;
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
vertices.length * vertices[0].sizeof +
|
||||
colors.length * colors[0].sizeof +
|
||||
texcoords.length * texcoords[0].sizeof,
|
||||
null,
|
||||
GL_STREAM_DRAW);
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER,
|
||||
0,
|
||||
vertices.length * vertices[0].sizeof,
|
||||
vertices.ptr);
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER,
|
||||
vertices.length * vertices[0].sizeof,
|
||||
colors.length * colors[0].sizeof,
|
||||
colors.ptr);
|
||||
glBufferSubData(
|
||||
GL_ARRAY_BUFFER,
|
||||
vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof,
|
||||
texcoords.length * texcoords[0].sizeof,
|
||||
texcoords.ptr);
|
||||
|
||||
glEnableVertexAttribArray(vertexLocation);
|
||||
glEnableVertexAttribArray(colAttrLocation);
|
||||
glEnableVertexAttribArray(texCoordLocation);
|
||||
|
||||
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
|
||||
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof));
|
||||
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * vertices[0].sizeof + colors.length * colors[0].sizeof));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
checkError("glDrawArrays");
|
||||
|
||||
glDisableVertexAttribArray(vertexLocation);
|
||||
glDisableVertexAttribArray(colAttrLocation);
|
||||
glDisableVertexAttribArray(texCoordLocation);
|
||||
|
||||
afterExecute();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
checkError("glBindTexture");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
__gshared GLSupport _glSupport;
|
||||
@property GLSupport glSupport() {
|
||||
if (!_glSupport) {
|
||||
|
@ -432,9 +542,10 @@ class GLSupport {
|
|||
|
||||
TextureProgram _textureProgram;
|
||||
SolidFillProgram _solidFillProgram;
|
||||
FontProgram _fontProgram;
|
||||
|
||||
@property bool valid() {
|
||||
return _textureProgram && _solidFillProgram;
|
||||
return _textureProgram && _solidFillProgram && _fontProgram;
|
||||
}
|
||||
|
||||
bool initShaders() {
|
||||
|
@ -443,6 +554,11 @@ class GLSupport {
|
|||
if (!_textureProgram.compile())
|
||||
return false;
|
||||
}
|
||||
if (_fontProgram is null) {
|
||||
_fontProgram = new FontProgram();
|
||||
if (!_fontProgram.compile())
|
||||
return false;
|
||||
}
|
||||
if (_solidFillProgram is null) {
|
||||
_solidFillProgram = new SolidFillProgram();
|
||||
if (!_solidFillProgram.compile())
|
||||
|
@ -458,6 +574,10 @@ class GLSupport {
|
|||
destroy(_textureProgram);
|
||||
_textureProgram = null;
|
||||
}
|
||||
if (_fontProgram !is null) {
|
||||
destroy(_fontProgram);
|
||||
_fontProgram = null;
|
||||
}
|
||||
if (_solidFillProgram !is null) {
|
||||
destroy(_solidFillProgram);
|
||||
_solidFillProgram = null;
|
||||
|
@ -522,6 +642,40 @@ class GLSupport {
|
|||
Log.e("No program");
|
||||
}
|
||||
|
||||
void drawColorAndTextureGlyphRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) {
|
||||
//Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc);
|
||||
drawColorAndTextureGlyphRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear);
|
||||
}
|
||||
|
||||
void drawColorAndTextureGlyphRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) {
|
||||
float[6*4] colors;
|
||||
LVGLFillColor(color, colors.ptr, 6);
|
||||
float dstx0 = cast(float)xx;
|
||||
float dsty0 = cast(float)(bufferDy - (yy));
|
||||
float dstx1 = cast(float)(xx + dx);
|
||||
float dsty1 = cast(float)(bufferDy - (yy + dy));
|
||||
|
||||
// don't flip for framebuffer
|
||||
if (currentFramebufferId) {
|
||||
dsty0 = cast(float)((yy));
|
||||
dsty1 = cast(float)((yy + dy));
|
||||
}
|
||||
|
||||
float srcx0 = srcx / cast(float)tdx;
|
||||
float srcy0 = srcy / cast(float)tdy;
|
||||
float srcx1 = (srcx + srcdx) / cast(float)tdx;
|
||||
float srcy1 = (srcy + srcdy) / cast(float)tdy;
|
||||
float[3 * 6] vertices = [dstx0,dsty0,Z_2D,
|
||||
dstx0,dsty1,Z_2D,
|
||||
dstx1,dsty1,Z_2D,
|
||||
dstx0,dsty0,Z_2D,
|
||||
dstx1,dsty1,Z_2D,
|
||||
dstx1,dsty0,Z_2D];
|
||||
float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0];
|
||||
_fontProgram.execute(vertices, texcoords, colors, textureId, linear);
|
||||
//drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear);
|
||||
}
|
||||
|
||||
void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) {
|
||||
//Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc);
|
||||
drawColorAndTextureRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear);
|
||||
|
|
Loading…
Reference in New Issue