DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 // Tell Mac OS X to shut up about deprecated OpenGL calls 00020 #ifndef GL_SILENCE_DEPRECATION 00021 #define GL_SILENCE_DEPRECATION 00022 #endif 00023 00024 #include <stdlib.h> 00025 #include <math.h> 00026 #include <map> 00027 00028 #include "dosbox.h" 00029 #include "video.h" 00030 00031 #include "voodoo_emu.h" 00032 #include "voodoo_opengl.h" 00033 #include "sdlmain.h" 00034 00035 #if C_OPENGL 00036 00037 #if defined(_MSC_VER) 00038 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */ 00039 #endif 00040 00041 #include "voodoo_def.h" 00042 00043 SDL_Surface* ogl_surface = NULL; 00044 00045 INT32 cached_line_front_y=-1; 00046 INT32 cached_line_front_width = -1; 00047 INT32 cached_line_front_length=-1; 00048 INT32 cached_line_front_pixels=-1; 00049 UINT32* cached_line_front_data=NULL; 00050 00051 INT32 cached_line_back_y=-1; 00052 INT32 cached_line_back_width = -1; 00053 INT32 cached_line_back_length=-1; 00054 INT32 cached_line_back_pixels=-1; 00055 UINT32* cached_line_back_data=NULL; 00056 00057 static INT32 adjust_x=0; 00058 static INT32 adjust_y=0; 00059 00060 static UINT32 last_clear_color=0; 00061 00062 static UINT32 last_width=0; 00063 static UINT32 last_height=0; 00064 static INT32 last_orientation=-1; 00065 00066 00067 static UINT32 ogl_texture_index = 1; 00068 00069 00070 /* texture cache buffer */ 00071 UINT32 texrgb[256*256]; 00072 00073 00074 /* texture address map */ 00075 std::map <const UINT32, ogl_texmap> textures[2]; 00076 00077 void GFX_PreventFullscreen(bool lockout); 00078 00079 int Voodoo_OGL_GetWidth() { 00080 if (v != NULL) 00081 return (int)v->fbi.width; 00082 else 00083 return 0; 00084 } 00085 00086 int Voodoo_OGL_GetHeight() { 00087 if (v != NULL) 00088 return (int)v->fbi.height; 00089 else 00090 return 0; 00091 } 00092 00093 bool Voodoo_OGL_Active() { 00094 return (v != NULL && v->clock_enabled && v->output_on); 00095 } 00096 00097 static void ogl_get_depth(voodoo_state* VV, INT32 ITERZ, INT64 ITERW, INT32 *depthval, INT32 *out_wfloat) 00098 { 00099 INT32 wfloat; 00100 UINT32 FBZMODE = VV->reg[fbzMode].u; 00101 UINT32 FBZCOLORPATH = VV->reg[fbzColorPath].u; 00102 00103 /* compute "floating point" W value (used for depth and fog) */ 00104 if ((ITERW) & LONGTYPE(0xffff00000000)) 00105 wfloat = 0x0000; 00106 else 00107 { 00108 UINT32 temp = (UINT32)(ITERW); 00109 if ((temp & 0xffff0000) == 0) 00110 wfloat = 0xffff; 00111 else 00112 { 00113 int exp = count_leading_zeros(temp); 00114 wfloat = ((exp << 12) | (INT32)(((~temp) >> (unsigned int)(19 - exp)) & 0xfffu)); 00115 if (wfloat < 0xffff) wfloat++; 00116 } 00117 } 00118 00119 /* compute depth value (W or Z) for this pixel */ 00120 if (FBZMODE_WBUFFER_SELECT(FBZMODE) == 0) 00121 CLAMPED_Z(ITERZ, FBZCOLORPATH, *depthval); 00122 else if (FBZMODE_DEPTH_FLOAT_SELECT(FBZMODE) == 0) 00123 *depthval = wfloat; 00124 else 00125 { 00126 if ((unsigned int)(ITERZ) & 0xf0000000l) 00127 *depthval = 0x0000; 00128 else 00129 { 00130 UINT32 temp = (UINT32)((ITERZ) << 4); 00131 if ((temp & 0xffff0000ul) == 0) 00132 *depthval = 0xffff; 00133 else 00134 { 00135 int exp = count_leading_zeros(temp); 00136 *depthval = ((exp << 12) | (INT32)(((~temp) >> (unsigned int)(19 - exp)) & 0xfffu)); 00137 if (*depthval < 0xffff) (*depthval)++; 00138 } 00139 } 00140 } 00141 00142 /* add the bias */ 00143 if (FBZMODE_ENABLE_DEPTH_BIAS(FBZMODE)) 00144 { 00145 *depthval += (INT16)(VV)->reg[zaColor].u; 00146 CLAMP(*depthval, 0, 0xffff); 00147 } 00148 00149 *out_wfloat = wfloat; 00150 } 00151 00152 void ogl_get_fog_blend(voodoo_state* v, INT32 wfloat, INT32 ITERZ, INT64 ITERW, INT32 *fogblend) 00153 { 00154 UINT32 FOGMODE = v->reg[fogMode].u; 00155 UINT32 FBZCP = v->reg[fbzColorPath].u; 00156 00157 *fogblend = 0; 00158 if (FOGMODE_ENABLE_FOG(FOGMODE) && !FOGMODE_FOG_CONSTANT(FOGMODE)) 00159 { 00160 /* fog blending mode */ 00161 switch (FOGMODE_FOG_ZALPHA(FOGMODE)) 00162 { 00163 case 0: /* fog table */ 00164 { 00165 INT32 delta = v->fbi.fogdelta[wfloat >> 10]; 00166 INT32 deltaval; 00167 00168 /* perform the multiply against lower 8 bits of wfloat */ 00169 deltaval = (delta & v->fbi.fogdelta_mask) * 00170 ((wfloat >> 2) & 0xff); 00171 00172 /* fog zones allow for negating this value */ 00173 if (FOGMODE_FOG_ZONES(FOGMODE) && (delta & 2)) 00174 deltaval = -deltaval; 00175 deltaval >>= 6; 00176 00177 /* apply dither */ 00178 // if (FOGMODE_FOG_DITHER(FOGMODE)) 00179 // deltaval += DITHER4[(XX) & 3]; 00180 deltaval >>= 4; 00181 00182 /* add to the blending factor */ 00183 *fogblend = v->fbi.fogblend[wfloat >> 10] + deltaval; 00184 break; 00185 } 00186 00187 case 1: /* iterated A */ 00188 // fogblend = ITERAXXX.rgb.a; 00189 break; 00190 00191 case 2: /* iterated Z */ 00192 CLAMPED_Z((ITERZ), FBZCP, *fogblend); 00193 *fogblend >>= 8; 00194 break; 00195 00196 case 3: /* iterated W - Voodoo 2 only */ 00197 CLAMPED_W((ITERW), FBZCP, *fogblend); 00198 break; 00199 } 00200 00201 } 00202 } 00203 00204 void ogl_get_vertex_data(INT32 x, INT32 y, const void *extradata, ogl_vertex_data *vd) { 00205 const poly_extra_data *extra = (const poly_extra_data *)extradata; 00206 v=(voodoo_state*)extra->state; 00207 INT32 iterr, iterg, iterb, itera; 00208 INT32 iterz; 00209 INT64 iterw; 00210 INT32 dx, dy; 00211 INT32 d; 00212 00213 dx = x - extra->ax; 00214 dy = y - extra->ay; 00215 iterr = extra->startr + ((dy * extra->drdy)>>4) + ((dx * extra->drdx)>>4); 00216 iterg = extra->startg + ((dy * extra->dgdy)>>4) + ((dx * extra->dgdx)>>4); 00217 iterb = extra->startb + ((dy * extra->dbdy)>>4) + ((dx * extra->dbdx)>>4); 00218 itera = extra->starta + ((dy * extra->dady)>>4) + ((dx * extra->dadx)>>4); 00219 iterz = extra->startz + ((dy * extra->dzdy)>>4) + ((dx * extra->dzdx)>>4); 00220 iterw = extra->startw + ((dy * extra->dwdy)>>4) + ((dx * extra->dwdx)>>4); 00221 00222 for (Bitu i=0; i<extra->texcount; i++) { 00223 INT64 iters,itert,iterw2; 00224 UINT32 smax,tmax; 00225 INT64 s, t; 00226 INT32 lod=0; 00227 00228 UINT32 texmode=v->tmu[i].reg[textureMode].u; 00229 UINT32 TEXMODE = texmode; 00230 INT32 LODBASE = (i==0) ? extra->lodbase0 : extra->lodbase1; 00231 00232 UINT32 ilod = (UINT32)(v->tmu[i].lodmin >> 8); 00233 if (!((v->tmu[i].lodmask >> ilod) & 1)) 00234 ilod++; 00235 00236 smax = (v->tmu[i].wmask >> ilod) + 1; 00237 tmax = (v->tmu[i].hmask >> ilod) + 1; 00238 00239 iterw2 = v->tmu[i].startw + ((dy * v->tmu[i].dwdy)>>4) + ((dx * v->tmu[i].dwdx)>>4); 00240 iters = v->tmu[i].starts + ((dy * v->tmu[i].dsdy)>>4) + ((dx * v->tmu[i].dsdx)>>4); 00241 itert = v->tmu[i].startt + ((dy * v->tmu[i].dtdy)>>4) + ((dx * v->tmu[i].dtdx)>>4); 00242 00243 /* determine the S/T/LOD values for this texture */ 00244 if (TEXMODE_ENABLE_PERSPECTIVE(texmode)) 00245 { 00246 INT64 oow = fast_reciplog((iterw2), &lod); 00247 s = (oow * (iters)) >> 29; 00248 t = (oow * (itert)) >> 29; 00249 lod += LODBASE; 00250 } 00251 else 00252 { 00253 s = (iters) >> 14; 00254 t = (itert) >> 14; 00255 lod = LODBASE; 00256 } 00257 00258 /* clamp the LOD */ 00259 lod += v->tmu[i].lodbias; 00260 // if (TEXMODE_ENABLE_LOD_DITHER(TEXMODE)) 00261 // lod += DITHER4[(XX) & 3] << 4; 00262 if (lod < v->tmu[i].lodmin) 00263 lod = v->tmu[i].lodmin; 00264 if (lod > v->tmu[i].lodmax) 00265 lod = v->tmu[i].lodmax; 00266 00267 /* clamp W */ 00268 if (TEXMODE_CLAMP_NEG_W(texmode) && (iterw2) < 0) 00269 s = t = 0; 00270 00271 if (s != 0) vd->m[i].s = (float)((float)s/(float)(smax*(1u<<(18u+ilod)))); 00272 else vd->m[i].s = 0.0f; 00273 if (t != 0) vd->m[i].t = (float)((float)t/(float)(tmax*(1u<<(18u+ilod)))); 00274 else vd->m[i].t = 0.0f; 00275 if (iterw2 != 0) vd->m[i].w = (float)((float)iterw2/(float)(0xffffff)); 00276 else vd->m[i].w = 0.0f; 00277 00278 vd->m[i].sw = vd->m[i].s * vd->m[i].w; 00279 vd->m[i].tw = vd->m[i].t * vd->m[i].w; 00280 vd->m[i].z = 0.0f; 00281 00282 INT32 lodblend=0; 00283 00284 if ((TEXMODE_TC_MSELECT(TEXMODE)==4) || (TEXMODE_TCA_MSELECT(TEXMODE)==4)) 00285 { 00286 if (v->tmu[i].detailbias <= lod) 00287 lodblend = 0; 00288 else 00289 { 00290 lodblend = (((v->tmu[i].detailbias - lod) << v->tmu[i].detailscale) >> 8); 00291 if (lodblend > v->tmu[i].detailmax) 00292 lodblend = v->tmu[i].detailmax; 00293 } 00294 } else if ((TEXMODE_TC_MSELECT(TEXMODE)==5) || (TEXMODE_TCA_MSELECT(TEXMODE)==5)) 00295 lodblend = lod & 0xff; 00296 00297 vd->m[i].lodblend = (float)lodblend/255.0f; 00298 } 00299 00300 vd->r = (float)((float)iterr/(float)(1<<20)); 00301 vd->g = (float)((float)iterg/(float)(1<<20)); 00302 vd->b = (float)((float)iterb/(float)(1<<20)); 00303 vd->a = (float)((float)itera/(float)(1<<20)); 00304 vd->z = (float)((float)iterz/(float)(1<<20)); 00305 vd->w = (float)((float)iterw/(float)(0xffffff)); 00306 00307 INT32 wfloat; 00308 ogl_get_depth(v,iterz,iterw,&d,&wfloat); 00309 vd->d = (float)((float)d/(float)(0xffff)); 00310 00311 INT32 fogblend; 00312 ogl_get_fog_blend(v,wfloat,iterz,iterw,&fogblend); 00313 vd->fogblend = (float)fogblend/255.0f; 00314 00315 // vd->x = (float)x / (16.0f); 00316 // vd->y = (float)y / (16.0f); 00317 00318 // OpenGL-correction for Blood/ShadowWarrior 00319 vd->x = (((float)x) - (1.0f/16.0f)) / 16.0f; 00320 vd->y = (((float)y) - (1.0f/16.0f)) / 16.0f; 00321 } 00322 00323 static UINT32 crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 00324 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 00325 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 00326 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 00327 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 00328 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 00329 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 00330 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 00331 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 00332 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 00333 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 00334 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 00335 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 00336 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 00337 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 00338 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 00339 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 00340 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 00341 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 00342 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 00343 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 00344 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 00345 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 00346 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 00347 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 00348 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 00349 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 00350 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 00351 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 00352 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 00353 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 00354 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 00355 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 00356 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 00357 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 00358 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 00359 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 00360 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 00361 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 00362 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 00363 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 00364 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 00365 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 00366 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 00367 }; 00368 00369 UINT32 calculate_palsum(UINT32 tmunum) { 00370 UINT32 csum = 0; 00371 for (Bitu pct=0; pct<256; pct++) { 00372 UINT32 pval = v->tmu[tmunum].palette[pct]; 00373 csum = crc_32_tab[(csum ^ pval) & 0xff] ^ (csum>>8); 00374 csum = crc_32_tab[(csum ^ (pval>>8)) & 0xff] ^ (csum>>8); 00375 csum = crc_32_tab[(csum ^ (pval>>16)) & 0xff] ^ (csum>>8); 00376 csum = crc_32_tab[(csum ^ (pval>>24)) & 0xff] ^ (csum>>8); 00377 } 00378 return csum; 00379 } 00380 00381 void ogl_cache_texture(const poly_extra_data *extra, ogl_texture_data *td) { 00382 v=(voodoo_state*)extra->state; 00383 00384 INT32 smax, tmax; 00385 UINT32 *texrgbp; 00386 GLuint texID; 00387 00388 UINT32 num_tmus = 1; 00389 if (v->tmu[1].ram != NULL) num_tmus++; 00390 00391 for (UINT32 j=0; j<num_tmus; j++) { 00392 UINT32 TEXMODE = (UINT32)(j==0 ? extra->r_textureMode0 : extra->r_textureMode1); 00393 00394 UINT32 ilod = (UINT32)(v->tmu[j].lodmin >> 8); 00395 if (!((v->tmu[j].lodmask >> ilod) & 1)) 00396 ilod++; 00397 00398 UINT32 texbase = v->tmu[j].lodoffset[ilod]; 00399 00400 if ( extra->texcount && (extra->texcount >= j) && (v->tmu[j].lodmin < (8 << 8)) ) { 00401 bool valid_texid = true; 00402 std::map<const UINT32, ogl_texmap>::iterator t; 00403 t = textures[j].find(texbase); 00404 bool reuse_id = false; 00405 if (t != textures[j].end()) { 00406 if (t->second.valid_pal) { 00407 texID = t->second.current_id; 00408 if (!t->second.valid_data) { 00409 valid_texid = false; 00410 reuse_id = true; 00411 t->second.valid_data = true; 00412 } 00413 } else { 00414 UINT32 psum = calculate_palsum(j); 00415 std::map<const UINT32, GLuint>::iterator u = t->second.ids->find(psum); 00416 if (u != t->second.ids->end()) { 00417 t->second.valid_pal = true; 00418 t->second.current_id = u->second; 00419 texID = u->second; 00420 } else { 00421 valid_texid = false; 00422 // LOG_MSG("texture removed... size %d",t->second.ids->size()); 00423 if (t->second.ids->size() > 8) { 00424 for (u=t->second.ids->begin(); u!=t->second.ids->end(); ++u) { 00425 glDeleteTextures(1,&u->second); 00426 } 00427 t->second.ids->clear(); 00428 } 00429 t->second.valid_pal = true; 00430 } 00431 } 00432 } else { 00433 valid_texid = false; 00434 } 00435 if (!valid_texid) { 00436 smax = (INT32)(v->tmu[j].wmask >> ilod) + 1; 00437 tmax = (INT32)(v->tmu[j].hmask >> ilod) + 1; 00438 00439 UINT32 texboffset = texbase; 00440 texrgbp = (UINT32 *)&texrgb[0]; 00441 memset(texrgbp,0,256*256*4); 00442 00443 if (!reuse_id) { 00444 texID = ogl_texture_index++; 00445 glGenTextures(1, &texID); 00446 } 00447 00448 if (TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u) < 8) { 00449 if (TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u) != 5) { 00450 for (int i=0; i<(smax*tmax); i++) { 00451 UINT8 *texptr8 = (UINT8 *)&v->tmu[j].ram[(texboffset) & v->tmu[j].mask]; 00452 UINT32 data = v->tmu[j].lookup[*texptr8]; 00453 *texrgbp = data; 00454 texboffset++; 00455 texrgbp++; 00456 } 00457 } else { 00458 for (int i=0; i<(smax*tmax); i++) { 00459 UINT8 *texptr8 = (UINT8 *)&v->tmu[j].ram[(texboffset) & v->tmu[j].mask]; 00460 UINT8 texel = *texptr8; 00461 UINT32 data = v->tmu[j].lookup[texel]; 00462 *texrgbp = data; 00463 texboffset++; 00464 texrgbp++; 00465 } 00466 } 00467 } else if (TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u) >= 10 && TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u) <= 12) { 00468 for (int i=0; i<(smax*tmax); i++) { 00469 UINT16 *texptr16 = (UINT16 *)&v->tmu[j].ram[(texboffset) & v->tmu[j].mask]; 00470 UINT32 data = v->tmu[j].lookup[*texptr16]; 00471 *texrgbp = data; 00472 texboffset+=2; 00473 texrgbp++; 00474 } 00475 } else if (TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u) != 14) { 00476 for (int i=0; i<(smax*tmax); i++) { 00477 UINT16 *texptr16 = (UINT16 *)&v->tmu[j].ram[(texboffset) & v->tmu[j].mask]; 00478 UINT32 data = (v->tmu[j].lookup[*texptr16 & 0xFF] & 0xFFFFFF) | ((*texptr16 & 0xff00u) << 16u); 00479 *texrgbp = data; 00480 texboffset+=2; 00481 texrgbp++; 00482 } 00483 } else { 00484 for (int i=0; i<(smax*tmax); i++) { 00485 UINT16 *texptr16 = (UINT16 *)&v->tmu[j].ram[(texboffset) & v->tmu[j].mask]; 00486 UINT16 texel1 = *texptr16 & 0xFF; 00487 UINT32 data = (v->tmu[j].lookup[texel1] & 0xFFFFFF) | ((*texptr16 & 0xff00u) << 16u); 00488 *texrgbp = data; 00489 texboffset+=2; 00490 texrgbp++; 00491 } 00492 } 00493 00494 texrgbp = (UINT32 *)&texrgb[0]; 00495 // LOG_MSG("texid %d format %d -- %d x %d", 00496 // texID,TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u),smax,tmax); 00497 00498 glBindTexture(GL_TEXTURE_2D, texID); 00499 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 00500 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 00501 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,TEXMODE_CLAMP_S(TEXMODE)?GL_CLAMP_TO_EDGE:GL_REPEAT); 00502 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,TEXMODE_CLAMP_T(TEXMODE)?GL_CLAMP_TO_EDGE:GL_REPEAT); 00503 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smax, tmax, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, texrgbp); 00504 extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; 00505 glGenerateMipmapEXT(GL_TEXTURE_2D); 00506 if ((TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u)==0x05) || (TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u)==0x0e)) { 00507 UINT32 palsum = calculate_palsum(j); 00508 if (t == textures[j].end()) { 00509 std::map<const UINT32, GLuint>* ids = new std::map<const UINT32, GLuint>(); 00510 (*ids)[palsum] = texID; 00511 ogl_texmap tex = { true, true, TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u), 00512 texID, ids }; 00513 textures[j][texbase] = tex; 00514 } else { 00515 (*textures[j][texbase].ids)[palsum] = texID; 00516 textures[j][texbase].current_id = texID; 00517 } 00518 } else { 00519 ogl_texmap tex = { true, true, TEXMODE_FORMAT(v->tmu[j].reg[textureMode].u), 00520 texID, NULL }; 00521 textures[j][texbase] = tex; 00522 } 00523 } 00524 00525 td[j].texID = texID; 00526 td[j].enable = true; 00527 } else { 00528 td[j].enable = false; 00529 } 00530 } 00531 } 00532 00533 void voodoo_ogl_invalidate_paltex(void) { 00534 std::map<const UINT32, ogl_texmap>::iterator t; 00535 for (int j=0; j<2; j++) { 00536 for (t=textures[j].begin(); t!=textures[j].end(); ++t) { 00537 if ((t->second.format == 0x05) || (t->second.format == 0x0e)) { 00538 t->second.valid_pal = false; 00539 } 00540 } 00541 } 00542 } 00543 00544 00545 GLhandleARB m_hProgramObject = (GLhandleARB)NULL; 00546 00547 00548 void ogl_printInfoLog(GLhandleARB obj) 00549 { 00550 int infologLength = 0; 00551 int charsWritten = 0; 00552 00553 glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); 00554 00555 if (infologLength > 0) 00556 { 00557 char *infoLog = (char *)malloc((size_t)infologLength); 00558 glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog); 00559 LOG_MSG("%s\n",infoLog); 00560 free(infoLog); 00561 } 00562 } 00563 00564 void ogl_sh_tex_combine(std::string *strFShader, const int TMU, const poly_extra_data *extra) { 00565 v=(voodoo_state*)extra->state; 00566 00567 UINT32 TEXMODE = v->tmu[TMU].reg[textureMode].u; 00568 00569 if (!TEXMODE_TC_ZERO_OTHER(TEXMODE)) 00570 *strFShader += " tt.rgb = cother.rgb;\n"; 00571 else 00572 *strFShader += " tt.rgb = vec3(0.0);\n"; 00573 00574 if (!TEXMODE_TCA_ZERO_OTHER(TEXMODE)) 00575 *strFShader += " tt.a = cother.a;\n"; 00576 else 00577 *strFShader += " tt.a = 0.0;\n"; 00578 00579 if (TEXMODE_TC_SUB_CLOCAL(TEXMODE)) 00580 *strFShader += " tt.rgb -= clocal.rgb;\n"; 00581 if (TEXMODE_TCA_SUB_CLOCAL(TEXMODE)) 00582 *strFShader += " tt.a -= clocal.a;\n"; 00583 00584 switch (TEXMODE_TC_MSELECT(TEXMODE)) 00585 { 00586 default: 00587 case 0: 00588 *strFShader += " blend.rgb = vec3(0.0);\n"; 00589 break; 00590 case 1: 00591 *strFShader += " blend.rgb = clocal.rgb;\n"; 00592 break; 00593 case 2: 00594 *strFShader += " blend.rgb = vec3(cother.a);\n"; 00595 break; 00596 case 3: 00597 *strFShader += " blend.rgb = vec3(clocal.a);\n"; 00598 break; 00599 case 4: 00600 // detail // 00601 case 5: 00602 // LOD // 00603 *strFShader += " blend.rgb = vec3(f_lodblend"; 00604 *strFShader += TMU==0?"0":"1"; 00605 *strFShader += ");\n"; 00606 break; 00607 } 00608 00609 switch (TEXMODE_TCA_MSELECT(TEXMODE)) 00610 { 00611 default: 00612 case 0: 00613 *strFShader += " blend.a = 0.0;\n"; 00614 break; 00615 case 1: 00616 *strFShader += " blend.a = clocal.a;\n"; 00617 break; 00618 case 2: 00619 *strFShader += " blend.a = cother.a;\n"; 00620 break; 00621 case 3: 00622 *strFShader += " blend.a = clocal.a;\n"; 00623 break; 00624 case 4: 00625 // detail // 00626 case 5: 00627 // LOD // 00628 *strFShader += " blend.a = f_lodblend"; 00629 *strFShader += TMU==0?"0":"1"; 00630 *strFShader += ";\n"; 00631 break; 00632 } 00633 00634 if (!TEXMODE_TC_REVERSE_BLEND(TEXMODE)) 00635 *strFShader += " blend.rgb = vec3(1.0) - blend.rgb;\n"; 00636 00637 if (!TEXMODE_TCA_REVERSE_BLEND(TEXMODE)) 00638 *strFShader += " blend.a = 1.0 - blend.a;\n"; 00639 00640 *strFShader += " tt *= blend;\n"; 00641 00642 switch (TEXMODE_TC_ADD_ACLOCAL(TEXMODE)) 00643 { 00644 case 3: 00645 case 0: 00646 break; 00647 case 1: 00648 *strFShader += " tt.rgb += clocal.rgb;\n"; 00649 break; 00650 case 2: 00651 *strFShader += " tt.rgb += vec3(clocal.a);\n"; 00652 break; 00653 } 00654 00655 if (TEXMODE_TCA_ADD_ACLOCAL(TEXMODE)) 00656 *strFShader += " tt.a += clocal.a;\n"; 00657 00658 *strFShader += " clocal = tt;\n"; 00659 00660 if (TEXMODE_TC_INVERT_OUTPUT(TEXMODE)) 00661 *strFShader += " clocal.rgb = vec3(1.0)-clocal.rgb;\n"; 00662 00663 if (TEXMODE_TCA_INVERT_OUTPUT(TEXMODE)) 00664 *strFShader += " clocal.a = 1.0 - clocal.a;\n"; 00665 00666 } 00667 00668 void ogl_sh_color_path(std::string *strFShader, const poly_extra_data *extra) { 00669 v=(voodoo_state*)extra->state; 00670 00671 UINT32 FBZCOLORPATH = v->reg[fbzColorPath].u; 00672 UINT32 FBZMODE = v->reg[fbzMode].u; 00673 UINT32 ALPHAMODE = v->reg[alphaMode].u; 00674 00675 switch (FBZCP_CC_RGBSELECT(FBZCOLORPATH)) 00676 { 00677 case 0: 00678 *strFShader += " cother = gl_Color;\n"; 00679 break; 00680 case 1: 00681 *strFShader += " cother = texel;\n"; 00682 break; 00683 case 2: 00684 *strFShader += " cother = color1;\n"; 00685 break; 00686 default: 00687 *strFShader += " cother = vec4(0.0);\n"; 00688 } 00689 00690 // TODO fix chroma key // 00691 if (FBZMODE_ENABLE_CHROMAKEY(FBZMODE)) { 00692 // if (!CHROMARANGE_ENABLE(v->reg[chromaRange].u)) 00693 *strFShader += " if (distance (cother.rgb , chromaKey.rgb) < 0.0001) discard;\n"; 00694 // else { 00695 // *strFShader += " if ((cother.rgb >= (chromaKey.rgb-0.01)) && (cother.rgb <= (chromaRange.rgb+0.01))) discard;"; 00696 // } 00697 } 00698 00699 00700 switch (FBZCP_CC_ASELECT(FBZCOLORPATH)) 00701 { 00702 case 0: 00703 *strFShader += " cother.a = gl_Color.a;\n"; 00704 break; 00705 case 1: 00706 *strFShader += " cother.a = texel.a;\n"; 00707 break; 00708 case 2: 00709 *strFShader += " cother.a = color1.a;\n"; 00710 break; 00711 default: 00712 *strFShader += " cother.a = 0.0;\n"; 00713 break; 00714 } 00715 00716 // TODO check alpha mask // 00717 // if (FBZMODE_ENABLE_ALPHA_MASK(FBZMODE)) 00718 // *strFShader += " if (cother.a > 0.0) discard;"; 00719 00720 if (ALPHAMODE_ALPHATEST(ALPHAMODE)) 00721 switch (ALPHAMODE_ALPHAFUNCTION(ALPHAMODE)) { 00722 case 0: 00723 *strFShader += " discard;\n"; 00724 break; 00725 case 1: 00726 *strFShader += " if (cother.a >= alphaRef) discard;\n"; 00727 break; 00728 case 2: 00729 // *strFShader += " if (cother.a != alphaRef) discard;\n"; 00730 *strFShader += " if (distance(cother.a , alphaRef) > 0.0001) discard;\n"; 00731 break; 00732 case 3: 00733 *strFShader += " if (cother.a > alphaRef) discard;\n"; 00734 break; 00735 case 4: 00736 *strFShader += " if (cother.a <= alphaRef) discard;\n"; 00737 break; 00738 case 5: 00739 // *strFShader += " if (cother.a == alphaRef) discard;\n"; 00740 *strFShader += " if (distance(cother.a , alphaRef) < 0.0001) discard;\n"; 00741 break; 00742 case 6: 00743 *strFShader += " if (cother.a < alphaRef) discard;\n"; 00744 break; 00745 case 7: 00746 break; 00747 } 00748 00749 if (FBZCP_CC_LOCALSELECT_OVERRIDE(FBZCOLORPATH) == 0) 00750 { 00751 if (FBZCP_CC_LOCALSELECT(FBZCOLORPATH) == 0) 00752 *strFShader += " clocal = gl_Color;\n"; 00753 else 00754 *strFShader += " clocal = color0;\n"; 00755 } 00756 else 00757 { 00758 *strFShader += " if (texel.a < 0.5) {\n" 00759 " clocal = gl_Color;\n" 00760 " } else {\n" 00761 " clocal = color0;\n" 00762 " }\n"; 00763 } 00764 00765 switch (FBZCP_CCA_LOCALSELECT(FBZCOLORPATH)) 00766 { 00767 default: 00768 case 0: 00769 *strFShader += " clocal.a = gl_Color.a;\n"; 00770 break; 00771 case 1: 00772 *strFShader += " clocal.a = color0.a;\n"; 00773 break; 00774 case 2: 00775 *strFShader += " clocal.a = gl_Color.a;\n"; // TODO CLAMPED_Z 00776 break; 00777 case 3: 00778 // voodoo2 only 00779 break; 00780 } 00781 00782 if (FBZCP_CC_ZERO_OTHER(FBZCOLORPATH) == 0) 00783 *strFShader += " tt.rgb = cother.rgb;\n"; 00784 else 00785 *strFShader += " tt.rgb = vec3(0.0);\n"; 00786 00787 if (FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH) == 0) 00788 *strFShader += " tt.a = cother.a;\n"; 00789 else 00790 *strFShader += " tt.a = 0.0;\n"; 00791 00792 if (FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH)) 00793 *strFShader += " tt.rgb -= clocal.rgb;\n"; 00794 00795 if (FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH)) 00796 *strFShader += " tt.a -= clocal.a;\n"; 00797 00798 switch (FBZCP_CC_MSELECT(FBZCOLORPATH)) 00799 { 00800 default: 00801 case 0: 00802 *strFShader += " blend.rgb = vec3(0.0);\n"; 00803 break; 00804 case 1: 00805 *strFShader += " blend.rgb = clocal.rgb;\n"; 00806 break; 00807 case 2: 00808 *strFShader += " blend.rgb = vec3(cother.a);\n"; 00809 break; 00810 case 3: 00811 *strFShader += " blend.rgb = vec3(clocal.a);\n"; 00812 break; 00813 case 4: 00814 *strFShader += " blend.rgb = vec3(texel.a);\n"; 00815 break; 00816 case 5: 00817 // voodoo2 only 00818 *strFShader += " blend.rgb = texel.rgb;\n"; 00819 break; 00820 } 00821 00822 switch (FBZCP_CCA_MSELECT(FBZCOLORPATH)) 00823 { 00824 default: 00825 case 0: 00826 *strFShader += " blend.a = 0.0;\n"; 00827 break; 00828 case 1: 00829 *strFShader += " blend.a = clocal.a;\n"; 00830 break; 00831 case 2: 00832 *strFShader += " blend.a = cother.a;\n"; 00833 break; 00834 case 3: 00835 *strFShader += " blend.a = clocal.a;\n"; 00836 break; 00837 case 4: 00838 *strFShader += " blend.a = texel.a;\n"; 00839 break; 00840 } 00841 00842 if (!FBZCP_CC_REVERSE_BLEND(FBZCOLORPATH)) 00843 *strFShader += " blend.rgb = vec3(1.0) - blend.rgb;\n"; 00844 00845 if (!FBZCP_CCA_REVERSE_BLEND(FBZCOLORPATH)) 00846 *strFShader += " blend.a = 1.0 - blend.a;\n"; 00847 00848 *strFShader += " tt *= blend;\n"; 00849 00850 switch (FBZCP_CC_ADD_ACLOCAL(FBZCOLORPATH)) 00851 { 00852 case 3: 00853 case 0: 00854 break; 00855 case 1: 00856 *strFShader += " tt.rgb += clocal.rgb;\n"; 00857 break; 00858 case 2: 00859 *strFShader += " tt.rgb += vec3(clocal.a);\n"; 00860 break; 00861 } 00862 00863 if (FBZCP_CCA_ADD_ACLOCAL(FBZCOLORPATH)) 00864 *strFShader += " tt.a += clocal.a;\n"; 00865 00866 // clamp ?? // 00867 00868 *strFShader += " pixel = tt;\n"; 00869 00870 if (FBZCP_CC_INVERT_OUTPUT(FBZCOLORPATH)) 00871 *strFShader += " pixel.rgb = vec3(1.0) - tt.rgb;\n"; 00872 00873 if (FBZCP_CCA_INVERT_OUTPUT(FBZCOLORPATH)) 00874 *strFShader += " pixel.a = 1.0 - tt.a;\n"; 00875 } 00876 00877 void ogl_sh_fog(std::string *strFShader, const poly_extra_data *extra) { 00878 v=(voodoo_state*)extra->state; 00879 00880 UINT32 FOGMODE = v->reg[fogMode].u; 00881 00882 *strFShader += " vec4 ff;\n"; 00883 00884 /* constant fog bypasses everything else */ 00885 if (FOGMODE_FOG_CONSTANT(FOGMODE)) 00886 *strFShader += " ff = fogColor;\n"; 00887 00888 /* non-constant fog comes from several sources */ 00889 else { 00890 /* if fog_add is zero, we start with the fog color */ 00891 if (FOGMODE_FOG_ADD(FOGMODE) == 0) 00892 *strFShader += " ff = fogColor;\n"; 00893 else 00894 *strFShader += " ff = vec4(0.0);\n"; 00895 00896 /* if fog_mult is zero, we subtract the incoming color */ 00897 if (FOGMODE_FOG_MULT(FOGMODE) == 0) 00898 *strFShader += " ff -= pixel;\n"; 00899 00900 *strFShader += " float fogblend;\n"; 00901 /* fog blending mode */ 00902 switch (FOGMODE_FOG_ZALPHA(FOGMODE)) 00903 { 00904 case 0: /* fog table */ 00905 // blend factor calculated in ogl_get_fog_blend // 00906 *strFShader += " fogblend = f_fogblend;\n"; 00907 break; 00908 case 1: /* iterated A */ 00909 *strFShader += " fogblend = gl_Color.a;\n"; 00910 break; 00911 case 2: /* iterated Z */ 00912 *strFShader += " fogblend = f_fogblend;\n"; 00913 break; 00914 case 3: /* iterated W - Voodoo 2 only */ 00915 *strFShader += " fogblend = f_fogblend;\n"; 00916 break; 00917 } 00918 00919 /* perform the blend */ 00920 *strFShader += " ff *= fogblend;\n"; 00921 00922 /* if fog_mult is 0, we add this to the original color */ 00923 if (FOGMODE_FOG_MULT(FOGMODE) == 0) 00924 *strFShader += " pixel.rgb += ff.rgb;\n"; 00925 /* otherwise this just becomes the new color */ 00926 else 00927 *strFShader += " pixel.rgb = ff.rgb;\n"; 00928 00929 } 00930 } 00931 00932 00933 void ogl_shaders(const poly_extra_data *extra) { 00934 v=(voodoo_state*)extra->state; 00935 00936 GLint res; 00937 std::string strVShader, strFShader; 00938 00939 /* shaders extensions not loaded */ 00940 if (!glCreateShaderObjectARB) return; 00941 00942 // UINT32 FBZMODE = extra->r_fbzMode; 00943 UINT32 FOGMODE = extra->r_fogMode; 00944 UINT32 texcount = extra->texcount; 00945 00946 /* build a new shader program */ 00947 if (!extra->info->shader_ready) { 00948 00949 /* create vertex shader */ 00950 int fcount=0; 00951 while (glGetError()!=0) { 00952 fcount++; 00953 if (fcount>1000) E_Exit("opengl error"); 00954 } 00955 00956 GLhandleARB m_hVertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); 00957 00958 strVShader = 00959 "attribute float v_fogblend;\n" 00960 "varying float f_fogblend;\n" 00961 "attribute float v_lodblend0;\n" 00962 "varying float f_lodblend0;\n" 00963 "attribute float v_lodblend1;\n" 00964 "varying float f_lodblend1;\n" 00965 "\n" 00966 "void main()" 00967 "{\n" 00968 " gl_TexCoord[0] = gl_MultiTexCoord0;\n" 00969 " gl_TexCoord[1] = gl_MultiTexCoord1;\n" 00970 " gl_FrontColor = gl_Color;\n" 00971 " f_fogblend = v_fogblend;\n" 00972 " f_lodblend0 = v_lodblend0;\n" 00973 " f_lodblend1 = v_lodblend1;\n" 00974 " gl_Position = ftransform();\n" 00975 "}\n"; 00976 00977 const char *szVShader = strVShader.c_str(); 00978 glShaderSourceARB(m_hVertexShader, 1, &szVShader, NULL); 00979 glCompileShaderARB(m_hVertexShader); 00980 glGetObjectParameterivARB(m_hVertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 00981 if(res == 0) { 00982 char infobuffer[1000]; 00983 int infobufferlen = 0; 00984 glGetInfoLogARB(m_hVertexShader, 999, &infobufferlen, infobuffer); 00985 infobuffer[infobufferlen] = 0; 00986 ogl_printInfoLog(m_hVertexShader); 00987 E_Exit("ERROR: Error compiling vertex shader"); 00988 return; 00989 } 00990 00991 /* create fragment shader */ 00992 GLhandleARB m_hFragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 00993 strFShader = 00994 "varying float f_fogblend;\n" 00995 "varying float f_lodblend0;\n" 00996 "varying float f_lodblend1;\n" 00997 "uniform sampler2D tex0;\n" 00998 "uniform sampler2D tex1;\n" 00999 "uniform vec4 color0;\n" 01000 "uniform vec4 color1;\n" 01001 "uniform vec4 chromaKey;\n" 01002 "uniform vec4 chromaRange;\n" 01003 "uniform float alphaRef;\n" 01004 "uniform float zaColor;\n" 01005 "uniform vec4 fogColor;\n" 01006 "\n" 01007 "void main()" 01008 "{\n" 01009 " vec4 pixel = vec4(0.0);\n" 01010 " vec4 texel = vec4(1.0);\n" 01011 " vec4 clocal = vec4(1.0);\n" 01012 " vec4 cother = vec4(0.0);\n" 01013 " vec4 tt = vec4(0.0);\n" 01014 " vec4 blend = vec4(0.0);\n"; 01015 01016 // TODO glsl depth test? // 01017 01018 if (texcount >= 2 && v->tmu[1].lodmin < (8 << 8)) 01019 { 01020 strFShader += " clocal = texture2DProj(tex1,gl_TexCoord[1]);\n"; 01021 ogl_sh_tex_combine(&strFShader, 1, extra); 01022 strFShader += " cother = clocal;\n"; 01023 strFShader += " texel = clocal;\n"; 01024 } 01025 01026 if (texcount >= 1 && v->tmu[0].lodmin < (8 << 8)) 01027 { 01028 strFShader += " clocal = texture2DProj(tex0,gl_TexCoord[0]);\n"; 01029 ogl_sh_tex_combine(&strFShader, 0, extra); 01030 strFShader += " texel = clocal;\n"; 01031 } 01032 01033 // TODO Clamped ARGB // 01034 01035 ogl_sh_color_path(&strFShader, extra); 01036 01037 // fogging // 01038 if (FOGMODE_ENABLE_FOG(FOGMODE)) 01039 ogl_sh_fog(&strFShader, extra); 01040 01041 strFShader += " gl_FragColor = pixel;\n"; 01042 01043 strFShader += 01044 "}"; 01045 01046 const char *szFShader = strFShader.c_str(); 01047 glShaderSourceARB(m_hFragmentShader, 1, &szFShader, NULL); 01048 01049 glCompileShaderARB(m_hFragmentShader); 01050 glGetObjectParameterivARB(m_hFragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &res); 01051 if(res == 0) { 01052 ogl_printInfoLog(m_hFragmentShader); 01053 E_Exit("ERROR: Error compiling fragment shader"); 01054 return; 01055 } 01056 01057 01058 /* create program object */ 01059 m_hProgramObject = glCreateProgramObjectARB(); 01060 01061 glAttachObjectARB(m_hProgramObject, m_hVertexShader); 01062 glAttachObjectARB(m_hProgramObject, m_hFragmentShader); 01063 01064 glLinkProgramARB(m_hProgramObject); 01065 01066 glGetObjectParameterivARB(m_hProgramObject, GL_OBJECT_LINK_STATUS_ARB, &res); 01067 if(res == 0) { 01068 ogl_printInfoLog(m_hProgramObject); 01069 E_Exit("ERROR: Error linking program"); 01070 return; 01071 } 01072 01073 /* use this shader */ 01074 glUseProgramObjectARB(m_hProgramObject); 01075 extra->info->so_shader_program=(uintptr_t)m_hProgramObject; 01076 extra->info->so_vertex_shader=(uintptr_t)m_hVertexShader; 01077 extra->info->so_fragment_shader=(uintptr_t)m_hFragmentShader; 01078 01079 extra->info->shader_ready=true; 01080 01081 GLenum glerr=glGetError(); 01082 if (glerr!=0) { 01083 E_Exit("create shader start glError->%x",glerr); 01084 } 01085 01086 int* locations=new int[12]; 01087 locations[0]=glGetUniformLocationARB(m_hProgramObject, "chromaKey"); 01088 locations[1]=glGetUniformLocationARB(m_hProgramObject, "chromaRange"); 01089 locations[2]=glGetUniformLocationARB(m_hProgramObject, "color0"); 01090 locations[3]=glGetUniformLocationARB(m_hProgramObject, "color1"); 01091 locations[4]=glGetUniformLocationARB(m_hProgramObject, "alphaRef"); 01092 locations[5]=glGetUniformLocationARB(m_hProgramObject, "zaColor"); 01093 locations[6]=glGetUniformLocationARB(m_hProgramObject, "tex0"); 01094 locations[7]=glGetUniformLocationARB(m_hProgramObject, "tex1"); 01095 locations[8]=glGetUniformLocationARB(m_hProgramObject, "fogColor"); 01096 01097 locations[9] = glGetAttribLocationARB(m_hProgramObject, "v_fogblend"); 01098 locations[10] = glGetAttribLocationARB(m_hProgramObject, "v_lodblend0"); 01099 locations[11] = glGetAttribLocationARB(m_hProgramObject, "v_lodblend1"); 01100 extra->info->shader_ulocations=locations; 01101 } else { 01102 /* use existing shader program */ 01103 if (m_hProgramObject != (GLhandleARB)extra->info->so_shader_program) { 01104 glUseProgramObjectARB((GLhandleARB)extra->info->so_shader_program); 01105 m_hProgramObject = (GLhandleARB)extra->info->so_shader_program; 01106 } 01107 } 01108 01109 if (extra->info->shader_ulocations[0]>=0) glUniform4fARB(extra->info->shader_ulocations[0], v->reg[chromaKey].rgb.r/255.0f, v->reg[chromaKey].rgb.g/255.0f, v->reg[chromaKey].rgb.b/255.0f,0); 01110 if (extra->info->shader_ulocations[1]>=0) glUniform4fARB(extra->info->shader_ulocations[1], v->reg[chromaRange].rgb.r/255.0f, v->reg[chromaRange].rgb.g/255.0f, v->reg[chromaRange].rgb.b/255.0f,0); 01111 if (extra->info->shader_ulocations[2]>=0) glUniform4fARB(extra->info->shader_ulocations[2], v->reg[color0].rgb.r/255.0f, v->reg[color0].rgb.g/255.0f, v->reg[color0].rgb.b/255.0f, v->reg[color0].rgb.a/255.0f); 01112 if (extra->info->shader_ulocations[3]>=0) glUniform4fARB(extra->info->shader_ulocations[3], v->reg[color1].rgb.r/255.0f, v->reg[color1].rgb.g/255.0f, v->reg[color1].rgb.b/255.0f, v->reg[color1].rgb.a/255.0f); 01113 if (extra->info->shader_ulocations[4]>=0) glUniform1fARB(extra->info->shader_ulocations[4], v->reg[alphaMode].rgb.a/255.0f); 01114 if (extra->info->shader_ulocations[5]>=0) glUniform1fARB(extra->info->shader_ulocations[5], (float)((UINT16)v->reg[zaColor].u)/65535.0f); 01115 if (extra->info->shader_ulocations[8]>=0) glUniform4fARB(extra->info->shader_ulocations[8], v->reg[fogColor].rgb.r/255.0f, v->reg[fogColor].rgb.g/255.0f, v->reg[fogColor].rgb.b/255.0f,1.0f); 01116 01117 } 01118 01119 01120 void voodoo_ogl_draw_triangle(poly_extra_data *extra) { 01121 v=extra->state; 01122 ogl_texture_data td[2]; 01123 ogl_vertex_data vd[3]; 01124 01125 VOGL_ClearBeginMode(); 01126 01127 td[0].enable = false; 01128 td[1].enable = false; 01129 01130 UINT32 ALPHAMODE = extra->r_alphaMode; 01131 UINT32 FBZMODE = extra->r_fbzMode; 01132 01133 01134 ogl_get_vertex_data(v->fbi.ax, v->fbi.ay, (void*)extra, &vd[0]); 01135 ogl_get_vertex_data(v->fbi.bx, v->fbi.by, (void*)extra, &vd[1]); 01136 ogl_get_vertex_data(v->fbi.cx, v->fbi.cy, (void*)extra, &vd[2]); 01137 01138 01139 if (FBZMODE_DEPTH_SOURCE_COMPARE(FBZMODE) && VOGL_CheckFeature(VOGL_HAS_STENCIL_BUFFER)) { 01140 if (m_hProgramObject != 0) { 01141 glUseProgramObjectARB(0); 01142 m_hProgramObject = 0; 01143 } 01144 01145 if ((FBZMODE_ENABLE_DEPTHBUF(FBZMODE)) && (FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) == 0)) { 01146 VOGL_SetDepthMode(1,FBZMODE_DEPTH_FUNCTION(FBZMODE)); 01147 } else { 01148 VOGL_SetDepthMode(0,0); 01149 } 01150 01151 VOGL_SetDepthMaskMode(false); 01152 VOGL_SetColorMaskMode(false, false); 01153 01154 VOGL_SetAlphaMode(0, 0,0,0,0); 01155 01156 if (FBZMODE_DRAW_BUFFER(v->reg[fbzMode].u)==0) { 01157 VOGL_SetDrawMode(true); 01158 } else { 01159 VOGL_SetDrawMode(false); 01160 } 01161 01162 glEnable(GL_STENCIL_TEST); 01163 glClear(GL_STENCIL_BUFFER_BIT); 01164 glStencilFunc(GL_ALWAYS, 1, 1); 01165 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 01166 01167 glBegin(GL_TRIANGLES); 01168 01169 glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 01170 01171 float depth = (float)(v->reg[zaColor].u&0xffff)/(float)0xffff; 01172 for (int i=0;i<3;i++) 01173 glVertex3f(vd[i].x, vd[i].y, depth); 01174 01175 glEnd(); 01176 } 01177 01178 ogl_cache_texture(extra,td); 01179 ogl_shaders(extra); 01180 01181 if (extra->texcount > 0) { 01182 for (unsigned int t=0; t<2; t++) 01183 if ( td[t].enable ) { 01184 UINT32 TEXMODE = v->tmu[t].reg[textureMode].u; 01185 glActiveTexture(GL_TEXTURE0_ARB+t); 01186 glBindTexture (GL_TEXTURE_2D, td[t].texID); 01187 if (!extra->info->shader_ready) { 01188 glEnable (GL_TEXTURE_2D); 01189 // TODO proper fixed-pipeline combiners 01190 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 01191 } else { 01192 if (extra->info->shader_ulocations[6+t] >= 0) 01193 glUniform1iARB(extra->info->shader_ulocations[6+t],(GLint)t); 01194 } 01195 01196 GLint minFilter; 01197 minFilter = (int)GL_NEAREST + (int)TEXMODE_MINIFICATION_FILTER(TEXMODE); 01198 if (v->tmu[t].lodmin != v->tmu[t].lodmax) 01199 minFilter += 0x0100 + (int)TEXMODE_TRILINEAR(TEXMODE)*2; 01200 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,minFilter); 01201 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,(int)GL_NEAREST+(int)TEXMODE_MAGNIFICATION_FILTER(TEXMODE)); 01202 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,TEXMODE_CLAMP_S(TEXMODE)?GL_CLAMP_TO_EDGE:GL_REPEAT); 01203 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,TEXMODE_CLAMP_T(TEXMODE)?GL_CLAMP_TO_EDGE:GL_REPEAT); 01204 } 01205 } 01206 01207 if (FBZMODE_DEPTH_SOURCE_COMPARE(FBZMODE) && VOGL_CheckFeature(VOGL_HAS_STENCIL_BUFFER)) { 01208 glStencilFunc(GL_EQUAL, 1, 1); 01209 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 01210 if (FBZMODE_ENABLE_DEPTHBUF(FBZMODE)) { 01211 VOGL_SetDepthMode(1,GL_ALWAYS-GL_NEVER); 01212 } else { 01213 VOGL_SetDepthMode(0,0); 01214 } 01215 } else { 01216 if (FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) == 0) { 01217 if (FBZMODE_ENABLE_DEPTHBUF(FBZMODE)) { 01218 VOGL_SetDepthMode(1,FBZMODE_DEPTH_FUNCTION(FBZMODE)); 01219 } else { 01220 if (FBZMODE_AUX_BUFFER_MASK(FBZMODE) > 0) { 01221 VOGL_SetDepthMode(1,GL_ALWAYS-GL_NEVER); 01222 } else { 01223 VOGL_SetDepthMode(0,0); 01224 } 01225 } 01226 } else { 01227 VOGL_SetDepthMode(1,GL_ALWAYS-GL_NEVER); 01228 } 01229 } 01230 01231 bool color_mask = (FBZMODE_RGB_BUFFER_MASK(FBZMODE) > 0); 01232 01233 if (FBZMODE_AUX_BUFFER_MASK(FBZMODE) > 0) { 01234 VOGL_SetDepthMaskMode(FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) == 0); 01235 VOGL_SetColorMaskMode(color_mask, true); 01236 } else { 01237 VOGL_SetDepthMaskMode(false); 01238 VOGL_SetColorMaskMode(color_mask, false); 01239 } 01240 01241 if (ALPHAMODE_ALPHABLEND(ALPHAMODE)) { 01242 VOGL_SetAlphaMode(1, ogl_sfactor[ALPHAMODE_SRCRGBBLEND(ALPHAMODE)], ogl_dfactor[ALPHAMODE_DSTRGBBLEND(ALPHAMODE)], 01243 (ALPHAMODE_SRCALPHABLEND(ALPHAMODE)==4)?GL_ONE:GL_ZERO, 01244 (ALPHAMODE_DSTALPHABLEND(ALPHAMODE)==4)?GL_ONE:GL_ZERO); 01245 } else { 01246 VOGL_SetAlphaMode(0, 0,0,0,0); 01247 } 01248 01249 if (FBZMODE_DRAW_BUFFER(v->reg[fbzMode].u)==0) { 01250 VOGL_SetDrawMode(true); 01251 v->fbi.vblank_flush_pending=true; 01252 cached_line_front_y=-1; 01253 } else { 01254 VOGL_SetDrawMode(false); 01255 cached_line_back_y=-1; 01256 } 01257 01258 01259 glBegin(GL_TRIANGLES); 01260 01261 for (unsigned int i=0;i<3;i++) { 01262 glColor4fv(&vd[i].r); 01263 01264 for (unsigned int t=0;t<2;t++) 01265 if (td[t].enable) { 01266 glMultiTexCoord4fv(GL_TEXTURE0_ARB+t,&vd[i].m[t].sw); 01267 if (extra->info->shader_ulocations[10u+t] >= 0) 01268 glVertexAttrib1fARB((GLuint)extra->info->shader_ulocations[10u+t],vd[i].m[t].lodblend); 01269 } 01270 01271 if (extra->info->shader_ulocations[9] >= 0) 01272 glVertexAttrib1fARB((GLuint)extra->info->shader_ulocations[9],vd[i].fogblend); 01273 01274 glVertex3fv(&vd[i].x); 01275 } 01276 01277 glEnd(); 01278 01279 if (FBZMODE_DEPTH_SOURCE_COMPARE(FBZMODE) && VOGL_CheckFeature(VOGL_HAS_STENCIL_BUFFER)) { 01280 glDisable(GL_STENCIL_TEST); 01281 } 01282 01283 if (!extra->info->shader_ready) { 01284 glDisable (GL_TEXTURE_2D); 01285 } 01286 } 01287 01288 01289 void voodoo_ogl_swap_buffer() { 01290 VOGL_ClearBeginMode(); 01291 01292 SDL_GL_SwapBuffers(); 01293 01294 cached_line_front_y=-1; 01295 cached_line_back_y=-1; 01296 } 01297 01298 01299 void voodoo_ogl_texture_clear(UINT32 texbase, int TMU) { 01300 std::map<const UINT32, ogl_texmap>::iterator t; 01301 t=textures[TMU].find(texbase); 01302 if (t != textures[TMU].end()) { 01303 VOGL_ClearBeginMode(); 01304 if (t->second.ids != NULL) { 01305 std::map<const UINT32, GLuint>::iterator u; 01306 for (u=t->second.ids->begin(); u!=t->second.ids->end(); ++u) { 01307 glDeleteTextures(1,&u->second); 01308 } 01309 delete t->second.ids; 01310 t->second.ids = NULL; 01311 } else { 01312 t->second.valid_data = false; 01313 } 01314 textures[TMU].erase(t); 01315 } 01316 } 01317 01318 void voodoo_ogl_draw_pixel(int x, int y, bool has_rgb, bool has_alpha, int r, int g, int b, int a) { 01319 GLfloat x2, y2; 01320 01321 if (m_hProgramObject != 0) { 01322 glUseProgramObjectARB(0); 01323 m_hProgramObject = 0; 01324 } 01325 01326 if (LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u)==0) { 01327 VOGL_SetDrawMode(true); 01328 v->fbi.vblank_flush_pending=true; 01329 } else { 01330 VOGL_SetDrawMode(false); 01331 } 01332 01333 VOGL_SetDepthMode(0,0); 01334 01335 VOGL_SetDepthMaskMode(false); 01336 VOGL_SetColorMaskMode(has_rgb, has_alpha); 01337 01338 VOGL_SetAlphaMode(0, 0,0,0,0); 01339 01340 x2 = (GLfloat) x + 0.5; 01341 y2 = (GLfloat) y + 0.5; 01342 01343 VOGL_BeginMode(GL_POINTS); 01344 glColor4ub((GLubyte)(r&0xff), (GLubyte)(g&0xff), (GLubyte)(b&0xff), (GLubyte)(a&0xff)); 01345 glVertex2f(x2, y2); 01346 } 01347 01348 void voodoo_ogl_draw_z(int x, int y, int z) { 01349 // VOGL_ClearBeginMode(); 01350 01351 if (m_hProgramObject != 0) { 01352 glUseProgramObjectARB(0); 01353 m_hProgramObject = 0; 01354 } 01355 01356 if (LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u)==0) { 01357 VOGL_SetDrawMode(true); 01358 v->fbi.vblank_flush_pending=true; 01359 } else { 01360 VOGL_SetDrawMode(false); 01361 } 01362 01363 VOGL_SetDepthMode(1,GL_ALWAYS-GL_NEVER); 01364 01365 VOGL_SetDepthMaskMode(true); 01366 VOGL_SetColorMaskMode(false, false); 01367 01368 VOGL_SetAlphaMode(0, 0,0,0,0); 01369 01370 VOGL_BeginMode(GL_POINTS); 01371 // glBegin(GL_POINTS); 01372 glVertex3i(x, y, z); // z adjustment?? 01373 // glEnd(); 01374 } 01375 01376 void voodoo_ogl_draw_pixel_pipeline(int x, int y, int r, int g, int b) { 01377 // VOGL_ClearBeginMode(); 01378 GLfloat x2, y2; 01379 01380 // TODO redo everything // 01381 if (m_hProgramObject != 0) { 01382 glUseProgramObjectARB(0); 01383 m_hProgramObject = 0; 01384 } 01385 01386 if (LFBMODE_WRITE_BUFFER_SELECT(v->reg[lfbMode].u)==0) { 01387 VOGL_SetDrawMode(true); 01388 v->fbi.vblank_flush_pending=true; 01389 } else { 01390 VOGL_SetDrawMode(false); 01391 } 01392 01393 VOGL_SetDepthMode(0,0); 01394 01395 VOGL_SetDepthMaskMode(false); 01396 if (FBZMODE_AUX_BUFFER_MASK(v->reg[fbzMode].u) > 0) { 01397 VOGL_SetColorMaskMode(true, true); 01398 } else { 01399 VOGL_SetColorMaskMode(true, false); 01400 } 01401 01402 if (ALPHAMODE_ALPHABLEND(v->reg[alphaMode].u)) { 01403 VOGL_SetAlphaMode(1, ogl_sfactor[ALPHAMODE_SRCRGBBLEND(v->reg[alphaMode].u)], ogl_dfactor[ALPHAMODE_DSTRGBBLEND(v->reg[alphaMode].u)], 01404 (ALPHAMODE_SRCALPHABLEND(v->reg[alphaMode].u)==4)?GL_ONE:GL_ZERO, 01405 (ALPHAMODE_DSTALPHABLEND(v->reg[alphaMode].u)==4)?GL_ONE:GL_ZERO); 01406 } else { 01407 VOGL_SetAlphaMode(0, 0,0,0,0); 01408 } 01409 01410 x2 = (GLfloat) x + 0.5; 01411 y2 = (GLfloat) y + 0.5; 01412 01413 VOGL_BeginMode(GL_POINTS); 01414 // glBegin(GL_POINTS); 01415 // glColor3f((float)r/255.0f, (float)g/255.0f, (float)b/255.0f); 01416 glColor3ub((GLubyte)(r&0xff), (GLubyte)(g&0xff), (GLubyte)(b&0xff)); 01417 glVertex2f(x2, y2); 01418 // glEnd(); 01419 } 01420 01421 01422 void voodoo_ogl_clip_window(voodoo_state *v) { 01423 (void)v;//UNUSED 01424 /* VOGL_ClearBeginMode(); 01425 01426 int sx = (v->reg[clipLeftRight].u >> 16) & 0x3ff; 01427 int ex = (v->reg[clipLeftRight].u >> 0) & 0x3ff; 01428 int sy = (v->reg[clipLowYHighY].u >> 16) & 0x3ff; 01429 int ey = (v->reg[clipLowYHighY].u >> 0) & 0x3ff; 01430 01431 if (FBZMODE_Y_ORIGIN(v->reg[fbzMode].u)) { 01432 sy = (v->fbi.yorigin+1 - sy) & 0x3ff; 01433 ey = (v->fbi.yorigin+1 - ey) & 0x3ff; 01434 } 01435 01436 if ((sx>0) || (sy>0) || (ex<v->fbi.width) || (ey<v->fbi.height)) 01437 { 01438 glEnable(GL_SCISSOR_TEST); 01439 glScissor(sx,sy,ex-sx,ey-sy); 01440 } else { 01441 glScissor(0,0,v->fbi.width,v->fbi.height); 01442 glDisable(GL_SCISSOR_TEST); 01443 } */ 01444 } 01445 01446 01447 void voodoo_ogl_fastfill(void) { 01448 VOGL_ClearBeginMode(); 01449 01450 VOGL_SetDepthMaskMode(true); 01451 01452 int sx = (v->reg[clipLeftRight].u >> 16) & 0x3ff; 01453 int ex = (v->reg[clipLeftRight].u >> 0) & 0x3ff; 01454 int sy = (v->reg[clipLowYHighY].u >> 16) & 0x3ff; 01455 int ey = (v->reg[clipLowYHighY].u >> 0) & 0x3ff; 01456 01457 // if (FBZMODE_Y_ORIGIN(v->reg[fbzMode].u)) 01458 { 01459 int tmp = ((int)v->fbi.yorigin+1 - ey) & 0x3ff; 01460 ey = ((int)v->fbi.yorigin+1 - sy) & 0x3ff; 01461 sy = tmp; 01462 } 01463 01464 bool scissors_needed = true; 01465 if ((sx == 0) && (sy == 0)) { 01466 if (((Bitu)ex == (Bitu)v->fbi.width) && ((Bitu)ey == (Bitu)v->fbi.height)) scissors_needed = false; 01467 } 01468 01469 if (scissors_needed) { 01470 glEnable(GL_SCISSOR_TEST); 01471 glScissor(sx,sy,ex-sx,ey-sy); 01472 } 01473 01474 01475 Bit32u clear_mask=0; 01476 if (FBZMODE_RGB_BUFFER_MASK(v->reg[fbzMode].u)) { 01477 clear_mask|=GL_COLOR_BUFFER_BIT; 01478 01479 // if (FBZMODE_AUX_BUFFER_MASK(v->reg[fbzMode].u) && v->fbi.auxoffs != (UINT32)(~0)) ... 01480 VOGL_SetColorMaskMode(true, true); 01481 01482 if (last_clear_color!=v->reg[color1].u) { 01483 glClearColor((float)v->reg[color1].rgb.r/255.0f, 01484 (float)v->reg[color1].rgb.g/255.0f, 01485 (float)v->reg[color1].rgb.b/255.0f, 01486 (float)v->reg[color1].rgb.a/255.0f); 01487 last_clear_color=v->reg[color1].u; 01488 } 01489 if (FBZMODE_DRAW_BUFFER(v->reg[fbzMode].u)==0) { 01490 VOGL_SetDrawMode(true); 01491 v->fbi.vblank_flush_pending=true; 01492 cached_line_front_y=-1; 01493 } else { 01494 VOGL_SetDrawMode(false); 01495 cached_line_back_y=-1; 01496 } 01497 } 01498 if (FBZMODE_AUX_BUFFER_MASK(v->reg[fbzMode].u) && v->fbi.auxoffs != (UINT32)(~0)) { 01499 // if (FBZMODE_ENABLE_DEPTHBUF(v->reg[fbzMode].u)) { 01500 clear_mask|=GL_DEPTH_BUFFER_BIT; 01501 glClearDepth((float)((UINT16)v->reg[zaColor].u)/65535.0f); 01502 } 01503 01504 if (clear_mask) glClear(clear_mask); 01505 01506 if (scissors_needed) { 01507 glScissor(0,0,(int)v->fbi.width,(int)v->fbi.height); 01508 glDisable(GL_SCISSOR_TEST); 01509 } 01510 } 01511 01512 void voodoo_ogl_clear(void) { 01513 VOGL_ClearBeginMode(); 01514 01515 VOGL_SetDrawMode(false); 01516 01517 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 01518 last_clear_color = 0; 01519 glClearDepth(1.0f); 01520 glClearStencil(0); 01521 01522 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01523 voodoo_ogl_swap_buffer(); 01524 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 01525 } 01526 01527 01528 UINT32 voodoo_ogl_read_pixel(int x, int y) { 01529 UINT32 data[2]; 01530 if ((x < 0) || (y < 0) || (x >= (INT32)v->fbi.width) || (y >= (INT32)v->fbi.height)) return 0xffffffff; 01531 01532 UINT32 mode=GL_RGBA; 01533 switch (LFBMODE_READ_BUFFER_SELECT(v->reg[lfbMode].u)) { 01534 case 0: /* front buffer */ 01535 VOGL_SetReadMode(true); 01536 if ((cached_line_front_y != y) || (x+1 >= cached_line_front_width)) { 01537 if (cached_line_front_length<(INT32)v->fbi.width) { 01538 if (cached_line_front_data!=NULL) free(cached_line_front_data); 01539 size_t span_length=((v->fbi.width+64u)&(~15u)); 01540 cached_line_front_data=(UINT32*)malloc(sizeof(UINT32)*span_length); 01541 cached_line_front_length=(INT32)span_length; 01542 } 01543 glReadPixels(0,(int)v->fbi.height-y,(int)v->fbi.width,1,mode,GL_UNSIGNED_BYTE,cached_line_front_data); 01544 cached_line_front_y=y; 01545 cached_line_front_width = (INT32)v->fbi.width; 01546 } 01547 data[0]=cached_line_front_data[x]; 01548 data[1]=cached_line_front_data[x+1]; 01549 break; 01550 case 1: /* back buffer */ 01551 VOGL_SetReadMode(false); 01552 if ((cached_line_back_y != y) || (x+1 >= cached_line_back_width)) { 01553 if (cached_line_back_length<(INT32)v->fbi.width) { 01554 if (cached_line_back_data!=NULL) free(cached_line_back_data); 01555 size_t span_length=((v->fbi.width+64u)&(~15u)); 01556 cached_line_back_data=(UINT32*)malloc(sizeof(UINT32)*span_length); 01557 cached_line_back_length=(INT32)span_length; 01558 } 01559 glReadPixels(0,(int)v->fbi.height-y,(int)v->fbi.width,1,mode,GL_UNSIGNED_BYTE,cached_line_back_data); 01560 cached_line_back_y=y; 01561 cached_line_back_width = (INT32)v->fbi.width; 01562 } 01563 data[0]=cached_line_back_data[x]; 01564 data[1]=cached_line_back_data[x+1]; 01565 break; 01566 case 2: /* aux buffer */ 01567 mode=GL_DEPTH_COMPONENT; 01568 VOGL_SetReadMode(false); 01569 glReadPixels(x,(int)v->fbi.height-y,2,1,mode,GL_UNSIGNED_INT,&data); 01570 return ((data[0]>>16)&0xffff) | (data[1] & 0xffff0000); 01571 default: 01572 E_Exit("read from invalid buf %x",LFBMODE_READ_BUFFER_SELECT(v->reg[lfbMode].u)); 01573 break; 01574 } 01575 01576 return ((RGB_BLUE(data[0])>>3)<<11) | ((RGB_GREEN(data[0])>>2)<<5) | (RGB_RED(data[0])>>3) | 01577 ((RGB_BLUE(data[1])>>3)<<27) | ((RGB_GREEN(data[1])>>2)<<21) | ((RGB_RED(data[1])>>3)<<16); 01578 } 01579 01580 01581 void voodoo_ogl_vblank_flush(void) { 01582 VOGL_ClearBeginMode(); 01583 glFlush(); 01584 } 01585 01586 01587 void voodoo_ogl_set_window(voodoo_state *v) { 01588 VOGL_ClearBeginMode(); 01589 01590 // matrix mode GL_PROJECTION assumed 01591 bool size_changed=false; 01592 if ((v->fbi.width!=last_width) || (v->fbi.height!=last_height)) size_changed=true; 01593 if (size_changed || (last_orientation != (INT32)FBZMODE_Y_ORIGIN(v->reg[fbzMode].u))) { 01594 glLoadIdentity( ); 01595 if (FBZMODE_Y_ORIGIN(v->reg[fbzMode].u)) 01596 glOrtho( 0, v->fbi.width, 0, v->fbi.height, 0.0f, -1.0f ); 01597 else 01598 glOrtho( 0, v->fbi.width, v->fbi.height, 0, 0.0f, -1.0f ); 01599 if (last_orientation != (INT32)FBZMODE_Y_ORIGIN(v->reg[fbzMode].u)) 01600 last_orientation = FBZMODE_Y_ORIGIN(v->reg[fbzMode].u); 01601 } 01602 if (size_changed) { 01603 //correction for viewport if 640x400 01604 if( v->fbi.height < 480 && GFX_IsFullscreen()) adjust_y=(480-(int)v->fbi.height)/2; 01605 if( v->fbi.width < 640 && GFX_IsFullscreen()) adjust_x=(640-(int)v->fbi.width)/2; 01606 glViewport( adjust_x, adjust_y, (int)v->fbi.width, (int)v->fbi.height ); 01607 last_width = v->fbi.width; 01608 last_height = v->fbi.height; 01609 } 01610 } 01611 01612 void voodoo_ogl_reset_videomode(void) { 01613 #if defined(WIN32) && !defined(C_SDL2) 01614 /* always show the menu */ 01615 void DOSBox_SetMenu(void); 01616 DOSBox_SetMenu(); 01617 #endif 01618 01619 #if defined(C_SDL2) 01620 E_Exit("SDL2 3Dfx OpenGL emulation not implemented yet"); 01621 #else 01622 GFX_PreventFullscreen(true); 01623 01624 last_clear_color=0; 01625 01626 last_width=0; 01627 last_height=0; 01628 last_orientation=-1; 01629 01630 VOGL_Reset(); 01631 01632 GFX_TearDown(); 01633 01634 bool full_sdl_restart = true; // make dependent on surface=opengl 01635 01636 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 01637 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 01638 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); 01639 01640 bool has_alpha = true; 01641 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); 01642 01643 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 01644 01645 bool has_stencil = true; 01646 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 01647 01648 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 01649 01650 /*glMatrixMode( GL_PROJECTION ); 01651 glLoadIdentity(); 01652 glOrtho( 0, v->fbi.width, v->fbi.height, 0, -1, 1 ); 01653 glMatrixMode( GL_MODELVIEW ); 01654 glLoadIdentity();*/ 01655 // END OF FIX 01656 01657 #if defined (WIN32) && SDL_VERSION_ATLEAST(1, 2, 11) 01658 SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 ); 01659 #endif 01660 01661 #if !defined (WIN32) && SDL_VERSION_ATLEAST(1, 2, 10) 01662 // broken on windows (longstanding SDL bug), may help other platforms to force hardware acceleration 01663 SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 ); 01664 #endif 01665 01666 ogl_surface = NULL; 01667 01668 void GFX_ReleaseMouse(void); 01669 void GFX_ForceFullscreenExit(void); 01670 01671 GFX_ReleaseMouse(); 01672 GFX_ForceFullscreenExit(); 01673 01674 Uint32 sdl_flags = SDL_OPENGL; 01675 01676 ogl_surface = SDL_SetVideoMode((int)v->fbi.width, (int)v->fbi.height, 32, sdl_flags); 01677 01678 if (ogl_surface == NULL) { 01679 if (full_sdl_restart) { 01680 SDL_QuitSubSystem(SDL_INIT_VIDEO); 01681 SDL_InitSubSystem(SDL_INIT_VIDEO); 01682 ogl_surface = SDL_SetVideoMode((int)v->fbi.width, (int)v->fbi.height, 32, sdl_flags); 01683 } 01684 if (ogl_surface == NULL) { 01685 has_alpha = false; 01686 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); 01687 if ((ogl_surface = SDL_SetVideoMode((int)v->fbi.width, (int)v->fbi.height, 32, sdl_flags)) == NULL) { 01688 has_stencil = false; 01689 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); 01690 if ((ogl_surface = SDL_SetVideoMode((int)v->fbi.width, (int)v->fbi.height, 32, sdl_flags)) == NULL) { 01691 if (sdl_flags & SDL_FULLSCREEN) { 01692 sdl_flags &= ~(SDL_FULLSCREEN); 01693 if ((ogl_surface = SDL_SetVideoMode((int)v->fbi.width, (int)v->fbi.height, 32, sdl_flags)) == NULL) { 01694 E_Exit("VOODOO: opengl init error"); 01695 } 01696 } else { 01697 E_Exit("VOODOO: opengl init error"); 01698 } 01699 } 01700 LOG_MSG("VOODOO: Graphics mode does not support Stencil/Alpha channels"); 01701 } else { 01702 LOG_MSG("VOODOO: Graphics mode does not support Alpha channel"); 01703 } 01704 } 01705 } 01706 01707 v->ogl_dimchange = true; 01708 01709 glViewport( 0, 0, (int)v->fbi.width, (int)v->fbi.height ); 01710 last_width = v->fbi.width; 01711 last_height = v->fbi.height; 01712 01713 /* NTS: Some demoscene 3Dfx stuff looks terrible without this. 01714 * This is said to be the initial state of an OpenGL context. 01715 * This is in direct contradiction to the OpenGL output setup 01716 * in src/gui/sdlmain.cpp that sets up GL_FLAT shading */ 01717 glShadeModel (GL_SMOOTH); 01718 01719 GFX_UpdateSDLCaptureState(); 01720 01721 int value; 01722 01723 bool few_colors = false; 01724 if (SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value) == 0) { 01725 if (value < 8) few_colors = true; 01726 } 01727 if (SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &value) == 0) { 01728 if (value < 8) few_colors = true; 01729 } 01730 if (SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value) == 0) { 01731 if (value < 8) few_colors = true; 01732 } 01733 if (few_colors) LOG_MSG("opengl: warning: graphics mode with insufficient color depth"); 01734 01735 if (SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value) == 0) { 01736 if (value < 24) LOG_MSG("opengl: warning: depth buffer with insufficient resolution"); 01737 } 01738 01739 if (SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &value) == 0) { 01740 if (value < 1) has_stencil = false; 01741 } 01742 if (SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &value) == 0) { 01743 if (value < 8) has_alpha = false; 01744 } 01745 01746 if (has_stencil) VOGL_FlagFeature(VOGL_HAS_STENCIL_BUFFER); 01747 if (has_alpha) VOGL_FlagFeature(VOGL_HAS_ALPHA_PLANE); 01748 01749 GLint depth_csize; 01750 glGetIntegerv(GL_DEPTH_BITS, &depth_csize); 01751 if (depth_csize < 16) { 01752 LOG_MSG("VOODOO: OpenGL: invalid depth size %d",depth_csize); 01753 } 01754 01755 #if defined(WIN32) && !defined(C_SDL2) 01756 // Windows SDL 1.x builds may destroy and re-create the window, and lose our menu bar. 01757 // make sure to put it back. 01758 void DOSBox_SetMenu(void); 01759 DOSBox_SetMenu(); 01760 #endif 01761 01762 /* Something in Windows keeps changing the shade model on us from the last glShadeModel() call. Change it back. */ 01763 glShadeModel(GL_SMOOTH); 01764 01765 LOG_MSG("VOODOO: OpenGL: mode set, resolution %d:%d %s", v->fbi.width, v->fbi.height, (sdl_flags & SDL_FULLSCREEN) ? "(fullscreen)" : ""); 01766 #endif 01767 } 01768 01769 void voodoo_ogl_update_dimensions(void) { 01770 voodoo_ogl_leave(false); 01771 01772 voodoo_ogl_reset_videomode(); 01773 01774 glMatrixMode( GL_PROJECTION ); 01775 voodoo_ogl_set_window(v); 01776 01777 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 01778 01779 glMatrixMode( GL_MODELVIEW ); 01780 glLoadIdentity( ); 01781 glMatrixMode( GL_PROJECTION ); 01782 } 01783 01784 bool voodoo_ogl_init(voodoo_state *v) { 01785 extern void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); 01786 // CPU_Core_Dyn_X86_SetFPUMode(false); 01787 01788 extern void CPU_Core_Dyn_X86_Cache_Reset(void); 01789 // CPU_Core_Dyn_X86_Cache_Reset(); 01790 01791 01792 voodoo_ogl_reset_videomode(); 01793 01794 if (!VOGL_Initialize()) { 01795 VOGL_Reset(); 01796 // reset video mode etc. 01797 return false; 01798 } 01799 01800 /* std::string features = ""; 01801 if (VOGL_CheckFeature(VOGL_HAS_SHADERS)) features += " shader"; 01802 if (VOGL_CheckFeature(VOGL_HAS_ALPHA_PLANE)) features += " alpha-plane"; 01803 if (VOGL_CheckFeature(VOGL_HAS_STENCIL_BUFFER)) features += " stencil-buffer"; 01804 01805 if (features == "") features = " none"; 01806 01807 LOG_MSG("VOODOO: OpenGL: features enabled:%s",features.c_str()); */ 01808 01809 01810 glMatrixMode( GL_PROJECTION ); 01811 voodoo_ogl_set_window(v); 01812 01813 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 01814 01815 glMatrixMode( GL_MODELVIEW ); 01816 glLoadIdentity( ); 01817 glMatrixMode( GL_PROJECTION ); 01818 01819 return true; 01820 } 01821 01822 void voodoo_ogl_leave(bool leavemode) { 01823 VOGL_ClearBeginMode(); 01824 01825 std::map<const UINT32, ogl_texmap>::iterator t; 01826 for (int j=0; j<2; j++) { 01827 for (t=textures[j].begin(); t!=textures[j].end(); ++t) { 01828 if (t->second.ids != NULL) { 01829 std::map<const UINT32, GLuint>::iterator u; 01830 for (u=t->second.ids->begin(); u!=t->second.ids->end(); ++u) { 01831 glDeleteTextures(1,&u->second); 01832 } 01833 if (!t->second.ids->empty()) t->second.ids->clear(); 01834 delete t->second.ids; 01835 t->second.ids = NULL; 01836 } else { 01837 glDeleteTextures(1,&t->second.current_id); 01838 } 01839 } 01840 if (!textures[j].empty()) textures[j].clear(); 01841 } 01842 01843 01844 if (m_hProgramObject != 0) { 01845 glUseProgramObjectARB(0); 01846 m_hProgramObject = 0; 01847 } 01848 01849 for (int hct=0; hct<RASTER_HASH_SIZE; hct++) { 01850 raster_info *info = v->raster_hash[hct]; 01851 for (; info; info = info->next) { 01852 if (info->shader_ready) { 01853 delete[] info->shader_ulocations; 01854 info->shader_ulocations=NULL; 01855 01856 if (info->so_shader_program > 0) { 01857 if (info->so_vertex_shader > 0) glDetachObjectARB((GLhandleARB)info->so_shader_program, (GLhandleARB)info->so_vertex_shader); 01858 if (info->so_fragment_shader > 0) glDetachObjectARB((GLhandleARB)info->so_shader_program, (GLhandleARB)info->so_fragment_shader); 01859 if (info->so_vertex_shader > 0) glDeleteObjectARB((GLhandleARB)info->so_vertex_shader); 01860 if (info->so_fragment_shader > 0) glDeleteObjectARB((GLhandleARB)info->so_fragment_shader); 01861 glDeleteObjectARB((GLhandleARB)info->so_shader_program); 01862 } 01863 01864 info->shader_ready=false; 01865 } 01866 } 01867 } 01868 01869 01870 cached_line_front_y=-1; 01871 cached_line_back_y=-1; 01872 01873 if (leavemode) { 01874 LOG_MSG("VOODOO: OpenGL: quit"); 01875 01876 ogl_surface = NULL; 01877 GFX_PreventFullscreen(false); 01878 GFX_RestoreMode(); 01879 } 01880 } 01881 01882 void voodoo_ogl_shutdown(voodoo_state *v) { 01883 // TODO revert to previous video mode // 01884 01885 voodoo_ogl_leave(false); 01886 01887 v->active = false; 01888 } 01889 01890 #else 01891 01892 01893 bool voodoo_ogl_init(voodoo_state *v) { 01894 (void)v; 01895 return false; 01896 } 01897 01898 void voodoo_ogl_leave(void) { 01899 } 01900 01901 void voodoo_ogl_shutdown(voodoo_state *v) { 01902 (void)v; 01903 } 01904 01905 void voodoo_ogl_set_window(voodoo_state *v) { 01906 (void)v; 01907 E_Exit("invalid call to voodoo_ogl_set_window"); 01908 } 01909 01910 void voodoo_ogl_swap_buffer(void) { 01911 E_Exit("invalid call to voodoo_ogl_swap_buffer"); 01912 } 01913 01914 void voodoo_ogl_vblank_flush(void) { 01915 E_Exit("invalid call to voodoo_ogl_vblank_flush"); 01916 } 01917 01918 void voodoo_ogl_clear(void) { 01919 E_Exit("invalid call to voodoo_ogl_clear"); 01920 } 01921 01922 void voodoo_ogl_fastfill(void) { 01923 E_Exit("invalid call to voodoo_ogl_fastfill"); 01924 } 01925 01926 void voodoo_ogl_clip_window(voodoo_state *v) { 01927 (void)v; 01928 E_Exit("invalid call to voodoo_ogl_clip_window"); 01929 } 01930 01931 void voodoo_ogl_texture_clear(UINT32 texbase, int TMU) { 01932 (void)texbase; 01933 (void)TMU; 01934 E_Exit("invalid call to voodoo_ogl_texture_clear"); 01935 } 01936 01937 void voodoo_ogl_invalidate_paltex(void) { 01938 E_Exit("invalid call to voodoo_ogl_invalidate_paltex"); 01939 } 01940 01941 void voodoo_ogl_draw_pixel(int x, int y, bool has_rgb, bool has_alpha, int r, int g, int b, int a) { 01942 (void)has_alpha; 01943 (void)has_rgb; 01944 (void)x; 01945 (void)y; 01946 (void)r; 01947 (void)g; 01948 (void)b; 01949 (void)a; 01950 E_Exit("invalid call to voodoo_ogl_draw_pixel"); 01951 } 01952 01953 void voodoo_ogl_draw_z(int x, int y, int z1, int z2) { 01954 (void)z1; 01955 (void)z2; 01956 (void)x; 01957 (void)y; 01958 E_Exit("invalid call to voodoo_ogl_draw_z"); 01959 } 01960 01961 void voodoo_ogl_draw_pixel_pipeline(int x, int y, int r, int g, int b) { 01962 (void)x; 01963 (void)y; 01964 (void)r; 01965 (void)g; 01966 (void)b; 01967 E_Exit("invalid call to voodoo_ogl_draw_pixel_pipeline"); 01968 } 01969 01970 UINT32 voodoo_ogl_read_pixel(int x, int y) { 01971 (void)x; 01972 (void)y; 01973 E_Exit("invalid call to voodoo_ogl_read_pixel"); 01974 return 0; 01975 } 01976 01977 void voodoo_ogl_draw_triangle(poly_extra_data *extra) { 01978 (void)extra; 01979 E_Exit("invalid call to voodoo_ogl_draw_triangle"); 01980 } 01981 01982 #endif