Fix blitting, add optional position arg to Bitmap.snap_to_bitmap

This commit is contained in:
Roza 2021-05-03 19:09:36 -04:00
parent 077b7da204
commit 67c158e418
3 changed files with 51 additions and 29 deletions

View file

@ -663,7 +663,7 @@ RB_METHOD(bitmapGetLooping){
Bitmap *b = getPrivateData<Bitmap>(self); Bitmap *b = getPrivateData<Bitmap>(self);
bool ret; bool ret;
GUARD_EXC(b->getLooping();); GUARD_EXC(ret = b->getLooping(););
return rb_bool_new(ret); return rb_bool_new(ret);
} }
@ -671,12 +671,14 @@ RB_METHOD(bitmapGetLooping){
RB_METHOD(bitmapSnapToBitmap) { RB_METHOD(bitmapSnapToBitmap) {
RB_UNUSED_PARAM; RB_UNUSED_PARAM;
rb_check_argc(argc, 0); VALUE position;
rb_scan_args(argc, argv, "01", &position);
Bitmap *b = getPrivateData<Bitmap>(self); Bitmap *b = getPrivateData<Bitmap>(self);
Bitmap *newbitmap = 0; Bitmap *newbitmap = 0;
GUARD_EXC(newbitmap = new Bitmap(*b, false);); int pos = (position == RUBY_Qnil) ? -1 : NUM2INT(position);
GUARD_EXC(newbitmap = new Bitmap(*b, pos););
VALUE ret = rb_obj_alloc(rb_class_of(self)); VALUE ret = rb_obj_alloc(rb_class_of(self));

View file

@ -637,16 +637,29 @@ Bitmap::Bitmap(void *pixeldata, int width, int height)
p->addTaintedArea(rect()); p->addTaintedArea(rect());
} }
Bitmap::Bitmap(const Bitmap &other, bool copyAllFrames) // frame is -2 for "any and all", -1 for "current", anything else for a specific frame
Bitmap::Bitmap(const Bitmap &other, int frame)
{ {
other.ensureNonMega(); other.ensureNonMega();
if (frame > -2) other.ensureAnimated();
p = new BitmapPrivate(this); p = new BitmapPrivate(this);
if (!other.isAnimated() || !copyAllFrames) { if (!other.isAnimated() || frame >= -1) {
other.ensureNotPlaying(); if (frame == -1) other.ensureNotPlaying();
p->gl = shState->texPool().request(other.width(), other.height()); p->gl = shState->texPool().request(other.width(), other.height());
blt(0, 0, other, rect());
GLMeta::blitBegin(p->gl);
// Blit just the current frame of the other animated bitmap
if (frame == -1) {
GLMeta::blitSource(other.getGLTypes());
}
else {
auto &frames = other.getFrames();
GLMeta::blitSource(frames[clamp(frame, 0, (int)frames.size() - 1)]);
}
GLMeta::blitRectangle(rect(), rect(), true);
GLMeta::blitEnd();
} }
else { else {
p->animation.enabled = true; p->animation.enabled = true;
@ -657,10 +670,10 @@ Bitmap::Bitmap(const Bitmap &other, bool copyAllFrames)
p->animation.loop = other.getLooping(); p->animation.loop = other.getLooping();
char *tmp = new char[p->animation.width * p->animation.height * 4]; char *tmp = new char[p->animation.width * p->animation.height * 4];
for (const TEXFBO &frame : other.getFrames()) { for (TEXFBO &sourceframe : other.getFrames()) {
TEXFBO copyframe; TEXFBO newframe;
try { try {
copyframe = shState->texPool().request(p->animation.width, p->animation.height); newframe = shState->texPool().request(p->animation.width, p->animation.height);
} catch(const Exception &e) { } catch(const Exception &e) {
for (TEXFBO &f : p->animation.frames) for (TEXFBO &f : p->animation.frames)
shState->texPool().release(f); shState->texPool().release(f);
@ -668,17 +681,17 @@ Bitmap::Bitmap(const Bitmap &other, bool copyAllFrames)
throw e; throw e;
} }
// FIXME: gotta see if I can copy textures directly from one TEXFBO to the other GLMeta::blitBegin(newframe);
// I'm an idiot so I don't already know GLMeta::blitSource(sourceframe);
FBO::bind(frame.fbo); GLMeta::blitRectangle(rect(), rect(), true);
gl.ReadPixels(0,0,p->animation.width,p->animation.height,GL_RGBA,GL_UNSIGNED_BYTE,tmp); GLMeta::blitEnd();
TEX::bind(copyframe.tex);
TEX::uploadImage(p->animation.width, p->animation.height, tmp, GL_RGBA);
p->animation.frames.push_back(copyframe); p->animation.frames.push_back(newframe);
} }
delete[] tmp; delete[] tmp;
} }
p->addTaintedArea(rect());
} }
Bitmap::~Bitmap() Bitmap::~Bitmap()
@ -859,7 +872,7 @@ void Bitmap::stretchBlt(const IntRect &destRect,
{ {
/* Fast blit */ /* Fast blit */
GLMeta::blitBegin(getGLTypes()); GLMeta::blitBegin(getGLTypes());
GLMeta::blitSource(getGLTypes()); GLMeta::blitSource(source.getGLTypes());
GLMeta::blitRectangle(sourceRect, destRect); GLMeta::blitRectangle(sourceRect, destRect);
GLMeta::blitEnd(); GLMeta::blitEnd();
} }
@ -1770,7 +1783,7 @@ void Bitmap::setInitFont(Font *value)
p->font = value; p->font = value;
} }
TEXFBO &Bitmap::getGLTypes() TEXFBO &Bitmap::getGLTypes() const
{ {
return (p->animation.enabled) ? p->animation.currentFrame() : p->gl; return (p->animation.enabled) ? p->animation.currentFrame() : p->gl;
} }
@ -1801,6 +1814,14 @@ void Bitmap::ensureNonAnimated() const
GUARD_ANIMATED; GUARD_ANIMATED;
} }
void Bitmap::ensureAnimated() const
{
if (isDisposed())
return;
GUARD_UNANIMATED;
}
void Bitmap::ensureNotPlaying() const void Bitmap::ensureNotPlaying() const
{ {
if (isDisposed()) if (isDisposed())
@ -1899,14 +1920,10 @@ int Bitmap::addFrame(Bitmap &source, int position)
p->surface = 0; p->surface = 0;
} }
else { else {
// FIXME: gotta see if I can copy textures directly from one TEXFBO to the other GLMeta::blitBegin(newframe);
// I'm an idiot so I don't already know GLMeta::blitSource(source.getGLTypes());
auto pixels = new char[source.width() * source.height() * 4]; GLMeta::blitRectangle(rect(), rect(), true);
FBO::bind(source.getGLTypes().fbo); GLMeta::blitEnd();
gl.ReadPixels(0,0,source.width(),source.height(),GL_RGBA,GL_UNSIGNED_BYTE,pixels);
TEX::bind(newframe.tex);
TEX::uploadImage(newframe.width, newframe.height, pixels, GL_RGBA);
delete[] pixels;
} }
int ret; int ret;

View file

@ -42,7 +42,9 @@ public:
Bitmap(int width, int height); Bitmap(int width, int height);
Bitmap(void *pixeldata, int width, int height); Bitmap(void *pixeldata, int width, int height);
/* Clone constructor */ /* Clone constructor */
Bitmap(const Bitmap &other, bool copyAllFrames = true);
// frame is -2 for "any and all", -1 for "current", anything else for a specific frame
Bitmap(const Bitmap &other, int frame = -2);
~Bitmap(); ~Bitmap();
int width() const; int width() const;
@ -114,11 +116,12 @@ public:
void setInitFont(Font *value); void setInitFont(Font *value);
/* <internal> */ /* <internal> */
TEXFBO &getGLTypes(); TEXFBO &getGLTypes() const;
SDL_Surface *surface() const; SDL_Surface *surface() const;
SDL_Surface *megaSurface() const; SDL_Surface *megaSurface() const;
void ensureNonMega() const; void ensureNonMega() const;
void ensureNonAnimated() const; void ensureNonAnimated() const;
void ensureAnimated() const;
// Animation functions // Animation functions
void stop(); void stop();