SDL 1.2.13
[crawl:crawl-sdl.git] / src / video / fbcon / SDL_fbriva.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2006 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@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 }