shithub: npe

ref: 979ae53cfee913c2d303ab0f95aaa65dace1c7b5
dir: /libnpe_sdl3/render.c/

View raw version
#include "_sdl.h"

static SDL_Renderer oneren;
static u8int *backcopy;
static Image *front;
static u32int renddrawcol = DBlack;

bool
SDL_GetRenderVSync(SDL_Renderer *, int *)
{
	return false;
}

bool
SDL_SetRenderVSync(SDL_Renderer *, int)
{
	return true;
}

bool
SDL_SetRenderDrawBlendMode(SDL_Renderer *, SDL_BlendMode blendMode)
{
	if(blendMode != SDL_BLENDMODE_NONE){
		werrstr("SDL_SetRenderDrawBlendMode: only SDL_BLENDMODE_NONE is supported");
		return false;
	}
	return true;
}

bool
SDL_GetRendererInfo(SDL_Renderer *, SDL_RendererInfo *info)
{
	if(info == nil)	
		return false;
	info->max_texture_width = npe_sdl.physw;
	info->max_texture_height = npe_sdl.physh;
	return true;
}

bool
SDL_SetRenderDrawColor(SDL_Renderer *, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
	renddrawcol = r<<24 | g<<16 | b<<8 | a;
	if(npe_sdl.rendcol != nil)
		memfillcolor(npe_sdl.rendcol, renddrawcol);
	return true;
}

bool
SDL_SetRenderLogicalPresentation(SDL_Renderer *r, int w, int h, SDL_RendererLogicalPresentation)
{
	if(r->logiw != w || r->logih != h){
		r->logiw = w;
		r->logih = h;
		npe_sdl.fullredraw = 1;
	}
	return true;
}

bool
SDL_GetRendererOutputSize(SDL_Renderer *r, int *w, int *h)
{
	if(w != nil)
		*w = r->logiw;
	if(h != nil)
		*h = r->logih;
	return true;
}

void
SDL_RenderGetViewport(SDL_Renderer *r, SDL_Rect *rect)
{
	rect->x = rect->y = 0;
	rect->w = r->logiw;
	rect->h = r->logih;
}

bool
SDL_RenderClear(SDL_Renderer *)
{
	if(npe_sdl.back != nil)
		memfillcolor(npe_sdl.back, renddrawcol);
	return true;
}

bool
SDL_RenderFillRect(SDL_Renderer *r, SDL_FRect *rect)
{
	Rectangle rr;

	if(npe_sdl.back == nil)
		return true;
	if(rect == nil)
		return SDL_RenderClear(r);
	if(npe_sdl.rendcol == nil)
		return true;
	rr = Rect(rect->x, rect->y, rect->x+rect->w, rect->y+rect->h);
	memimagedraw(npe_sdl.back, rr, npe_sdl.rendcol, ZP, nil, ZP, SoverD);
	return true;
}

bool
SDL_RenderLines(SDL_Renderer *, SDL_FPoint *pp, int n)
{
	Point p0, p1;
	SDL_FPoint *p;

	if(npe_sdl.rendcol == nil)
		return false;
	for(p=pp; n>1; n--, p++){
		if(p == pp){
			p0 = Pt(p->x, p->y);
			p++;
		}
		p1 = Pt(p->x, p->y);
		memimageline(npe_sdl.back, p0, p1, 0, 0, 0, npe_sdl.rendcol, ZP, SoverD);
		p0 = p1;
	}
	return true;
}

bool
SDL_RenderPoints(SDL_Renderer *, SDL_FPoint *pp, int n)
{
	Point c;
	SDL_FPoint *p;

	if(npe_sdl.rendcol == nil)
		return false;
	for(p=pp; n>0; n--, p++){
		c = Pt(p->x, p->y);
		memellipse(npe_sdl.back, c, 0, 0, 0, npe_sdl.rendcol, ZP, SoverD);
	}
	return true;
}

static int
duff(SDL_BlendMode mode)
{
	if(mode == SDL_BLENDMODE_BLEND)
		return SoverD;
	return S;
}

bool
SDL_RenderTexture(SDL_Renderer *rend, SDL_Texture *t, const SDL_FRect *sre, const SDL_FRect *dre)
{
	Rectangle sr, dr;
	int logiw, logih;
	ulong chan;
	Memimage *m;

	if(rend->logiw > 0 && rend->logih > 0){
		logiw = rend->logiw;
		logih = rend->logih;
	}else{
		logiw = npe_sdl.physw;
		logih = npe_sdl.physh;
	}

	sr = t->m->r;
	if(sre != nil){
		sr.min = Pt(sre->x, sre->y);
		sr.max = addpt(sr.min, Pt(sre->w, sre->h));
	}

	dr = Rect(0, 0, logiw, logih);
	if(dre != nil){
		dr.min = Pt(dre->x, dre->y);
		dr.max = addpt(dr.min, Pt(dre->w, dre->h));
	}

	if(npe_sdl.back == nil || Dx(npe_sdl.back->r) != logiw || Dy(npe_sdl.back->r) != logih){
		freememimage(npe_sdl.back);
		if(screen)
			chan = screen->chan;
		else
			chan = ARGB32;
		npe_sdl.back = allocmemimage(Rect(0, 0, logiw, logih), chan);
		if(npe_sdl.back == nil){
			werrstr("SDL_RenderCopy: %r");
			return false;
		}
		npe_sdl.rendcol = allocmemimage(Rect(0, 0, logiw, 1), npe_sdl.back->chan);
		if(npe_sdl.rendcol != nil){
			memfillcolor(npe_sdl.rendcol, renddrawcol);
			npe_sdl.rendcol->flags |= Frepl;
			npe_sdl.rendcol->clipr = memwhite->clipr;
		}
		npe_sdl.target->m = npe_sdl.back;
		free(backcopy);
		backcopy = malloc(logiw*logih*4);
	}

	m = t->mod == nil ? t->m : t->mod;

	if(Dx(dr)/Dx(sr) > 1 || Dy(dr)/Dy(sr) > 1)
		npe_sdl_scale((u32int*)byteaddr(m, ZP), Dx(sr), Dy(sr), (u32int*)byteaddr(npe_sdl.back, ZP), logiw, logih);
	else
		memimagedraw(npe_sdl.back, dr, m, sr.min, nil, ZP, duff(t->blend));
	return true;
}

