/******************************************************* * SecondDriver * * Second driver is a Drvier abstraction layer for the * OBOS app_server. It provides access to the Graphic * HW via the low level api calls. This provides a * way to run the app_server on real HW. * This driver also makes it easy for you to run the * OBOS app_server in parallel with the Be app_server * when two or more video cards are installed in your * computer. * * @author YNOP (ynop@beunited.org) * @version beta1 (p5) * * History: * - Added Ellipse (Stroke & Fill) * Ran though test app to make sure worked * Fixed HorizLine to used fill_span instead of fill_rect :P * Updated the Cursor code to work again. * Made new cursor (Be-hand like) * - Added StrokeBezir * Added HorizLine for speed * - Added HW acceleration methods * - Brez Line added * - Created by YNOP * * Todo: * Clean up src and add more comments :P * Redo StrokeLine to use PenSize * Redo StrokeLine to use pattern * Mouse Cursor seems to be broken in proto5 ? * Add in a way to read app_server_settings file so we can get the real settings * Make display mode settings more flexable * Look into FreeType for DrawString :P fun fun fun * * Todo methods: * Blit() DrawBitmap() DrawString() FillArc() FillBezier() FillPolygon() * FillRegion() FillRoundRect() FillShape() FillTriangle() * StrokeArc() StrokeRoundRect() StrokeShpae() * *******************************************************/ #include #include #include #include "PortLink.h" #include "ServerProtocol.h" #include "ServerBitmap.h" #include "ServerCursor.h" #include "DebugTools.h" #include "SecondDriver.h" #include "SecondDriverHelper.h" /******************************************************* * @description *******************************************************/ SecondDriver::SecondDriver(void):DisplayDriver(){ SetupBezier(); hide_cursor = false; fd = -1; image = -1; gah = NULL; bits = NULL; bpr = -1; scs = NULL; mc = NULL; sc = NULL; et = NULL; re = NULL; s2sb = NULL; fr = NULL; ir = NULL; s2stb = NULL; fs = NULL; } /******************************************************* * @description *******************************************************/ SecondDriver::~SecondDriver(void){ if(is_initialized){ } } /******************************************************* * @description *******************************************************/ void SecondDriver::Initialize(void){ et = NULL; bits = NULL; // Find a driver fd = get_device(); if(fd < 0){ printf("No Device settings found.\n"); fd = find_device(); }else{ printf("Device read from settings file\n"); } if(fd < 0){ printf("No device find, trying fallback stub\n"); fd = fallback_device(); } if(fd < 0){ printf("Didn't find device :(\n"); is_initialized = false; } /* load the accelerant */ image = load_accelerant(fd, &gah); if (image >= 0){ // Set up the display to a valid resolution if(get_and_set_mode(gah,&dm) == B_OK){ // Here we are all good if(dm.space == B_CMAP8){ set_palette(gah); } get_frame_buffer(gah, &fbc); bits = (uint32*)fbc.frame_buffer/*_dma*/; bpr = fbc.bytes_per_row/4; // sould be by depth if(dm.flags & B_HARDWARE_CURSOR){ // Lets check out tha hardwar cursoer stuff :P printf("Mode supports Hardware cursors\n"); scs = (set_cursor_shape)gah(B_SET_CURSOR_SHAPE,NULL); mc = (move_cursor)gah(B_MOVE_CURSOR,NULL); sc = (show_cursor)gah(B_SHOW_CURSOR,NULL); } // Ok. now lets see if we can add some spiffy // 2D acceleration to this :) accelerant_engine_count aec = (accelerant_engine_count)gah(B_ACCELERANT_ENGINE_COUNT,NULL); uint32 count = aec(); if(count > 0){ acquire_engine ae = (acquire_engine)gah(B_ACQUIRE_ENGINE,NULL); re = (release_engine)gah(B_RELEASE_ENGINE,NULL); if(ae(B_2D_ACCELERATION,1000,&st,&et) == B_OK){ // Now lets see if we have some functions printf("You should be verry happy. You have 2D hardware Acceleration\n"); s2sb = (screen_to_screen_blit)gah(B_SCREEN_TO_SCREEN_BLIT,NULL); fr = (fill_rectangle)gah(B_FILL_RECTANGLE,NULL); ir = (invert_rectangle)gah(B_INVERT_RECTANGLE,NULL); s2stb = (screen_to_screen_transparent_blit)gah(B_SCREEN_TO_SCREEN_TRANSPARENT_BLIT,NULL); fs = (fill_span)gah(B_FILL_SPAN,NULL); } } is_initialized = true; }else{ // failed to set mode is_initialized = false; } }else{ // image failed to load is_initialized = false; } if(is_initialized){ printf("\n\tSecond Driver by YNOP (ynop@beunited.org)\n"); printf("\tSecond Driver is copyrigth YNOP 2002\n"); printf("\tHave fun, its all set up :)\n\n"); } SetCursor((ServerCursor*)NULL); ShowCursor(); int32 h = GetHeight(); int32 w = GetWidth(); MoveCursorTo(w/2,h/2); } /******************************************************* * @description *******************************************************/ void SecondDriver::Shutdown(void){ printf("\tShuting down SecondDriver\n"); if(et){ if(re(et,&st) != B_OK){ printf("Failed to release engine\n"); } } uninit_accelerant ua = (uninit_accelerant)gah(B_UNINIT_ACCELERANT,NULL); if(ua){ ua();} unload_add_on(image); // clsoe the file now... close(fd); is_initialized=false; } /******************************************************* * @description *******************************************************/ bool SecondDriver::IsInitialized(void){ return is_initialized; } /******************************************************* * @description *******************************************************/ void SecondDriver::SafeMode(void){ } /******************************************************* * @description *******************************************************/ void SecondDriver::Reset(void){ } /******************************************************* * @description *******************************************************/ void SecondDriver::SetScreen(uint32 space){ // Clear(51,102,152); } /******************************************************* * @description *******************************************************/ void SecondDriver::Clear(uint8 red, uint8 green, uint8 blue){ rgb_color r; r.red = red; r.blue = blue; r.green = green; Clear(r); } /******************************************************* * @description *******************************************************/ void SecondDriver::Clear(rgb_color col){ highcol = col; FillRect(BRect(0,0,GetHeight()-1,GetWidth()-1),NULL); } /******************************************************* * @description *******************************************************/ int32 SecondDriver::GetHeight(void){ // Gets the height of the current mode return dm.virtual_height; } /******************************************************* * @description *******************************************************/ int32 SecondDriver::GetWidth(void){ // Gets the width of the current mode return dm.virtual_width; } /******************************************************* * @description *******************************************************/ int SecondDriver::GetDepth(void){ // Gets the color depth of the current mode return 0; } /******************************************************* * @description *******************************************************/ #ifdef PROTO_4 void SecondDriver::Blit(BPoint loc, ServerBitmap *src, ServerBitmap *dest) #else void SecondDriver::Blit(BRect src, BRect dest) #endif { printf("Calling Blit (not wirten yet)\n"); if(s2sb){ printf("Accelerated Blit\n"); }else{ } } /******************************************************* * @description *******************************************************/ void SecondDriver::DrawBitmap(ServerBitmap *bitmap, BRect source, BRect dest){ printf("Calling DrawBitmap (not writen yet)\n"); } /******************************************************* * @description *******************************************************/ void SecondDriver::DrawChar(char c, BPoint point){ char string[2]; string[0]=c; string[1]='\0'; DrawString(string,2,point); } /******************************************************* * @description *******************************************************/ void SecondDriver::DrawString(char *string, int length, BPoint point){ printf("DrawString is not writen yet\n"); // i would say that libtruetype would do some good herer } /******************************************************* * @description *******************************************************/ void SecondDriver::FillArc(int centerx, int centery, int xradius, int yradius, float angle, float span, uint8 *pattern){ printf("FillArc is not writen yet\n"); StrokeArc(centerx,centery,xradius,yradius,angle,span,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillBezier(BPoint *points, uint8 *pattern){ printf("FillBezier is not writen yet\n"); StrokeBezier(points,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillEllipse(float centerx, float centery, float x_radius, float y_radius,uint8 *pattern){ MidpointEllipse(centerx,centery,x_radius,y_radius,true,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillPolygon(int *x, int *y, int numpoints, bool is_closed){ printf("FillPolygon is not writen yet\n"); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillRect(BRect rect, uint8 *pattern){ if(fr){ // usieng accelertated 2d file union{ uint8 bytes[4]; uint32 word; }c1; //printf("Accelerated Fill\n"); fill_rect_params frp; frp.left =(uint16) rect.left; frp.top =(uint16) rect.top; frp.right =(uint16) rect.right; frp.bottom =(uint16) rect.bottom; c1.bytes[0] = highcol.blue; c1.bytes[1] = highcol.green; c1.bytes[2] = highcol.red; fr(et,c1.word,&frp,1); }else{ for(int32 i = 0;i < rect.Height()-1;i++){ MovePenTo(BPoint(rect.left,rect.top+i)); StrokeLine(BPoint(rect.right,rect.top+i),pattern); //HorizLine(rect.left,rect.right,rect.top+i); // uses accel :P } } } /******************************************************* * @description *******************************************************/ void SecondDriver::FillRect(BRect rect, rgb_color col){ rgb_color tmpc = highcol; highcol = col; FillRect(rect, NULL); highcol = tmpc; } /******************************************************* * @description *******************************************************/ void SecondDriver::FillRegion(BRegion *region){ printf("RillRegion is not writen yet\n"); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillRoundRect(BRect rect,float xradius, float yradius, uint8 *pattern){ printf("FillRoundRect is not writen yet\n"); StrokeRoundRect(rect,xradius,yradius,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillShape(BShape *shape){ printf("FillShape is not writen yet\n"); StrokeShape(shape); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillTriangle(BPoint first, BPoint second, BPoint third, BRect rect, uint8 *pattern){ printf("FillTriangle is not writen yet\n"); StrokeTriangle(first,second,third,rect,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::FillTriangle(BPoint first, BPoint second, BPoint third, BRect rect, rgb_color color){ printf("FillTriangle is not writen yet\n"); StrokeTriangle(first,second,third,rect,color); } /******************************************************* * @description *******************************************************/ void SecondDriver::HideCursor(void){ if(sc){ sc(false); cursor_visible = false; }else{ printf("Shoftware Hide Cursor\n"); } } /******************************************************* * @description *******************************************************/ bool SecondDriver::IsCursorHidden(void){ return cursor_visible; } /******************************************************* * @description *******************************************************/ void SecondDriver::ObscureCursor(void){ // Hides cursor until mouse is moved HideCursor(); show_on_move = true; } /******************************************************* * @description *******************************************************/ void SecondDriver::MoveCursorTo(float x, float y){ if(show_on_move){ ShowCursor(); } if(mc){ mc((short unsigned int)x,(short unsigned int)y); }else{ printf("Software move Cursor\n"); } } /******************************************************* * @description *******************************************************/ void SecondDriver::MovePenTo(BPoint pt){ penpos = pt; } /******************************************************* * @description *******************************************************/ BPoint SecondDriver::PenPosition(void){ return penpos; } /******************************************************* * @description *******************************************************/ float SecondDriver::PenSize(void){ return pensize; } /******************************************************* * @description *******************************************************/ void SecondDriver::SetCursor(int32 value){ printf("Setcursoer value?\n"); // Uh what is this all about? } //0 - 1 = black //0 - 0 = what //1 - 0 = trans //1 - 1 = invert // Pointy cursor /*uint8 andMask[] = { 63,255,15,255,131,255,128,127,192,31,192,31,224,63,224,63, 224,31,240,15,243,7,255,131,255,193,255,224,255,240,255,248 }; uint8 xorMask[] = { 192,0,176,0,76,0,67,128,32,96,32,32,16,64,16,64, 16,32,11,16,12,136,0,68,0,34,0,17,0,9,0,7 };*/ // BeOS like cursor uint8 andMask[] = { 255,255,255,255,199,255,195,255,195,255,224,31,224,3,240,1, 240,0,192,0,128,0,128,0,192,0,240,0,252,1,254,7 }; uint8 xorMask[] = { 0,0,0,0,56,0,36,0,36,0,19,224,18,92,9,42, 8,1,60,0,76,0,66,0,48,0,12,0,2,0,1,0 }; /******************************************************* * @description *******************************************************/ void SecondDriver::SetCursor(ServerCursor *cursor){ printf("Setting cursor\n"); current_cursor = cursor; // uint8 *andMask; // uint8 *xorMask; if(scs){ // scs(cursor->width,cursor->height,(short unsigned int)cursor->hotspot.x,(short unsigned int)cursor->hotspot.y,andMask,xorMask); scs(16,16,3,3,andMask,xorMask); }else{ printf("Setting software cursor\n"); } } /******************************************************* * @description *******************************************************/ void SecondDriver::SetPenSize(float size){ pensize = size; } /******************************************************* * @description *******************************************************/ void SecondDriver::SetPixel(int x, int y, uint8 *pattern){ union{ uint8 bytes[4]; uint32 word; }c1; c1.bytes[0] = highcol.blue; c1.bytes[1] = highcol.green; c1.bytes[2] = highcol.red; c1.bytes[3] = highcol.alpha; *(bits + x + y*bpr) = c1.word; } /******************************************************* * @description *******************************************************/ void SecondDriver::ShowCursor(void){ printf("\tShow Cursor\n"); show_on_move = false; cursor_visible = true; if(sc){ sc(true); }else{ printf("Software show cursor\n"); } } /******************************************************* * @description *******************************************************/ void SecondDriver::StrokeArc(int centerx, int centery, int xradius, int yradius, float angle, float span, uint8 *pattern){ printf("StrokeArch is not writen yet\n"); } /******************************************************* * @description *******************************************************/ void SecondDriver::StrokeBezier(BPoint *pts, uint8 *pattern){ BPoint segment[SEGMENTS + 1]; computeSegments(pts[0], pts[1],pts[2],pts[3], segment); MovePenTo(segment[0]); for(int32 s = 1 ; s <= SEGMENTS ; ++s ){ if(segment[s].x != segment[s - 1].x || segment[s].y != segment[s - 1].y ) { StrokeLine(segment[s],pattern); } } } /******************************************************* * @description *******************************************************/ void SecondDriver::StrokeEllipse(float centerx, float centery, float x_radius, float y_radius,uint8 *pattern){ MidpointEllipse(centerx,centery,x_radius,y_radius,false,pattern); } /******************************************************* * @description *******************************************************/ void SecondDriver::StrokeLine(BPoint point, uint8 *pattern){ if(penpos.y == point.y){ HorizLine(penpos.x,point.x,point.y,pattern); return; } int oct = 0; int xoff = (int32)penpos.x; int yoff = (int32)penpos.y; int32 x2 = (int32)point.x-xoff; int32 y2 = (int32)point.y-yoff; int32 x1 = 0; int32 y1 = 0; // if(y2==0){ if (x1>x2){int t=x1;x1=x2;x2=t;}HorizLine(x1+xoff,x2+xoff,y1+yoff); return;} if(y2<0){ y2 = -y2; oct+=4; }//bit2=1 if(x2<0){ x2 = -x2; oct+=2;}//bit1=1 if(x2 x2){ int32 t=x1;x1=x2;x2=t; } if(fr){ union{ uint8 bytes[4]; uint32 word; }c1; //printf("Accelerated HorizLine\n"); uint16 list[3]; list[0] = y; list[1] = x1; list[2] = x2; c1.bytes[0] = highcol.blue; c1.bytes[1] = highcol.green; c1.bytes[2] = highcol.red; fs(et,c1.word,list,1); }else{ //software hline printf("\t!!HorizLine without HWaccel is a waist\n"); for(int32 i = x1; i <= x2;i++){ SetPixel(i,y,pattern); } } } //void EllipsePoints(float cx,float cy,int32 x, int32 y){ // view->StrokeLine(BPoint(x+cent.x,y+cent.y),BPoint(x+cent.x,y+cent.y)); // view->StrokeLine(BPoint(-x+cent.x,y+cent.y),BPoint(-x+cent.x,y+cent.y)); // view->StrokeLine(BPoint(x+cent.x,-y+cent.y),BPoint(x+cent.x,-y+cent.y)); // view->StrokeLine(BPoint(-x+cent.x,-y+cent.y),BPoint(-x+cent.x,-y+cent.y)); #define EllipsePoints(cx,cy,x,y,pattern){ \ SetPixel( x+cx, y+cx,pattern); \ SetPixel(-x+cx, y+cx,pattern); \ SetPixel( x+cx,-y+cx,pattern); \ SetPixel(-x+cx,-y+cx,pattern); \ } //void EllipsePointsFill(BPoint cent,int32 x, int32 y,pattern){ // view->StrokeLine(BPoint(-x+cent.x,y+cent.y),BPoint(x+cent.x,y+cent.y)); // view->StrokeLine(BPoint(-x+cent.x,-y+cent.y),BPoint(x+cent.x,-y+cent.y)); #define EllipsePointsFill(cx,cy,x,y,pattern){ \ HorizLine(-x+cx,x+cx, y+cy, pattern); \ HorizLine(-x+cx,x+cx, -y+cy, pattern); \ } /******************************************************* * *******************************************************/ void SecondDriver::MidpointEllipse(float centx,float centy,int32 xrad, int32 yrad,bool fill,uint8 *pattern){ if(xrad < 0){ xrad = -xrad; } if(yrad < 0){ yrad = -yrad; } double d2; int32 x = 0; int32 y = yrad; int32 xradSqr = xrad*xrad; int32 yradSqr = yrad*yrad; double dl = yradSqr - (xradSqr*yrad) + (0.25 *xradSqr); if(fill){ EllipsePointsFill(centx,centy,x,y,pattern); }else{ EllipsePoints(centx,centy,x,y,pattern); } // Test gradient if still in region 1 while((xradSqr*(y-.5)) > (yradSqr*(x+1))){ if(dl < 0){ // Select E dl += yradSqr*(2*x + 3); }else{ // Select SE dl += yradSqr*(2*x + 3) + xradSqr*(-2*y + 2); y--; } x++; if(fill){ EllipsePointsFill(centx,centy,x,y,pattern); }else{ EllipsePoints(centx,centy,x,y,pattern); } } d2 = (yradSqr*(x + .5)*(x + .5)) + (xradSqr*(y-1)*(y-1)) - xradSqr*yradSqr; while(y > 0){ if(d2 < 0){ // Select SE d2 += yradSqr*(2*x + 2) + xradSqr*(-2*y + 3); x++; }else{ // Select E d2 += xradSqr*(-2*y + 3); } y--; if(fill){ EllipsePointsFill(centx,centy,x,y,pattern); }else{ EllipsePoints(centx,centy,x,y,pattern); } } } #ifdef DEBUG_DRIVER_MODULE #undef DEBUG_DRIVER_MODULE #endif