ultimatepp/uppdev/MDraw/main.cpp
cxl 351994a6cc Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

437 lines
9.5 KiB
C++

#include "MDraw.h"
#include <emmintrin.h>
void DrawR(PixelBlock& w, int x, int y, Color c)
{}
static const byte n_o[] = {
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
};
void DrawO(PixelBlock& w, int x, int y, Color c)
{
const byte *s = n_o;
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
dword ic = c;
for(int w = 0; w < 11; w++) {
for(int q = 0; q < 6; q++) {
if(*s)
a[q] = ic;
s++;
}
a += d;
}
}
String of_packed;
void DrawOF(PixelBlock& w, int x, int y, Color c)
{
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
dword ic = c;
const byte *s = of_packed;
dword *t = a;
for(;;) {
byte c = *s++;
if(c == 0)
break;
t += (c >> 3) & 15;
switch(c & 7) {
case 7:
t[7] = ic;
case 6:
t[6] = ic;
case 5:
t[5] = ic;
case 4:
t[4] = ic;
case 3:
t[3] = ic;
case 2:
t[2] = ic;
case 1:
t[1] = ic;
}
t += c & 7;
if(c & 0x80) {
a += d;
t = a;
}
}
}
void PackOF() {
StringBuffer pk;
for(int w = 0; w < 11; w++) {
int n = 0;
const byte *ln = n_o + w * 6;
bool wasnot = true;
for(int q = 0; q < 6; q++)
if(ln[q]) {
int m = 0;
while(q < 6 && ln[q]) {
m++;
q++;
}
while(n > 15) {
pk.Cat((15 << 3));
n -= 15;
}
if(m > 7) {
pk.Cat((n << 3) | 7);
m -= 7;
while(m > 7) {
pk.Cat(7);
m -= 7;
}
if(m)
pk.Cat(m);
}
else
pk.Cat((n << 3) | m);
n = 1;
wasnot = false;
}
else
n++;
if(wasnot)
pk.Cat(0x80);
else
*(pk.End() - 1) |= 0x80;
}
pk.Cat(0);
of_packed = pk;
}
int BlendColor1(int a, int c, int cc)
{
return (byte)((((a + (a >> 7)) * (c - cc)) >> 8) + cc);
}
#define BLEND(i, d) \
{ \
const int alpha = d + (d >> 7); \
byte *m = (byte *)&a[i]; \
m[0] += (alpha * (tr - m[0]) >> 8); \
m[1] += (alpha * (tg - m[1]) >> 8); \
m[2] += (alpha * (tb - m[2]) >> 8); \
}
#define SET(i) a[i] = ic
void DrawF(PixelBlock& w, int x, int y, Color c)
{
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
byte tr = c.GetR();
byte tg = c.GetG();
byte tb = c.GetB();
dword ic = c;
BLEND(1, 0x80); SET(2); SET(3); BLEND(4, 0x80); a += d;
SET(1); BLEND(2, 0x10); BLEND(3, 0x10); SET(4); a += d;
BLEND(0, 0x80); BLEND(1, 0x80); BLEND(4, 0x80); BLEND(5, 0x80); a += d;
BLEND(0, 0xb0); BLEND(1, 0x70); BLEND(4, 0x70); BLEND(5, 0xb0); a += d;
// BLEND(0, 0xe0); BLEND(1, 0x30); BLEND(4, 0x30); BLEND(5, 0xe0); a += d;
SET(0); SET(5); a += d;
SET(0); SET(5); a += d;
SET(0); SET(5); a += d;
// BLEND(0, 0xe0); BLEND(1, 0x30); BLEND(4, 0x30); BLEND(5, 0xe0); a += d;
BLEND(0, 0xb0); BLEND(1, 0x70); BLEND(4, 0x70); BLEND(5, 0xb0); a += d;
BLEND(0, 0x80); BLEND(1, 0x80); BLEND(4, 0x80); BLEND(5, 0x80); a += d;
SET(1); BLEND(2, 0x10); BLEND(3, 0x10); SET(4); a += d;
BLEND(1, 0x80); SET(2); SET(3); BLEND(4, 0x80); a += d;
}
static const byte o[] = {
// 0 1 2 3 4 5
0x00, 0x80, 0xff, 0xff, 0x80, 0x00,
0x00, 0xff, 0x10, 0x10, 0xff, 0x00,
0x80, 0x80, 0x00, 0x00, 0xff, 0x80,
0xb0, 0x70, 0x00, 0x00, 0x70, 0xb0,
0xe0, 0x30, 0x00, 0x00, 0x30, 0xe0,
0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
0xe0, 0x30, 0x00, 0x00, 0x30, 0xe0,
0xb0, 0x70, 0x00, 0x00, 0x70, 0xb0,
0x80, 0x80, 0x00, 0x00, 0xff, 0x80,
0x00, 0xff, 0x10, 0x10, 0xff, 0x00,
0x00, 0x80, 0xff, 0xff, 0x80, 0x00,
};
void DrawO1(PixelBlock& w, int x, int y, Color c)
{
const byte *s = o;
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
byte tr = c.GetR();
byte tg = c.GetG();
byte tb = c.GetB();
for(int w = 0; w < 11; w++) {
for(int q = 0; q < 6; q++) {
int alpha = *s + (*s >> 7);
dword cc = a[q];
byte r = (byte)(cc >> 16);
byte g = (byte)(cc >> 8);
byte b = (byte)(cc);
r = (alpha * (tr - r) >> 8) + r;
g = (alpha * (tg - g) >> 8) + g;
b = (alpha * (tb - b) >> 8) + b;
a[q] = (byte(r) << 16) | (byte(g) << 8) | byte(b);
s++;
}
a += d;
}
}
void DrawO2(PixelBlock& w, int x, int y, Color c)
{
const byte *s = o;
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
byte tr = c.GetR();
byte tg = c.GetG();
byte tb = c.GetB();
for(int w = 0; w < 11; w++) {
for(int q = 0; q < 6; q++) {
int alpha = *s + (*s >> 7);
s++;
byte *m = (byte *)&a[q];
m[0] += (alpha * (tr - m[0]) >> 8);
m[1] += (alpha * (tg - m[1]) >> 8);
m[2] += (alpha * (tb - m[2]) >> 8);
}
a += d;
}
}
String op;
String PackOP(const byte *s, int cx, int cy)
{
StringBuffer result;
for(int i = 0; i < cy; i++) {
int j = 0;
while(j < cx) {
if(*s == 0) {
int n = 0;
while(*s == 0 && j < cx) {
n++;
j++;
s++;
}
while(n >= 255) {
result.Cat(0);
result.Cat(254);
n -= 254;
}
result.Cat(0);
result.Cat(n);
}
else {
result.Cat(*s++);
j++;
}
}
result.Cat(0);
result.Cat(0);
}
result.Cat(0);
result.Cat(255);
return result;
}
void DrawOP(PixelBlock& w, int x, int y, Color c)
{
const byte *s = op;
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
byte tr = c.GetR();
byte tg = c.GetG();
byte tb = c.GetB();
int q = 0;
for(;;) {
byte c = *s++;
if(c) {
byte *m = (byte *)&a[q];
int alpha = c + (c >> 7);
m[0] += alpha * (tr - m[0]) >> 8;
m[1] += alpha * (tg - m[1]) >> 8;
m[2] += alpha * (tb - m[2]) >> 8;
q++;
}
else {
c = *s++;
if(c)
q += c;
else {
if(s[0] == 0 && s[1] == 255)
return;
a += d;
q = 0;
}
}
}
a += d;
}
void DrawOPMMX(PixelBlock& w, int x, int y, Color color)
{
const byte *s = op;
dword *a = w.PointAdr(x, y);
int d = w.LineDelta();
byte tr = color.GetR();
byte tg = color.GetG();
byte tb = color.GetB();
int q = 0;
__m64 zero = _mm_setzero_si64();
__m64 mc = _mm_unpacklo_pi8(_mm_cvtsi32_si64(color.GetRaw()), zero);
__m64 mask = _mm_set1_pi16(0xff);
for(;;) {
byte c = *s++;
if(c) {
__m64 alpha = _mm_cvtsi32_si64(c);
alpha = _mm_unpacklo_pi16(alpha, alpha);
alpha = _mm_unpacklo_pi32(alpha, alpha);
__m64 h = _mm_srli_pi16(alpha, 7);
alpha = _mm_adds_pi16(alpha, h);
__m64 m = _mm_cvtsi32_si64(a[q]);
m = _mm_unpacklo_pi8(m, zero);
h = _mm_sub_pi16(mc, m);
h = _mm_mullo_pi16(alpha, h);
h = _mm_srli_pi16(h, 8);
m = _mm_add_pi16(m, h);
m = _mm_and_si64(m, mask);
m = _mm_packs_pu16(m, m);
a[q++] = _mm_cvtsi64_si32(m);
}
else {
c = *s++;
if(c)
q += c;
else {
if(s[0] == 0 && s[1] == 255)
break;
a += d;
q = 0;
}
}
}
_m_empty();
}
#define N 300
void DoTest(Draw& w, const char *name, void (*od)(PixelBlock&, int, int, Color))
{
for(int section = 0; section < 2; section++) {
String ss = section ? "SECTION " : "SETDIB ";
{
TimeStop tm;
PixelBlock b(1024, 768, section);
for(int i = 0; i < N; i++) {
if(od) {
b.DrawRect(0, 0, 512, 768, White);
b.DrawRect(512, 0, 512, 768, Red);
for(int x = 0; x < 1024 / 8 - 1; x++)
for(int y = 0; y < 768 / 16 - 1; y++)
(*od)(b, 8 * x, 16 * y, x < 512 / 8 ? Black : White);
}
b.Put(w, 0, 0);
Draw::Flush();
}
RLOG(ss << name << ": " << tm.Elapsed() / N << " ms");
}
{
TimeStop tm;
PixelBlock b(1024, 768, section);
for(int i = 0; i < N; i++) {
if(od) {
for(int y = 0; y < 768 / 16 - 1; y++) {
b.DrawRect(0, 16 * y, 1024, 16, Color(y & 255, y & 255, y & 255));
for(int x = 0; x < 1024 / 8 - 1; x++)
(*od)(b, 8 * x, 16 * y, x < 512 / 8 ? Black : White);
}
}
b.Put(w, 0, 0);
Draw::Flush();
}
RLOG(ss << name << " cached: " << tm.Elapsed() / N << " ms");
}
}
}
void MDraw::Paint(Draw& w)
{
Size sz = GetSize();
/*
{
TimeStop tm;
for(int i = 0; i < 1000; i++)
w.DrawRect(0, 0, 1024, 768, Color(i, i, i));
Draw::Flush();
RLOG("Painting using GDI: " << tm);
}
{
TimeStop tm;
for(int i = 0; i < 1000; i++) {
PixelBlock b(1024, 768, true);
b.DrawRect(0, 0, sz.cx, sz.cy, Color(i, i, i));
b.Put(w, 0, 0);
}
Draw::Flush();
RLOG("Painting using Section: " << tm);
}
*/
/* {
FontInfo fi = w.GetFontInfo(Arial(15));
String text = String('0', 1024 / fi['0']);
TimeStop tm;
for(int i = 0; i < N; i++) {
w.DrawRect(0, 0, 1024, 768, White);
for(int y = 0; y < 768; y += fi.GetHeight())
w.DrawText(0, y, text, Arial(15), Color(i, i, i));
Draw::Flush();
}
RLOG("GDI: " << tm.Elapsed() / N << " ms");
}
*/
DoTest(w, "R - Just PUT", NULL);
DoTest(w, "R - Just rect", DrawR);
DoTest(w, "01 - no antialiasing", DrawO);
DoTest(w, "0F - no antialiasing packed", DrawOF);
DoTest(w, "01 - shifts", DrawO1);
DoTest(w, "02 - loads", DrawO2);
DoTest(w, "F - fast", DrawF);
DoTest(w, "0P - packed", DrawOP);
DoTest(w, "0P - packed MMX", DrawOPMMX);
w.DrawRect(0, 0, 100, 100, SBlue);
}
GUI_APP_MAIN
{
PackOF();
DUMP(of_packed.GetLength());
op = PackOP(o, 6, 11);
LOGHEXDUMP(op, op.GetLength());
RDUMP(op.GetLength());
Ctrl::AutoBackPaintAreaSize = 0;
MDraw t;
t.SetRect(0, 0, 1024, 768);
t.Sizeable().Zoomable();
t.Run();
}