ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

graphics/tinygl/texture.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 /*
00024  * This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
00025  * which is licensed under the zlib-license (see LICENSE).
00026  * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
00027  */
00028 
00029 // Texture Manager
00030 
00031 #include "common/endian.h"
00032 
00033 #include "graphics/tinygl/zgl.h"
00034 
00035 namespace TinyGL {
00036 
00037 static GLTexture *find_texture(GLContext *c, unsigned int h) {
00038     GLTexture *t;
00039 
00040     t = c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
00041     while (t) {
00042         if (t->handle == h)
00043             return t;
00044         t = t->next;
00045     }
00046     return NULL;
00047 }
00048 
00049 void free_texture(GLContext *c, int h) {
00050     free_texture(c, find_texture(c, h));
00051 }
00052 
00053 void free_texture(GLContext *c, GLTexture *t) {
00054     GLTexture **ht;
00055     GLImage *im;
00056 
00057     if (!t->prev) {
00058         ht = &c->shared_state.texture_hash_table[t->handle % TEXTURE_HASH_TABLE_SIZE];
00059         *ht = t->next;
00060     } else {
00061         t->prev->next = t->next;
00062     }
00063     if (t->next)
00064         t->next->prev = t->prev;
00065 
00066     for (int i = 0; i < MAX_TEXTURE_LEVELS; i++) {
00067         im = &t->images[i];
00068         if (im->pixmap)
00069             im->pixmap.free();
00070     }
00071 
00072     gl_free(t);
00073 }
00074 
00075 GLTexture *alloc_texture(GLContext *c, int h) {
00076     GLTexture *t, **ht;
00077 
00078     t = (GLTexture *)gl_zalloc(sizeof(GLTexture));
00079 
00080     ht = &c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
00081 
00082     t->next = *ht;
00083     t->prev = NULL;
00084     if (t->next)
00085         t->next->prev = t;
00086     *ht = t;
00087 
00088     t->handle = h;
00089     t->disposed = false;
00090     t->versionNumber = 0;
00091 
00092     return t;
00093 }
00094 
00095 void glInitTextures(GLContext *c) {
00096     // textures
00097     c->texture_2d_enabled = 0;
00098     c->current_texture = find_texture(c, 0);
00099 }
00100 
00101 void glopBindTexture(GLContext *c, GLParam *p) {
00102     int target = p[1].i;
00103     int texture = p[2].i;
00104     GLTexture *t;
00105 
00106     assert(target == TGL_TEXTURE_2D && texture >= 0);
00107 
00108     t = find_texture(c, texture);
00109     if (!t) {
00110         t = alloc_texture(c, texture);
00111     }
00112     c->current_texture = t;
00113 }
00114 
00115 void glopTexImage2D(GLContext *c, GLParam *p) {
00116     int target = p[1].i;
00117     int level = p[2].i;
00118     int components = p[3].i;
00119     int width = p[4].i;
00120     int height = p[5].i;
00121     int border = p[6].i;
00122     int format = p[7].i;
00123     int type = p[8].i;
00124     byte *pixels = (byte *)p[9].p;
00125     GLImage *im;
00126     byte *pixels1;
00127     bool do_free_after_rgb2rgba = false;
00128 
00129     Graphics::PixelFormat sourceFormat;
00130     switch (format) {
00131         case TGL_RGBA:
00132             sourceFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
00133             break;
00134         case TGL_RGB:
00135             sourceFormat = Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0);
00136             break;
00137         case TGL_BGRA:
00138             sourceFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
00139             break;
00140         case TGL_BGR:
00141             sourceFormat = Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
00142             break;
00143         default:
00144             error("tglTexImage2D: Pixel format not handled.");
00145     }
00146 
00147     Graphics::PixelFormat pf;
00148     switch (format) {
00149         case TGL_RGBA:
00150         case TGL_RGB:
00151 #if defined(SCUMM_BIG_ENDIAN)
00152             pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
00153 #elif defined(SCUMM_LITTLE_ENDIAN)
00154             pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
00155 #endif
00156             break;
00157         case TGL_BGRA:
00158         case TGL_BGR:
00159 #if defined(SCUMM_BIG_ENDIAN)
00160             pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 0, 8, 16);
00161 #elif defined(SCUMM_LITTLE_ENDIAN)
00162             pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
00163 #endif
00164             break;
00165         default:
00166             break;
00167     }
00168     int bytes = pf.bytesPerPixel;
00169 
00170     // Simply unpack RGB into RGBA with 255 for Alpha.
00171     // FIXME: This will need additional checks when we get around to adding 24/32-bit backend.
00172     if (target == TGL_TEXTURE_2D && level == 0 && components == 3 && border == 0 && pixels != NULL) {
00173         if (format == TGL_RGB || format == TGL_BGR) {
00174             Graphics::PixelBuffer temp(pf, width * height, DisposeAfterUse::NO);
00175             Graphics::PixelBuffer pixPtr(sourceFormat, pixels);
00176 
00177             for (int i = 0; i < width * height; ++i) {
00178                 uint8 r, g, b;
00179                 pixPtr.getRGBAt(i, r, g, b);
00180                 temp.setPixelAt(i, 255, r, g, b);
00181             }
00182             pixels = temp.getRawBuffer();
00183             do_free_after_rgb2rgba = true;
00184         }
00185     } else if ((format != TGL_RGBA &&
00186             format != TGL_RGB &&
00187             format != TGL_BGR &&
00188             format != TGL_BGRA) ||
00189             (type != TGL_UNSIGNED_BYTE &&
00190              type != TGL_UNSIGNED_INT_8_8_8_8_REV)) {
00191         error("tglTexImage2D: combination of parameters not handled");
00192     }
00193 
00194     pixels1 = new byte[c->_textureSize * c->_textureSize * bytes];
00195     if (pixels != NULL) {
00196         if (width != c->_textureSize || height != c->_textureSize) {
00197             // we use interpolation for better looking result
00198             gl_resizeImage(pixels1, c->_textureSize, c->_textureSize, pixels, width, height);
00199             width = c->_textureSize;
00200             height = c->_textureSize;
00201         } else {
00202             memcpy(pixels1, pixels, c->_textureSize * c->_textureSize * bytes);
00203         }
00204 #if defined(SCUMM_BIG_ENDIAN)
00205         if (type == TGL_UNSIGNED_INT_8_8_8_8_REV) {
00206             for (int y = 0; y < height; y++) {
00207                 for (int x = 0; x < width; x++) {
00208                     uint32 offset = (y * width + x) * 4;
00209                     byte *data = pixels1 + offset;
00210                     WRITE_BE_UINT32(data, READ_LE_UINT32(data));
00211                 }
00212             }
00213         }
00214 #endif
00215     }
00216 
00217     c->current_texture->versionNumber++;
00218     im = &c->current_texture->images[level];
00219     im->xsize = width;
00220     im->ysize = height;
00221     if (im->pixmap)
00222         im->pixmap.free();
00223     im->pixmap = Graphics::PixelBuffer(pf, pixels1);
00224 
00225     if (do_free_after_rgb2rgba) {
00226         // pixels as been assigned to tmp.getRawBuffer() which was created with
00227         // DisposeAfterUse::NO, therefore delete[] it
00228         delete[] pixels;
00229     }
00230 }
00231 
00232 // TODO: not all tests are done
00233 void glopTexEnv(GLContext *, GLParam *p) {
00234     int target = p[1].i;
00235     int pname = p[2].i;
00236     int param = p[3].i;
00237 
00238     if (target != TGL_TEXTURE_ENV) {
00239 error:
00240         error("tglTexParameter: unsupported option");
00241     }
00242 
00243     if (pname != TGL_TEXTURE_ENV_MODE)
00244         goto error;
00245 
00246     if (param != TGL_DECAL)
00247         goto error;
00248 }
00249 
00250 // TODO: not all tests are done
00251 void glopTexParameter(GLContext *, GLParam *p) {
00252     int target = p[1].i;
00253     int pname = p[2].i;
00254     int param = p[3].i;
00255 
00256     if (target != TGL_TEXTURE_2D) {
00257 error:
00258         error("tglTexParameter: unsupported option");
00259     }
00260 
00261     switch (pname) {
00262     case TGL_TEXTURE_WRAP_S:
00263     case TGL_TEXTURE_WRAP_T:
00264         if (param != TGL_REPEAT)
00265             goto error;
00266         break;
00267     default:
00268         ;
00269     }
00270 }
00271 
00272 void glopPixelStore(GLContext *, GLParam *p) {
00273     int pname = p[1].i;
00274     int param = p[2].i;
00275 
00276     if (pname != TGL_UNPACK_ALIGNMENT || param != 1) {
00277         error("tglPixelStore: unsupported option");
00278     }
00279 }
00280 
00281 } // end of namespace TinyGL
00282 
00283 void tglGenTextures(int n, unsigned int *textures) {
00284     TinyGL::GLContext *c = TinyGL::gl_get_context();
00285     unsigned int max;
00286     TinyGL::GLTexture *t;
00287 
00288     max = 0;
00289     for (int i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) {
00290         t = c->shared_state.texture_hash_table[i];
00291         while (t) {
00292             if (t->handle > max)
00293                 max = t->handle;
00294             t = t->next;
00295         }
00296     }
00297     for (int i = 0; i < n; i++) {
00298         textures[i] = max + i + 1;
00299     }
00300 }
00301 
00302 void tglDeleteTextures(int n, const unsigned int *textures) {
00303     TinyGL::GLContext *c = TinyGL::gl_get_context();
00304     TinyGL::GLTexture *t;
00305 
00306     for (int i = 0; i < n; i++) {
00307         t = TinyGL::find_texture(c, textures[i]);
00308         if (t) {
00309             if (t == c->current_texture) {
00310                 tglBindTexture(TGL_TEXTURE_2D, 0);
00311             }
00312             t->disposed = true;
00313         }
00314     }
00315 }


Generated on Sat Feb 16 2019 05:01:08 for ResidualVM by doxygen 1.7.1
curved edge   curved edge