00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include <config.h>
00025 #endif
00026
00027 #ifdef HAVE_OPENGL
00028
00029 #include <GL/gl.h>
00030
00031 #include "glshape.h"
00032 #include "vgafile.h"
00033 #include "utils.h"
00034 #include "exult_constants.h"
00035 #include "ibuf8.h"
00036
00037 GL_manager *GL_manager::instance = 0;
00038
00039 const unsigned char transp = 255;
00040
00041
00042
00043
00044
00045
00046 void GL_texshape::create
00047 (
00048 Image_buffer8 *src,
00049 unsigned char *pal,
00050 Xform_palette *xforms,
00051 int xfcnt
00052 )
00053 {
00054 assert(pal != 0);
00055 const int xfstart = 0xff - xfcnt;
00056
00057 unsigned char *pixels = xforms ?
00058 src->rgba(pal, transp, xfstart, 0xfe, xforms)
00059 : src->rgba(pal, transp);
00060 GLuint tex;
00061 glGenTextures(1, &tex);
00062 texture = tex;
00063 glBindTexture(GL_TEXTURE_2D, texture);
00064
00065
00066
00067 GLint iformat = xforms ? GL_RGBA4 : GL_RGB5_A1;
00068
00069 glTexImage2D(GL_TEXTURE_2D, 0, iformat, texsize, texsize, 0, GL_RGBA,
00070 GL_UNSIGNED_BYTE, pixels);
00071 delete pixels;
00072
00073 #if 0
00074 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00075 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00076 #else
00077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00079 #endif
00080
00081
00082 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);
00083 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);
00084
00085 }
00086
00087
00088
00089
00090
00091 GL_texshape::GL_texshape
00092 (
00093 Shape_frame *f,
00094 unsigned char *pal,
00095 Xform_palette *xforms,
00096 int xfcnt
00097 ) : frame(f), lru_next(0), lru_prev(0)
00098 {
00099 int w = frame->get_width(), h = frame->get_height();
00100
00101
00102 int logw = Log2(2*w - 1), logh = Log2(2*h - 1);
00103 texsize = 1<<(logw > logh ? logw : logh);
00104
00105 Image_buffer8 buf8(texsize, texsize);
00106 buf8.fill8(transp);
00107
00108 frame->paint(&buf8, texsize - frame->get_xright() - 1,
00109 texsize - frame->get_ybelow() - 1);
00110 create(&buf8, pal, xforms, xfcnt);
00111 }
00112
00113
00114
00115
00116
00117 GL_texshape::GL_texshape
00118 (
00119 Image_buffer8 *src,
00120 unsigned char *pal
00121 ) : frame(0), lru_next(0), lru_prev(0)
00122 {
00123 int w = src->get_width(), h = src->get_height();
00124 assert (w == h);
00125 assert ((1<<Log2(w)) == w);
00126 texsize = w;
00127 create(src, pal);
00128 }
00129
00130
00131
00132
00133
00134 GL_texshape::~GL_texshape
00135 (
00136 )
00137 {
00138 glDeleteTextures(1, &texture);
00139 if (frame)
00140 frame->glshape = 0;
00141 }
00142
00143
00144
00145
00146
00147 void GL_texshape::paint
00148 (
00149 int px, int py
00150
00151 )
00152 {
00153 glEnable(GL_TEXTURE_2D);
00154 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00155 glPushMatrix();
00156 float x = static_cast<float>(px);
00157 float y = static_cast<float>(py) + texsize;
00158 if (frame)
00159 {
00160 x += frame->get_xright() + 1 - (int) texsize;
00161 y += frame->get_ybelow() + 1 - (int) texsize;
00162 }
00163
00164 y = -y;
00165 float w = static_cast<float>(texsize),
00166 h = static_cast<float>(texsize);
00167 glTranslatef(x, y, 0);
00168
00169 glBindTexture(GL_TEXTURE_2D, texture);
00170 glBegin(GL_QUADS);
00171 {
00172 glTexCoord2f(0, 0); glVertex3f(0, h, 0);
00173 glTexCoord2f(0, 1); glVertex3f(0, 0, 0);
00174 glTexCoord2f(1, 1); glVertex3f(w, 0, 0);
00175 glTexCoord2f(1, 0); glVertex3f(w, h, 0);
00176 }
00177 glEnd();
00178 glPopMatrix();
00179 }
00180
00181
00182
00183
00184
00185 GL_manager::GL_manager
00186 (
00187 ) : shapes(0), num_shapes(0), palette(0), scale(1)
00188 {
00189 assert (instance == 0);
00190 instance = this;
00191 GLint max_size;
00192 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
00193 max_texsize = max_size;
00194 glShadeModel(GL_SMOOTH);
00195 glClearColor(1, 1, 1, 0);
00196 glClearDepth(1);
00197
00198
00199
00200
00201
00202
00203
00204
00205 glDisable(GL_DEPTH_TEST);
00206 glDepthMask(GL_FALSE);
00207
00208 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00209 glEnable(GL_BLEND);
00210 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00211
00212
00213
00214
00215
00216
00217 }
00218
00219
00220
00221
00222
00223 GL_manager::~GL_manager
00224 (
00225 )
00226 {
00227 assert (this == instance);
00228 while (shapes)
00229 {
00230 GL_texshape *next = shapes->lru_next;
00231 delete shapes;
00232 shapes = next;
00233 }
00234 delete palette;
00235 instance = 0;
00236 }
00237
00238
00239
00240
00241 void GL_manager::resized
00242 (
00243 int new_width, int new_height,
00244 int new_scale
00245 )
00246 {
00247 scale = new_scale;
00248
00249 glViewport(0, 0, scale*new_width, scale*new_height);
00250 glMatrixMode(GL_PROJECTION);
00251 glLoadIdentity();
00252
00253 glOrtho(0, new_width, -new_height, 0, 1, -16);
00254 glMatrixMode(GL_MODELVIEW);
00255 glLoadIdentity();
00256
00257 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00258 }
00259
00260
00261
00262
00263
00264 static void Paint_image
00265 (
00266 Shape_frame *frame,
00267 int px, int py,
00268 unsigned char *pal,
00269 int scale
00270 )
00271 {
00272 px -= frame->get_xleft();
00273 py += frame->get_ybelow();
00274
00275 py = -py;
00276 int w = frame->get_width(), h = frame->get_height();
00277
00278 Image_buffer8 buf8(w, h);
00279 w = buf8.get_width(); h = buf8.get_height();
00280 buf8.fill8(transp);
00281 frame->paint(&buf8, frame->get_xleft(), frame->get_yabove());
00282
00283 unsigned char *pixels = buf8.rgba(pal, transp);
00284 if (px < 0)
00285 {
00286 glPixelStorei(GL_UNPACK_SKIP_PIXELS, -px);
00287 glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
00288 w += px;
00289 px = 0;
00290 }
00291
00292
00293
00294 glPixelZoom(scale, -scale);
00295 glRasterPos2f(px, py + h);
00296 glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
00297 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00298 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00299 delete pixels;
00300 }
00301
00302
00303
00304
00305
00306 void GL_manager::paint
00307 (
00308 Shape_frame *frame,
00309 int px, int py,
00310 Xform_palette *xforms,
00311 int xfcnt
00312 )
00313 {
00314 GL_texshape *tex = frame->glshape;
00315 if (!tex)
00316 {
00317 if (frame->get_width() > max_texsize ||
00318 frame->get_height() > max_texsize)
00319 {
00320 Paint_image(frame, px, py, palette, scale);
00321 return;
00322 }
00323 frame->glshape = tex = new GL_texshape(frame, palette,
00324 xforms, xfcnt);
00325 num_shapes++;
00326
00327 }
00328 else
00329 {
00330 if (tex->lru_next)
00331 tex->lru_next->lru_prev = tex->lru_prev;
00332 if (tex->lru_prev)
00333 tex->lru_prev->lru_next = tex->lru_next;
00334 tex->lru_prev = 0;
00335 }
00336 tex->lru_next = shapes;
00337 if (shapes)
00338 shapes->lru_prev = tex;
00339 shapes = tex;
00340 tex->paint(px, py);
00341 }
00342
00343 #endif