Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

display_fbdev.cpp

Go to the documentation of this file.
00001 
00002 /*
00003         $Id: display_fbdev.cpp,v 1.3 2001/03/13 21:43:00 sphair Exp $
00004 
00005         ------------------------------------------------------------------------
00006         ClanLib, the platform independent game SDK.
00007 
00008         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00009         version 2. See COPYING for details.
00010 
00011         For a total list of contributers see CREDITS.
00012 
00013         ------------------------------------------------------------------------
00014 
00015         TODO:
00016                 -Only mmap mmio if there is a Matrox
00017 */
00018 
00019 #include "Core/precomp.h"
00020 #include <Display/Display/FBDev/blit_mga.h>
00021 #include <Display/Display/Generic/blitters.h>
00022 #include <Display/Display/Generic/colormap.h>
00023 #include <Display/Display/Generic/displaycard_generic.h>
00024 #include <API/Core/System/error.h>
00025 #include <Display/Display/FBDev/display_fbdev.h>
00026 #include <API/Display/Display/palette.h>
00027 #include <API/Display/Display/surfaceprovider.h>
00028 #include <Display/Display/FBDev/target_fbdev.h>
00029 #include <API/Display/Display/vidmode.h>
00030 #include <API/Display/Display/mousecursor.h>
00031 #include "Core/System/Unix/appconf.h"
00032 
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <iostream>
00037 
00038 #include <linux/fb.h>
00039 #include <unistd.h>
00040 #include <fcntl.h>
00041 #include <sys/ioctl.h>
00042 #include <sys/mman.h>
00043 //#include <asm/io.h>
00044 
00045 #include <math.h>
00046 
00047 
00048 #include "regs.h"
00049 #include "mmio.h"
00050 
00051 CL_FBDev_DisplayCard::CL_FBDev_DisplayCard(int card_no) : CL_DisplayCard_Generic(card_no)
00052 {
00053         FileConfig config("clanlib");
00054         fb_try_accel = config.readEntry("fb_try_accel", "yes");
00055 
00056         m_initialized = false;
00057         m_mmioaddr = NULL;
00058 
00059         m_palette = new CL_Palette();
00060 
00061         m_target = NULL;
00062         fb_mem = NULL;
00063         
00064         fd = open("/dev/fb0", O_RDWR);
00065         if (fd<0)
00066         {
00067                 throw CL_Error("FB dev: Couldn't open /dev/fb0, you must have read-write access!");
00068         }
00069 }
00070 
00071 CL_FBDev_DisplayCard::~CL_FBDev_DisplayCard()
00072 {
00073         CL_MouseCursor::hide();
00074         if (m_initialized)
00075         {
00076                 // clear out the framebuffer
00077                 memset((void*)fb_mem,0,fb_fix.smem_len);
00078 
00079                 delete m_target;
00080                 ioctl(fd,FBIOPUT_VSCREENINFO,&fb_var_orig);
00081         }
00082         
00083         close(fd);
00084 
00085         delete m_palette;
00086 }
00087 
00088 CL_Blitters CL_FBDev_DisplayCard::create_hw_blitters(CL_SurfaceProvider *provider)
00089 {
00090         CL_Blitters ret;
00091         
00092         if (m_mmioaddr)
00093         {
00094                 CL_Blit_MGA *blitter = new CL_Blit_MGA(this, provider, m_mmioaddr);
00095                 if (! blitter->init_surface(&ret) )
00096                 {
00097                         delete blitter;
00098                 }
00099         }
00100 
00101         return ret;
00102 }
00103                                                                         
00104 void CL_FBDev_DisplayCard::flip_display(bool sync)
00105 {
00106         cl_assert(m_initialized); // card not initialized!
00107 
00108         signal_preflip();
00109 
00110         m_target->put_image();
00111 
00112         if (doublebuffer)
00113         {
00114                 fb_var.yoffset = yoffset;
00115                 yoffset = (yoffset == get_height()) ? 0 : get_height();
00116 
00117                 if (m_mmioaddr)
00118                 {
00119                         mga_waitidle(m_mmioaddr);
00120                 }
00121 
00122                 ioctl( fd, FBIOPAN_DISPLAY, &fb_var);
00123 
00124                 set_card_clip();
00125         }
00126 
00127         signal_postflip();
00128 }
00129 
00130 void CL_FBDev_DisplayCard::put_display(const class CL_Rect &rect)
00131 {
00132         cl_assert(m_initialized);
00133 
00134         signal_preflip();
00135 
00136         // not implemented for this target yet. Someone with fbdev knowledge, please do so. :)
00137         // -- mbn 21. nov 2000
00138         cl_assert(false);
00139 
00140         signal_postflip();
00141 }
00142 
00143 void CL_FBDev_DisplayCard::set_palette(CL_Palette *pal)
00144 {
00145         m_palette = new CL_Palette(pal->palette);
00146 }
00147 
00148 CL_Palette *CL_FBDev_DisplayCard::get_palette()
00149 {
00150         return m_palette;
00151 }
00152 
00153 void CL_FBDev_DisplayCard::set_videomode(
00154         int width,
00155         int height,
00156         int bpp,
00157         bool fullscreen,
00158         bool allow_resize,
00159         bool video_memory)
00160 {
00161         if (m_initialized) // clean up
00162         {
00163                 delete m_target; m_target = NULL;
00164         }
00165         
00166         set_gfxmode(width, height, bpp, fullscreen, allow_resize);
00167 
00168         // fetch initial settings
00169         ioctl( fd, FBIOGET_VSCREENINFO, &fb_var_orig );
00170         ioctl( fd, FBIOGET_FSCREENINFO, &fb_fix );
00171         fb_var = fb_var_orig;
00172 
00173 
00174         // try to set resolution
00175         fb_var.activate = FB_ACTIVATE_NOW;
00176         fb_var.accel_flags = 0;
00177         fb_var.xres = get_width();
00178         fb_var.yres = get_height();
00179         fb_var.xres_virtual = get_width();
00180         fb_var.yres_virtual = get_height()*2;
00181         fb_var.bits_per_pixel = bpp;
00182         if (-1 == ioctl(fd,FBIOPUT_VSCREENINFO,&fb_var))
00183         {
00184                 doublebuffer = false;
00185                 fb_var.yres_virtual = get_height();
00186                 if (-1 == ioctl(fd,FBIOPUT_VSCREENINFO,&fb_var))
00187                 {
00188                         // Damn: Could not set proper video mode.
00189                         fb_var = fb_var_orig;
00190                         
00191                         // Test if we can use the current one (is it big enough?)
00192                         if ((int)fb_var.xres < get_width() || (int)fb_var.yres < get_height() || (int)fb_var.bits_per_pixel != bpp)
00193                         {
00194                                 char s[80];     // Don't diss me, tell me why it's so hard to fill a STL string; wanted to use streams like with CL_String!
00195                                 printf( s, "FBDev: Couldn't set proper video mode, need %dx%dx%d!", get_width(), get_height(), bpp );
00196                                 throw CL_Error( s );
00197                         }
00198                 }
00199         } else
00200         {
00201                 doublebuffer = true;
00202                 std::cout << "Using doublebuffer mode (panning)." << std::endl;
00203                 yoffset = get_height();
00204         }
00205 
00206         /* move viewport to upper left corner */
00207         fb_var.xoffset = 0;
00208         fb_var.yoffset = 0;
00209         ioctl(fd,FBIOPAN_DISPLAY,&fb_var);
00210         
00211         // map framebuffer and get the address
00212         if ( MAP_FAILED == (fb_mem = (unsigned char *) mmap(    NULL, 
00213                                                 fb_fix.smem_len, 
00214                                                 PROT_READ | PROT_WRITE, 
00215                                                 MAP_SHARED,
00216                                                 fd, 0 )) )
00217         {
00218                 throw CL_Error("FB dev: Couldn't mmap framebuffer");
00219         }
00220         
00221 
00222         if ( fb_try_accel == "yes"  &&  fb_var.accel_flags == 0 )
00223         {
00224                 m_mmioaddr = (unsigned char *) mmap(NULL, fb_fix.mmio_len,
00225                                                 PROT_READ | PROT_WRITE, MAP_SHARED,
00226                                                 fd, fb_fix.smem_len);
00227 
00228                 if (m_mmioaddr == MAP_FAILED  ||  m_mmioaddr == NULL)
00229                 {
00230                         std::cout << "No acceleration available." << std::endl;
00231                         m_mmioaddr = NULL;
00232                 }
00233                 else
00234                 {
00235                         std::cout << "Yeah, using acceleration!" << std::endl;
00236                         switch( fb_fix.accel )
00237                         {
00238 #ifdef FB_ACCEL_MATROX_MGAG400
00239                                 case FB_ACCEL_MATROX_MGAG400:
00240 #endif
00241                                 case FB_ACCEL_MATROX_MGAG200:
00242                                         m_accel_alpha_rect = true;
00243                                         m_accel_scale_blit = true;
00244                                         std::cout << "Using accelerated alpha rectangles." << std::endl;
00245                                         std::cout << "Using accelerated scaled blits." << std::endl;
00246                                         break;
00247                                 default:
00248                                         m_accel_alpha_rect = false;
00249                                         m_accel_scale_blit = false;
00250                                         break;
00251                         }
00252                 }
00253         } else
00254         {
00255                 std::cout << "Not trying to use acceleration." << std::endl;
00256         }
00257 
00258         // clear out the framebuffer
00259         memset((void*)fb_mem,0,fb_fix.smem_len);
00260 
00261         m_target = new CL_Target_FBDev( doublebuffer, (char*)fb_mem, get_width(), get_height(), &fb_var, m_mmioaddr );
00262 
00263         m_initialized = true;
00264 }
00265 
00266 unsigned int CL_FBDev_DisplayCard::get_virt_width()
00267 {
00268         return fb_var.xres_virtual;
00269 }
00270 
00271 unsigned char* CL_FBDev_DisplayCard::get_offscreen_mem()
00272 {
00273         if (!m_mmioaddr)
00274         {
00275                 return NULL;
00276         }
00277 
00278         return fb_mem + m_target->get_pitch()*get_height()*2;
00279 }
00280 
00281 bool CL_FBDev_DisplayCard::is_initialized()
00282 {
00283         return m_initialized;
00284 }
00285 
00286 const std::list<CL_VidMode*> &CL_FBDev_DisplayCard::get_videomodes()
00287 {
00288         cl_assert(false); // not implemented yet!
00289         static std::list<CL_VidMode*> ret;
00290         return ret;
00291 }
00292 
00293 void CL_FBDev_DisplayCard::draw_rect(
00294         int x1,
00295         int y1,
00296         int x2,
00297         int y2,
00298         float r,
00299         float g,
00300         float b,
00301         float a)
00302 {
00303         throw CL_Error("draw_rect not implemented in fbdev, please tell us to do that");
00304 }
00305 
00306 void CL_FBDev_DisplayCard::fill_rect(
00307         int x1,
00308         int y1,
00309         int x2,
00310         int y2,
00311         float r,
00312         float g,
00313         float b,
00314         float a)
00315 {
00316         if (a <= 0.01) return;
00317         if (!m_mmioaddr)
00318         {
00319                 CL_DisplayCard_Generic::fill_rect(x1, y1, x2, y2, r, g, b, a);
00320                 return;
00321         }
00322         if (a <= 0.99 && !m_accel_alpha_rect)
00323         {
00324                 CL_DisplayCard_Generic::fill_rect(x1, y1, x2, y2, r, g, b, a);
00325                 return;
00326         }
00327         
00328         // Translate coords into position:
00329         int trans_x = get_translate_offset_x();
00330         int trans_y = get_translate_offset_y();
00331         x1 += trans_x;
00332         y1 += trans_y;
00333         x2 += trans_x;
00334         y2 += trans_y;
00335 
00336         int y = y1 + yoffset;
00337         int h = y2 - y1;
00338 
00339         if (a <= 0.99)
00340         {
00341                 /* This one is for alpha rectangles */
00342 
00343                 mga_waitfifo( m_mmioaddr, 3 );
00344                 mga_out32( m_mmioaddr, SRC_ALPHA | DST_ONE_MINUS_SRC_ALPHA | ALPHACHANNEL, ALPHACTRL );
00345                 mga_out32( m_mmioaddr, 0, ALPHAXINC );
00346                 mga_out32( m_mmioaddr, 0, ALPHAYINC );
00347 
00348                 mga_waitfifo( m_mmioaddr, 3 );          // red start and increments
00349                 mga_out32( m_mmioaddr, FNORM_TO_F0915(r), DR4 );
00350                 mga_out32( m_mmioaddr, 0, DR6 );
00351                 mga_out32( m_mmioaddr, 0, DR7 );
00352 
00353                 mga_waitfifo( m_mmioaddr, 3 );          // green start and increments
00354                 mga_out32( m_mmioaddr, FNORM_TO_F0915(g), DR8 );
00355                 mga_out32( m_mmioaddr, 0, DR10 );
00356                 mga_out32( m_mmioaddr, 0, DR11 );
00357 
00358                 mga_waitfifo( m_mmioaddr, 3 );          // blue start and increments
00359                 mga_out32( m_mmioaddr, FNORM_TO_F0915(b), DR12 );
00360                 mga_out32( m_mmioaddr, 0, DR14 );
00361                 mga_out32( m_mmioaddr, 0, DR15 );
00362 
00363                 mga_waitfifo( m_mmioaddr, 5 );
00364                 mga_out32( m_mmioaddr, BLTMOD_BFCOL | BOP_COPY | SHFTZERO | SGNZERO | ARZERO | OP_TRAP | ATYPE_I, DWGCTL );
00365                 mga_out32( m_mmioaddr, FNORM_TO_F0915(a), ALPHASTART );
00366                 mga_out32( m_mmioaddr, (x2 << 16) | x1, FXBNDRY );
00367                 mga_out32( m_mmioaddr, (y << 16) | h, YDSTLEN | EXECUTE );
00368 
00369                 mga_out32( m_mmioaddr, 1, ALPHACTRL );  // turn off alpha blending
00370         } else
00371         {
00372                 /* This one is for solid rectangles */
00373 
00374                 CL_ColorMap cmap(get_target());
00375                 unsigned int fill_color = cmap.calc_color(r, g, b, a);
00376 
00377                 switch( fb_var.bits_per_pixel )
00378                 {
00379                         case 8:
00380                                 fill_color &= 0xFF;
00381                                 fill_color |= (fill_color<<8) | (fill_color<<16) | (fill_color<<24);
00382                         break;
00383                         case 16:
00384                                 fill_color &= 0xFFFF;
00385                                 fill_color |= (fill_color<<16);
00386                         break;
00387                 }
00388 
00389                 mga_waitfifo( m_mmioaddr, 4 );
00390                 mga_out32( m_mmioaddr, fill_color, FCOL );
00391                 mga_out32( m_mmioaddr, (x2 << 16) | x1, FXBNDRY );
00392                 mga_out32( m_mmioaddr, (y << 16) | h, YDSTLEN );
00393                 mga_out32( m_mmioaddr, BOP_COPY | SHFTZERO | SGNZERO | ARZERO | SOLID | OP_TRAP | ATYPE_BLK, DWGCTL | EXECUTE );
00394         }
00395 }
00396 
00397 void CL_FBDev_DisplayCard::set_card_clip()
00398 {
00399         if (!m_mmioaddr)
00400                 return;
00401 
00402         int topy = m_cur_clip.m_y1 + yoffset;
00403         int boty = (m_cur_clip.m_y2-1) + yoffset;
00404 
00405         mga_waitfifo(m_mmioaddr, 3);
00406         mga_out32(m_mmioaddr, (m_cur_clip.m_x1 & 0x07FF) | (((m_cur_clip.m_x2-1) & 0x07FF) << 16), CXBNDRY);
00407         mga_out32(m_mmioaddr, (fb_var.xres_virtual * topy) & 0x00FFFFFF, YTOP);
00408         mga_out32(m_mmioaddr, (fb_var.xres_virtual * boty) & 0x00FFFFFF, YBOT);
00409 }

Generated at Wed Apr 4 19:54:00 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001