1 /* nm Acceleration functions */ 2 /* Authors: 3 Mark Watson 2/2000, 4 Rudolf Cornelissen 10/2002-8/2003. 5 */ 6 7 #define MODULE_BIT 0x00080000 8 9 #include "nm_std.h" 10 11 /*acceleration notes*/ 12 13 /*functions Be's app_server uses: 14 fill span (horizontal only) 15 fill rectangle (these 2 are very similar) 16 invert rectangle 17 blit 18 */ 19 20 /* G100 pre SRCORG/DSTORG registers */ 21 static uint32 src_dst; 22 /* MIL1/2 adress linearisation does not always work */ 23 static uint8 y_lin; 24 static uint8 depth; 25 26 /* needed by MIL 1/2 because of adress linearisation constraints */ 27 #define ACCW_YDSTLEN(dst, len) do { \ 28 if (y_lin) { \ 29 ACCW(YDST,((dst)* (si->fbc.bytes_per_row / (depth >> 3))) >> 5); \ 30 ACCW(LEN,len); \ 31 } else ACCW(YDSTLEN,((dst)<<16)|(len)); \ 32 } while (0) 33 34 status_t nm_acc_wait_idle() 35 { 36 // volatile int i; 37 // while (ACCR(STATUS)&(1<<16)) 38 // { 39 // for (i=0;i<10000;i++); /*spin in place so I do not hammer the bus*/ 40 // }; 41 return B_OK; 42 } 43 44 /* AFAIK this must be done for every new screenmode. 45 * Engine required init. */ 46 status_t nm_acc_init() 47 { 48 /* used for convenience: MACCESS is a write only register! */ 49 uint32 maccess = 0x00000000; 50 51 /* preset using hardware adress linearisation */ 52 y_lin = 0x00; 53 /* reset depth */ 54 depth = 0; 55 56 /* cleanup bitblt */ 57 ACCW(OPMODE,0); 58 59 /* Set the Z origin to the start of FB (otherwise lockup on blits) */ 60 ACCW(ZORG,0); 61 62 /* Set pixel width */ 63 switch(si->dm.space) 64 { 65 case B_CMAP8: 66 ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x00)); 67 depth = 8; 68 break; 69 case B_RGB15_LITTLE:case B_RGB16_LITTLE: 70 ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x01)); 71 depth = 16; 72 break; 73 case B_RGB32_LITTLE:case B_RGBA32_LITTLE: 74 ACCW(MACCESS, ((maccess & 0xfffffffc) | 0x02)); 75 depth = 32; 76 break; 77 default: 78 LOG(8,("ACC: init, invalid bit depth\n")); 79 return B_ERROR; 80 } 81 82 /* setup PITCH: very cardtype specific! */ 83 switch (si->ps.card_type) 84 { 85 case G100: 86 /* always using hardware adress linearisation, because 2D/3D 87 * engine works on every pitch multiple of 32 */ 88 ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x0FFF)); 89 break; 90 default: 91 /* G200 and up are equal.. */ 92 /* always using hardware adress linearisation, because 2D/3D 93 * engine works on every pitch multiple of 32 */ 94 ACCW(PITCH, ((si->fbc.bytes_per_row / (depth >> 3)) & 0x1FFF)); 95 break; 96 } 97 98 /* disable plane write mask (needed for SDRAM): actual change needed to get it sent to RAM */ 99 ACCW(PLNWT,0x00000000); 100 ACCW(PLNWT,0xffffffff); 101 102 if (si->ps.card_type >= G200) { 103 /*DSTORG - location of active screen in framebuffer*/ 104 ACCW(DSTORG,((uint8*)si->fbc.frame_buffer) - ((uint8*)si->framebuffer)); 105 106 /*SRCORG - init source address - same as dest*/ 107 ACCW(SRCORG,((uint8*)si->fbc.frame_buffer) - ((uint8*)si->framebuffer)); 108 } 109 110 /* init YDSTORG - apsed, if not inited, BitBlts may fails on <= G200 */ 111 src_dst = 0; 112 ACCW(YDSTORG, src_dst); 113 114 /* <= G100 uses this register as SRCORG/DSTORG replacement, but 115 * MIL 1/2 does not need framebuffer space for the hardcursor! */ 116 if ((si->ps.card_type == G100) && (si->settings.hardcursor)) 117 { 118 switch (si->dm.space) 119 { 120 case B_CMAP8: 121 src_dst = 1024 / 1; 122 break; 123 case B_RGB15_LITTLE: 124 case B_RGB16_LITTLE: 125 src_dst = 1024 / 2; 126 break; 127 case B_RGB32_LITTLE: 128 src_dst = 1024 / 4; 129 break; 130 default: 131 LOG(8,("ACC: G100 hardcursor not supported for current colorspace\n")); 132 return B_ERROR; 133 } 134 } 135 ACCW(YDSTORG,src_dst); 136 137 /* clipping */ 138 /* i.e. highest and lowest X pixel adresses */ 139 ACCW(CXBNDRY,(((si->fbc.bytes_per_row / (depth >> 3)) - 1) << 16) | (0)); 140 141 /* Y pixel addresses must be linear */ 142 /* lowest adress */ 143 ACCW(YTOP, 0 + src_dst); 144 /* highest adress */ 145 ACCW(YBOT,((si->dm.virtual_height - 1) * 146 (si->fbc.bytes_per_row / (depth >> 3))) + src_dst); 147 148 return B_OK; 149 } 150 151 /* screen to screen blit - i.e. move windows around. 152 * Engine function bitblit, paragraph 4.5.7.2 */ 153 status_t nm_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h) 154 { 155 uint32 t_start,t_end,offset; 156 uint32 b_start,b_end; 157 158 /*find where the top,bottom and offset are*/ 159 offset = (si->fbc.bytes_per_row / (depth >> 3)); 160 161 t_end = t_start = xs + (offset*ys) + src_dst; 162 t_end += w; 163 164 b_end = b_start = xs + (offset*(ys+h)) + src_dst; 165 b_end +=w; 166 167 /* sgnzero bit _must_ be '0' before accessing SGN! */ 168 ACCW(DWGCTL,0x00000000); 169 170 /*find which quadrant */ 171 switch((yd>ys)|((xd>xs)<<1)) 172 { 173 case 0: /*L->R,down*/ 174 ACCW(SGN,0); 175 176 ACCW(AR3,t_start); 177 ACCW(AR0,t_end); 178 ACCW(AR5,offset); 179 180 ACCW_YDSTLEN(yd,h+1); 181 break; 182 case 1: /*L->R,up*/ 183 ACCW(SGN,4); 184 185 ACCW(AR3,b_start); 186 ACCW(AR0,b_end); 187 ACCW(AR5,-offset); 188 189 ACCW_YDSTLEN(yd+h,h+1); 190 break; 191 case 2: /*R->L,down*/ 192 ACCW(SGN,1); 193 194 ACCW(AR3,t_end); 195 ACCW(AR0,t_start); 196 ACCW(AR5,offset); 197 198 ACCW_YDSTLEN(yd,h+1); 199 break; 200 case 3: /*R->L,up*/ 201 ACCW(SGN,5); 202 203 ACCW(AR3,b_end); 204 ACCW(AR0,b_start); 205 ACCW(AR5,-offset); 206 207 ACCW_YDSTLEN(yd+h,h+1); 208 break; 209 } 210 ACCW(FXBNDRY,((xd+w)<<16)|xd); 211 212 /*do the blit*/ 213 ACCGO(DWGCTL,0x040C4018); // atype RSTR 214 215 return B_OK; 216 } 217 218 /* screen to screen tranparent blit - not sure what uses this. 219 * Engine function bitblit, paragraph 4.5.7.2 */ 220 status_t nm_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h,uint32 colour) 221 { 222 uint32 t_start,t_end,offset; 223 uint32 b_start,b_end; 224 225 return B_ERROR; 226 227 /*find where the top,bottom and offset are*/ 228 offset = (si->fbc.bytes_per_row / (depth >> 3)); 229 230 t_end = t_start = xs + (offset*ys) + src_dst; 231 t_end += w; 232 233 b_end = b_start = xs + (offset*(ys+h)) + src_dst; 234 b_end +=w; 235 236 /* sgnzero bit _must_ be '0' before accessing SGN! */ 237 ACCW(DWGCTL,0x00000000); 238 239 /*find which quadrant */ 240 switch((yd>ys)|((xd>xs)<<1)) 241 { 242 case 0: /*L->R,down*/ 243 ACCW(SGN,0); 244 245 ACCW(AR3,t_start); 246 ACCW(AR0,t_end); 247 ACCW(AR5,offset); 248 249 ACCW_YDSTLEN(yd,h+1); 250 break; 251 case 1: /*L->R,up*/ 252 ACCW(SGN,4); 253 254 ACCW(AR3,b_start); 255 ACCW(AR0,b_end); 256 ACCW(AR5,-offset); 257 258 ACCW_YDSTLEN(yd+h,h+1); 259 break; 260 case 2: /*R->L,down*/ 261 ACCW(SGN,1); 262 263 ACCW(AR3,t_end); 264 ACCW(AR0,t_start); 265 ACCW(AR5,offset); 266 267 ACCW_YDSTLEN(yd,h+1); 268 break; 269 case 3: /*R->L,up*/ 270 ACCW(SGN,5); 271 272 ACCW(AR3,b_end); 273 ACCW(AR0,b_start); 274 ACCW(AR5,-offset); 275 276 ACCW_YDSTLEN(yd+h,h+1); 277 break; 278 } 279 ACCW(FXBNDRY,((xd+w)<<16)|xd); 280 281 /*do the blit*/ 282 ACCW(FCOL,colour); 283 ACCW(BCOL,0xffffffff); 284 ACCGO(DWGCTL,0x440C4018); // atype RSTR 285 return B_OK; 286 } 287 288 /* rectangle fill. 289 * Engine function rectangle_fill: paragraph 4.5.5.2 */ 290 /*colorIndex,fill_rect_params,count*/ 291 status_t nm_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col) 292 { 293 /* 294 FXBNDRY - left and right coordinates a 295 YDSTLEN - y start and no of lines a 296 (or YDST and LEN) 297 DWGCTL - atype must be RSTR or BLK a 298 FCOL - foreground colour a 299 */ 300 301 ACCW(FXBNDRY,(xe<<16)|xs); /*set x start and end*/ 302 ACCW_YDSTLEN(ys,yl); /*set y start and length*/ 303 ACCW(FCOL,col); /*set colour*/ 304 305 //acc fixme: checkout blockmode constraints for G100+ (mil: nc?): also add blockmode 306 // for other functions, and use fastblt on MIL1/2 if possible... 307 //or is CMAP8 contraint a non-blockmode contraint? (linearisation problem maybe?) 308 if (si->dm.space==B_CMAP8) 309 { 310 ACCGO(DWGCTL,0x400C7814); // atype RSTR 311 } 312 else 313 { 314 ACCGO(DWGCTL,0x400C7844); // atype BLK 315 } 316 return B_OK; 317 } 318 319 /* rectangle invert. 320 * Engine function rectangle_fill: paragraph 4.5.5.2 */ 321 /*colorIndex,fill_rect_params,count*/ 322 status_t nm_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl,uint32 col) 323 { 324 /* 325 FXBNDRY - left and right coordinates a 326 YDSTLEN - y start and no of lines a 327 (or YDST and LEN) 328 DWGCTL - atype must be RSTR or BLK a 329 FCOL - foreground colour a 330 */ 331 332 ACCW(FXBNDRY,(xe<<16)|xs); /*set x start and end*/ 333 ACCW_YDSTLEN(ys,yl); /*set y start and length*/ 334 ACCW(FCOL,col); /*set colour*/ 335 336 /*draw it! top nibble is c is clipping enabled*/ 337 ACCGO(DWGCTL,0x40057814); // atype RSTR 338 339 return B_OK; 340 } 341 342 /* screen to screen scaled filtered blit - i.e. scale video in memory. 343 * Engine function texture mapping for video, paragraphs 4.5.5.5 - 4.5.5.9 */ 344 status_t nm_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs, 345 uint16 xd,uint16 yd,uint16 wd,uint16 hd) 346 { 347 //fixme: implement. 348 349 return B_OK; 350 } 351