home *** CD-ROM | disk | FTP | other *** search
- //========================================================================
- //
- // 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);
- }
-
-
-