//**************************************************************
//* OpenGLide - Glide to OpenGL Wrapper
//* http://openglide.sourceforge.net
//*
//* framebuffer emulation
//*
//* OpenGLide is OpenSource under LGPL license
//* Mac version and additional features by Jens-Olaf Hemprich
//**************************************************************
#include"Framebuffer.h"#include"Glide.h"#include"GlideApplication.h"#include"GlideSettings.h"#include"GLRender.h"#include"GLRenderUpdateState.h"#include"GLColorAlphaCombineEnvTables.h"// Displays small dots in tile edges, disables all optimisations
// #define DEBUG_TILE_RENDERING
Framebuffer::Framebuffer():m_x_step_start(0),m_y_step_start(0),m_x_step_start_opaque(0),m_y_step_start_opaque(0),m_width(0),m_height(0),m_framebuffer(NULL),m_texbuffer(NULL),m_origin(GR_ORIGIN_UPPER_LEFT),m_glInternalFormat(-1),m_glFormat(-1),m_glType(-1),m_glDepth(1.0f),m_format_valid(false),m_useRectangleARB(false),m_must_clear_buffer(true),m_custom_tilesizes(NULL){#ifdef __ALTIVEC__for(inti=0;i<4;i++){(&m_glAlpha.Scalar)[i]=0x000000ff;}#elsem_glAlpha.Scalar=0x000000ff;#endif}Framebuffer::~Framebuffer(){}inlineintFramebuffer::getTileCount()const{returnm_tilesizesCount+m_customtilesizesCount;}boolFramebuffer::initialise_buffers(BufferStruct*framebuffer,BufferStruct*texbuffer,FxU32width,FxU32height,consttilesize*tilesizetable){#ifdef OGL_FRAMEBUFFERGlideMsg("GlideFrameBuffer::initialise_buffers(---, ---, %d, %d, ---)\n",width,height);#endifm_custom_tilesizes=tilesizetable;returninitialise_buffers(framebuffer,texbuffer,width,height,0,0);}boolFramebuffer::initialise_buffers(BufferStruct*framebuffer,BufferStruct*texbuffer,FxU32width,FxU32height,FxU32x_tile,FxU32y_tile){#ifdef OGL_FRAMEBUFFERGlideMsg("Framebuffer::initialise_buffers(---, ---, %d, %d, %d, %d)\n",width,height,x_tile,y_tile);#endifm_framebuffer=framebuffer;m_texbuffer=texbuffer;m_framebuffer->WriteMode=m_texbuffer->WriteMode=GR_LFBWRITEMODE_UNUSED;m_width=width;m_height=height;// find out largest texture size
GLinttile_size;glGetIntegerv(GL_MAX_TEXTURE_SIZE,&tile_size);m_x_step_start_opaque=tile_size;m_y_step_start_opaque=tile_size;m_x_step_start=min(tile_size,x_tile);m_y_step_start=min(tile_size,y_tile);m_x_step_start=max(16,m_x_step_start);m_y_step_start=max(16,m_y_step_start);m_useRectangleARB=InternalConfig.ARB_texture_rectangle&&InternalConfig.EXT_compiled_vertex_array;// If a game has its own tilesize table, use
// the largest tiles for opaque renderings
GLinty_step=y_tile==0?m_y_step_start_opaque:m_y_step_start;// init default/opaque tilesize table
intw=0;for(FxU32y=0;y<m_height&&w<MaxTiles;y+=y_step,w++){while(m_height-y<y_step){y_step=y_step>>1;}m_tilesizes[w].y=y_step;GLintx_step=x_tile==0?m_x_step_start_opaque:m_x_step_start;intv=0;for(FxU32x=0;x<m_width&&v<MaxTiles;x+=x_step,v++){while(m_width-x<x_step){x_step=x_step>>1;}m_tilesizes[w].x[v]=x_step;}}// This is always initialised as the immediate mode also uses the precalculated tile coordinates
buildVertexArrays();// The texture priority is set to maximum
// because of the altivec checksum feature
constGLfloatpriority=1.0f;constinttileCount=getTileCount();glGenTextures(tileCount,&m_textureNames[0]);glPrioritizeTextures(tileCount,&m_textureNames[0],&priority);for(inti=0;i<tileCount;i++){constGLenumtextureTarget=m_useRectangleARB?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D;glBindTexture(textureTarget,m_textureNames[i]);glTexParameteri(textureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexParameteri(textureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(textureTarget,GL_TEXTURE_WRAP_S,GL_CL