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 top;
int right; int right;
int bottom; 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 width() { return right - left; }
@property int height() { return bottom - top; } @property int height() { return bottom - top; }
this(int x0, int y0, int x1, int y1) { 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 /// blend two RGB pixels using alpha
uint blendARGB(uint dst, uint src, uint alpha) { uint blendARGB(uint dst, uint src, uint alpha) {
uint dstalpha = dst >> 24;
if (dstalpha > 0x80)
return src;
uint srcr = (src >> 16) & 0xFF; uint srcr = (src >> 16) & 0xFF;
uint srcg = (src >> 8) & 0xFF; uint srcg = (src >> 8) & 0xFF;
uint srcb = (src >> 0) & 0xFF; uint srcb = (src >> 0) & 0xFF;

View File

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

View File

@ -13,6 +13,7 @@ import dlangui.platforms.common.platform;
import dlangui.platforms.windows.win32fonts; import dlangui.platforms.windows.win32fonts;
import dlangui.platforms.windows.win32drawbuf; import dlangui.platforms.windows.win32drawbuf;
import dlangui.graphics.drawbuf; import dlangui.graphics.drawbuf;
import dlangui.graphics.images;
import dlangui.graphics.fonts; import dlangui.graphics.fonts;
import dlangui.graphics.glsupport; import dlangui.graphics.glsupport;
import dlangui.core.logger; import dlangui.core.logger;
@ -131,7 +132,7 @@ class Win32Window : Window {
_caption = windowCaption; _caption = windowCaption;
_hwnd = CreateWindow(toUTF16z(WIN_CLASS_NAME), // window class name _hwnd = CreateWindow(toUTF16z(WIN_CLASS_NAME), // window class name
toUTF16z(windowCaption), // window caption toUTF16z(windowCaption), // window caption
WS_OVERLAPPEDWINDOW, // window style WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // window style
CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial x size
@ -226,6 +227,12 @@ class Win32Window : Window {
void onPaint() { void onPaint() {
Log.d("onPaint()"); Log.d("onPaint()");
if (useOpengl && _hGLRC) { 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.gl3;
import derelict.opengl3.wgl; import derelict.opengl3.wgl;
import dlangui.graphics.gldrawbuf; import dlangui.graphics.gldrawbuf;
@ -245,9 +252,22 @@ class Win32Window : Window {
buf.fillRect(Rect(100, 100, 200, 200), 0x704020); buf.fillRect(Rect(100, 100, 200, 200), 0x704020);
buf.fillRect(Rect(40, 70, 100, 120), 0x000000); buf.fillRect(Rect(40, 70, 100, 120), 0x000000);
buf.fillRect(Rect(80, 80, 150, 150), 0x80008000); // green 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(); buf.afterDrawing();
//Log.d("onPaint() end drawing opengl"); //Log.d("onPaint() end drawing opengl");
SwapBuffers(hdc); SwapBuffers(hdc);
wglMakeCurrent(hdc, null);
} else { } else {
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hdc = BeginPaint(_hwnd, &ps); HDC hdc = BeginPaint(_hwnd, &ps);
@ -268,14 +288,14 @@ class Win32Platform : Platform {
//MSG msg; //MSG msg;
WNDCLASS wndclass; WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = &WndProc; wndclass.lpfnWndProc = &WndProc;
wndclass.cbClsExtra = 0; wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0; wndclass.cbWndExtra = 0;
wndclass.hInstance = _hInstance; wndclass.hInstance = _hInstance;
wndclass.hIcon = LoadIcon(null, IDI_APPLICATION); wndclass.hIcon = LoadIcon(null, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(null, IDC_ARROW); 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.lpszMenuName = null;
wndclass.lpszClassName = toUTF16z(WIN_CLASS_NAME); wndclass.lpszClassName = toUTF16z(WIN_CLASS_NAME);