📄 fbvideo.c
字号:
if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) { GAL_SetError("Couldn't get console screen info"); return(NULL); }#ifdef FBCON_DEBUG fprintf(stderr, "Printing original vinfo:\n"); print_vinfo(&vinfo);#endif#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (!mgIsServer) { vinfo.xres = width; vinfo.yres = height; } if ( mgIsServer && ((vinfo.xres != width) || (vinfo.yres != height) || (vinfo.bits_per_pixel != bpp) /* || (flags & GAL_DOUBLEBUF) */) ) {#else if ( ((vinfo.xres != width) || (vinfo.yres != height) || (vinfo.bits_per_pixel != bpp) /* || (flags & GAL_DOUBLEBUF) */) ) {#endif vinfo.activate = FB_ACTIVATE_NOW; vinfo.accel_flags = 0; vinfo.bits_per_pixel = bpp; vinfo.xres = width; vinfo.xres_virtual = width; vinfo.yres = height;#if 0 if ( flags & GAL_DOUBLEBUF ) { vinfo.yres_virtual = height*2; } else { vinfo.yres_virtual = height; }#else vinfo.yres_virtual = height;#endif vinfo.xoffset = 0; vinfo.yoffset = 0; vinfo.red.length = vinfo.red.offset = 0; vinfo.green.length = vinfo.green.offset = 0; vinfo.blue.length = vinfo.blue.offset = 0; vinfo.transp.length = vinfo.transp.offset = 0; if ( ! choose_fbmodes_mode(&vinfo) && vinfo.xres >= 320 ) { choose_vesa_mode(&vinfo); }#ifdef FBCON_DEBUG fprintf(stderr, "Printing wanted vinfo:\n"); print_vinfo(&vinfo);#endif if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { vinfo.yres_virtual = height; if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { GAL_SetError("Couldn't set console screen info"); return(NULL); } } } else { int maxheight; /* Figure out how much video memory is available */#if 0 if ( flags & GAL_DOUBLEBUF ) { maxheight = height*2; } else { maxheight = height; }#else maxheight = height;#endif if ( vinfo.yres_virtual > maxheight ) { vinfo.yres_virtual = maxheight; } } cache_vinfo = vinfo;#ifdef FBCON_DEBUG fprintf (stderr, "Printing actual vinfo:\n"); print_vinfo(&vinfo);#endif Rmask = 0; for ( i=0; i<vinfo.red.length; ++i ) { Rmask <<= 1; Rmask |= (0x00000001<<vinfo.red.offset); } Gmask = 0; for ( i=0; i<vinfo.green.length; ++i ) { Gmask <<= 1; Gmask |= (0x00000001<<vinfo.green.offset); } Bmask = 0; for ( i=0; i<vinfo.blue.length; ++i ) { Bmask <<= 1; Bmask |= (0x00000001<<vinfo.blue.offset); } if (!GAL_ReallocFormat(current, vinfo.bits_per_pixel, Rmask, Gmask, Bmask, 0) ) { return(NULL); } /* Get the fixed information about the console hardware. This is necessary since finfo.line_length changes. */ if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { GAL_SetError("Couldn't get console hardware info"); return(NULL); } /* Save hardware palette, if needed */ FB_SavePalette(this, &finfo, &vinfo); /* Set up the new mode framebuffer */ current->flags = (GAL_FULLSCREEN|GAL_HWSURFACE); current->w = vinfo.xres; current->h = vinfo.yres; current->pitch = finfo.line_length; current->pixels = mapped_mem+mapped_offset; /* Set up the information for hardware surfaces */ surfaces_mem = (char *)current->pixels + vinfo.yres_virtual*current->pitch; surfaces_len = (mapped_memlen-(surfaces_mem-mapped_mem));#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer)#endif { FB_FreeHWSurfaces(this); FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len); }#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) else { current->hwdata = NULL; }#endif /* Let the application know we have a hardware palette */ switch (finfo.visual) { case FB_VISUAL_PSEUDOCOLOR: current->flags |= GAL_HWPALETTE; break; default: break; }#if 0 /* Update for double-buffering, if we can */ if ( flags & GAL_DOUBLEBUF ) { if ( vinfo.yres_virtual == (height*2) ) { current->flags |= GAL_DOUBLEBUF; flip_page = 0; flip_address[0] = (char *)current->pixels; flip_address[1] = (char *)current->pixels+ current->h*current->pitch; this->screen = current; FB_FlipHWSurface(this, current); this->screen = NULL; } } /* Set the update rectangle function */ this->UpdateRects = FB_DirectUpdate;#endif /* We're done */ return(current);}#ifdef FBCON_DEBUGstatic void FB_DumpHWSurfaces(_THIS){ vidmem_bucket *bucket; fprintf(stderr, "Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal); fprintf(stderr, "\n"); fprintf(stderr, " Base Size\n"); for ( bucket=&surfaces; bucket; bucket=bucket->next ) { fprintf(stderr, "Bucket: %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free"); if ( bucket->prev ) { if ( bucket->base != bucket->prev->base+bucket->prev->size ) { fprintf(stderr, "Warning, corrupt bucket list! (prev)\n"); } } else { if ( bucket != &surfaces ) { fprintf(stderr, "Warning, corrupt bucket list! (!prev)\n"); } } if ( bucket->next ) { if ( bucket->next->base != bucket->base+bucket->size ) { fprintf(stderr, "Warning, corrupt bucket list! (next)\n"); } } } fprintf(stderr, "\n");}#endifstatic int FB_InitHWSurfaces(_THIS, GAL_Surface *screen, char *base, int size){ vidmem_bucket *bucket; surfaces_memtotal = size; surfaces_memleft = size; if ( surfaces_memleft > 0 ) { bucket = (vidmem_bucket *)malloc(sizeof(*bucket)); if ( bucket == NULL ) { GAL_OutOfMemory(); return(-1); } bucket->prev = &surfaces; bucket->used = 0; bucket->dirty = 0; bucket->base = base; bucket->size = size; bucket->next = NULL; } else { bucket = NULL; } surfaces.prev = NULL; surfaces.used = 1; surfaces.dirty = 0; surfaces.base = screen->pixels; surfaces.size = (unsigned int)((long)base - (long)surfaces.base); surfaces.next = bucket; screen->hwdata = (struct private_hwdata *)&surfaces; return(0);}static void FB_FreeHWSurfaces(_THIS){ vidmem_bucket *bucket, *freeable; bucket = surfaces.next; while ( bucket ) { freeable = bucket; bucket = bucket->next; free(freeable); } surfaces.next = NULL;}static void FB_RequestHWSurface (_THIS, const REQ_HWSURFACE* request, REP_HWSURFACE* reply){ if (request->bucket == NULL) { /* alloc hw surface */ vidmem_bucket *bucket; int size; int extra; reply->bucket = NULL; /* Temporarily, we only allow surfaces the same width as display. Some blitters require the pitch between two hardware surfaces to be the same. Others have interesting alignment restrictions. Until someone who knows these details looks at the code... */ if (request->pitch > GAL_VideoSurface->pitch) { GAL_SetError("Surface requested wider than screen"); return; } reply->pitch = GAL_VideoSurface->pitch; size = request->h * reply->pitch;#ifdef FBCON_DEBUG fprintf(stderr, "Allocating bucket of %d bytes\n", size);#endif /* Quick check for available mem */ if ( size > surfaces_memleft ) { GAL_SetError("Not enough video memory"); return; } /* Search for an empty bucket big enough */ for ( bucket=&surfaces; bucket; bucket=bucket->next ) { if ( ! bucket->used && (size <= bucket->size) ) { break; } } if ( bucket == NULL ) { GAL_SetError("Video memory too fragmented"); return; } /* Create a new bucket for left-over memory */ extra = (bucket->size - size); if ( extra ) { vidmem_bucket *newbucket;#ifdef FBCON_DEBUG fprintf(stderr, "Adding new free bucket of %d bytes\n", extra);#endif newbucket = (vidmem_bucket *)malloc(sizeof(*newbucket)); if ( newbucket == NULL ) { GAL_OutOfMemory(); return; } newbucket->prev = bucket; newbucket->used = 0; newbucket->base = bucket->base + size; newbucket->size = extra; newbucket->next = bucket->next; if ( bucket->next ) { bucket->next->prev = newbucket; } bucket->next = newbucket; } /* Set the current bucket values and return it! */ bucket->used = 1; bucket->size = size; bucket->dirty = 0;#ifdef FBCON_DEBUG fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base);#endif surfaces_memleft -= size; reply->bucket = bucket; reply->offset = bucket->base - mapped_mem; } else { /* free hw surface */ vidmem_bucket *bucket, *freeable; /* Look for the bucket in the current list */ for ( bucket=&surfaces; bucket; bucket=bucket->next ) { if ( bucket == (vidmem_bucket *)request->bucket) { break; } } if ( bucket && bucket->used ) { /* Add the memory back to the total */#ifdef FBCON_DEBUG fprintf(stderr, "Freeing bucket of %d bytes\n", bucket->size);#endif surfaces_memleft += bucket->size; /* Can we merge the space with surrounding buckets? */ bucket->used = 0; if ( bucket->next && ! bucket->next->used ) {#ifdef FBCON_DEBUG fprintf(stderr, "Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size);#endif freeable = bucket->next; bucket->size += bucket->next->size; bucket->next = bucket->next->next; if ( bucket->next ) { bucket->next->prev = bucket; } free(freeable); } if ( bucket->prev && ! bucket->prev->used ) {#ifdef FBCON_DEBUG fprintf(stderr, "Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size);#endif freeable = bucket; bucket->prev->size += bucket->size; bucket->prev->next = bucket->next; if ( bucket->next ) { bucket->next->prev = bucket->prev; } free(freeable); } } }}static int FB_AllocHWSurface (_THIS, GAL_Surface *surface){ REQ_HWSURFACE request = {surface->w, surface->h, surface->pitch, 0, NULL}; REP_HWSURFACE reply = {0, 0, NULL};#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer) FB_RequestHWSurface (this, &request, &reply); else { REQUEST req; req.id = REQID_HWSURFACE; req.data = &request; req.len_data = sizeof (REQ_HWSURFACE); cli_request (&req, &reply, sizeof (REP_HWSURFACE)); }#else FB_RequestHWSurface (this, &request, &reply);#endif if (reply.bucket == NULL) return -1; surface->flags |= GAL_HWSURFACE; surface->pitch = reply.pitch; surface->pixels = mapped_mem + reply.offset; surface->hwdata = (struct private_hwdata *)reply.bucket; return 0;}static void FB_FreeHWSurface(_THIS, GAL_Surface *surface){ REQ_HWSURFACE request = {surface->w, surface->h, surface->pitch, 0, surface->hwdata}; REP_HWSURFACE reply = {0, 0}; request.offset = (char*)surface->pixels - (char*)mapped_mem;#if defined(_LITE_VERSION) && !defined(_STAND_ALONE) if (mgIsServer) FB_RequestHWSurface (this, &request, &reply); else { REQUEST req; if (surface->hwdata == NULL) { surface->pixels = NULL; return; } request.bucket = surface->hwdata; req.id = REQID_HWSURFACE; req.data = &request; req.len_data = sizeof (REQ_HWSURFACE); cli_request (&req, &reply, sizeof (REP_HWSURFACE)); }#else FB_RequestHWSurface (this, &request, &reply);#endif surface->pixels = NULL; surface->hwdata = NULL;}#if 0static int FB_LockHWSurface(_THIS, GAL_Surface *surface){ if ( surface == this->screen ) { GAL_mutexP(hw_lock); if ( FB_IsSurfaceBusy(surface) ) { FB_WaitBusySurfaces(this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -