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