GL texture drawing is working

This commit is contained in:
Vadim Lopatin 2014-03-11 17:40:43 +04:00
parent 2dc0a9ff82
commit 69fd696458
6 changed files with 94 additions and 34 deletions

View File

@ -16,6 +16,14 @@ struct Rect {
int top;
int right;
int bottom;
@property int middlex() { return (left + right) / 2; }
@property int middley() { return (top + bottom) / 2; }
void offset(int dx, int dy) {
left += dx;
right += dx;
top += dy;
bottom += dy;
}
@property int width() { return right - left; }
@property int height() { return bottom - top; }
this(int x0, int y0, int x1, int y1) {

View File

@ -5,6 +5,9 @@ import dlangui.core.logger;
/// blend two RGB pixels using alpha
uint blendARGB(uint dst, uint src, uint alpha) {
uint dstalpha = dst >> 24;
if (dstalpha > 0x80)
return src;
uint srcr = (src >> 16) & 0xFF;
uint srcg = (src >> 8) & 0xFF;
uint srcb = (src >> 0) & 0xFF;

View File

@ -63,10 +63,20 @@ class GLDrawBuf : DrawBuf {
/// draw source buffer rectangle contents to destination buffer
override void drawFragment(int x, int y, DrawBuf src, Rect srcrect) {
assert(_scene !is null);
GLImageCacheItem item = glImageCache.get(src.id);
if (item is null)
item = glImageCache.set(src);
Rect dstrect = Rect(x, y, x + srcrect.width, y + srcrect.height);
// TODO: clipping
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
}
/// draw source buffer rectangle contents to destination buffer rectangle applying rescaling
override void drawRescaled(Rect dstrect, DrawBuf src, Rect srcrect) {
assert(_scene !is null);
GLImageCacheItem item = glImageCache.get(src.id);
if (item is null)
item = glImageCache.set(src);
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, 0xFFFFFF, 0, null, 0));
}
override void clear() {
}
@ -80,10 +90,7 @@ public:
@property GLImageCachePage page() { return _page; }
uint _objectId;
// image size
int _dx;
int _dy;
int _x0;
int _y0;
Rect _rc;
bool _deleted;
this(GLImageCachePage page, uint objectId) { _page = page; _objectId = objectId; }
};
@ -197,10 +204,10 @@ public:
_map.clear();
}
/// draw cached item
void drawItem(uint objectId, int x, int y, int dx, int dy, int srcx, int srcy, int srcwidth, int srcheight, uint color, int options, Rect * clip, int rotationAngle) {
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, x, y, dx, dy, srcx, srcy, srcwidth, srcheight, color, options, clip, rotationAngle);
item.page.drawItem(item, dstrc, srcrc, color, options, clip, rotationAngle);
}
}
/// handle cached object deletion, mark as deleted
@ -314,13 +321,10 @@ public:
}
}
void invertAlpha(GLImageCacheItem item) {
int x0 = item._x0;
int y0 = item._y0;
int x1 = x0 + item._dx;
int y1 = y0 + item._dy;
for (int y = y0; y < y1; y++) {
Rect rc = item._rc;
for (int y = rc.top; y < rc.bottom; y++) {
uint * row = _drawbuf.scanLine(y);
for (int x = x0; x < x1; x++) {
for (int x = rc.left; x < rc.right; x++) {
uint cl = row[x];
cl ^= 0xFF000000;
uint r = (cl & 0x00FF0000) >> 16;
@ -335,30 +339,27 @@ public:
return null;
// next line if necessary
if (_x + width > _tdx) {
if (_x + width + 2 > _tdx) {
// move to next line
_currentLine = _nextLine;
_x = 0;
}
// check if no room left for glyph height
if (_currentLine + height > _tdy) {
if (_currentLine + height + 2 > _tdy) {
_closed = true;
return null;
}
cacheItem._dx = width;
cacheItem._dy = height;
cacheItem._x0 = _x;
cacheItem._y0 = _currentLine;
cacheItem._rc = Rect(_x + 1, _currentLine + 1, _x + width + 1, _currentLine + height + 1);
if (height && width) {
if (_nextLine < _currentLine + height)
_nextLine = _currentLine + height;
if (_nextLine < _currentLine + height + 2)
_nextLine = _currentLine + height + 2;
if (!_drawbuf) {
_drawbuf = new ColorDrawBuf(_tdx, _tdy);
//_drawbuf.SetBackgroundColor(0x000000);
//_drawbuf.SetTextColor(0xFFFFFF);
_drawbuf.fill(0xFF000000);
}
_x += width;
_x += width + 1;
_needUpdateTexture = true;
}
_itemCount++;
@ -373,12 +374,12 @@ public:
if (cacheItem is null)
return null;
buf.onDestroyCallback = &onObjectDestroyedCallback;
_drawbuf.drawImage(cacheItem._x0, cacheItem._y0, buf);
_drawbuf.drawImage(cacheItem._rc.left, cacheItem._rc.top, buf);
invertAlpha(cacheItem);
_needUpdateTexture = true;
return cacheItem;
}
void drawItem(GLImageCacheItem item, int x, int y, int dx, int dy, int srcx, int srcy, int srcdx, int srcdy, uint color, uint options, Rect * clip, int rotationAngle) {
void drawItem(GLImageCacheItem item, Rect dstrc, Rect srcrc, uint color, uint options, Rect * clip, int rotationAngle) {
//CRLog::trace("drawing item at %d,%d %dx%d <= %d,%d %dx%d ", x, y, dx, dy, srcx, srcy, srcdx, srcdy);
if (_needUpdateTexture)
updateTexture();
@ -388,15 +389,14 @@ public:
return;
}
//rotationAngle = 0;
int rx = x + dx / 2;
int ry = (y + dy / 2);
int rx = dstrc.middlex;
int ry = dstrc.middley;
if (rotationAngle) {
//rotationAngle = 0;
//setRotation(rx, ry, rotationAngle);
}
Rect srcrc = Rect(item._x0 + srcx, item._y0 + srcy, item._x0 + srcx+srcdx, item._y0 + srcy+srcdy);
Rect dstrc = Rect(x, y, x + dx, y+dy);
// convert coordinates to cached texture
srcrc.offset(item._rc.left, item._rc.top);
if (clip) {
int srcw = srcrc.width();
int srch = srcrc.height();
@ -416,7 +416,7 @@ public:
dstrc.bottom -= clip.bottom;
}
if (!dstrc.empty)
drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); //srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()
//drawColorAndTextureRect(vertices, texcoords, color, _textureId);
if (rotationAngle) {
@ -437,3 +437,31 @@ public:
};
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() {
}
};

View File

@ -59,7 +59,7 @@ void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint colo
x1,y1,Z_2D,
x1,y0,Z_2D];
if (_solidFillProgram !is null) {
Log.d("solid fill: vertices ", vertices, " colors ", colors);
//Log.d("solid fill: vertices ", vertices, " colors ", colors);
_solidFillProgram.execute(vertices, colors);
} else
Log.e("No program");
@ -67,6 +67,7 @@ void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint colo
}
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);
}

View File

@ -82,7 +82,7 @@ __gshared DrawableCache _drawableCache;
/// drawable cache singleton
@property DrawableCache drawableCache() { return _drawableCache; }
static this() {
shared static this() {
_imageCache = new ImageCache();
_drawableCache = new DrawableCache();
}

View File

@ -13,6 +13,7 @@ import dlangui.platforms.common.platform;
import dlangui.platforms.windows.win32fonts;
import dlangui.platforms.windows.win32drawbuf;
import dlangui.graphics.drawbuf;
import dlangui.graphics.images;
import dlangui.graphics.fonts;
import dlangui.graphics.glsupport;
import dlangui.core.logger;
@ -131,7 +132,7 @@ class Win32Window : Window {
_caption = windowCaption;
_hwnd = CreateWindow(toUTF16z(WIN_CLASS_NAME), // window class name
toUTF16z(windowCaption), // window caption
WS_OVERLAPPEDWINDOW, // window style
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
@ -226,6 +227,12 @@ class Win32Window : Window {
void onPaint() {
Log.d("onPaint()");
if (useOpengl && _hGLRC) {
// hack to stop infinite WM_PAINT loop
PAINTSTRUCT ps;
HDC hdc2 = BeginPaint(_hwnd, &ps);
EndPaint(_hwnd, &ps);
import derelict.opengl3.gl3;
import derelict.opengl3.wgl;
import dlangui.graphics.gldrawbuf;
@ -245,9 +252,22 @@ class Win32Window : Window {
buf.fillRect(Rect(100, 100, 200, 200), 0x704020);
buf.fillRect(Rect(40, 70, 100, 120), 0x000000);
buf.fillRect(Rect(80, 80, 150, 150), 0x80008000); // green
DrawableRef img = drawableCache.get("exit");
if (!img.isNull) {
img.drawTo(buf, Rect(300, 100, 364, 164));
img.drawTo(buf, Rect(400, 200, 528, 328));
}
DrawableRef img2 = drawableCache.get("btn_default_pressed");
if (!img2.isNull) {
img2.drawTo(buf, Rect(300, 200, 564, 264));
img2.drawTo(buf, Rect(600, 200, 628, 328));
}
drawableCache.get("btn_default_normal").drawTo(buf, Rect(300, 0, 400, 50));;
drawableCache.get("btn_default_selected").drawTo(buf, Rect(0, 0, 100, 50));;
buf.afterDrawing();
//Log.d("onPaint() end drawing opengl");
SwapBuffers(hdc);
wglMakeCurrent(hdc, null);
} else {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(_hwnd, &ps);
@ -268,14 +288,14 @@ class Win32Platform : Platform {
//MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = &WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = _hInstance;
wndclass.hIcon = LoadIcon(null, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(null, IDC_ARROW);
wndclass.hbrBackground = cast(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hbrBackground = null; //cast(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = null;
wndclass.lpszClassName = toUTF16z(WIN_CLASS_NAME);