ref: 979ae53cfee913c2d303ab0f95aaa65dace1c7b5
dir: /libnpe_sdl3/render.c/
#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;
}