e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 | } |