mirror of https://github.com/buggins/dlangui.git
GL caches refactoring
This commit is contained in:
parent
e4f27b1966
commit
31e1693074
|
@ -8,10 +8,13 @@ private import std.algorithm;
|
||||||
/// drawing buffer - image container which allows to perform some drawing operations
|
/// drawing buffer - image container which allows to perform some drawing operations
|
||||||
class GLDrawBuf : DrawBuf {
|
class GLDrawBuf : DrawBuf {
|
||||||
|
|
||||||
int _dx;
|
protected int _dx;
|
||||||
int _dy;
|
protected int _dy;
|
||||||
bool _framebuffer;
|
protected bool _framebuffer;
|
||||||
Scene _scene;
|
protected Scene _scene;
|
||||||
|
|
||||||
|
/// get current scene (exists only between beforeDrawing() and afterDrawing() calls
|
||||||
|
@property Scene scene() { return _scene; }
|
||||||
|
|
||||||
this(int dx, int dy, bool framebuffer = false) {
|
this(int dx, int dy, bool framebuffer = false) {
|
||||||
_dx = dx;
|
_dx = dx;
|
||||||
|
@ -38,6 +41,8 @@ class GLDrawBuf : DrawBuf {
|
||||||
setOrthoProjection(_dx, _dy);
|
setOrthoProjection(_dx, _dy);
|
||||||
_scene.draw();
|
_scene.draw();
|
||||||
flushGL();
|
flushGL();
|
||||||
|
destroy(_scene);
|
||||||
|
_scene = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resize buffer
|
/// resize buffer
|
||||||
|
@ -63,10 +68,8 @@ class GLDrawBuf : DrawBuf {
|
||||||
Rect srcrect = Rect(0, 0, glyph.blackBoxX, glyph.blackBoxY);
|
Rect srcrect = Rect(0, 0, glyph.blackBoxX, glyph.blackBoxY);
|
||||||
//Log.v("GLDrawBuf.frawFragment dst=", dstrect, " src=", srcrect);
|
//Log.v("GLDrawBuf.frawFragment dst=", dstrect, " src=", srcrect);
|
||||||
if (applyClipping(dstrect, srcrect)) {
|
if (applyClipping(dstrect, srcrect)) {
|
||||||
GLGlyphCacheItem item = glGlyphCache.get(glyph.id);
|
if (!glGlyphCache.get(glyph.id))
|
||||||
if (item is null)
|
glGlyphCache.put(glyph);
|
||||||
item = glGlyphCache.set(glyph);
|
|
||||||
// TODO: clipping
|
|
||||||
_scene.add(new GlyphSceneItem(glyph.id, dstrect, srcrect, color, null));
|
_scene.add(new GlyphSceneItem(glyph.id, dstrect, srcrect, color, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,10 +79,8 @@ class GLDrawBuf : DrawBuf {
|
||||||
Rect dstrect = Rect(x, y, x + srcrect.width, y + srcrect.height);
|
Rect dstrect = Rect(x, y, x + srcrect.width, y + srcrect.height);
|
||||||
//Log.v("GLDrawBuf.frawFragment dst=", dstrect, " src=", srcrect);
|
//Log.v("GLDrawBuf.frawFragment dst=", dstrect, " src=", srcrect);
|
||||||
if (applyClipping(dstrect, srcrect)) {
|
if (applyClipping(dstrect, srcrect)) {
|
||||||
GLImageCacheItem item = glImageCache.get(src.id);
|
if (glImageCache.get(src.id))
|
||||||
if (item is null)
|
glImageCache.put(src);
|
||||||
item = glImageCache.set(src);
|
|
||||||
// TODO: clipping
|
|
||||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
|
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,9 +89,8 @@ class GLDrawBuf : DrawBuf {
|
||||||
assert(_scene !is null);
|
assert(_scene !is null);
|
||||||
//Log.v("GLDrawBuf.frawRescaled dst=", dstrect, " src=", srcrect);
|
//Log.v("GLDrawBuf.frawRescaled dst=", dstrect, " src=", srcrect);
|
||||||
if (applyClipping(dstrect, srcrect)) {
|
if (applyClipping(dstrect, srcrect)) {
|
||||||
GLImageCacheItem item = glImageCache.get(src.id);
|
if (glImageCache.get(src.id))
|
||||||
if (item is null)
|
glImageCache.put(src);
|
||||||
item = glImageCache.set(src);
|
|
||||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
|
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,11 +128,9 @@ bool hasActiveScene() {
|
||||||
return activeSceneCount > 0;
|
return activeSceneCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
immutable int MIN_TEX_SIZE = 64;
|
immutable int MIN_TEX_SIZE = 64;
|
||||||
immutable int MAX_TEX_SIZE = 4096;
|
immutable int MAX_TEX_SIZE = 4096;
|
||||||
int nearestPOT(int n) {
|
private int nearestPOT(int n) {
|
||||||
for (int i = MIN_TEX_SIZE; i <= MAX_TEX_SIZE; i *= 2) {
|
for (int i = MIN_TEX_SIZE; i <= MAX_TEX_SIZE; i *= 2) {
|
||||||
if (n <= i)
|
if (n <= i)
|
||||||
return i;
|
return i;
|
||||||
|
@ -164,136 +162,34 @@ void LVGLClearImageCache() {
|
||||||
glGlyphCache.clear();
|
glGlyphCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GLImageCacheItem {
|
/// OpenGL texture cache for ColorDrawBuf objects
|
||||||
GLImageCachePage _page;
|
private class GLImageCache {
|
||||||
public:
|
|
||||||
|
static class GLImageCacheItem {
|
||||||
|
private GLImageCachePage _page;
|
||||||
|
|
||||||
@property GLImageCachePage page() { return _page; }
|
@property GLImageCachePage page() { return _page; }
|
||||||
|
|
||||||
uint _objectId;
|
uint _objectId;
|
||||||
// image size
|
|
||||||
Rect _rc;
|
Rect _rc;
|
||||||
bool _deleted;
|
bool _deleted;
|
||||||
|
|
||||||
this(GLImageCachePage page, uint objectId) { _page = page; _objectId = objectId; }
|
this(GLImageCachePage page, uint objectId) { _page = page; _objectId = objectId; }
|
||||||
};
|
};
|
||||||
|
|
||||||
private class GLImageCache {
|
static class GLImageCachePage {
|
||||||
GLImageCacheItem[uint] _map;
|
private GLImageCache _cache;
|
||||||
GLImageCachePage[] _pages;
|
private int _tdx;
|
||||||
GLImageCachePage _activePage;
|
private int _tdy;
|
||||||
int tdx;
|
private ColorDrawBuf _drawbuf;
|
||||||
int tdy;
|
private int _currentLine;
|
||||||
void removePage(GLImageCachePage page) {
|
private int _nextLine;
|
||||||
if (_activePage == page)
|
private int _x;
|
||||||
_activePage = null;
|
private bool _closed;
|
||||||
for (int i = 0; i < _pages.length; i++)
|
private bool _needUpdateTexture;
|
||||||
if (_pages[i] == page) {
|
private uint _textureId;
|
||||||
_pages.remove(i);
|
private int _itemCount;
|
||||||
break;
|
|
||||||
}
|
|
||||||
destroy(page);
|
|
||||||
}
|
|
||||||
void updateTextureSize() {
|
|
||||||
if (!tdx) {
|
|
||||||
// TODO
|
|
||||||
tdx = tdy = 1024; //getMaxTextureSize();
|
|
||||||
if (tdx > 1024)
|
|
||||||
tdx = tdy = 1024;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
this() {
|
|
||||||
}
|
|
||||||
~this() {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
GLImageCacheItem get(uint obj) {
|
|
||||||
if (obj in _map)
|
|
||||||
return _map[obj];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
GLImageCacheItem set(DrawBuf img) {
|
|
||||||
updateTextureSize();
|
|
||||||
GLImageCacheItem res = null;
|
|
||||||
if (img.width <= tdx / 3 && img.height < tdy / 3) {
|
|
||||||
// trying to reuse common page for small images
|
|
||||||
if (_activePage is null) {
|
|
||||||
_activePage = new GLImageCachePage(this, tdx, tdy);
|
|
||||||
_pages ~= _activePage;
|
|
||||||
}
|
|
||||||
res = _activePage.addItem(img);
|
|
||||||
if (!res) {
|
|
||||||
_activePage = new GLImageCachePage(this, tdx, tdy);
|
|
||||||
_pages ~= _activePage;
|
|
||||||
res = _activePage.addItem(img);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// use separate page for big image
|
|
||||||
GLImageCachePage page = new GLImageCachePage(this, img.width, img.height);
|
|
||||||
_pages ~= page;
|
|
||||||
res = page.addItem(img);
|
|
||||||
page.close();
|
|
||||||
}
|
|
||||||
_map[img.id] = res;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
void clear() {
|
|
||||||
for (int i = 0; i < _pages.length; i++) {
|
|
||||||
destroy(_pages[i]);
|
|
||||||
_pages[i] = null;
|
|
||||||
}
|
|
||||||
_pages.clear();
|
|
||||||
_map.clear();
|
|
||||||
}
|
|
||||||
/// draw cached item
|
|
||||||
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, int options, Rect * clip, int rotationAngle) {
|
|
||||||
if (objectId in _map) {
|
|
||||||
GLImageCacheItem item = _map[objectId];
|
|
||||||
item.page.drawItem(item, dstrc, srcrc, color, options, clip, rotationAngle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// handle cached object deletion, mark as deleted
|
|
||||||
void onCachedObjectDeleted(uint objectId) {
|
|
||||||
if (objectId in _map) {
|
|
||||||
GLImageCacheItem item = _map[objectId];
|
|
||||||
if (hasActiveScene()) {
|
|
||||||
item._deleted = true;
|
|
||||||
} else {
|
|
||||||
int itemsLeft = item.page.deleteItem(item);
|
|
||||||
//CRLog::trace("itemsLeft = %d", itemsLeft);
|
|
||||||
if (itemsLeft <= 0) {
|
|
||||||
//CRLog::trace("removing page");
|
|
||||||
removePage(item.page);
|
|
||||||
}
|
|
||||||
_map.remove(objectId);
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// remove deleted items - remove page if contains only deleted items
|
|
||||||
void removeDeletedItems() {
|
|
||||||
uint[] list;
|
|
||||||
foreach (GLImageCacheItem item; _map) {
|
|
||||||
if (item._deleted)
|
|
||||||
list ~= item._objectId;
|
|
||||||
}
|
|
||||||
for (int i = 0 ; i < list.length; i++) {
|
|
||||||
onCachedObjectDeleted(list[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private class GLImageCachePage {
|
|
||||||
GLImageCache _cache;
|
|
||||||
int _tdx;
|
|
||||||
int _tdy;
|
|
||||||
ColorDrawBuf _drawbuf;
|
|
||||||
int _currentLine;
|
|
||||||
int _nextLine;
|
|
||||||
int _x;
|
|
||||||
bool _closed;
|
|
||||||
bool _needUpdateTexture;
|
|
||||||
uint _textureId;
|
|
||||||
int _itemCount;
|
|
||||||
public:
|
|
||||||
this(GLImageCache cache, int dx, int dy) {
|
this(GLImageCache cache, int dx, int dy) {
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
Log.v("created image cache page ", dx, "x", dy);
|
Log.v("created image cache page ", dx, "x", dy);
|
||||||
|
@ -335,6 +231,7 @@ public:
|
||||||
_drawbuf = null;
|
_drawbuf = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void invertAlpha(GLImageCacheItem item) {
|
void invertAlpha(GLImageCacheItem item) {
|
||||||
Rect rc = item._rc;
|
Rect rc = item._rc;
|
||||||
for (int y = rc.top; y < rc.bottom; y++) {
|
for (int y = rc.top; y < rc.bottom; y++) {
|
||||||
|
@ -348,6 +245,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLImageCacheItem reserveSpace(uint objectId, int width, int height) {
|
GLImageCacheItem reserveSpace(uint objectId, int width, int height) {
|
||||||
GLImageCacheItem cacheItem = new GLImageCacheItem(this, objectId);
|
GLImageCacheItem cacheItem = new GLImageCacheItem(this, objectId);
|
||||||
if (_closed)
|
if (_closed)
|
||||||
|
@ -449,59 +347,15 @@ public:
|
||||||
if (_needUpdateTexture)
|
if (_needUpdateTexture)
|
||||||
updateTexture();
|
updateTexture();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private class TextureSceneItem : SceneItem {
|
|
||||||
uint objectId;
|
|
||||||
//CacheableObject * img;
|
|
||||||
Rect dstrc;
|
|
||||||
Rect srcrc;
|
|
||||||
uint color;
|
|
||||||
uint options;
|
|
||||||
Rect * clip;
|
|
||||||
int rotationAngle;
|
|
||||||
public:
|
|
||||||
override void draw() {
|
|
||||||
if (glImageCache)
|
|
||||||
glImageCache.drawItem(objectId, dstrc, srcrc, color, options, clip, rotationAngle);
|
|
||||||
}
|
}
|
||||||
this(uint _objectId, Rect _dstrc, Rect _srcrc, uint _color, uint _options, Rect * _clip, int _rotationAngle)
|
|
||||||
{
|
|
||||||
objectId = _objectId;
|
|
||||||
dstrc = _dstrc;
|
|
||||||
srcrc = _srcrc;
|
|
||||||
color = _color;
|
|
||||||
options = _options;
|
|
||||||
clip = _clip;
|
|
||||||
rotationAngle = _rotationAngle;
|
|
||||||
}
|
|
||||||
~this() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
private GLImageCacheItem[uint] _map;
|
||||||
|
private GLImageCachePage[] _pages;
|
||||||
|
private GLImageCachePage _activePage;
|
||||||
|
private int tdx;
|
||||||
|
private int tdy;
|
||||||
|
|
||||||
|
private void removePage(GLImageCachePage page) {
|
||||||
|
|
||||||
|
|
||||||
private class GLGlyphCacheItem {
|
|
||||||
GLGlyphCachePage _page;
|
|
||||||
public:
|
|
||||||
@property GLGlyphCachePage page() { return _page; }
|
|
||||||
uint _objectId;
|
|
||||||
// image size
|
|
||||||
Rect _rc;
|
|
||||||
bool _deleted;
|
|
||||||
this(GLGlyphCachePage page, uint objectId) { _page = page; _objectId = objectId; }
|
|
||||||
};
|
|
||||||
|
|
||||||
private class GLGlyphCache {
|
|
||||||
GLGlyphCacheItem[uint] _map;
|
|
||||||
GLGlyphCachePage[] _pages;
|
|
||||||
GLGlyphCachePage _activePage;
|
|
||||||
int tdx;
|
|
||||||
int tdy;
|
|
||||||
void removePage(GLGlyphCachePage page) {
|
|
||||||
if (_activePage == page)
|
if (_activePage == page)
|
||||||
_activePage = null;
|
_activePage = null;
|
||||||
for (int i = 0; i < _pages.length; i++)
|
for (int i = 0; i < _pages.length; i++)
|
||||||
|
@ -511,7 +365,8 @@ private class GLGlyphCache {
|
||||||
}
|
}
|
||||||
destroy(page);
|
destroy(page);
|
||||||
}
|
}
|
||||||
void updateTextureSize() {
|
|
||||||
|
private void updateTextureSize() {
|
||||||
if (!tdx) {
|
if (!tdx) {
|
||||||
// TODO
|
// TODO
|
||||||
tdx = tdy = 1024; //getMaxTextureSize();
|
tdx = tdy = 1024; //getMaxTextureSize();
|
||||||
|
@ -519,33 +374,44 @@ private class GLGlyphCache {
|
||||||
tdx = tdy = 1024;
|
tdx = tdy = 1024;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
this() {
|
this() {
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
GLGlyphCacheItem get(uint obj) {
|
/// returns true if object exists in cache
|
||||||
|
bool get(uint obj) {
|
||||||
if (obj in _map)
|
if (obj in _map)
|
||||||
return _map[obj];
|
return true;
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
GLGlyphCacheItem set(Glyph * glyph) {
|
/// put new object to cache
|
||||||
|
void put(DrawBuf img) {
|
||||||
updateTextureSize();
|
updateTextureSize();
|
||||||
GLGlyphCacheItem res = null;
|
GLImageCacheItem res = null;
|
||||||
|
if (img.width <= tdx / 3 && img.height < tdy / 3) {
|
||||||
|
// trying to reuse common page for small images
|
||||||
if (_activePage is null) {
|
if (_activePage is null) {
|
||||||
_activePage = new GLGlyphCachePage(this, tdx, tdy);
|
_activePage = new GLImageCachePage(this, tdx, tdy);
|
||||||
_pages ~= _activePage;
|
_pages ~= _activePage;
|
||||||
}
|
}
|
||||||
res = _activePage.addItem(glyph);
|
res = _activePage.addItem(img);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
_activePage = new GLGlyphCachePage(this, tdx, tdy);
|
_activePage = new GLImageCachePage(this, tdx, tdy);
|
||||||
_pages ~= _activePage;
|
_pages ~= _activePage;
|
||||||
res = _activePage.addItem(glyph);
|
res = _activePage.addItem(img);
|
||||||
}
|
}
|
||||||
_map[glyph.id] = res;
|
} else {
|
||||||
return res;
|
// use separate page for big image
|
||||||
|
GLImageCachePage page = new GLImageCachePage(this, img.width, img.height);
|
||||||
|
_pages ~= page;
|
||||||
|
res = page.addItem(img);
|
||||||
|
page.close();
|
||||||
}
|
}
|
||||||
|
_map[img.id] = res;
|
||||||
|
}
|
||||||
|
/// clears cache
|
||||||
void clear() {
|
void clear() {
|
||||||
for (int i = 0; i < _pages.length; i++) {
|
for (int i = 0; i < _pages.length; i++) {
|
||||||
destroy(_pages[i]);
|
destroy(_pages[i]);
|
||||||
|
@ -555,16 +421,16 @@ public:
|
||||||
_map.clear();
|
_map.clear();
|
||||||
}
|
}
|
||||||
/// draw cached item
|
/// draw cached item
|
||||||
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, Rect * clip) {
|
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, int options, Rect * clip, int rotationAngle) {
|
||||||
if (objectId in _map) {
|
if (objectId in _map) {
|
||||||
GLGlyphCacheItem item = _map[objectId];
|
GLImageCacheItem item = _map[objectId];
|
||||||
item.page.drawItem(item, dstrc, srcrc, color, clip);
|
item.page.drawItem(item, dstrc, srcrc, color, options, clip, rotationAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// handle cached object deletion, mark as deleted
|
/// handle cached object deletion, mark as deleted
|
||||||
void onCachedObjectDeleted(uint objectId) {
|
void onCachedObjectDeleted(uint objectId) {
|
||||||
if (objectId in _map) {
|
if (objectId in _map) {
|
||||||
GLGlyphCacheItem item = _map[objectId];
|
GLImageCacheItem item = _map[objectId];
|
||||||
if (hasActiveScene()) {
|
if (hasActiveScene()) {
|
||||||
item._deleted = true;
|
item._deleted = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -582,7 +448,7 @@ public:
|
||||||
/// remove deleted items - remove page if contains only deleted items
|
/// remove deleted items - remove page if contains only deleted items
|
||||||
void removeDeletedItems() {
|
void removeDeletedItems() {
|
||||||
uint[] list;
|
uint[] list;
|
||||||
foreach (GLGlyphCacheItem item; _map) {
|
foreach (GLImageCacheItem item; _map) {
|
||||||
if (item._deleted)
|
if (item._deleted)
|
||||||
list ~= item._objectId;
|
list ~= item._objectId;
|
||||||
}
|
}
|
||||||
|
@ -592,19 +458,68 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private class GLGlyphCachePage {
|
|
||||||
GLGlyphCache _cache;
|
|
||||||
int _tdx;
|
private class TextureSceneItem : SceneItem {
|
||||||
int _tdy;
|
private uint objectId;
|
||||||
GrayDrawBuf _drawbuf;
|
//CacheableObject * img;
|
||||||
int _currentLine;
|
private Rect dstrc;
|
||||||
int _nextLine;
|
private Rect srcrc;
|
||||||
int _x;
|
private uint color;
|
||||||
bool _closed;
|
private uint options;
|
||||||
bool _needUpdateTexture;
|
private Rect * clip;
|
||||||
uint _textureId;
|
private int rotationAngle;
|
||||||
int _itemCount;
|
|
||||||
|
override void draw() {
|
||||||
|
if (glImageCache)
|
||||||
|
glImageCache.drawItem(objectId, dstrc, srcrc, color, options, clip, rotationAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
this(uint _objectId, Rect _dstrc, Rect _srcrc, uint _color, uint _options, Rect * _clip, int _rotationAngle)
|
||||||
|
{
|
||||||
|
objectId = _objectId;
|
||||||
|
dstrc = _dstrc;
|
||||||
|
srcrc = _srcrc;
|
||||||
|
color = _color;
|
||||||
|
options = _options;
|
||||||
|
clip = _clip;
|
||||||
|
rotationAngle = _rotationAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
~this() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class GLGlyphCache {
|
||||||
|
|
||||||
|
static class GLGlyphCacheItem {
|
||||||
|
GLGlyphCachePage _page;
|
||||||
public:
|
public:
|
||||||
|
@property GLGlyphCachePage page() { return _page; }
|
||||||
|
uint _objectId;
|
||||||
|
// image size
|
||||||
|
Rect _rc;
|
||||||
|
bool _deleted;
|
||||||
|
this(GLGlyphCachePage page, uint objectId) { _page = page; _objectId = objectId; }
|
||||||
|
};
|
||||||
|
|
||||||
|
static class GLGlyphCachePage {
|
||||||
|
private GLGlyphCache _cache;
|
||||||
|
private int _tdx;
|
||||||
|
private int _tdy;
|
||||||
|
private GrayDrawBuf _drawbuf;
|
||||||
|
private int _currentLine;
|
||||||
|
private int _nextLine;
|
||||||
|
private int _x;
|
||||||
|
private bool _closed;
|
||||||
|
private bool _needUpdateTexture;
|
||||||
|
private uint _textureId;
|
||||||
|
private int _itemCount;
|
||||||
|
|
||||||
this(GLGlyphCache cache, int dx, int dy) {
|
this(GLGlyphCache cache, int dx, int dy) {
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
Log.v("created image cache page ", dx, "x", dy);
|
Log.v("created image cache page ", dx, "x", dy);
|
||||||
|
@ -729,6 +644,103 @@ public:
|
||||||
if (_needUpdateTexture)
|
if (_needUpdateTexture)
|
||||||
updateTexture();
|
updateTexture();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLGlyphCacheItem[uint] _map;
|
||||||
|
GLGlyphCachePage[] _pages;
|
||||||
|
GLGlyphCachePage _activePage;
|
||||||
|
int tdx;
|
||||||
|
int tdy;
|
||||||
|
void removePage(GLGlyphCachePage page) {
|
||||||
|
if (_activePage == page)
|
||||||
|
_activePage = null;
|
||||||
|
for (int i = 0; i < _pages.length; i++)
|
||||||
|
if (_pages[i] == page) {
|
||||||
|
_pages.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
destroy(page);
|
||||||
|
}
|
||||||
|
private void updateTextureSize() {
|
||||||
|
if (!tdx) {
|
||||||
|
// TODO
|
||||||
|
tdx = tdy = 1024; //getMaxTextureSize();
|
||||||
|
if (tdx > 1024)
|
||||||
|
tdx = tdy = 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this() {
|
||||||
|
}
|
||||||
|
~this() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
/// check if item is in cache
|
||||||
|
bool get(uint obj) {
|
||||||
|
if (obj in _map)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/// put new item to cache
|
||||||
|
void put(Glyph * glyph) {
|
||||||
|
updateTextureSize();
|
||||||
|
GLGlyphCacheItem res = null;
|
||||||
|
if (_activePage is null) {
|
||||||
|
_activePage = new GLGlyphCachePage(this, tdx, tdy);
|
||||||
|
_pages ~= _activePage;
|
||||||
|
}
|
||||||
|
res = _activePage.addItem(glyph);
|
||||||
|
if (!res) {
|
||||||
|
_activePage = new GLGlyphCachePage(this, tdx, tdy);
|
||||||
|
_pages ~= _activePage;
|
||||||
|
res = _activePage.addItem(glyph);
|
||||||
|
}
|
||||||
|
_map[glyph.id] = res;
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
for (int i = 0; i < _pages.length; i++) {
|
||||||
|
destroy(_pages[i]);
|
||||||
|
_pages[i] = null;
|
||||||
|
}
|
||||||
|
_pages.clear();
|
||||||
|
_map.clear();
|
||||||
|
}
|
||||||
|
/// draw cached item
|
||||||
|
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, Rect * clip) {
|
||||||
|
if (objectId in _map) {
|
||||||
|
GLGlyphCacheItem item = _map[objectId];
|
||||||
|
item.page.drawItem(item, dstrc, srcrc, color, clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// handle cached object deletion, mark as deleted
|
||||||
|
void onCachedObjectDeleted(uint objectId) {
|
||||||
|
if (objectId in _map) {
|
||||||
|
GLGlyphCacheItem item = _map[objectId];
|
||||||
|
if (hasActiveScene()) {
|
||||||
|
item._deleted = true;
|
||||||
|
} else {
|
||||||
|
int itemsLeft = item.page.deleteItem(item);
|
||||||
|
//CRLog::trace("itemsLeft = %d", itemsLeft);
|
||||||
|
if (itemsLeft <= 0) {
|
||||||
|
//CRLog::trace("removing page");
|
||||||
|
removePage(item.page);
|
||||||
|
}
|
||||||
|
_map.remove(objectId);
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// remove deleted items - remove page if contains only deleted items
|
||||||
|
void removeDeletedItems() {
|
||||||
|
uint[] list;
|
||||||
|
foreach (GLGlyphCacheItem item; _map) {
|
||||||
|
if (item._deleted)
|
||||||
|
list ~= item._objectId;
|
||||||
|
}
|
||||||
|
for (int i = 0 ; i < list.length; i++) {
|
||||||
|
onCachedObjectDeleted(list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -736,6 +748,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SolidRectSceneItem : SceneItem {
|
class SolidRectSceneItem : SceneItem {
|
||||||
Rect _rc;
|
Rect _rc;
|
||||||
uint _color;
|
uint _color;
|
||||||
|
|
Loading…
Reference in New Issue