00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "Core/precomp.h"
00022
00023 #include <Display/Display/FBDev/blit_mga.h>
00024 #include <Display/Display/Generic/blitters.h>
00025 #include <API/Display/Display/cliprect.h>
00026 #include <Display/Display/Generic/colormap.h>
00027 #include <Display/Display/FBDev/display_fbdev.h>
00028 #include <Display/Display/Generic/pixeldata.h>
00029 #include <API/Display/Display/surfaceprovider.h>
00030 #include <API/Display/Display/target.h>
00031 #include <Display/Display/Generic/blit_alphamask_rle.h>
00032
00033 #include <linux/fb.h>
00034
00035 #include "regs.h"
00036 #include "mmio.h"
00037
00038 static int store_index = 0;
00039
00040 std::list<CL_Blit_MGA*> CL_Blit_MGA::m_loaded_surfaces;
00041
00042 CL_Blit_MGA::CL_Blit_MGA(
00043 CL_FBDev_DisplayCard *card,
00044 CL_SurfaceProvider *provider,
00045 volatile unsigned char *mmioaddr)
00046 {
00047 m_card = card;
00048 m_provider = provider;
00049 m_alphablitter = NULL;
00050 m_transparent = false;
00051 m_mmioaddr = mmioaddr;
00052 }
00053
00054 CL_Blit_MGA::~CL_Blit_MGA()
00055 {
00056 if (m_alphablitter != NULL) delete m_alphablitter;
00057 }
00058
00059 bool CL_Blit_MGA::init_surface(CL_Blitters *blitters)
00060 {
00061 m_width = m_provider->get_width();
00062 m_height = m_provider->get_height();
00063
00064
00065 if (m_card->get_total_memory() <= 4096*1024)
00066 {
00067 if ((m_width>400) || (m_height>300)) return false;
00068 }
00069
00070 if (!reload(false, true)) return false;
00071
00072 blitters->set_clip(this);
00073 blitters->set_noclip(this);
00074
00075 if (m_card->accel_scale_blit())
00076 {
00077 blitters->set_scale_noclip(this);
00078 blitters->set_scale_clip(this);
00079 }
00080
00081 m_loaded_surfaces.push_back(this);
00082
00083 return true;
00084 }
00085
00086 void CL_Blit_MGA::blt_noclip(
00087 CL_Target *target,
00088 int x,
00089 int y,
00090 int spr_no)
00091 {
00092 int new_store = m_store;
00093 if (spr_no)
00094 {
00095 new_store += spr_no*m_size;
00096 }
00097
00098 y += m_card->yoffset;
00099
00100 if (m_transparent)
00101 {
00102 mga_waitfifo(m_mmioaddr, 7);
00103
00104 mga_out32(m_mmioaddr, BLTMOD_BU32RGB | BOP_COPY | SHFTZERO | OP_BITBLT
00105 | SGNZERO | LINEAR | NOCLIP | ATYPE_RSTR | TRANS, DWGCTL);
00106 mga_out32(m_mmioaddr, m_transcol, FCOL);
00107 mga_out32(m_mmioaddr, 0xFFFFFFFF, BCOL);
00108 } else
00109 {
00110 mga_waitfifo(m_mmioaddr, 5);
00111
00112 mga_out32(m_mmioaddr, BLTMOD_BU32RGB | BOP_COPY | SHFTZERO | OP_BITBLT
00113 | SGNZERO | LINEAR | NOCLIP | ATYPE_RPL, DWGCTL);
00114 }
00115
00116 mga_out32(m_mmioaddr, new_store, AR3);
00117 mga_out32(m_mmioaddr, new_store+m_size, AR0);
00118 mga_out32(m_mmioaddr, ((x + m_width-1) << 16) | x, FXBNDRY);
00119 mga_out32(m_mmioaddr, (y << 16) | m_height, YDSTLEN | EXECUTE);
00120
00121
00122 }
00123
00124 void CL_Blit_MGA::blt_clip(
00125 CL_Target *target,
00126 int x,
00127 int y,
00128 int spr_no,
00129 const CL_ClipRect &clip)
00130 {
00131 int new_store = m_store;
00132 if (spr_no)
00133 {
00134 new_store += spr_no*m_size;
00135 }
00136
00137 y += m_card->yoffset;
00138
00139 if (m_transparent)
00140 {
00141 mga_waitfifo(m_mmioaddr, 7);
00142
00143 mga_out32(m_mmioaddr, BLTMOD_BU32RGB | BOP_COPY | SHFTZERO | OP_BITBLT
00144 | SGNZERO | LINEAR | ATYPE_RSTR | TRANS, DWGCTL);
00145 mga_out32(m_mmioaddr, m_transcol, FCOL);
00146 mga_out32(m_mmioaddr, 0xFFFFFFFF, BCOL);
00147 } else
00148 {
00149 mga_waitfifo(m_mmioaddr, 5);
00150
00151 mga_out32(m_mmioaddr, BLTMOD_BU32RGB | BOP_COPY | SHFTZERO | OP_BITBLT
00152 | SGNZERO | LINEAR | ATYPE_RPL, DWGCTL);
00153 }
00154
00155 mga_out32(m_mmioaddr, new_store, AR3);
00156 mga_out32(m_mmioaddr, new_store+m_size, AR0);
00157 mga_out32(m_mmioaddr, ((x + m_width-1) << 16) | x, FXBNDRY);
00158 mga_out32(m_mmioaddr, (y << 16) | m_height, YDSTLEN | EXECUTE);
00159
00160
00161 }
00162
00163 void CL_Blit_MGA::blt_scale_noclip(
00164 CL_Target *target,
00165 int x,
00166 int y,
00167 int dest_width,
00168 int dest_height,
00169 int spr_no)
00170 {
00171 int new_store = m_store;
00172 if (spr_no)
00173 {
00174 new_store += spr_no*m_size;
00175 }
00176
00177 y += m_card->yoffset;
00178
00179
00180 if (m_transparent)
00181 {
00182 mga_waitfifo( m_mmioaddr, 9 );
00183 mga_out32( m_mmioaddr, DECALDIS, TEXCTL2 );
00184 mga_out32( m_mmioaddr, 0xFFFF0000 | (m_transcol & 0xFFFF) | (1<<30), TEXTRANS );
00185 } else
00186 {
00187 mga_waitfifo( m_mmioaddr, 8 );
00188 mga_out32( m_mmioaddr, DECALDIS | CKSTRANSDIS, TEXCTL2 );
00189 }
00190
00191 mga_out32( m_mmioaddr, BOP_COPY | SHFTZERO | SGNZERO | ARZERO | OP_TEXTURE_TRAP | ATYPE_I, DWGCTL );
00192 mga_out32( m_mmioaddr, (3<<27) | ((m_width)<<9) | LINEXT | TW16, TEXCTL );
00193 mga_out32( m_mmioaddr, (1<<20) | MAG_BILINEAR | MIN_BILINEAR, TEXFILTER );
00194 mga_out32( m_mmioaddr, ((m_width-1)<<18) | 2<<9 | 6, TEXWIDTH );
00195 mga_out32( m_mmioaddr, ((m_height-1)<<18) | 2<<9 | 6, TEXHEIGHT );
00196 mga_out32( m_mmioaddr, F1220(1/(float)(dest_width)), TMR0 );
00197 mga_out32( m_mmioaddr, 0, TMR1 );
00198
00199 mga_waitfifo( m_mmioaddr, 10 );
00200 mga_out32( m_mmioaddr, 0, TMR2 );
00201 mga_out32( m_mmioaddr, F1220((1/(float)(dest_height)) / (m_width/(float)(m_height))), TMR3 );
00202 mga_out32( m_mmioaddr, 0, TMR4 );
00203 mga_out32( m_mmioaddr, 0, TMR5 );
00204 mga_out32( m_mmioaddr, 0, TMR6 );
00205 mga_out32( m_mmioaddr, 0, TMR7 );
00206 mga_out32( m_mmioaddr, F1616(64/(float)(m_width)), TMR8 );
00207 mga_out32( m_mmioaddr, new_store*2, TEXORG );
00208 mga_out32( m_mmioaddr, ((x+dest_width-1) << 16) | x, FXBNDRY );
00209 mga_out32( m_mmioaddr, (y << 16) | dest_height, YDSTLEN | EXECUTE );
00210 }
00211
00212 void CL_Blit_MGA::blt_scale_clip(
00213 CL_Target *target,
00214 int x,
00215 int y,
00216 int dest_width,
00217 int dest_height,
00218 int spr_no,
00219 const CL_ClipRect &clip)
00220 {
00221 int new_store = m_store;
00222 if (spr_no)
00223 {
00224 new_store += spr_no*m_size;
00225 }
00226
00227 y += m_card->yoffset;
00228
00229
00230 if (m_transparent)
00231 {
00232 mga_waitfifo( m_mmioaddr, 9 );
00233 mga_out32( m_mmioaddr, DECALDIS, TEXCTL2 );
00234 mga_out32( m_mmioaddr, 0xFFFF0000 | (m_transcol & 0xFFFF) | (1<<30), TEXTRANS );
00235 } else
00236 {
00237 mga_waitfifo( m_mmioaddr, 8 );
00238 mga_out32( m_mmioaddr, DECALDIS | CKSTRANSDIS, TEXCTL2 );
00239 }
00240
00241 mga_out32( m_mmioaddr, BOP_COPY | SHFTZERO | SGNZERO | ARZERO | OP_TEXTURE_TRAP | ATYPE_I, DWGCTL );
00242 mga_out32( m_mmioaddr, (3<<27) | ((m_width)<<9) | LINEXT | TW16, TEXCTL );
00243 mga_out32( m_mmioaddr, (1<<20) | MAG_BILINEAR | MIN_BILINEAR, TEXFILTER );
00244 mga_out32( m_mmioaddr, ((m_width-1)<<18) | 2<<9 | 6, TEXWIDTH );
00245 mga_out32( m_mmioaddr, ((m_height-1)<<18) | 2<<9 | 6, TEXHEIGHT );
00246 mga_out32( m_mmioaddr, F1220(1/(float)(dest_width)), TMR0 );
00247 mga_out32( m_mmioaddr, 0, TMR1 );
00248
00249 mga_waitfifo( m_mmioaddr, 10 );
00250 mga_out32( m_mmioaddr, 0, TMR2 );
00251 mga_out32( m_mmioaddr, F1220((1/(float)(dest_height)) / (m_width/(float)(m_height))), TMR3 );
00252 mga_out32( m_mmioaddr, 0, TMR4 );
00253 mga_out32( m_mmioaddr, 0, TMR5 );
00254 mga_out32( m_mmioaddr, 0, TMR6 );
00255 mga_out32( m_mmioaddr, 0, TMR7 );
00256 mga_out32( m_mmioaddr, F1616(64/(float)(m_width)), TMR8 );
00257 mga_out32( m_mmioaddr, new_store*2, TEXORG );
00258 mga_out32( m_mmioaddr, ((x+dest_width-1) << 16) | x, FXBNDRY );
00259 mga_out32( m_mmioaddr, (y << 16) | dest_height, YDSTLEN | EXECUTE );
00260 }
00261
00262 bool CL_Blit_MGA::reload(bool lock_provider, bool create_surface)
00263 {
00264 if (lock_provider) m_provider->lock();
00265
00266 CL_PixelData input(
00267 m_card->get_target()->get_red_mask(),
00268 m_card->get_target()->get_green_mask(),
00269 m_card->get_target()->get_blue_mask(),
00270 m_card->get_target()->get_alpha_mask(),
00271 m_provider,
00272 (m_card->get_target()->get_depth()+7)/8);
00273
00274 CL_PixelData alpha( 0, 0, 0, 255, m_provider, 1 );
00275
00276
00277 while ((int)(m_card->get_offscreen_mem()+store_index*input.get_bytes_per_pixel()) %8)
00278 {
00279 store_index++;
00280 }
00281
00282 m_store = store_index + m_card->get_virt_width()*m_card->get_height()*2;
00283 m_size = m_width*m_height;
00284
00285 if ((int)(m_card->get_target()->get_pitch()*m_card->get_height()*2+(store_index+m_size)*input.get_bytes_per_pixel()) > m_card->get_total_memory())
00286 {
00287
00288 return false;
00289 }
00290
00291 CL_ColorMap color_map(m_card->get_target());
00292 unsigned char* dest = m_card->get_offscreen_mem() + store_index * input.get_bytes_per_pixel();
00293 unsigned short trans_color = color_map.calc_color(0.05f, 0.05f, 0.05f, 0);
00294
00295 m_transcol = (trans_color<<16) | trans_color;
00296
00297 for( unsigned int i=0; i<m_height*m_provider->get_num_frames(); i++)
00298 {
00299 memcpy( dest, input.get_line_pixel(i), input.get_bytes_pr_line() );
00300
00301 unsigned short* dd = (unsigned short*)dest;
00302 unsigned char* aa = alpha.get_line_pixel(i);
00303 for ( int a=0; a<alpha.get_bytes_pr_line(); a++ )
00304 {
00305 if (*dd == trans_color)
00306 {
00307 (*dd)++;
00308 }
00309 if (*aa != 255)
00310 {
00311 *dd = trans_color;
00312 m_transparent = true;
00313 }
00314 aa++;
00315 dd++;
00316 }
00317
00318 dest += input.get_bytes_pr_line();
00319 store_index += m_width;
00320 }
00321
00322 if (lock_provider) m_provider->unlock();
00323
00324
00325
00326 return true;
00327 }
00328
00329 void CL_Blit_MGA::reload_all_surfaces()
00330 {
00331 store_index = 0;
00332 for (
00333 std::list<CL_Blit_MGA*>::iterator counter = m_loaded_surfaces.begin();
00334 counter != m_loaded_surfaces.end();
00335 counter++)
00336 {
00337 (*counter)->reload(true, false);
00338 }
00339 }