Files
love-android/jni/devil-1.7.8/src-ILUT/src/ilut_x11.c
T

400 lines
7.2 KiB
C

//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2002 by Denton Woods
// Copyright (C) 2002 Nelson Rush.
// Last modified: 05/18/2002
//
// Filename: src-ILUT/src/ilut_x11.c
//
// Description: X11 Pixmap and XImage binding functions (with XShm)
//
//-----------------------------------------------------------------------------
/*
** This file was created by Jesse Maurais Wed April 4, 2007
** Contact: www.jessemaurais@gmail.com
**
**
** This patch to the Devil Tookit binds to the X Windows System Version 11,
** using client-side XImages and server-side Pixmaps, with support for both
** ZPixmaps and the insane XYPixmap format. (Depends on the X server)
**
** If the XShm extension to X11 is present at the time of ./configure then
** support for shared memory XImages and Pixmaps is also compiled in. Note
** that "shared" does not mean Devil and X are sharing the same memory space.
** This is not possible, because both libraries make byte-for-byte copies
** of their data. It means that memory is part of an inter-process memory
** segment (see XShm spec).
**
** TODO
** 1) Assumed the display depth is 24 bits (the most common) but there should
** be a check, and iXConvertImage should handle this properly. I don't think
** this should be difficult to modify from whats here.
** 2) It would be nice to convert from an XImage back to a Devil image for
** saving changes. Would be seful for an interactive image editor.
** 3) Possibly some additional OpenGL bindings for GLX Pbuffers.
**
** FYI
** It was a long night figuring out the under-documented XYPixmap format.
*/
#include "ilut_internal.h"
#ifdef ILUT_USE_X11
int bits; // bits per pixel
int field; // bits per channel
int bytes; // bytes per pixel
int grain; // bytes per line
int width; // pixels per line
int height; // number of lines
ILpal* palette; // for indexed colors
char* data; // pointer to pixels
void iXGrabImage( ILimage * img )
{
bits = img->Bpp*8; // bits per pixel
field = img->Bpc; // bits per channel
bytes = img->Bpp; // bytes per pixel
grain = img->Bps; // bytes per line
width = img->Width;
height = img->Height;
palette = &img->Pal;
data = (char*)img->Data;
}
Bool iXGrabCurrentImage(void)
{
ilutCurImage = ilGetCurImage();
if (!ilutCurImage) {
return False;
}
iXGrabImage(ilutCurImage);
return True;
}
void iXConvertImage( Display * dpy, XImage * img )
{
int x,y,z;
int sX,dX;
int sY,dY;
int sZ,dZ;
int plane;
ILimage * tmp;
switch ( img->byte_order )
{
case LSBFirst:
tmp = iConvertImage( ilutCurImage,IL_BGR,IL_UNSIGNED_BYTE );
break;
case MSBFirst:
tmp = iConvertImage( ilutCurImage,IL_RGB,IL_UNSIGNED_BYTE );
break;
default:
return;
}
if ( !tmp ) return;
iXGrabImage( tmp );
switch ( img->format )
{
case ZPixmap:
for ( y = 0; y < height; y ++ )
{
dY = y * img->bytes_per_line;
sY = y * grain;
for ( x = 0; x < width; x ++ )
{
dX = x * img->bits_per_pixel / 8;
sX = x * bytes;
for ( z = 0; z < bytes; z ++ )
{
img->data[dX+dY+z] = data[sX+sY+z];
}
}
}
break;
case XYPixmap:
for ( y = 0; y < height; y ++ )
{
sY = y * grain;
for ( x = 0; x < width; x ++ )
{
sX = x * bytes;
for ( z = 0; z < bits; z ++ )
{
sZ = z / 8;
dZ = z % 8;
if ( data[sY+sX+sZ] & ( 1 << dZ ) )
{
plane = bits - z - 1;
sZ = x % 8;
dX = x / 8;
dY = y * img->bytes_per_line;
dZ = plane * img->bytes_per_line * height;
img->data[dZ+dY+dX] |= 1 << sZ;
}
}
}
}
break;
default:
ilSetError( ILUT_NOT_SUPPORTED );
}
ilCloseImage( tmp );
}
ILboolean ilutXInit(void) {
return IL_TRUE;
}
XImage * ILAPIENTRY ilutXCreateImage( Display * dpy )
{
Visual * vis;
XImage * img;
char * buffer;
if (!iXGrabCurrentImage()) {
return NULL;
}
buffer = malloc( width * height * 4 );
if (!buffer) {
return NULL;
}
vis = CopyFromParent;
img = XCreateImage( dpy,vis, 24,ZPixmap,0,buffer,width,height,8,0 );
if (!img) {
free(buffer);
return NULL;
}
iXConvertImage( dpy,img );
return img;
}
Pixmap ILAPIENTRY ilutXCreatePixmap( Display * dpy, Drawable draw )
{
XImage * img;
GC gc;
Pixmap pix;
img = ilutXCreateImage( dpy );
if (!img) {
return None;
}
gc = DefaultGC(dpy,DefaultScreen(dpy));
if (!gc) {
XDestroyImage( img );
return None;
}
pix = XCreatePixmap( dpy,draw, width,height,24 );
if (!pix ) {
XDestroyImage( img );
return None;
}
XPutImage( dpy,pix,gc,img, 0,0,0,0,width,height );
XDestroyImage( img );
return pix;
}
XImage * ILAPIENTRY ilutXLoadImage( Display * dpy, char * filename )
{
iBindImageTemp();
if (!ilLoadImage(filename)) {
return NULL;
}
return ilutXCreateImage( dpy );
}
Pixmap ILAPIENTRY ilutXLoadPixmap( Display * dpy, Drawable draw, char * filename )
{
iBindImageTemp();
if (!ilLoadImage(filename)) {
return None;
}
return ilutXCreatePixmap( dpy,draw );
}
#ifdef ILUT_USE_XSHM
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
XImage * ILAPIENTRY ilutXShmCreateImage( Display * dpy, XShmSegmentInfo * info )
{
Visual * vis;
XImage * img;
// Get server supported format
int size,format = XShmPixmapFormat( dpy );
// Grab the current image
if (!iXGrabCurrentImage()) {
return NULL;
}
// Create a shared image
vis = CopyFromParent;
img = XShmCreateImage( dpy,vis, 24,format,NULL,info,width,height );
if (!img) {
return NULL;
}
// Create shared memory
size = img->bytes_per_line * img->height;
info->shmid = shmget( IPC_PRIVATE, size, IPC_CREAT | 0666 );
info->shmaddr = img->data = shmat( info->shmid, 0, 0 );
info->readOnly = False;
// Attach to server
XShmAttach( dpy,info );
// Copy image pixels to shared memory
iXConvertImage( dpy,img );
return img;
}
void ILAPIENTRY ilutXShmDestroyImage( Display * dpy, XImage * img, XShmSegmentInfo * info )
{
XShmDetach( dpy,info );
XDestroyImage( img );
XFlush( dpy );
shmdt( info->shmaddr );
shmctl( info->shmid, IPC_RMID, 0 );
}
Pixmap ILAPIENTRY ilutXShmCreatePixmap( Display * dpy, Drawable draw, XShmSegmentInfo * info )
{
Pixmap pix;
XImage*img;
// Create a dumby image
img = ilutXShmCreateImage( dpy,info );
if (!img) {
return None;
}
// Use the same memory segment in the pixmap
pix = XShmCreatePixmap( dpy,draw, info->shmaddr,info,width,height,24 );
if (!pix) {
ilutXShmDestroyImage( dpy,img,info );
return None;
}
// Riddance to the image
XDestroyImage( img );
return pix;
}
void ILAPIENTRY ilutXShmFreePixmap( Display * dpy, Pixmap pix, XShmSegmentInfo * info )
{
XShmDetach( dpy,info );
XFreePixmap( dpy,pix );
XFlush( dpy );
shmdt( info->shmaddr );
shmctl( info->shmid, IPC_RMID, 0 );
}
XImage * ILAPIENTRY ilutXShmLoadImage( Display * dpy, char* filename, XShmSegmentInfo * info )
{
iBindImageTemp();
if (!ilLoadImage(filename)) {
return NULL;
}
return ilutXShmCreateImage( dpy,info );
}
Pixmap ILAPIENTRY ilutXShmLoadPixmap( Display * dpy, Drawable draw, char* filename, XShmSegmentInfo * info )
{
iBindImageTemp();
if (!ilLoadImage(filename)) {
return None;
}
return ilutXShmCreatePixmap( dpy,draw,info );
}
#endif//ILUT_USE_XSHM
#endif//ILUT_USE_X11