1 /* nm Acceleration functions */ 2 3 /* Author: 4 Rudolf Cornelissen 3/2004. 5 */ 6 7 #define MODULE_BIT 0x00080000 8 9 #include "nm_std.h" 10 11 //static status_t nm_acc_wait_fifo(uint32 n); 12 13 /*acceleration notes*/ 14 15 /*functions Be's app_server uses: 16 fill span (horizontal only) 17 fill rectangle (these 2 are very similar) 18 invert rectangle 19 blit 20 */ 21 22 //fixme: acc setup for NM2097 and NM2160 only for now... 23 status_t nm_acc_wait_idle() 24 { 25 /* wait until engine completely idle */ 26 /* Note: 27 * because we have no FIFO functionality we have to make sure we return ASAP(!). 28 * snoozing() for just 1 microSecond already more than halfs the engine 29 * performance... */ 30 while (ACCR(STATUS) & 0x00000001); 31 32 return B_OK; 33 } 34 35 /* wait for enough room in fifo */ 36 //static status_t nm_acc_wait_fifo(uint32 n) 37 //{ 38 // while (((ACCR(STATUS) & 0x0000ff00) >> 8) < n) 39 // { 40 /* snooze a bit so I do not hammer the bus */ 41 // snooze (10); 42 // } 43 //} 44 45 /* AFAIK this must be done for every new screenmode. 46 * Engine required init. */ 47 status_t nm_acc_init() 48 { 49 /* Set pixel width */ 50 switch(si->dm.space) 51 { 52 case B_CMAP8: 53 /* b8-9 determine engine colordepth */ 54 si->engine.control = (1 << 8); 55 si->engine.depth = 1; 56 break; 57 case B_RGB15_LITTLE:case B_RGB16_LITTLE: 58 /* b8-9 determine engine colordepth */ 59 si->engine.control = (2 << 8); 60 si->engine.depth = 2; 61 break; 62 case B_RGB24_LITTLE: 63 /* no acceleration supported on NM2097 and NM2160 */ 64 default: 65 LOG(8,("ACC: init, invalid bit depth\n")); 66 return B_ERROR; 67 } 68 69 /* setup memory pitch (b10-12): 70 * this works with a table, there are very few fixed settings.. */ 71 switch(si->fbc.bytes_per_row / si->engine.depth) 72 { 73 case 640: 74 si->engine.control |= (2 << 10); 75 break; 76 case 800: 77 si->engine.control |= (3 << 10); 78 break; 79 case 1024: 80 si->engine.control |= (4 << 10); 81 break; 82 case 1152: 83 si->engine.control |= (5 << 10); 84 break; 85 case 1280: 86 si->engine.control |= (6 << 10); 87 break; 88 case 1600: 89 si->engine.control |= (7 << 10); 90 break; 91 default: 92 LOG(8,("ACC: init, invalid mode width\n")); 93 return B_ERROR; 94 } 95 96 /* enable engine FIFO */ 97 /* fixme when/if possible: 98 * does not work on most cards.. (tried NM2160) 99 * workaround: always wait until engine completely idle before programming. */ 100 // si->engine.control |= (1 << 27); 101 102 /* setup buffer startadress */ 103 /* fixme when/if possible: 104 * not possible on all cards or not enough specs known. (tried NM2160) 105 * workaround: place cursor bitmap at _end_ of cardRAM instead of in _beginning_. */ 106 107 /* setup clipping */ 108 /* note: 109 * on NM2160 the max acc engine width of 1600 pixels can be programmed, but 110 * the max. height is only 1023 pixels (height register holds just 10 bits)! 111 * note also: 112 * while the vertical clipping feature can do upto and including 1023 pixels, 113 * the engine itself can do upto and including 1024 pixels vertically. 114 * So: 115 * Don't use the engine's clipping feature as we want to get the max out of the 116 * engine. We won't export the acc hooks for modes beyond the acc engine's 117 * capabilities. */ 118 // si->engine.control |= (1 << 26); 119 // ACCW(CLIPLT, 0); 120 // ACCW(CLIPRB, ((si->dm.virtual_height << 16) | (si->dm.virtual_width & 0x0000ffff))); 121 122 return B_OK; 123 } 124 125 /* screen to screen blit - i.e. move windows around and scroll within them. */ 126 status_t nm_acc_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h) 127 { 128 /* make sure the previous command (if any) is completed */ 129 // does not work yet: 130 // nm_acc_wait_fifo(4); 131 // so: 132 nm_acc_wait_idle(); 133 134 if ((yd < ys) || ((yd == ys) && (xd < xs))) 135 { 136 /* start with upper left corner */ 137 /* use ROP GXcopy (b16-19), and use XY coord. system (b24-25) */ 138 ACCW(CONTROL, si->engine.control | 0x830c0000); 139 /* send command and exexute */ 140 ACCW(SRCSTARTOFF, ((ys << 16) | (xs & 0x0000ffff))); 141 ACCW(DSTSTARTOFF, ((yd << 16) | (xd & 0x0000ffff))); 142 ACCW(XYEXT, (((h + 1) << 16) | ((w + 1) & 0x0000ffff))); 143 } 144 else 145 { 146 /* start with lower right corner */ 147 /* use ROP GXcopy (b16-19), and use XY coord. system (b24-25) */ 148 ACCW(CONTROL, (si->engine.control | 0x830c0013)); 149 /* send command and exexute */ 150 ACCW(SRCSTARTOFF, (((ys + h) << 16) | ((xs + w) & 0x0000ffff))); 151 ACCW(DSTSTARTOFF, (((yd + h) << 16) | ((xd + w) & 0x0000ffff))); 152 ACCW(XYEXT, (((h + 1) << 16) | ((w + 1) & 0x0000ffff))); 153 } 154 155 return B_OK; 156 } 157 158 /* rectangle fill - i.e. workspace and window background color */ 159 /* span fill - i.e. (selected) menuitem background color (Dano) */ 160 status_t nm_acc_setup_rectangle(uint32 color) 161 { 162 // does not work yet: 163 // nm_acc_wait_fifo(2); 164 // so: 165 nm_acc_wait_idle(); 166 167 /* use ROP GXcopy (b16-19), use XY coord. system (b24-25), do foreground color (b3) */ 168 ACCW(CONTROL, (si->engine.control | 0x830c0008)); 169 /* setup color */ 170 ACCW(FGCOLOR, color); 171 172 return B_OK; 173 } 174 175 status_t nm_acc_rectangle(uint32 xs,uint32 xe,uint32 ys,uint32 yl) 176 { 177 /* The engine does not take kindly if we try to let it fill a rect with 178 * zero width. Dano's app_server occasionally tries to let us do that though! 179 * Testable with BeRoMeter 1.2.6, all Ellipses tests. Effect of zero width fill: 180 * horizontal lines across the entire screen at top and bottom of ellipses. */ 181 if (xe == xs) return B_OK; 182 183 /* make sure the previous command (if any) is completed */ 184 // does not work yet: 185 // nm_acc_wait_fifo(2); 186 // so: 187 nm_acc_wait_idle(); 188 189 /* send command and exexute */ 190 ACCW(DSTSTARTOFF, ((ys << 16) | (xs & 0x0000ffff))); 191 ACCW(XYEXT, ((yl << 16) | ((xe - xs) & 0x0000ffff))); 192 193 return B_OK; 194 } 195 196 /* rectangle invert - i.e. text cursor and text selection */ 197 status_t nm_acc_setup_rect_invert() 198 { 199 /* make sure the previous command (if any) is completed */ 200 // does not work yet: 201 // nm_acc_wait_fifo(4); 202 // so: 203 nm_acc_wait_idle(); 204 205 /* use ROP GXinvert (b16-19), use XY coord. system (b24-25), do foreground color (b3) */ 206 ACCW(CONTROL, (si->engine.control | 0x83050008)); 207 /* reset color */ 208 ACCW(FGCOLOR, 0); 209 210 return B_OK; 211 } 212 213 status_t nm_acc_rectangle_invert(uint32 xs,uint32 xe,uint32 ys,uint32 yl) 214 { 215 /* The engine probably also does not take kindly if we try to let it invert a 216 * rect with zero width... (see nm_acc_rectangle() routine for explanation.) */ 217 if (xe == xs) return B_OK; 218 219 /* make sure the previous command (if any) is completed */ 220 // does not work yet: 221 // nm_acc_wait_fifo(4); 222 // so: 223 nm_acc_wait_idle(); 224 225 /* send command and exexute */ 226 ACCW(DSTSTARTOFF, ((ys << 16) | (xs & 0x0000ffff))); 227 ACCW(XYEXT, ((yl << 16) | ((xe - xs) & 0x0000ffff))); 228 229 return B_OK; 230 } 231 232 /* screen to screen tranparent blit */ 233 status_t nm_acc_transparent_blit(uint16 xs,uint16 ys,uint16 xd,uint16 yd,uint16 w,uint16 h,uint32 colour) 234 { 235 //fixme: implement. 236 237 return B_ERROR; 238 } 239 240 /* screen to screen scaled filtered blit - i.e. scale video in memory */ 241 status_t nm_acc_video_blit(uint16 xs,uint16 ys,uint16 ws, uint16 hs, 242 uint16 xd,uint16 yd,uint16 wd,uint16 hd) 243 { 244 //fixme: implement. 245 246 return B_OK; 247 } 248