comparison src/video/fbcon/SDL_fbvideo.c @ 106:63ec24e0575f

Merged DGA video surface handling improvements, unified locking code. Fixed matrox blit bug where src Y less than dst Y Fixed hardware surface init when no resolution change
author Sam Lantinga <slouken@lokigames.com>
date Fri, 13 Jul 2001 10:19:51 +0000
parents e85e03f195b4
children 5d4bafca35cd
comparison
equal deleted inserted replaced
105:2136ea8953f9 106:63ec24e0575f
131 #endif 131 #endif
132 static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); 132 static int FB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
133 static void FB_VideoQuit(_THIS); 133 static void FB_VideoQuit(_THIS);
134 134
135 /* Hardware surface functions */ 135 /* Hardware surface functions */
136 static int FB_InitHWSurfaces(_THIS, char *base, int size); 136 static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size);
137 static void FB_FreeHWSurfaces(_THIS); 137 static void FB_FreeHWSurfaces(_THIS);
138 static int FB_AllocHWSurface(_THIS, SDL_Surface *surface); 138 static int FB_AllocHWSurface(_THIS, SDL_Surface *surface);
139 static int FB_LockHWSurface(_THIS, SDL_Surface *surface); 139 static int FB_LockHWSurface(_THIS, SDL_Surface *surface);
140 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface); 140 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface);
141 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface); 141 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface);
142 static void FB_WaitVBL(_THIS); 142 static void FB_WaitVBL(_THIS);
143 static void FB_WaitIdle(_THIS);
143 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface); 144 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface);
144 145
145 /* Internal palette functions */ 146 /* Internal palette functions */
146 static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo, 147 static void FB_SavePalette(_THIS, struct fb_fix_screeninfo *finfo,
147 struct fb_var_screeninfo *vinfo); 148 struct fb_var_screeninfo *vinfo);
189 } 190 }
190 return(0); 191 return(0);
191 } 192 }
192 memset(this->hidden, 0, (sizeof *this->hidden)); 193 memset(this->hidden, 0, (sizeof *this->hidden));
193 wait_vbl = FB_WaitVBL; 194 wait_vbl = FB_WaitVBL;
195 wait_idle = FB_WaitIdle;
194 mouse_fd = -1; 196 mouse_fd = -1;
195 keyboard_fd = -1; 197 keyboard_fd = -1;
196 198
197 /* Set the function pointers */ 199 /* Set the function pointers */
198 this->VideoInit = FB_VideoInit; 200 this->VideoInit = FB_VideoInit;
663 print_vinfo(&vinfo); 665 print_vinfo(&vinfo);
664 #endif 666 #endif
665 if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { 667 if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
666 return(NULL); 668 return(NULL);
667 } 669 }
668 current->format->palette->ncolors = 16; 670 current->format->palette->ncolors = 16;
669 671
670 /* Get the fixed information about the console hardware. 672 /* Get the fixed information about the console hardware.
671 This is necessary since finfo.line_length changes. 673 This is necessary since finfo.line_length changes.
672 */ 674 */
673 if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) { 675 if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) {
757 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) { 759 if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) {
758 SDL_SetError("Couldn't set console screen info"); 760 SDL_SetError("Couldn't set console screen info");
759 return(NULL); 761 return(NULL);
760 } 762 }
761 } 763 }
764 } else {
765 int maxheight;
766
767 /* Figure out how much video memory is available */
768 if ( flags & SDL_DOUBLEBUF ) {
769 maxheight = height*2;
770 } else {
771 maxheight = height;
772 }
773 if ( vinfo.yres_virtual > maxheight ) {
774 vinfo.yres_virtual = maxheight;
775 }
762 } 776 }
763 cache_vinfo = vinfo; 777 cache_vinfo = vinfo;
764 #ifdef FBCON_DEBUG 778 #ifdef FBCON_DEBUG
765 fprintf(stderr, "Printing actual vinfo:\n"); 779 fprintf(stderr, "Printing actual vinfo:\n");
766 print_vinfo(&vinfo); 780 print_vinfo(&vinfo);
800 current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); 814 current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
801 current->w = vinfo.xres; 815 current->w = vinfo.xres;
802 current->h = vinfo.yres; 816 current->h = vinfo.yres;
803 current->pitch = finfo.line_length; 817 current->pitch = finfo.line_length;
804 current->pixels = mapped_mem+mapped_offset; 818 current->pixels = mapped_mem+mapped_offset;
819
820 /* Set up the information for hardware surfaces */
821 surfaces_mem = (char *)current->pixels +
822 vinfo.yres_virtual*current->pitch;
823 surfaces_len = (mapped_memlen-(surfaces_mem-mapped_mem));
824 FB_FreeHWSurfaces(this);
825 FB_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);
805 826
806 /* Let the application know we have a hardware palette */ 827 /* Let the application know we have a hardware palette */
807 switch (finfo.visual) { 828 switch (finfo.visual) {
808 case FB_VISUAL_PSEUDOCOLOR: 829 case FB_VISUAL_PSEUDOCOLOR:
809 current->flags |= SDL_HWPALETTE; 830 current->flags |= SDL_HWPALETTE;
818 current->flags |= SDL_DOUBLEBUF; 839 current->flags |= SDL_DOUBLEBUF;
819 flip_page = 0; 840 flip_page = 0;
820 flip_address[0] = (char *)current->pixels; 841 flip_address[0] = (char *)current->pixels;
821 flip_address[1] = (char *)current->pixels+ 842 flip_address[1] = (char *)current->pixels+
822 current->h*current->pitch; 843 current->h*current->pitch;
844 this->screen = current;
823 FB_FlipHWSurface(this, current); 845 FB_FlipHWSurface(this, current);
824 } 846 this->screen = NULL;
825 } 847 }
826 848 }
827 /* Set up the information for hardware surfaces */
828 surfaces_mem = (char *)current->pixels +
829 vinfo.yres_virtual*current->pitch;
830 surfaces_len = (mapped_memlen-(surfaces_mem-mapped_mem));
831 FB_FreeHWSurfaces(this);
832 FB_InitHWSurfaces(this, surfaces_mem, surfaces_len);
833 849
834 /* Set the update rectangle function */ 850 /* Set the update rectangle function */
835 this->UpdateRects = FB_DirectUpdate; 851 this->UpdateRects = FB_DirectUpdate;
836 852
837 /* We're done */ 853 /* We're done */
865 } 881 }
866 printf("\n"); 882 printf("\n");
867 } 883 }
868 #endif 884 #endif
869 885
870 static int FB_InitHWSurfaces(_THIS, char *base, int size) 886 static int FB_InitHWSurfaces(_THIS, SDL_Surface *screen, char *base, int size)
871 { 887 {
872 surfaces.prev = NULL; 888 vidmem_bucket *bucket;
873 surfaces.used = 0; 889
874 surfaces.base = base;
875 surfaces.size = size;
876 surfaces.next = NULL;
877 surfaces_memtotal = size; 890 surfaces_memtotal = size;
878 surfaces_memleft = size; 891 surfaces_memleft = size;
892
893 if ( surfaces_memleft > 0 ) {
894 bucket = (vidmem_bucket *)malloc(sizeof(*bucket));
895 if ( bucket == NULL ) {
896 SDL_OutOfMemory();
897 return(-1);
898 }
899 bucket->prev = &surfaces;
900 bucket->used = 0;
901 bucket->dirty = 0;
902 bucket->base = base;
903 bucket->size = size;
904 bucket->next = NULL;
905 } else {
906 bucket = NULL;
907 }
908
909 surfaces.prev = NULL;
910 surfaces.used = 1;
911 surfaces.dirty = 0;
912 surfaces.base = screen->pixels;
913 surfaces.size = (unsigned int)((long)base - (long)surfaces.base);
914 surfaces.next = bucket;
915 screen->hwdata = (struct private_hwdata *)&surfaces;
879 return(0); 916 return(0);
880 } 917 }
881 static void FB_FreeHWSurfaces(_THIS) 918 static void FB_FreeHWSurfaces(_THIS)
882 { 919 {
883 vidmem_bucket *bucket, *freeable; 920 vidmem_bucket *bucket, *freeable;
954 } 991 }
955 992
956 /* Set the current bucket values and return it! */ 993 /* Set the current bucket values and return it! */
957 bucket->used = 1; 994 bucket->used = 1;
958 bucket->size = size; 995 bucket->size = size;
996 bucket->dirty = 0;
959 #ifdef FBCON_DEBUG 997 #ifdef FBCON_DEBUG
960 fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base); 998 fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base);
961 #endif 999 #endif
962 surfaces_memleft -= size; 1000 surfaces_memleft -= size;
963 surface->flags |= SDL_HWSURFACE; 1001 surface->flags |= SDL_HWSURFACE;
964 surface->pixels = bucket->base; 1002 surface->pixels = bucket->base;
1003 surface->hwdata = (struct private_hwdata *)bucket;
965 return(0); 1004 return(0);
966 } 1005 }
967 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface) 1006 static void FB_FreeHWSurface(_THIS, SDL_Surface *surface)
968 { 1007 {
969 vidmem_bucket *bucket, *freeable; 1008 vidmem_bucket *bucket, *freeable;
970 1009
971 /* Look for the bucket in the current list */ 1010 /* Look for the bucket in the current list */
972 for ( bucket=&surfaces; bucket; bucket=bucket->next ) { 1011 for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
973 if ( bucket->base == (char *)surface->pixels ) { 1012 if ( bucket == (vidmem_bucket *)surface->hwdata ) {
974 break; 1013 break;
975 } 1014 }
976 } 1015 }
977 if ( (bucket == NULL) || ! bucket->used ) { 1016 if ( bucket && bucket->used ) {
978 return; 1017 /* Add the memory back to the total */
979 } 1018 #ifdef DGA_DEBUG
980
981 /* Add the memory back to the total */
982 #ifdef FBCON_DEBUG
983 printf("Freeing bucket of %d bytes\n", bucket->size); 1019 printf("Freeing bucket of %d bytes\n", bucket->size);
984 #endif 1020 #endif
985 surfaces_memleft += bucket->size; 1021 surfaces_memleft += bucket->size;
986 1022
987 /* Can we merge the space with surrounding buckets? */ 1023 /* Can we merge the space with surrounding buckets? */
988 bucket->used = 0; 1024 bucket->used = 0;
989 if ( bucket->next && ! bucket->next->used ) { 1025 if ( bucket->next && ! bucket->next->used ) {
990 #ifdef FBCON_DEBUG 1026 #ifdef DGA_DEBUG
991 printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size); 1027 printf("Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size);
992 #endif 1028 #endif
993 freeable = bucket->next; 1029 freeable = bucket->next;
994 bucket->size += bucket->next->size; 1030 bucket->size += bucket->next->size;
995 bucket->next = bucket->next->next; 1031 bucket->next = bucket->next->next;
996 if ( bucket->next ) { 1032 if ( bucket->next ) {
997 bucket->next->prev = bucket; 1033 bucket->next->prev = bucket;
998 } 1034 }
999 free(freeable); 1035 free(freeable);
1000 } 1036 }
1001 if ( bucket->prev && ! bucket->prev->used ) { 1037 if ( bucket->prev && ! bucket->prev->used ) {
1002 #ifdef FBCON_DEBUG 1038 #ifdef DGA_DEBUG
1003 printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size); 1039 printf("Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size);
1004 #endif 1040 #endif
1005 freeable = bucket; 1041 freeable = bucket;
1006 bucket->prev->size += bucket->size; 1042 bucket->prev->size += bucket->size;
1007 bucket->prev->next = bucket->next; 1043 bucket->prev->next = bucket->next;
1008 if ( bucket->next ) { 1044 if ( bucket->next ) {
1009 bucket->next->prev = bucket->prev; 1045 bucket->next->prev = bucket->prev;
1010 } 1046 }
1011 free(freeable); 1047 free(freeable);
1048 }
1012 } 1049 }
1013 surface->pixels = NULL; 1050 surface->pixels = NULL;
1051 surface->hwdata = NULL;
1014 } 1052 }
1015 static int FB_LockHWSurface(_THIS, SDL_Surface *surface) 1053 static int FB_LockHWSurface(_THIS, SDL_Surface *surface)
1016 { 1054 {
1017 if ( surface == SDL_VideoSurface ) { 1055 if ( surface == this->screen ) {
1018 SDL_mutexP(hw_lock); 1056 SDL_mutexP(hw_lock);
1057 if ( FB_IsSurfaceBusy(surface) ) {
1058 FB_WaitBusySurfaces(this);
1059 }
1060 } else {
1061 if ( FB_IsSurfaceBusy(surface) ) {
1062 FB_WaitBusySurfaces(this);
1063 }
1019 } 1064 }
1020 return(0); 1065 return(0);
1021 } 1066 }
1022 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface) 1067 static void FB_UnlockHWSurface(_THIS, SDL_Surface *surface)
1023 { 1068 {
1024 if ( surface == SDL_VideoSurface ) { 1069 if ( surface == this->screen ) {
1025 SDL_mutexV(hw_lock); 1070 SDL_mutexV(hw_lock);
1026 } 1071 }
1027 } 1072 }
1028 1073
1029 static void FB_WaitVBL(_THIS) 1074 static void FB_WaitVBL(_THIS)
1032 ioctl(console_fd, FBIOWAITRETRACE, 0); 1077 ioctl(console_fd, FBIOWAITRETRACE, 0);
1033 #endif 1078 #endif
1034 return; 1079 return;
1035 } 1080 }
1036 1081
1082 static void FB_WaitIdle(_THIS)
1083 {
1084 return;
1085 }
1086
1037 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface) 1087 static int FB_FlipHWSurface(_THIS, SDL_Surface *surface)
1038 { 1088 {
1039 /* Wait for vertical retrace and then flip display */ 1089 /* Wait for vertical retrace and then flip display */
1040 cache_vinfo.yoffset = flip_page*surface->h; 1090 cache_vinfo.yoffset = flip_page*surface->h;
1091 if ( FB_IsSurfaceBusy(this->screen) ) {
1092 FB_WaitBusySurfaces(this);
1093 }
1041 wait_vbl(this); 1094 wait_vbl(this);
1042 if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) { 1095 if ( ioctl(console_fd, FBIOPAN_DISPLAY, &cache_vinfo) < 0 ) {
1043 SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed"); 1096 SDL_SetError("ioctl(FBIOPAN_DISPLAY) failed");
1044 return(-1); 1097 return(-1);
1045 } 1098 }