Browse files

GLVideoDriver: More clean, more stable. Fixed problems with attached …

…palettes. Implemented GetScreenshot()
  • Loading branch information...
1 parent fb5bd1a commit f7ecbaca6af6868fda7603930ef747176bd907fd @BehoIder BehoIder committed with lynxlynxlynx Jan 11, 2014
View
44 gemrb/plugins/SDLVideo/GLPaletteManager.cpp
@@ -10,12 +10,10 @@
using namespace GemRB;
-std::map<PaletteKey, PaletteValue> GLPaletteManager::textures;
-
GLuint GLPaletteManager::CreatePaletteTexture(Palette* palette, unsigned int colorKey)
{
- PaletteKey key = std::make_pair(palette, colorKey);
- if (GLPaletteManager::textures.find(key) == GLPaletteManager::textures.end())
+ const PaletteKey key(palette, colorKey);
+ if (textures.find(key) == textures.end())
{
// not found, we need to create it
GLuint texture;
@@ -41,6 +39,7 @@ GLuint GLPaletteManager::CreatePaletteTexture(Palette* palette, unsigned int col
delete[] colors;
PaletteValue value = std::make_pair(texture, 1);
textures.insert(std::make_pair(key, value));
+ indexes.insert(std::make_pair(texture, key));
}
else
{
@@ -51,7 +50,7 @@ GLuint GLPaletteManager::CreatePaletteTexture(Palette* palette, unsigned int col
void GLPaletteManager::RemovePaletteTexture(Palette* palette, unsigned int colorKey)
{
- std::pair<Palette*, unsigned int> key = std::make_pair(palette, colorKey);
+ const PaletteKey key(palette, colorKey);
if (textures.find(key) == textures.end())
{
// nothing found
@@ -62,6 +61,7 @@ void GLPaletteManager::RemovePaletteTexture(Palette* palette, unsigned int color
if (value.second > 1) value.second --;
else
{
+ indexes.erase(value.first);
glDeleteTextures(1, &(value.first));
textures.erase(key);
}
@@ -70,29 +70,41 @@ void GLPaletteManager::RemovePaletteTexture(Palette* palette, unsigned int color
void GLPaletteManager::RemovePaletteTexture(GLuint texture)
{
- for(std::map<std::pair<Palette*, unsigned int>, PaletteValue>::iterator it = textures.begin(); it != textures.end(); ++it)
+ if (indexes.find(texture) == indexes.end())
{
- if(textures[it->first].first == texture)
+ // nothing found
+ }
+ else
+ {
+ PaletteKey key = indexes[texture];
+ PaletteValue value = textures[key];
+ if (value.second > 1) value.second --;
+ else
{
- if (textures[it->first].second > 1)
- textures[it->first].second--;
- else
- {
- glDeleteTextures(1, &texture);
- textures.erase(it->first);
- }
- return;
+ indexes.erase(texture);
+ glDeleteTextures(1, &texture);
+ textures.erase(key);
}
}
}
void GLPaletteManager::Clear()
{
- for(std::map<std::pair<Palette*, unsigned int>, PaletteValue>::iterator it = textures.begin(); it != textures.end(); ++it)
+ for(std::map<PaletteKey, PaletteValue, PaletteKey>::iterator it = textures.begin(); it != textures.end(); ++it)
{
glDeleteTextures(1, &(textures[it->first].first));
}
textures.clear();
+ indexes.clear();
+}
+
+GLPaletteManager::GLPaletteManager()
+{
+}
+
+GLPaletteManager::~GLPaletteManager()
+{
+ Clear();
}
View
32 gemrb/plugins/SDLVideo/GLPaletteManager.h
@@ -7,18 +7,38 @@ namespace GemRB
{
class Palette;
- typedef std::pair<Palette*, unsigned int> PaletteKey;
+ struct PaletteKey
+ {
+ Palette* palette;
+ unsigned int colorKey;
+ bool operator () (const PaletteKey& lhs, const PaletteKey& rhs) const
+ {
+ if (lhs.palette < rhs.palette) return true;
+ else
+ if (rhs.palette < lhs.palette) return false;
+ if (lhs.colorKey < rhs.colorKey) return true;
+ else
+ if (rhs.colorKey < lhs.colorKey) return false;
+ return false;
+ }
+ PaletteKey(Palette* pal, unsigned int key) { colorKey = key; palette = pal; }
+ PaletteKey() {}
+ };
+
typedef std::pair<GLuint, unsigned int> PaletteValue;
class GLPaletteManager
{
private:
- static std::map<PaletteKey, PaletteValue> textures;
+ std::map<PaletteKey, PaletteValue, PaletteKey> textures;
+ std::map<GLuint, PaletteKey> indexes;
public:
- static GLuint CreatePaletteTexture(Palette* palette, unsigned int colorKey);
- static void RemovePaletteTexture(Palette* palette, unsigned int colorKey);
- static void RemovePaletteTexture(GLuint texture);
- static void Clear();
+ GLuint CreatePaletteTexture(Palette* palette, unsigned int colorKey);
+ void RemovePaletteTexture(Palette* palette, unsigned int colorKey);
+ void RemovePaletteTexture(GLuint texture);
+ void Clear();
+ ~GLPaletteManager();
+ GLPaletteManager();
};
}
View
51 gemrb/plugins/SDLVideo/GLTextureSprite2D.cpp
@@ -41,9 +41,9 @@ GLTextureSprite2D::~GLTextureSprite2D()
if (glTexture != 0) glDeleteTextures(1, &glTexture);
if (glMaskTexture != 0) glDeleteTextures(1, &glMaskTexture);
if (glPaletteTexture != 0)
- GLPaletteManager::RemovePaletteTexture(currentPalette, colorKeyIndex);
+ paletteManager->RemovePaletteTexture(glPaletteTexture);
if (glAttachedPaletteTexture != 0)
- GLPaletteManager::RemovePaletteTexture(attachedPalette, colorKeyIndex);
+ paletteManager->RemovePaletteTexture(glAttachedPaletteTexture);
}
GLTextureSprite2D::GLTextureSprite2D(const GLTextureSprite2D &obj) : Sprite2D(obj)
@@ -56,6 +56,7 @@ GLTextureSprite2D::GLTextureSprite2D(const GLTextureSprite2D &obj) : Sprite2D(ob
currentPalette = NULL;
attachedPalette = NULL;
colorKeyIndex = obj.colorKeyIndex;
+ paletteManager = obj.paletteManager;
rMask = obj.rMask;
gMask = obj.bMask;
bMask = obj.bMask;
@@ -70,13 +71,13 @@ GLTextureSprite2D* GLTextureSprite2D::copy() const
void GLTextureSprite2D::SetPalette(Palette *pal)
{
- if(!IsPaletted() || currentPalette == pal || !pal) return;
+ if (!IsPaletted() || pal == NULL || currentPalette == pal) return;
pal->acquire();
- if (currentPalette)
+ if (currentPalette != NULL)
{
currentPalette->release();
}
- if (glPaletteTexture != 0) GLPaletteManager::RemovePaletteTexture(currentPalette, colorKeyIndex);
+ if (glPaletteTexture != 0) paletteManager->RemovePaletteTexture(glPaletteTexture);
glPaletteTexture = 0;
currentPalette = pal;
}
@@ -90,12 +91,13 @@ Palette* GLTextureSprite2D::GetPalette() const
void GLTextureSprite2D::SetColorKey(ieDword index)
{
+ if (colorKeyIndex == index) return;
colorKeyIndex = index;
if(IsPaletted())
{
glDeleteTextures(1, &glMaskTexture);
- if (glPaletteTexture != 0) GLPaletteManager::RemovePaletteTexture(currentPalette, colorKeyIndex);
- if (glAttachedPaletteTexture != 0) GLPaletteManager::RemovePaletteTexture(attachedPalette, colorKeyIndex);
+ if (glPaletteTexture != 0) paletteManager->RemovePaletteTexture(glPaletteTexture);
+ if (glAttachedPaletteTexture != 0) paletteManager->RemovePaletteTexture(glAttachedPaletteTexture);
glPaletteTexture = 0;
glAttachedPaletteTexture = 0;
glMaskTexture = 0;
@@ -113,15 +115,26 @@ Color GLTextureSprite2D::GetPixel(unsigned short x, unsigned short y) const
if (Bpp == 8)
{
Uint8 pixel = ((Uint8*)pixels)[y*Width + x];
- Color color = currentPalette->col[pixel]; // hack (we have a = 0 for non-transparent pixels on palette)
- if(pixel != colorKeyIndex) color.a = 255;
+ Color color = currentPalette->col[pixel];
+ // hack (we have a = 0 for non-transparent pixels on palette)
+ if (pixel != colorKeyIndex) color.a = 255;
+ return color;
+ }
+ else
+ {
+ Uint32 pixel = ((Uint32*)pixels)[y*Width + x];
+ Color color;
+ color.r = (pixel & rMask) >> GetShiftValue(rMask);
+ color.g = (pixel & gMask) >> GetShiftValue(gMask);
+ color.b = (pixel & bMask) >> GetShiftValue(bMask);
+ color.a = (pixel & aMask) >> GetShiftValue(aMask);
return color;
}
- return Color(); // not supported yet
}
void GLTextureSprite2D::createGlTexture()
{
+ if (Bpp != 32 && Bpp != 8) return;
if (glTexture != 0) glDeleteTextures(1, &glTexture);
glGenTextures(1, &glTexture);
glBindTexture(GL_TEXTURE_2D, glTexture);
@@ -158,7 +171,7 @@ void GLTextureSprite2D::createGlTexture()
void GLTextureSprite2D::createGlTextureForPalette()
{
- glPaletteTexture = GLPaletteManager::CreatePaletteTexture(currentPalette, colorKeyIndex);
+ glPaletteTexture = paletteManager->CreatePaletteTexture(currentPalette, colorKeyIndex);
}
void GLTextureSprite2D::createGLMaskTexture()
@@ -191,17 +204,25 @@ GLuint GLTextureSprite2D::GetPaletteTexture()
}
// use this method only for adding external palettes
-GLuint GLTextureSprite2D::GetPaletteTexture(Palette* attached)
+GLuint GLTextureSprite2D::GetAttachedPaletteTexture(Palette* attached)
{
- if (attached == NULL || !IsPaletted()) return 0; // nothing to do
-
+ if (!IsPaletted()) return 0;
// we already have a texture for requested palette
if (attached == attachedPalette && glAttachedPaletteTexture != 0) return glAttachedPaletteTexture;
attachedPalette = attached;
- glAttachedPaletteTexture = GLPaletteManager::CreatePaletteTexture(attachedPalette, colorKeyIndex);
+ attachedPalette->acquire();
+ glAttachedPaletteTexture = paletteManager->CreatePaletteTexture(attachedPalette, colorKeyIndex);
return glAttachedPaletteTexture;
}
+void GLTextureSprite2D::RemoveAttachedPaletteTexture()
+{
+ if (glAttachedPaletteTexture != 0) paletteManager->RemovePaletteTexture(glAttachedPaletteTexture);
+ glAttachedPaletteTexture = 0;
+ attachedPalette->release();
+ attachedPalette = NULL;
+}
+
GLuint GLTextureSprite2D::GetMaskTexture()
{
if (!IsPaletted()) return 0; // nothing to do
View
8 gemrb/plugins/SDLVideo/GLTextureSprite2D.h
@@ -5,6 +5,8 @@
namespace GemRB
{
+ class GLPaletteManager;
+
class GLTextureSprite2D : public Sprite2D
{
private:
@@ -19,12 +21,15 @@ namespace GemRB
Palette* attachedPalette;
GLuint glAttachedPaletteTexture;
+ GLPaletteManager* paletteManager;
+
void createGlTexture();
void createGlTextureForPalette();
void createGLMaskTexture();
public:
GLuint GetTexture();
- GLuint GetPaletteTexture(Palette* pal);
+ GLuint GetAttachedPaletteTexture(Palette* attached);
+ void RemoveAttachedPaletteTexture();
GLuint GetPaletteTexture();
GLuint GetMaskTexture();
void SetPaletteTexture(int texture);
@@ -35,6 +40,7 @@ namespace GemRB
ieDword GetColorKey() const { return colorKeyIndex; }
void SetColorKey(ieDword);
bool IsPaletted() const { return Bpp == 8; }
+ void SetPaletteManager(GLPaletteManager* manager) { paletteManager = manager; }
GLTextureSprite2D (int Width, int Height, int Bpp, void* pixels, Uint32 rmask=0, Uint32 gmask=0, Uint32 bmask=0, Uint32 amask=0);
~GLTextureSprite2D();
GLTextureSprite2D(const GLTextureSprite2D &obj);
View
82 gemrb/plugins/SDLVideo/SDL20GLVideo.cpp
@@ -137,7 +137,7 @@ GLVideoDriver::~GLVideoDriver()
glDeleteProgram(programPalGrayed);
glDeleteProgram(programPalSepia);
glDeleteProgram(programRect);
- GLPaletteManager::Clear();
+ delete paletteManager;
SDL_GL_DeleteContext(context);
}
@@ -232,6 +232,7 @@ int GLVideoDriver::CreateDisplay(int w, int h, int bpp, bool fs, const char* tit
glewInit();
#endif
if (!createPrograms()) return GEM_ERROR;
+ paletteManager = new GLPaletteManager();
glViewport(0, 0, width, height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -340,6 +341,7 @@ Sprite2D* GLVideoDriver::CreateSprite(int w, int h, int bpp, ieDword rMask, ieDw
Sprite2D* GLVideoDriver::CreatePalettedSprite(int w, int h, int bpp, void* pixels, Color* palette, bool cK, int index)
{
GLTextureSprite2D* spr = new GLTextureSprite2D(w, h, bpp, pixels);
+ spr->SetPaletteManager(paletteManager);
Palette* pal = new Palette(palette);
spr->SetPalette(pal);
if (cK) spr->SetColorKey(index);
@@ -351,7 +353,7 @@ Sprite2D* GLVideoDriver::CreateSprite8(int w, int h, void* pixels, Palette* pale
return CreatePalettedSprite(w, h, 8, pixels, palette->col, cK, index);
}
-void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Region* clip, unsigned int flags, const Color* tint, GLTextureSprite2D* mask)
+void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Region* clip, Palette* attachedPal, unsigned int flags, const Color* tint, GLTextureSprite2D* mask)
{
float hscale, vscale;
SDL_Rect spriteRect;
@@ -421,6 +423,7 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
// shader program selection
GLuint program;
+ GLuint palTexture;
if(spr->IsPaletted())
{
if (flags & BLIT_GREY)
@@ -429,12 +432,17 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
program = programPalSepia;
else
program = programPal;
+
+ glActiveTexture(GL_TEXTURE1);
+ if (attachedPal)
+ palTexture = spr->GetAttachedPaletteTexture(attachedPal);
+ else
+ palTexture = spr->GetPaletteTexture();
+ glBindTexture(GL_TEXTURE_2D, palTexture);
}
else
{
program = program32;
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, 0);
}
useProgram(program);
@@ -448,6 +456,7 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
GLuint maskTexture = ((GLTextureSprite2D*)mask)->GetMaskTexture();
glBindTexture(GL_TEXTURE_2D, maskTexture);
}
+ else
if(flags & BLIT_EXTERNAL_MASK) {} // used with external mask
else
{
@@ -483,6 +492,9 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
glDisableVertexAttribArray(a_texCoord);
glDisableVertexAttribArray(a_position);
+ // renove attached texture
+ if (attachedPal && !attachedPal->IsShared()) spr->RemoveAttachedPaletteTexture();
+
glDeleteBuffers(1, &buffer);
spritesPerFrame++;
}
@@ -497,43 +509,26 @@ void GLVideoDriver::BlitTile(const Sprite2D* spr, const Sprite2D* mask, int x, i
if (flags & TILE_HALFTRANS) blitFlags |= BLIT_HALFTRANS;
if (flags & TILE_GREY) blitFlags |= BLIT_GREY;
if (flags & TILE_SEPIA) blitFlags |= BLIT_SEPIA;
- GLTextureSprite2D* glSprite = (GLTextureSprite2D*)spr;
- if (glSprite->IsPaletted())
- {
- GLuint palTexture = glSprite->GetPaletteTexture();
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, palTexture);
- }
+
if (core->GetGame())
{
const Color* totint = core->GetGame()->GetGlobalTint();
- return blitSprite(glSprite, tx, ty, clip, blitFlags, totint, (GLTextureSprite2D*)mask);
+ return blitSprite((GLTextureSprite2D*)spr, tx, ty, clip, NULL, blitFlags, totint, (GLTextureSprite2D*)mask);
}
- return blitSprite(glSprite, tx, ty, clip, blitFlags, NULL, (GLTextureSprite2D*)mask);
+ return blitSprite((GLTextureSprite2D*)spr, tx, ty, clip, NULL, blitFlags, NULL, (GLTextureSprite2D*)mask);
}
-
void GLVideoDriver::BlitSprite(const Sprite2D* spr, int x, int y, bool anchor, const Region* clip, Palette* palette)
{
// x, y is a position on screen (if anchor) or viewport (if !anchor)
- GLTextureSprite2D* glSprite = (GLTextureSprite2D*)spr;
int tx = x - spr->XPos;
int ty = y - spr->YPos;
if (!anchor)
{
tx -= Viewport.x;
ty -= Viewport.y;
}
- if (glSprite->IsPaletted())
- {
- GLuint palTexture;
- if (palette) palTexture = glSprite->GetPaletteTexture(palette);
- else palTexture = glSprite->GetPaletteTexture();
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, palTexture);
- }
-
- return blitSprite(glSprite, tx, ty, clip);
+ return blitSprite((GLTextureSprite2D*)spr, tx, ty, clip, palette);
}
void GLVideoDriver::BlitGameSprite(const Sprite2D* spr, int x, int y, unsigned int flags, Color tint, SpriteCover* cover, Palette *palette, const Region* clip, bool anchor)
@@ -580,16 +575,6 @@ void GLVideoDriver::BlitGameSprite(const Sprite2D* spr, int x, int y, unsigned i
delete[] data;
flags |= BLIT_EXTERNAL_MASK;
}
-
- if (glSprite->IsPaletted())
- {
- GLuint palTexture;
- if (palette) palTexture = glSprite->GetPaletteTexture(palette);
- else palTexture = glSprite->GetPaletteTexture();
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, palTexture);
- }
-
if (!anchor && core->GetGame())
{
const Color *totint = core->GetGame()->GetGlobalTint();
@@ -606,15 +591,15 @@ void GLVideoDriver::BlitGameSprite(const Sprite2D* spr, int x, int y, unsigned i
flags |= BLIT_TINTED;
tint = *totint;
}
- blitSprite(glSprite, tx, ty, clip, flags, &tint);
+ blitSprite(glSprite, tx, ty, clip, palette, flags, &tint);
}
- else blitSprite(glSprite, tx, ty, clip, flags);
+ else blitSprite(glSprite, tx, ty, clip, palette, flags);
}
else
- blitSprite(glSprite, tx, ty, clip, flags);
+ blitSprite(glSprite, tx, ty, clip, palette, flags);
}
else
- blitSprite(glSprite, tx, ty, clip, flags);
+ blitSprite(glSprite, tx, ty, clip, palette, flags);
if (coverTexture != 0)
{
glActiveTexture(GL_TEXTURE2);
@@ -720,9 +705,22 @@ Sprite2D* GLVideoDriver::GetScreenshot(Region r)
{
unsigned int w = r.w ? r.w : width - r.x;
unsigned int h = r.h ? r.h : height - r.y;
- Uint8* pixels = new Uint8[3*w*h];
- glReadPixels(r.x, r.y, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels);
- Sprite2D* screenshot = new GLTextureSprite2D(w, h, 24, pixels, 0x00ff0000, 0x0000ff00, 0x000000ff);
+
+ Uint32* glPixels = (Uint32*)malloc( w * h * 4 );
+ Uint32* pixels = (Uint32*)malloc( w * h * 4 );
+ glReadBuffer(GL_BACK);
+ glReadPixels(r.x, r.y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, glPixels);
+ // flip pixels vertical
+ Uint32* pixelDstPointer = pixels;
+ Uint32* pixelSrcPointer = glPixels + (h-1)*w;
+ for(int i=0; i<h; i++)
+ {
+ memcpy(pixelDstPointer, pixelSrcPointer, w*4);
+ pixelDstPointer += w;
+ pixelSrcPointer -= w;
+ }
+ free(glPixels);
+ Sprite2D* screenshot = new GLTextureSprite2D(w, h, 32, pixels, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
return screenshot;
}
View
5 gemrb/plugins/SDLVideo/SDL20GLVideo.h
@@ -14,6 +14,7 @@
namespace GemRB
{
class GLTextureSprite2D;
+ class GLPaletteManager;
class GLVideoDriver : public SDL20VideoDriver
{
@@ -29,9 +30,11 @@ namespace GemRB
Uint32 spritesPerFrame; // sprites counter
GLuint lastUsedProgram; // stores last used program to prevent switching if possible (switching may cause performance lack)
+ GLPaletteManager* paletteManager; // palette manager instance
+
void useProgram(GLuint program); // use this instead glUseProgram
bool createPrograms();
- void blitSprite(GLTextureSprite2D* spr, int x, int y, const Region* clip, unsigned int flags = 0, const Color* tint = NULL, GLTextureSprite2D* mask = NULL);
+ void blitSprite(GLTextureSprite2D* spr, int x, int y, const Region* clip, Palette* attachedPal = NULL, unsigned int flags = 0, const Color* tint = NULL, GLTextureSprite2D* mask = NULL);
void drawColoredRect(const Region& rgn, const Color& color);
public:
View
2 gemrb/plugins/SDLVideo/SDLVideo.h
@@ -98,7 +98,7 @@ class SDLVideoDriver : public Video {
SpriteCover* cover, Palette *palette = NULL,
const Region* clip = NULL, bool anchor = false);
- Sprite2D* GetScreenshot( Region r );
+ virtual Sprite2D* GetScreenshot( Region r );
/** This function Draws the Border of a Rectangle as described by the Region parameter. The Color used to draw the rectangle is passes via the Color parameter. */
virtual void DrawRect(const Region& rgn, const Color& color, bool fill = true, bool clipped = false);
void DrawRectSprite(const Region& rgn, const Color& color, const Sprite2D* sprite);

0 comments on commit f7ecbac

Please sign in to comment.