home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
xpdf
/
agfx.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-04
|
7KB
|
362 lines
//========================================================================
//
// AGfx.cc
//
// Copyright 1999 Emmanuel Lesueur
//
//========================================================================
#include <stdio.h>
#include <stdlib.h>
#include "gmem.h"
#ifdef __SASC
# define throw(x) (printf("Exception: %s\n",x),exit(EXIT_FAILURE))
#endif
#ifdef __PPC__
//#define DEBUGMSG
#include <exec/nodes.h>
#include <exec/memory.h>
#include <powerup/ppclib/message.h>
#include <powerup/ppclib/tasks.h>
#include <powerup/ppclib/memory.h>
#include <powerup/gcclib/powerup_protos.h>
#include "AGfx.h"
#include "AGfxcomm.h"
#include "AComm.h"
AGfx::Image::Image(short w,short h)
: width(w),height(h),bytes_per_row(((w+15)>>4)<<4) {
im=(pixel_color*)PPCAllocVec(bytes_per_row*h,MEMF_ANY);
if(!im)
throw("No memory.");
}
AGfx::Image::~Image() {
PPCFreeVec(im);
}
AGfx::Image24::Image24(short w,short h)
: width(w),height(h) {
im=(Color*)PPCAllocVec(w*h*sizeof(Color),MEMF_ANY);
if(!im)
throw("No memory.");
}
AGfx::Image24::~Image24() {
PPCFreeVec(im);
}
AGfx::ColorTable::ColorTable(int n) : num(n) {
entries=(ColorEntry*)PPCAllocVec((n+1)*sizeof(ColorEntry),MEMF_ANY);
if(!entries)
throw("No memory.");
}
AGfx::ColorTable::~ColorTable() {
PPCFreeVec(entries);
}
#ifdef USE_GFX_PIPE
static const int bufsize=50000;
static short stubbuf[10];
AGfx::AGfx(void* port1)
: port(port1),reply_port(NULL),buf(NULL),pipe(NULL),
msg(NULL),msg_sent(false),in_page_draw(false) {
buf=(short*)PPCAllocVec(sizeof(GfxPipe)+bufsize*2,MEMF_NOCACHESYNCPPC|MEMF_NOCACHESYNCM68K);
if(!buf) {
static GfxPipe p;
pipe=&p;
ptr=stubbuf;
end=ptr;
} else {
pipe=(volatile GfxPipe*)buf;
ptr=pipe->data;
end=ptr+bufsize;
}
if(buf) {
if(reply_port=PPCCreatePort(NULL))
msg=PPCCreateMessage(reply_port,bufsize*2);
}
}
AGfx::~AGfx() {
if(msg_sent) {
pipe->done=1;
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
if(msg)
PPCDeleteMessage(msg);
if(reply_port)
PPCDeletePort(reply_port);
if(buf)
PPCFreeVec(buf);
}
void AGfx::init() {
if(!buf)
ptr=stubbuf;
else if(!msg_sent && msg) {
// no need to flush caches here, so MSGLENGTH=0
pipe->done=0;
ptr=pipe->data;
pipe->writep=ptr;
pipe->readp=ptr;
PPCSendMessage(port,msg,buf,0,MSGID_GFXPIPE);
msg_sent=true;
}
}
void AGfx::flush(bool complete) {
if(msg_sent) {
pipe->done=1;
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
msg_sent=false;
}
if(!complete)
init();
}
#else
static const int bufsize=2000;
AGfx::AGfx(void* port1)
: port(port1),reply_port(NULL),buf(NULL),buf2(NULL),
msg(NULL),msg_sent(false),in_page_draw(false) {
buf=(short*)PPCAllocVec(bufsize*2,MEMF_ANY);
if(!buf) {
static short b[10];
ptr=b;
sz=10;
} else {
ptr=buf;
sz=bufsize;
}
if(buf) {
buf2=(short*)PPCAllocVec(bufsize*2,MEMF_ANY);
if(reply_port=PPCCreatePort(NULL))
msg=PPCCreateMessage(reply_port,bufsize*2);
}
}
AGfx::~AGfx() {
if(msg_sent) {
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
if(msg)
PPCDeleteMessage(msg);
if(reply_port)
PPCDeletePort(reply_port);
if(buf)
PPCFreeVec(buf);
if(buf2)
PPCFreeVec(buf2);
}
void AGfx::flush(bool complete) {
if(msg_sent) {
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
msg_sent=false;
}
if(buf) {
if(ptr!=buf && msg) {
//printf("flush\n");
if(buf2) {
short* t=buf;
buf=buf2;
buf2=t;
PPCSendMessage(port,msg,buf2,(ptr-buf2)*2,MSGID_GFX);
if(complete) {
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
} else
msg_sent=true;
} else {
PPCSendMessage(port,msg,buf,(ptr-buf)*2,MSGID_GFX);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
ptr=buf;
sz=bufsize;
} else {
sz=10;
ptr=buf;
}
}
#endif
void AGfx::put_image(const Image& i,short x,short y) {
check_size(5);
short* p=get_ptr();
*p++=AGFX_IMAGE;
*p++=x;
*p++=y;
*p++=i.width;
*p++=i.height;
set_ptr(p);
flush(true);
if(msg) {
PPCSendMessage(port,msg,i.im,i.height*i.bytes_per_row,MSGID_GFXSYNC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
void AGfx::get_image(Image& i,short x,short y) {
check_size(5);
short* p=get_ptr();
*p++=AGFX_GETIMAGE;
*p++=x;
*p++=y;
*p++=i.width;
*p++=i.height;
set_ptr(p);
flush(true);
if(msg) {
PPCSendMessage(port,msg,i.im,i.height*i.bytes_per_row,MSGID_GFXSYNC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
void AGfx::put_image(const Image24& i,short x,short y) {
check_size(5);
short* p=get_ptr();
*p++=AGFX_IMAGE24;
*p++=x;
*p++=y;
*p++=i.width;
*p++=i.height;
set_ptr(p);
flush(true);
if(msg) {
PPCSendMessage(port,msg,i.im,i.height*i.width*sizeof(Color),MSGID_GFXSYNC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
void AGfx::get_image(Image24& i,short x,short y) {
check_size(5);
short* p=get_ptr();
*p++=AGFX_GETIMAGE24;
*p++=x;
*p++=y;
*p++=i.width;
*p++=i.height;
set_ptr(p);
flush(true);
if(msg) {
PPCSendMessage(port,msg,i.im,i.height*i.width*sizeof(Color),MSGID_GFXSYNC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
void AGfx::get_colors(ColorTable& t,int n) {
check_size(2);
short* p=get_ptr();
*p++=AGFX_GETCOLORS;
*p++=short(n);
set_ptr(p);
flush(true);
if(msg) {
PPCSendMessage(port,msg,t.entries,sizeof(ColorEntry)*n,MSGID_GFXSYNC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
#else
#include "AGfx.h"
AGfx::Image::Image(short w,short h)
: width(w),height(h),bytes_per_row(((w+15)>>4)<<4) {
im=(pixel_color*)gmalloc(bytes_per_row*h);
if(!im)
throw("No memory.");
}
AGfx::Image::~Image() {
gfree(im);
}
AGfx::Image24::Image24(short w,short h)
: width(w),height(h) {
im=(Color*)gmalloc(w*h*sizeof(Color));
if(!im)
throw("No memory.");
}
AGfx::Image24::~Image24() {
gfree(im);
}
AGfx::ColorTable::ColorTable(int n) : num(n) {
entries=(ColorEntry*)gmalloc((n+1)*sizeof(ColorEntry));
if(!entries)
throw("No memory.");
}
AGfx::ColorTable::~ColorTable() {
gfree(entries);
}
void AGfx::polydraw(const Polygon<short>& p) {
if(!p.empty()) {
Polygon<short> q;
short dx=x0;
short dy=y0;
if(dx || dy) {
q.reserve(p.size());
for(Polygon<short>::const_iterator v(p.begin());v!=p.end();++v) {
q.push_back(Vertex<short>(v->x-dx,v->y-dy));
}
} else
q=p;
Polygon<short>::const_iterator v(q.begin());
Move(rp,v->x,v->y);
PolyDraw(rp,q.size()-1,(short*)(v+1));
}
}
#endif
AGfx::AreaDrawer::~AreaDrawer() {
gfx.initarea(n);
for(PArea<short>::const_iterator p(area.begin());p!=area.end();++p)
gfx.areapoly(*p);
gfx.areaend();
}
void AGfx::AreaDrawer::add(const Polygon<short>& p) {
n+=p.size()+1;
#ifndef __PPC__
short dx=gfx.x0;
short dy=gfx.y0;
if(dx || dy) {
Polygon<short> q;
q.reserve(p.size());
for(Polygon<short>::const_iterator v(p.begin());v!=p.end();++v) {
q.push_back(Vertex<short>(v->x-dx,v->y-dy));
}
area.push_back(q);
} else
#endif
area.push_back(p);
}