From e0a4dfe3729ad8c4787eb30d8b11f9efa052a21b Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Fri, 31 Jan 2014 10:19:16 +0100 Subject: [PATCH] Bitmap: Make #get_pixel/#set_pixel more accurate This gets rid of the "batch/flush" semantics for #set_pixel and instead just directly uploads the pixel color to the texture, circumventing the float conversion entirely. Also makes a lot of code simpler in many places as calling 'flush()' is no longer required for bitmaps. --- binding-mri/bitmap-binding.cpp | 4 +- binding-mruby/bitmap-binding.cpp | 4 +- src/bitmap.cpp | 74 ++++++++------------------------ src/bitmap.h | 7 +-- src/gl-util.h | 9 ---- src/plane.cpp | 3 -- src/quadarray.h | 63 --------------------------- src/sprite.cpp | 3 -- src/tilemap.cpp | 7 --- src/window.cpp | 6 --- 10 files changed, 23 insertions(+), 157 deletions(-) diff --git a/binding-mri/bitmap-binding.cpp b/binding-mri/bitmap-binding.cpp index f87d8e2..4454bd1 100644 --- a/binding-mri/bitmap-binding.cpp +++ b/binding-mri/bitmap-binding.cpp @@ -202,7 +202,7 @@ RB_METHOD(bitmapGetPixel) return Qnil; ) - Vec4 value; + Color value; GUARD_EXC( value = b->getPixel(x, y); ); Color *color = new Color(value); @@ -223,7 +223,7 @@ RB_METHOD(bitmapSetPixel) color = getPrivateDataCheck(colorObj, ColorType); - GUARD_EXC( b->setPixel(x, y, color->norm); ); + GUARD_EXC( b->setPixel(x, y, *color); ); return self; } diff --git a/binding-mruby/bitmap-binding.cpp b/binding-mruby/bitmap-binding.cpp index f000b07..9010d02 100644 --- a/binding-mruby/bitmap-binding.cpp +++ b/binding-mruby/bitmap-binding.cpp @@ -194,7 +194,7 @@ MRB_METHOD(bitmapGetPixel) return mrb_nil_value(); ) - Vec4 value; + Color value; GUARD_EXC( value = b->getPixel(x, y); ) Color *color = new Color(value); @@ -215,7 +215,7 @@ MRB_METHOD(bitmapSetPixel) color = getPrivateDataCheck(mrb, colorObj, ColorType); - GUARD_EXC( b->setPixel(x, y, color->norm); ) + GUARD_EXC( b->setPixel(x, y, *color); ) return mrb_nil_value(); } diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 68b2ac8..0e3b21d 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -55,10 +55,6 @@ struct BitmapPrivate { TEXFBO gl; - /* 'setPixel()' calls are cached and executed - * in batches on 'flush()' */ - PointArray pointArray; - Font *font; /* "Mega surfaces" are a hack to allow Tilesets to be used @@ -154,32 +150,9 @@ struct BitmapPrivate glState.blendMode.pop(); } - void flushPoints() - { - if (pointArray.count() == 0) - return; - - SimpleColorShader &shader = shState->shaders().simpleColor; - shader.bind(); - shader.setTranslation(Vec2i()); - - bindFBO(); - pushSetViewport(shader); - glState.blendMode.pushSet(BlendNone); - - pointArray.commit(); - pointArray.draw(); - pointArray.reset(); - - glState.blendMode.pop(); - popViewport(); - } - void fillRect(const IntRect &rect, const Vec4 &color) { - flushPoints(); - bindFBO(); glState.scissorTest.pushSet(true); @@ -271,7 +244,6 @@ Bitmap::Bitmap(const Bitmap &other) p->gl = shState->texPool().request(other.width(), other.height()); - other.flush(); blt(0, 0, other, rect()); } @@ -368,8 +340,6 @@ void Bitmap::stretchBlt(const IntRect &destRect, if (opacity == 255 && !p->touchesTaintedArea(destRect)) { /* Fast blit */ - flush(); - FBO::bind(source.p->gl.fbo, FBO::Read); FBO::bind(p->gl.fbo, FBO::Draw); @@ -379,8 +349,6 @@ void Bitmap::stretchBlt(const IntRect &destRect, else { /* Fragment pipeline */ - flush(); - float normOpacity = (float) opacity / 255.0f; TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h); @@ -666,9 +634,6 @@ void Bitmap::clear() GUARD_MEGA; - /* Any queued points won't be visible after this anyway */ - p->pointArray.reset(); - p->bindFBO(); glState.clearColor.pushSet(Vec4()); @@ -682,7 +647,7 @@ void Bitmap::clear() modified(); } -Vec4 Bitmap::getPixel(int x, int y) const +Color Bitmap::getPixel(int x, int y) const { GUARD_DISPOSED; @@ -691,24 +656,34 @@ Vec4 Bitmap::getPixel(int x, int y) const if (x < 0 || y < 0 || x >= width() || y >= height()) return Vec4(); - flush(); - FBO::bind(p->gl.fbo, FBO::Read); glState.viewport.pushSet(IntRect(0, 0, width(), height())); - Vec4 pixel = FBO::getPixel(x, y); + + uint8_t pixel[4]; + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + glState.viewport.pop(); - return pixel; + return Color(pixel[0], pixel[1], pixel[2], pixel[3]); } -void Bitmap::setPixel(int x, int y, const Vec4 &color) +void Bitmap::setPixel(int x, int y, const Color &color) { GUARD_DISPOSED; GUARD_MEGA; - p->pointArray.append(Vec2(x+.5, y+.5), color); + uint8_t pixel[] = + { + (uint8_t) clamp(color.red, 0, 255), + (uint8_t) clamp(color.green, 0, 255), + (uint8_t) clamp(color.blue, 0, 255), + (uint8_t) clamp(color.alpha, 0, 255) + }; + + TEX::bind(p->gl.tex); + TEX::uploadSubImage(x, y, 1, 1, &pixel, GL_RGBA); p->addTaintedArea(IntRect(x, y, 1, 1)); @@ -724,8 +699,6 @@ void Bitmap::hueChange(int hue) if ((hue % 360) == 0) return; - flush(); - TEXFBO newTex = shState->texPool().request(width(), height()); FloatRect texRect(rect()); @@ -777,8 +750,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) if (str[0] == ' ' && str[1] == '\0') return; - flush(); - TTF_Font *font = p->font->getSdlFont(); Color *fontColor = p->font->getColor(); @@ -1009,17 +980,6 @@ IntRect Bitmap::textSize(const char *str) DEF_ATTR_SIMPLE(Bitmap, Font, Font*, p->font) -void Bitmap::flush() const -{ - if (isDisposed()) - return; - - if (p->megaSurface) - return; - - p->flushPoints(); -} - TEXFBO &Bitmap::getGLTypes() { return p->gl; diff --git a/src/bitmap.h b/src/bitmap.h index 0ac418b..86ca4c2 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -81,8 +81,8 @@ public: void clear(); - Vec4 getPixel(int x, int y) const; - void setPixel(int x, int y, const Vec4 &color); + Color getPixel(int x, int y) const; + void setPixel(int x, int y, const Color &color); void hueChange(int hue); @@ -105,9 +105,6 @@ public: DECL_ATTR(Font, Font*) /* */ - /* Warning: Flushing might change the current - * FBO binding (so don't call it during 'draw()' routines */ - void flush() const; TEXFBO &getGLTypes(); SDL_Surface *megaSurface() const; void ensureNonMega() const; diff --git a/src/gl-util.h b/src/gl-util.h index a00c119..d283bf5 100644 --- a/src/gl-util.h +++ b/src/gl-util.h @@ -216,15 +216,6 @@ namespace FBO blit(srcX, srcY, srcW, srcH, dstX, dstY, srcW, srcH, mode); } - inline Vec4 getPixel(int x, int y) - { - Vec4 pixel; - - glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &pixel.x); - - return pixel; - } - inline void clear() { glClear(GL_COLOR_BUFFER_BIT); diff --git a/src/plane.cpp b/src/plane.cpp index 8a876d8..cb76967 100644 --- a/src/plane.cpp +++ b/src/plane.cpp @@ -93,9 +93,6 @@ struct PlanePrivate updateQuadSource(); quadSourceDirty = false; } - - if (bitmap) - bitmap->flush(); } }; diff --git a/src/quadarray.h b/src/quadarray.h index 42c0c81..249bf8e 100644 --- a/src/quadarray.h +++ b/src/quadarray.h @@ -110,67 +110,4 @@ struct ColorQuadArray } }; -struct PointArray -{ - std::vector vertices; - VBO::ID vbo; - VAO::ID vao; - - PointArray() - { - vbo = VBO::gen(); - vao = VAO::gen(); - - VAO::bind(vao); - VBO::bind(vbo); - - glEnableVertexAttribArray(Shader::Color); - glEnableVertexAttribArray(Shader::Position); - - glVertexAttribPointer(Shader::Color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::colorOffset()); - glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::posOffset()); - - VAO::unbind(); - VBO::unbind(); - } - - ~PointArray() - { - VBO::del(vbo); - VAO::del(vao); - } - - void append(const Vec2 &pos, const Vec4 &color) - { - Vertex vert; - vert.pos = pos; - vert.color = color; - vertices.push_back(vert); - } - - void commit() - { - VBO::bind(vbo); - VBO::uploadData(vertices.size() * sizeof(Vertex), &vertices[0]); - VBO::unbind(); - } - - void reset() - { - vertices.clear(); - } - - void draw() - { - VAO::bind(vao); - glDrawArrays(GL_POINTS, 0, count()); - VAO::unbind(); - } - - int count() - { - return vertices.size(); - } -}; - #endif // QUADARRAY_H diff --git a/src/sprite.cpp b/src/sprite.cpp index 4a797d9..21bdf92 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -163,9 +163,6 @@ struct SpritePrivate void prepare() { - if (bitmap) - bitmap->flush(); - updateVisibility(); } }; diff --git a/src/tilemap.cpp b/src/tilemap.cpp index c1bd2b9..88cab6e 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -511,8 +511,6 @@ struct TilemapPrivate usableATs.push_back(i); - autotiles[i]->flush(); - if (autotiles[i]->width() > autotileW) animatedATs.push_back(i); } @@ -623,13 +621,8 @@ struct TilemapPrivate /* Assembles atlas from tileset and autotile bitmaps */ void buildAtlas() { - tileset->flush(); - updateAutotileInfo(); - for (size_t i = 0; i < atlas.usableATs.size(); ++i) - autotiles[atlas.usableATs[i]]->flush(); - TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size); /* Clear atlas */ diff --git a/src/window.cpp b/src/window.cpp index 0fd7198..4eb3a88 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -508,12 +508,6 @@ struct WindowPrivate { bool updateBaseQuadArray = false; - if (windowskin) - windowskin->flush(); - - if (contents) - contents->flush(); - if (baseVertDirty) { buildBaseVert();