bool
SDL_RenderPresent(SDL_Renderer *rend)
{
	Rectangle r;
	static u32int *b;
	uchar *rb;
	int logiw, logih;

	/* may be called before SDL_RenderCopy is ever called;
	 * nanobsp does this during initialization */
	if(npe_sdl.back == nil)
		return false;

	if(rend->logiw > 0 && rend->logih > 0){
		logiw = rend->logiw;
		logih = rend->logih;
	}else{
		logiw = npe_sdl.physw;
		logih = npe_sdl.physh;
	}

	npe_sdl.scale = (float)logiw / (float)npe_sdl.physw;

	if(!npe_sdl.fullredraw && (npe_sdl.fullredraw = memcmp(backcopy, byteaddr(npe_sdl.back, ZP), logiw*logih*4)) == 0 && !npe_sdl.mredraw)
		return false;

	r = Rect(0, 0, npe_sdl.physw, npe_sdl.physh);
	if(front != nil && (Dx(front->r) != npe_sdl.physw || Dy(front->r) != npe_sdl.physh)){
		freeimage(front);
		front = nil;
		free(b);
		b = nil;
	}
	if(b == nil && (b = realloc(b, npe_sdl.physw*npe_sdl.physh*4)) == nil){
		fprint(2, "SDL_RenderPresent: %r\n");
		return false;
	}
	if(npe_sdl.fullredraw || front == nil){
		rb = npe_sdl_scale((u32int*)byteaddr(npe_sdl.back, ZP), Dx(npe_sdl.back->r), Dy(npe_sdl.back->r), b, npe_sdl.physw, npe_sdl.physh);
		if(front == nil && (front = allocimage(display, r, XRGB32, 0, DNofill)) == nil){
			fprint(2, "SDL_RenderPresent: %r\n");
			return false;
		}
		if(loadimage(front, r, rb, Dx(r)*Dy(r)*4) < 0){
			fprint(2, "SDL_RenderPresent: %r\n");
			return false;
		}
	}
	while(screen == nil && getwindow(display, Refnone) != 1)
		/* drawterm window change lag */;
	draw(screen, screen->r, front, nil, ZP);
	npe_draw_cursor();
	npe_sdl.mredraw = 0;

	flushimage(display, 1);

	if(npe_sdl.fullredraw)
		memmove(backcopy, byteaddr(npe_sdl.back, ZP), logiw*logih*4);
	else
		replclipr(screen, 0, screen->r);
	npe_sdl.fullredraw = 0;
	return true;
}

bool
SDL_RenderReadPixels(SDL_Renderer *rend, SDL_Rect *rect, Uint32 fmt, void *pixels, int pitch)
{
	Rectangle r, r2;
	Memimage *m;
	int n;

	USED(pitch); /* FIXME pitch */

	if(rect != nil)
		r = Rect(rect->x, rect->y, rect->x+rect->w, rect->y+rect->h);
	else
		r = Rect(0, 0, rend->logiw, rend->logih);

	n = Dx(r)*Dy(r);
	switch(fmt){
	case SDL_PIXELFORMAT_ARGB8888:
	case SDL_PIXELFORMAT_XRGB8888:
		n *= 4;
		m = npe_sdl.back;
		break;
	case SDL_PIXELFORMAT_ABGR8888:
		n *= 4;
		r2 = Rect(0,0,Dx(r),Dy(r));
		if((m = allocmemimage(r2, ABGR32)) == nil)
			return false;
		memfillcolor(m, DBlack);
		memimagedraw(m, r2, npe_sdl.back, r.min, nil, ZP, S);
		break;
	case SDL_PIXELFORMAT_RGB24:
		n *= 3;
		r2 = Rect(0,0,Dx(r),Dy(r));
		if((m = allocmemimage(r2, RGB24)) == nil)
			return false;
		memfillcolor(m, DBlack);
		memimagedraw(m, r2, npe_sdl.back, r.min, nil, ZP, S);
		break;
	default:
		werrstr("SDL_RenderReadPixels: format not supported");
		return false;
	}

	unloadmemimage(m, r, pixels, n);
	if(m != npe_sdl.back)
		freememimage(m);
	return true;
}

void
SDL_DestroyRenderer(SDL_Renderer *)
{
	/* nothing to do here */
}

SDL_Renderer *
SDL_CreateRenderer(SDL_Window *, char *)
{
	return &oneren;
}