This commit is contained in:
Vadim Lopatin 2014-03-14 17:35:53 +04:00
parent 05d1ec598a
commit bf57f2f26f
4 changed files with 437 additions and 397 deletions

369
3rdparty/X11/xcb/image.d vendored Normal file
View File

@ -0,0 +1,369 @@
// Manually created
module std.c.linux.X11.xcb.image;
import std.c.linux.X11.xcb.xcb;
import std.c.linux.X11.xcb.shm;
import std.c.linux.X11.xcb.xproto;
import std.c.stdlib;
import std.conv;
struct xcb_image_t
{
ushort width;
ushort height;
xcb_image_format_t format;
ubyte scanline_pad;
ubyte depth;
ubyte bpp;
ubyte unit;
uint plane_mask;
xcb_image_order_t byte_order;
xcb_image_order_t bit_order;
uint stride;
uint size;
void * base;
ubyte * data;
}
xcb_format_t *
find_format_by_depth (xcb_setup_t *setup, ubyte depth)
{
xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
for(; fmt != fmtend; ++fmt)
if(fmt.depth == depth)
return fmt;
return null;
}
xcb_image_format_t
effective_format(xcb_image_format_t format, ubyte bpp)
{
if (format == XCB_IMAGE_FORMAT_Z_PIXMAP && bpp != 1)
return format;
return XCB_IMAGE_FORMAT_XY_PIXMAP;
}
int
format_valid (ubyte depth, ubyte bpp, ubyte unit,
xcb_image_format_t format, ubyte xpad)
{
xcb_image_format_t ef = effective_format(format, bpp);
if (depth > bpp)
return 0;
switch(ef) {
case XCB_IMAGE_FORMAT_XY_PIXMAP:
switch(unit) {
case 8:
case 16:
case 32:
break;
default:
return 0;
}
if (xpad < bpp)
return 0;
switch (xpad) {
case 8:
case 16:
case 32:
break;
default:
return 0;
}
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
switch (bpp) {
case 4:
if (unit != 8)
return 0;
break;
case 8:
case 16:
case 24:
case 32:
if (unit != bpp)
return 0;
break;
default:
return 0;
}
break;
default:
return 0;
}
return 1;
}
int
image_format_valid (xcb_image_t *image) {
return format_valid(image.depth,
image.bpp,
image.unit,
image.format,
image.scanline_pad);
}
uint xcb_roundup(uint base,
uint pad
)
{
uint b = base + pad - 1;
/* faster if pad is a power of two */
if (((pad - 1) & pad) == 0)
return b & -pad;
return b - b % pad;
}
void
xcb_image_annotate (xcb_image_t *image)
{
xcb_image_format_t ef = effective_format(image.format, image.bpp);
switch (ef) {
case XCB_IMAGE_FORMAT_XY_PIXMAP:
image.stride = xcb_roundup(image.width, image.scanline_pad) >> 3;
image.size = image.height * image.stride * image.depth;
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
image.stride = xcb_roundup(cast(uint)image.width *
cast(uint)image.bpp,
image.scanline_pad) >> 3;
image.size = image.height * image.stride;
break;
default:
assert(0);
}
}
xcb_image_t *
xcb_image_create_native (xcb_connection_t * c,
ushort width,
ushort height,
xcb_image_format_t format,
ubyte depth,
void * base,
uint bytes,
ubyte * data)
{
xcb_setup_t * setup = xcb_get_setup(c);
xcb_format_t * fmt;
xcb_image_format_t ef = format;
if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP && depth == 1)
ef = XCB_IMAGE_FORMAT_XY_PIXMAP;
switch (ef) {
case XCB_IMAGE_FORMAT_XY_BITMAP:
if (depth != 1)
return null;
/* fall through */
case XCB_IMAGE_FORMAT_XY_PIXMAP:
if (depth > 1) {
fmt = find_format_by_depth(setup, depth);
if (!fmt)
return null;
}
return xcb_image_create(width, height, format,
setup.bitmap_format_scanline_pad,
depth, depth, setup.bitmap_format_scanline_unit,
setup.image_byte_order,
setup.bitmap_format_bit_order,
base, bytes, data);
case XCB_IMAGE_FORMAT_Z_PIXMAP:
fmt = find_format_by_depth(setup, depth);
if (!fmt)
return null;
return xcb_image_create(width, height, format,
fmt.scanline_pad,
fmt.depth, fmt.bits_per_pixel, 0,
setup.image_byte_order,
XCB_IMAGE_ORDER_MSB_FIRST,
base, bytes, data);
default:
assert(0);
}
assert(0);
}
uint xcb_mask(uint n)
{
return n == 32 ? ~0 : (1 << n) - 1;
}
xcb_image_t *
xcb_image_create (ushort width,
ushort height,
xcb_image_format_t format,
ubyte xpad,
ubyte depth,
ubyte bpp,
ubyte unit,
xcb_image_order_t byte_order,
xcb_image_order_t bit_order,
void * base,
uint bytes,
ubyte * data)
{
xcb_image_t * image;
if (unit == 0) {
switch (format) {
case XCB_IMAGE_FORMAT_XY_BITMAP:
case XCB_IMAGE_FORMAT_XY_PIXMAP:
unit = 32;
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
if (bpp == 1) {
unit = 32;
break;
}
if (bpp < 8) {
unit = 8;
break;
}
unit = bpp;
break;
default:
break;
}
}
if (!format_valid(depth, bpp, unit, format, xpad))
return null;
import std.c.stdlib;
image = cast(xcb_image_t*)malloc(xcb_image_t.sizeof);
if (image is null)
return null;
image.width = width;
image.height = height;
image.format = format;
image.scanline_pad = xpad;
image.depth = depth;
image.bpp = bpp;
image.unit = unit;
image.plane_mask = xcb_mask(depth);
image.byte_order = byte_order;
image.bit_order = bit_order;
xcb_image_annotate(image);
/*
* Ways this function can be called:
* * with data: we fail if bytes isn't
* large enough, else leave well enough alone.
* * with base and !data: if bytes is zero, we
* default; otherwise we fail if bytes isn't
* large enough, else fill in data
* * with !base and !data: we malloc storage
* for the data, save that address as the base,
* and fail if malloc does.
*
* When successful, we establish the invariant that data
* points at sufficient storage that may have been
* supplied, and base is set iff it should be
* auto-freed when the image is destroyed.
*
* Except as a special case when base = 0 && data == 0 &&
* bytes == ~0 we just return the image structure and let
* the caller deal with getting the allocation right.
*/
if (!base && !data && bytes == ~0) {
image.base = null;
image.data = null;
return image;
}
if (!base && data && bytes == 0)
bytes = image.size;
image.base = base;
image.data = data;
if (!image.data) {
if (image.base) {
image.data = cast(ubyte*)image.base;
} else {
bytes = image.size;
image.base = malloc(bytes);
image.data = cast(ubyte*)image.base;
}
}
if (!image.data || bytes < image.size) {
free(image);
return null;
}
return image;
}
void
xcb_image_destroy (xcb_image_t *image)
{
if (image.base)
free (image.base);
free (image);
}
ubyte
xcb_aux_get_depth(xcb_connection_t *c,
xcb_screen_t *screen)
{
xcb_drawable_t drawable;
xcb_get_geometry_reply_t *geom;
ubyte depth;
drawable = screen.root;
geom = xcb_get_geometry_reply (c, xcb_get_geometry(c, drawable), null);
if (!geom) {
//Log.e("GetGeometry(root) failed");
exit (0);
}
depth = geom.depth;
free (geom);
return depth;
}
extern (C) int xcb_image_shm_get(xcb_connection_t * conn,
xcb_drawable_t draw,
xcb_image_t * image,
xcb_shm_segment_info_t shminfo,
ushort x,
ushort y,
uint plane_mask);
const XCB_ALL_PLANES = ~0;
extern (C) xcb_image_t *
xcb_image_shm_put (xcb_connection_t * conn,
xcb_drawable_t draw,
xcb_gcontext_t gc,
xcb_image_t * image,
xcb_shm_segment_info_t shminfo,
short src_x,
short src_y,
short dest_x,
short dest_y,
ushort src_width,
ushort src_height,
ubyte send_event);
/**
* @struct xcb_shm_segment_info_t
* A structure that stores the informations needed by the MIT Shm
* Extension.
*/
struct xcb_shm_segment_info_t
{
xcb_shm_seg_t shmseg;
uint shmid;
ubyte *shmaddr;
}
alias int key_t;
extern (C) int shmget(key_t key, size_t size, int shmflg);
extern (C) int getpagesize();
extern (C) ubyte *shmat(int shmid, ubyte *shmaddr, int shmflg);
extern (C) int shmctl(int shmid, int cmd, void *buf);
const IPC_CREAT = octal!1000;
const IPC_PRIVATE = (cast(key_t) 0);
const IPC_RMID = 0;

