00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cassert>
00024 #include <iostream>
00025
00026
00027
00028
00029
00030
00031 #include "util/structures/rect.h"
00032 #include "video/sdl/sdlimage.h"
00033 #include "video/renderbackend.h"
00034
00035 #include "glimage.h"
00036
00037 namespace FIFE {
00038 GLImage::GLImage(SDL_Surface* surface):
00039 Image(surface) {
00040 m_sdlimage = new SDLImage(surface);
00041
00042 m_textureids = NULL;
00043
00044 resetGlimage();
00045 }
00046
00047 GLImage::GLImage(const uint8_t* data, unsigned int width, unsigned int height):
00048 Image(data, width, height) {
00049 assert(m_surface);
00050 m_sdlimage = new SDLImage(m_surface);
00051
00052 m_textureids = NULL;
00053
00054 resetGlimage();
00055 }
00056
00057 GLImage::~GLImage() {
00058
00059 m_sdlimage->detachSurface();
00060 delete m_sdlimage;
00061
00062 cleanup();
00063 }
00064
00065 void GLImage::invalidate() {
00066 resetGlimage();
00067 }
00068
00069 void GLImage::resetGlimage() {
00070 cleanup();
00071
00072 m_chunk_size_w = 0;
00073 m_chunk_size_h = 0;
00074
00075 m_colorkey = RenderBackend::instance()->getColorKey();
00076 }
00077
00078 void GLImage::cleanup() {
00079 if (m_textureids) {
00080 glDeleteTextures(1, &m_textureids[0]);
00081
00082 delete[] m_textureids;
00083 m_textureids = NULL;
00084 }
00085
00086 m_col_tex_coord = 0;
00087 m_row_tex_coord = 0;
00088 }
00089
00090 void GLImage::render(const Rect& rect, SDL_Surface* screen, unsigned char alpha) {
00091 if (!m_textureids) {
00092 generateGLTexture();
00093 }
00094
00095
00096 if (rect.right() < 0 || rect.x > static_cast<int>(screen->w) || rect.bottom() < 0 || rect.y > static_cast<int>(screen->h)) {
00097 return;
00098 }
00099
00100
00101 if (0 == alpha) {
00102 return;
00103 }
00104
00105
00106 float scale_x = static_cast<float>(rect.w) / static_cast<float>(m_surface->w);
00107 float scale_y = static_cast<float>(rect.h) / static_cast<float>(m_surface->h);
00108
00109
00110 uint16_t w = static_cast<int>(round(scale_x*m_surface->w));
00111 uint16_t h = static_cast<int>(round(scale_y*m_surface->h));
00112
00113
00114 glColor4ub( 255, 255, 255, alpha );
00115
00116 glEnable(GL_TEXTURE_2D);
00117 glBindTexture(GL_TEXTURE_2D, m_textureids[0]);
00118
00119 glBegin(GL_QUADS);
00120 glTexCoord2f(0.0f, 0.0f);
00121 glVertex2i(rect.x, rect.y);
00122
00123 glTexCoord2f(0.0f, m_row_tex_coord);
00124 glVertex2i(rect.x, rect.y + h);
00125
00126 glTexCoord2f(m_col_tex_coord, m_row_tex_coord);
00127 glVertex2i(rect.x + w, rect.y + h);
00128
00129 glTexCoord2f(m_col_tex_coord, 0.0f);
00130 glVertex2i(rect.x + w, rect.y);
00131 glEnd();
00132 glDisable(GL_TEXTURE_2D);
00133
00134 }
00135
00136 void GLImage::generateGLTexture() {
00137 const unsigned int width = m_surface->w;
00138 const unsigned int height = m_surface->h;
00139
00140
00141 m_chunk_size_w = nextPow2(width);
00142 m_chunk_size_h = nextPow2(height);
00143
00144
00145 m_col_tex_coord = static_cast<float>(m_surface->w%m_chunk_size_w) / static_cast<float>(m_chunk_size_w);
00146 m_row_tex_coord = static_cast<float>(m_surface->h%m_chunk_size_h) / static_cast<float>(m_chunk_size_h);
00147
00148 if (m_col_tex_coord == 0.0f){
00149 m_col_tex_coord = 1.0f;
00150 }
00151
00152 if (m_row_tex_coord == 0.0f){
00153 m_row_tex_coord = 1.0f;
00154 }
00155
00156 uint8_t* data = static_cast<uint8_t*>(m_surface->pixels);
00157 int pitch = m_surface->pitch;
00158
00159
00160 assert(!m_textureids);
00161
00162 m_textureids = new GLuint[1];
00163 memset(m_textureids, 0x00, 1*sizeof(GLuint));
00164
00165
00166 uint32_t* oglbuffer = new uint32_t[m_chunk_size_w * m_chunk_size_h];
00167 memset(oglbuffer, 0x00, m_chunk_size_w*m_chunk_size_h*sizeof(uint32_t));
00168
00169 for (unsigned int y = 0; y < height; ++y) {
00170 for (unsigned int x = 0; x < width; ++x) {
00171 unsigned int pos = (y * pitch) + (x * 4);
00172
00173 uint8_t r = data[pos + 3];
00174 uint8_t g = data[pos + 2];
00175 uint8_t b = data[pos + 1];
00176 uint8_t a = data[pos + 0];
00177
00178 if (RenderBackend::instance()->isColorKeyEnabled()) {
00179
00180 if (r == m_colorkey.r && g == m_colorkey.g && b == m_colorkey.b) {
00181 a = 0;
00182 }
00183 }
00184
00185 oglbuffer[(y*m_chunk_size_w) + x] = r | (g << 8) | (b << 16) | (a<<24);
00186 }
00187 }
00188
00189
00190 glGenTextures(1, &m_textureids[0]);
00191
00192 glBindTexture(GL_TEXTURE_2D, m_textureids[0]);
00193
00194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00196
00197 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_chunk_size_w, m_chunk_size_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(oglbuffer));
00198
00199 delete[] oglbuffer;
00200 }
00201
00202 void GLImage::saveImage(const std::string& filename) {
00203 const unsigned int swidth = getWidth();
00204 const unsigned int sheight = getHeight();
00205 SDL_Surface *surface = NULL;
00206 uint8_t *pixels;
00207
00208 surface = SDL_CreateRGBSurface(SDL_SWSURFACE, swidth,
00209 sheight, 24,
00210 RMASK,GMASK,BMASK, NULLMASK);
00211
00212 if(surface == NULL) {
00213 return;
00214 }
00215
00216 SDL_LockSurface(surface);
00217 pixels = new uint8_t[swidth * sheight * 3];
00218 glReadPixels(0, 0, swidth, sheight, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(pixels));
00219
00220 uint8_t *imagepixels = reinterpret_cast<uint8_t*>(surface->pixels);
00221
00222 for (int y = (sheight - 1); y >= 0; --y) {
00223 uint8_t *rowbegin = pixels + y * swidth * 3;
00224 uint8_t *rowend = rowbegin + swidth * 3;
00225
00226 std::copy(rowbegin, rowend, imagepixels);
00227
00228
00229 imagepixels += surface->pitch;
00230 }
00231
00232 SDL_UnlockSurface(surface);
00233 saveAsPng(filename, *surface);
00234 SDL_FreeSurface(surface);
00235 delete [] pixels;
00236 }
00237
00238 void GLImage::setClipArea(const Rect& cliparea, bool clear) {
00239 glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h);
00240
00241 if (clear) {
00242 glClear(GL_COLOR_BUFFER_BIT);
00243 }
00244 }
00245
00246 bool GLImage::putPixel(int x, int y, int r, int g, int b, int a) {
00247 cleanup();
00248 return m_sdlimage->putPixel(x, y, r, g, b, a);
00249 }
00250
00251 void GLImage::drawLine(const Point& p1, const Point& p2, int r, int g, int b, int a) {
00252 cleanup();
00253 m_sdlimage->drawLine(p1, p2, r, g, b, a);
00254 }
00255
00256 void GLImage::drawTriangle(const Point& p1, const Point& p2, const Point& p3, int r, int g, int b, int a) {
00257 cleanup();
00258 m_sdlimage->drawTriangle(p1, p2, p3, r, g, b, a);
00259 }
00260
00261 void GLImage::drawRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00262 cleanup();
00263 m_sdlimage->drawRectangle(p, w, h, r, g, b, a);
00264 }
00265
00266 void GLImage::fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00267 cleanup();
00268 m_sdlimage->fillRectangle(p, w, h, r, g, b, a);
00269 }
00270
00271 void GLImage::drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a) {
00272 cleanup();
00273 m_sdlimage->drawQuad(p1, p2, p3, p4, r, g, b, a);
00274 }
00275
00276 void GLImage::drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a) {
00277 cleanup();
00278 m_sdlimage->drawVertex(p, size, r, g, b, a);
00279 }
00280
00281 void GLImage::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) {
00282 cleanup();
00283 m_sdlimage->drawLightPrimitive(p, intensity, radius, subdivisions, xstretch, ystretch, red, green, blue);
00284 }
00285 }