Home | History | Annotate | Download | only in fbcon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #include "SDL_video.h"
     25 #include "../SDL_blit.h"
     26 #include "SDL_fbriva.h"
     27 #include "riva_mmio.h"
     28 #include "riva_regs.h"
     29 
     30 
     31 static int FifoEmptyCount = 0;
     32 static int FifoFreeCount = 0;
     33 
     34 /* Wait for vertical retrace */
     35 static void WaitVBL(_THIS)
     36 {
     37 	volatile Uint8 *port = (Uint8 *)(mapped_io + PCIO_OFFSET + 0x3DA);
     38 
     39 	while (  (*port & 0x08) )
     40 		;
     41 	while ( !(*port & 0x08) )
     42 		;
     43 }
     44 static void NV3WaitIdle(_THIS)
     45 {
     46 	RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET);
     47 	while ( (Rop->FifoFree < FifoEmptyCount) ||
     48 	        (*(mapped_io + PGRAPH_OFFSET + 0x000006B0) & 0x01) )
     49 		;
     50 }
     51 static void NV4WaitIdle(_THIS)
     52 {
     53 	RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET);
     54 	while ( (Rop->FifoFree < FifoEmptyCount) ||
     55 	        (*(mapped_io + PGRAPH_OFFSET + 0x00000700) & 0x01) )
     56 		;
     57 }
     58 
     59 #if 0 /* Not yet implemented? */
     60 /* Sets video mem colorkey and accelerated blit function */
     61 static int SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key)
     62 {
     63 	return(0);
     64 }
     65 
     66 /* Sets per surface hardware alpha value */
     67 static int SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 value)
     68 {
     69 	return(0);
     70 }
     71 #endif /* Not yet implemented */
     72 
     73 static int FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color)
     74 {
     75 	int dstX, dstY;
     76 	int dstW, dstH;
     77 	RivaBitmap *Bitmap = (RivaBitmap *)(mapped_io + BITMAP_OFFSET);
     78 
     79 	/* Don't blit to the display surface when switched away */
     80 	if ( switched_away ) {
     81 		return -2; /* no hardware access */
     82 	}
     83 	if ( dst == this->screen ) {
     84 		SDL_mutexP(hw_lock);
     85 	}
     86 
     87 	/* Set up the X/Y base coordinates */
     88 	dstW = rect->w;
     89 	dstH = rect->h;
     90 	FB_dst_to_xy(this, dst, &dstX, &dstY);
     91 
     92 	/* Adjust for the current rectangle */
     93 	dstX += rect->x;
     94 	dstY += rect->y;
     95 
     96 	RIVA_FIFO_FREE(Bitmap, 1);
     97 	Bitmap->Color1A = color;
     98 
     99 	RIVA_FIFO_FREE(Bitmap, 2);
    100 	Bitmap->UnclippedRectangle[0].TopLeft     = (dstX << 16) | dstY;
    101 	Bitmap->UnclippedRectangle[0].WidthHeight = (dstW << 16) | dstH;
    102 
    103 	FB_AddBusySurface(dst);
    104 
    105 	if ( dst == this->screen ) {
    106 		SDL_mutexV(hw_lock);
    107 	}
    108 	return(0);
    109 }
    110 
    111 static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
    112                        SDL_Surface *dst, SDL_Rect *dstrect)
    113 {
    114 	SDL_VideoDevice *this = current_video;
    115 	int srcX, srcY;
    116 	int dstX, dstY;
    117 	int dstW, dstH;
    118 	RivaScreenBlt *Blt = (RivaScreenBlt *)(mapped_io + BLT_OFFSET);
    119 
    120 	/* FIXME: For now, only blit to display surface */
    121 	if ( dst->pitch != SDL_VideoSurface->pitch ) {
    122 		return(src->map->sw_blit(src, srcrect, dst, dstrect));
    123 	}
    124 
    125 	/* Don't blit to the display surface when switched away */
    126 	if ( switched_away ) {
    127 		return -2; /* no hardware access */
    128 	}
    129 	if ( dst == this->screen ) {
    130 		SDL_mutexP(hw_lock);
    131 	}
    132 
    133 	/* Calculate source and destination base coordinates (in pixels) */
    134 	dstW = dstrect->w;
    135 	dstH = dstrect->h;
    136 	FB_dst_to_xy(this, src, &srcX, &srcY);
    137 	FB_dst_to_xy(this, dst, &dstX, &dstY);
    138 
    139 	/* Adjust for the current blit rectangles */
    140 	srcX += srcrect->x;
    141 	srcY += srcrect->y;
    142 	dstX += dstrect->x;
    143 	dstY += dstrect->y;
    144 
    145 	RIVA_FIFO_FREE(Blt, 3);
    146 	Blt->TopLeftSrc  = (srcY << 16) | srcX;
    147 	Blt->TopLeftDst  = (dstY << 16) | dstX;
    148 	Blt->WidthHeight = (dstH  << 16) | dstW;
    149 
    150 	FB_AddBusySurface(src);
    151 	FB_AddBusySurface(dst);
    152 
    153 	if ( dst == this->screen ) {
    154 		SDL_mutexV(hw_lock);
    155 	}
    156 	return(0);
    157 }
    158 
    159 static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
    160 {
    161 	int accelerated;
    162 
    163 	/* Set initial acceleration on */
    164 	src->flags |= SDL_HWACCEL;
    165 
    166 	/* Set the surface attributes */
    167 	if ( (src->flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
    168 		if ( ! this->info.blit_hw_A ) {
    169 			src->flags &= ~SDL_HWACCEL;
    170 		}
    171 	}
    172 	if ( (src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {
    173 		if ( ! this->info.blit_hw_CC ) {
    174 			src->flags &= ~SDL_HWACCEL;
    175 		}
    176 	}
    177 
    178 	/* Check to see if final surface blit is accelerated */
    179 	accelerated = !!(src->flags & SDL_HWACCEL);
    180 	if ( accelerated ) {
    181 		src->map->hw_blit = HWAccelBlit;
    182 	}
    183 	return(accelerated);
    184 }
    185 
    186 void FB_RivaAccel(_THIS, __u32 card)
    187 {
    188 	RivaRop *Rop = (RivaRop *)(mapped_io + ROP_OFFSET);
    189 
    190 	/* We have hardware accelerated surface functions */
    191 	this->CheckHWBlit = CheckHWBlit;
    192 	wait_vbl = WaitVBL;
    193 	switch (card) {
    194 	    case FB_ACCEL_NV3:
    195 		wait_idle = NV3WaitIdle;
    196 		break;
    197 	    case FB_ACCEL_NV4:
    198 		wait_idle = NV4WaitIdle;
    199 		break;
    200 	    default:
    201 		/* Hmm... FIXME */
    202 		break;
    203 	}
    204 	FifoEmptyCount = Rop->FifoFree;
    205 
    206 	/* The Riva has an accelerated color fill */
    207 	this->info.blit_fill = 1;
    208 	this->FillHWRect = FillHWRect;
    209 
    210 	/* The Riva has accelerated normal and colorkey blits. */
    211 	this->info.blit_hw = 1;
    212 #if 0 /* Not yet implemented? */
    213 	this->info.blit_hw_CC = 1;
    214 	this->SetHWColorKey = SetHWColorKey;
    215 #endif
    216 
    217 #if 0 /* Not yet implemented? */
    218 	/* The Riva has an accelerated alpha blit */
    219 	this->info.blit_hw_A = 1;
    220 	this->SetHWAlpha = SetHWAlpha;
    221 #endif
    222 }
    223