View File

@ -160,6 +160,7 @@
<Compile Include="3rdparty\X11\xcb\xv.d" />
<Compile Include="3rdparty\X11\xcb\xvmc.d" />
<Compile Include="3rdparty\X11\keysymdef.d" />
<Compile Include="3rdparty\X11\xcb\image.d" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\dlangui\platforms\x11\" />

View File

@ -9,6 +9,7 @@ version (linux) {
pragma(lib, "xcb-shm");
pragma(lib, "xcb-image");
pragma(lib, "X11");
pragma(lib, "dl");
}
/// workaround for link issue when WinMain is located in library
@ -27,7 +28,11 @@ version(Windows) {
/// entry point for dlangui based application
extern (C) int UIAppMain(string[] args) {
// setup resource dir
string resourceDir = exePath() ~ "..\\res\\";
version (Windows) {
string resourceDir = exePath() ~ "..\\res\\";
} else {
string resourceDir = exePath() ~ "../../res/";
}
string[] imageDirs = [
resourceDir
];

View File

@ -6,6 +6,7 @@ import std.string;
import std.c.linux.X11.xcb.xcb;
import std.c.linux.X11.xcb.shm;
import std.c.linux.X11.xcb.xproto;
import std.c.linux.X11.xcb.image;
import std.c.linux.X11.keysymdef;
import std.c.linux.linux;
import std.c.stdlib;
@ -13,367 +14,9 @@ import std.conv;
import dlangui.core.logger;
import dlangui.graphics.drawbuf;
import dlangui.graphics.fonts;
import dlangui.graphics.ftfonts;
import dlangui.platforms.common.platform;
struct xcb_image_t
{
ushort width;
ushort height;
xcb_image_format_t format;
ubyte scanline_pad;
ubyte depth;
ubyte bpp;
ubyte unit;
uint plane_mask;
xcb_image_order_t byte_order;
xcb_image_order_t bit_order;
uint stride;
uint size;
void * base;
ubyte * data;
}
xcb_format_t *
find_format_by_depth (xcb_setup_t *setup, ubyte depth)
{
xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
for(; fmt != fmtend; ++fmt)
if(fmt.depth == depth)
return fmt;
return null;
}
xcb_image_format_t
effective_format(xcb_image_format_t format, ubyte bpp)
{
if (format == XCB_IMAGE_FORMAT_Z_PIXMAP && bpp != 1)
return format;
return XCB_IMAGE_FORMAT_XY_PIXMAP;
}
int
format_valid (ubyte depth, ubyte bpp, ubyte unit,
xcb_image_format_t format, ubyte xpad)
{
xcb_image_format_t ef = effective_format(format, bpp);
if (depth > bpp)
return 0;
switch(ef) {
case XCB_IMAGE_FORMAT_XY_PIXMAP:
switch(unit) {
case 8:
case 16:
case 32:
break;
default:
return 0;
}
if (xpad < bpp)
return 0;
switch (xpad) {
case 8:
case 16:
case 32:
break;
default:
return 0;
}
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
switch (bpp) {
case 4:
if (unit != 8)
return 0;
break;
case 8:
case 16:
case 24:
case 32:
if (unit != bpp)
return 0;
break;
default:
return 0;
}
break;
default:
return 0;
}
return 1;
}
int
image_format_valid (xcb_image_t *image) {
return format_valid(image.depth,
image.bpp,
image.unit,
image.format,
image.scanline_pad);
}
uint xcb_roundup(uint base,
uint pad
)
{
uint b = base + pad - 1;
/* faster if pad is a power of two */
if (((pad - 1) & pad) == 0)
return b & -pad;
return b - b % pad;
}
void
xcb_image_annotate (xcb_image_t *image)
{
xcb_image_format_t ef = effective_format(image.format, image.bpp);
switch (ef) {
case XCB_IMAGE_FORMAT_XY_PIXMAP:
image.stride = xcb_roundup(image.width, image.scanline_pad) >> 3;
image.size = image.height * image.stride * image.depth;
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
image.stride = xcb_roundup(cast(uint)image.width *
cast(uint)image.bpp,
image.scanline_pad) >> 3;
image.size = image.height * image.stride;
break;
default:
assert(0);
}
}
xcb_image_t *
xcb_image_create_native (xcb_connection_t * c,
ushort width,
ushort height,
xcb_image_format_t format,
ubyte depth,
void * base,
uint bytes,
ubyte * data)
{
xcb_setup_t * setup = xcb_get_setup(c);
xcb_format_t * fmt;
xcb_image_format_t ef = format;
if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP && depth == 1)
ef = XCB_IMAGE_FORMAT_XY_PIXMAP;
switch (ef) {
case XCB_IMAGE_FORMAT_XY_BITMAP:
if (depth != 1)
return null;
/* fall through */
case XCB_IMAGE_FORMAT_XY_PIXMAP:
if (depth > 1) {
fmt = find_format_by_depth(setup, depth);
if (!fmt)
return null;
}
return xcb_image_create(width, height, format,
setup.bitmap_format_scanline_pad,
depth, depth, setup.bitmap_format_scanline_unit,
setup.image_byte_order,
setup.bitmap_format_bit_order,
base, bytes, data);
case XCB_IMAGE_FORMAT_Z_PIXMAP:
fmt = find_format_by_depth(setup, depth);
if (!fmt)
return null;
return xcb_image_create(width, height, format,
fmt.scanline_pad,
fmt.depth, fmt.bits_per_pixel, 0,
setup.image_byte_order,
XCB_IMAGE_ORDER_MSB_FIRST,
base, bytes, data);
default:
assert(0);
}
assert(0);
}
uint xcb_mask(uint n)
{
return n == 32 ? ~0 : (1 << n) - 1;
}
xcb_image_t *
xcb_image_create (ushort width,
ushort height,
xcb_image_format_t format,
ubyte xpad,
ubyte depth,
ubyte bpp,
ubyte unit,
xcb_image_order_t byte_order,
xcb_image_order_t bit_order,
void * base,
uint bytes,
ubyte * data)
{
xcb_image_t * image;
if (unit == 0) {
switch (format) {
case XCB_IMAGE_FORMAT_XY_BITMAP:
case XCB_IMAGE_FORMAT_XY_PIXMAP:
unit = 32;
break;
case XCB_IMAGE_FORMAT_Z_PIXMAP:
if (bpp == 1) {
unit = 32;
break;
}
if (bpp < 8) {
unit = 8;
break;
}
unit = bpp;
break;
default:
break;
}
}
if (!format_valid(depth, bpp, unit, format, xpad))
return null;
import std.c.stdlib;
image = cast(xcb_image_t*)malloc(xcb_image_t.sizeof);
if (image is null)
return null;
image.width = width;
image.height = height;
image.format = format;
image.scanline_pad = xpad;
image.depth = depth;
image.bpp = bpp;
image.unit = unit;
image.plane_mask = xcb_mask(depth);
image.byte_order = byte_order;
image.bit_order = bit_order;
xcb_image_annotate(image);
/*
* Ways this function can be called:
* * with data: we fail if bytes isn't
* large enough, else leave well enough alone.
* * with base and !data: if bytes is zero, we
* default; otherwise we fail if bytes isn't
* large enough, else fill in data
* * with !base and !data: we malloc storage
* for the data, save that address as the base,
* and fail if malloc does.
*
* When successful, we establish the invariant that data
* points at sufficient storage that may have been
* supplied, and base is set iff it should be
* auto-freed when the image is destroyed.
*
* Except as a special case when base = 0 && data == 0 &&
* bytes == ~0 we just return the image structure and let
* the caller deal with getting the allocation right.
*/
if (!base && !data && bytes == ~0) {
image.base = null;
image.data = null;
return image;
}
if (!base && data && bytes == 0)
bytes = image.size;
image.base = base;
image.data = data;
if (!image.data) {
if (image.base) {
image.data = cast(ubyte*)image.base;
} else {
bytes = image.size;
image.base = malloc(bytes);
image.data = cast(ubyte*)image.base;
}
}
if (!image.data || bytes < image.size) {
free(image);
return null;
}
return image;
}
void
xcb_image_destroy (xcb_image_t *image)
{
if (image.base)
free (image.base);
free (image);
}
ubyte
xcb_aux_get_depth(xcb_connection_t *c,
xcb_screen_t *screen)
{
xcb_drawable_t drawable;
xcb_get_geometry_reply_t *geom;
ubyte depth;
drawable = screen.root;
geom = xcb_get_geometry_reply (c, xcb_get_geometry(c, drawable), null);
if (!geom) {
Log.e("GetGeometry(root) failed");
exit (0);
}
depth = geom.depth;
free (geom);
return depth;
}
extern (C) int xcb_image_shm_get(xcb_connection_t * conn,
xcb_drawable_t draw,
xcb_image_t * image,
xcb_shm_segment_info_t shminfo,
ushort x,
ushort y,
uint plane_mask);
const XCB_ALL_PLANES = ~0;
extern (C) xcb_image_t *
xcb_image_shm_put (xcb_connection_t * conn,
xcb_drawable_t draw,
xcb_gcontext_t gc,
xcb_image_t * image,
xcb_shm_segment_info_t shminfo,
short src_x,
short src_y,
short dest_x,
short dest_y,
ushort src_width,
ushort src_height,
ubyte send_event);
/**
* @struct xcb_shm_segment_info_t
* A structure that stores the informations needed by the MIT Shm
* Extension.
*/
struct xcb_shm_segment_info_t
{
xcb_shm_seg_t shmseg;
uint shmid;
ubyte *shmaddr;
}
alias int key_t;
extern (C) int shmget(key_t key, size_t size, int shmflg);
extern (C) int getpagesize();
extern (C) ubyte *shmat(int shmid, ubyte *shmaddr, int shmflg);
extern (C) int shmctl(int shmid, int cmd, void *buf);
const IPC_CREAT = octal!1000;
const IPC_PRIVATE = (cast(key_t) 0);
const IPC_RMID = 0;
class XCBWindow : Window {
xcb_window_t _w;
@ -467,41 +110,41 @@ class XCBWindow : Window {
}
}
void draw(ColorDrawBuf buf) {
int i;
i = xcb_image_shm_get(_xcbconnection, _w,
_image, shminfo,
0, 0,
XCB_ALL_PLANES);
if (!i) {
Log.e("cannot get shm image");
return;
}
Rect rc;
rc.right = buf.width;
rc.bottom = buf.height;
switch ( _image.bpp ) {
case 32:
{
for (int y = rc.top; y<rc.bottom; y++) {
uint * src = buf.scanLine(y);
uint * dst = cast(uint *)(_image.data + _image.stride * y);
for ( int x = 0; x < rc.right; x++ ) {
uint data = src[x];
dst[x] = data;
}
void draw(ColorDrawBuf buf) {
int i;
i = xcb_image_shm_get(_xcbconnection, _w,
_image, shminfo,
0, 0,
XCB_ALL_PLANES);
if (!i) {
Log.e("cannot get shm image");
return;
}
Rect rc;
rc.right = buf.width;
rc.bottom = buf.height;
switch ( _image.bpp ) {
case 32:
{
for (int y = rc.top; y<rc.bottom; y++) {
uint * src = buf.scanLine(y);
uint * dst = cast(uint *)(_image.data + _image.stride * y);
for ( int x = 0; x < rc.right; x++ ) {
uint data = src[x];
dst[x] = data;
}
}
break;
default:
Log.d("image bit depth not supported: ", _image.bpp);
break;
}
xcb_image_shm_put(_xcbconnection, _w, _g,
_image, shminfo,
cast(short)rc.left, cast(short)rc.top, cast(short)rc.left, cast(short)rc.top, cast(ushort)rc.width(), cast(ushort)rc.height(), 0);
xcb_flush(_xcbconnection);
}
}
break;
default:
Log.d("image bit depth not supported: ", _image.bpp);
break;
}
xcb_image_shm_put(_xcbconnection, _w, _g,
_image, shminfo,
cast(short)rc.left, cast(short)rc.top, cast(short)rc.left, cast(short)rc.top, cast(ushort)rc.width(), cast(ushort)rc.height(), 0);
xcb_flush(_xcbconnection);
}
override void show() {
Log.d("XCBWindow.show()");
@ -525,14 +168,23 @@ class XCBWindow : Window {
cast(uint)_caption.length,
cast(void*)title);
}
ColorDrawBuf _drawbuf;
void processExpose(xcb_expose_event_t * event) {
if (!_drawbuf)
_drawbuf = new ColorDrawBuf(_dx, _dy);
_drawbuf.resize(_dx, _dy);
Log.d("calling createImage");
createImage();
Log.d("done createImage");
onDraw(_drawbuf);
draw(_drawbuf);
/*
xcb_rectangle_t r = { 20, 20, 60, 60 };
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
r = xcb_rectangle_t(cast(short)(_dx - 20 - 60), cast(short)(_dy - 20 - 60), 60, 60);
xcb_poly_fill_rectangle(_xcbconnection, _w, _g, 1, &r);
*/
xcb_flush(_xcbconnection);
}
@ -728,11 +380,18 @@ class XCBPlatform : Platform {
XCBWindow[xcb_window_t] _windowMap;
}
// entry point
extern(C) int UIAppMain(string[] args);
int main(string[] args)
{
setStderrLogger();
setLogLevel(LogLevel.Trace);
FreeTypeFontManager ft = new FreeTypeFontManager();
ft.registerFont("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FontFamily.SansSerif, "DejaVu", false, FontWeight.Normal);
FontManager.instance = ft;
XCBPlatform xcb = new XCBPlatform();
if (!xcb.connect()) {
@ -740,10 +399,16 @@ int main(string[] args)
}
Platform.setInstance(xcb);
Window window = xcb.createWindow("Window Caption", null);
window.show();
int res = 0;
int res = xcb.enterMessageLoop();
static if (true) {
res = UIAppMain(args);
} else {
Window window = xcb.createWindow("Window Caption", null);
window.show();
res = xcb.enterMessageLoop();
}
Platform.setInstance(null);
destroy(xcb);