ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_vosf.h
Revision: 1.16
Committed: 2001-05-20T20:31:50Z (23 years, 6 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: snapshot-29052001, release-0_9-1
Changes since 1.15: +9 -100 lines
Log Message:
- new and updated SIGSEGV support functions:
  + configure script cleanups
  + possible support for Direct Addressing / VOSF on other platforms

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * video_vosf.h - Video/graphics emulation, video on SEGV signals support
3     *
4 gbeauche 1.13 * Basilisk II (C) 1997-2001 Christian Bauer
5 gbeauche 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #ifndef VIDEO_VOSF_H
22     #define VIDEO_VOSF_H
23    
24     // Note: this file is #include'd in video_x.cpp
25     #ifdef ENABLE_VOSF
26    
27     /*
28     * Page-aligned memory allocation
29     */
30    
31     // Align on page boundaries
32 gbeauche 1.4 static uintptr align_on_page_boundary(uintptr size)
33 gbeauche 1.1 {
34     const uint32 page_size = getpagesize();
35     const uint32 page_mask = page_size - 1;
36     return (size + page_mask) & ~page_mask;
37     }
38    
39     // Allocate memory on page boundary
40     static void * allocate_framebuffer(uint32 size, uint8 * hint = 0)
41     {
42     // Remind that the system can allocate at 0x00000000...
43     return mmap((caddr_t)hint, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zero_fd, 0);
44     }
45    
46 gbeauche 1.16 // Screen fault handler
47     static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
48 gbeauche 1.1 {
49 gbeauche 1.16 D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
50     const uintptr addr = (uintptr)fault_address;
51    
52 gbeauche 1.11 /* Someone attempted to write to the frame buffer. Make it writeable
53     * now so that the data could actually be written. It will be made
54     * read-only back in one of the screen update_*() functions.
55     */
56     if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
57     const int page = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
58     caddr_t page_ad = (caddr_t)(addr & ~(mainBuffer.pageSize - 1));
59     LOCK_VOSF;
60     PFLAG_SET(page);
61     mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE);
62 gbeauche 1.13 mainBuffer.dirty = true;
63 gbeauche 1.11 UNLOCK_VOSF;
64 gbeauche 1.16 return true;
65 gbeauche 1.1 }
66    
67 gbeauche 1.11 /* Otherwise, we don't know how to handle the fault, let it crash */
68     fprintf(stderr, "do_handle_screen_fault: unhandled address 0x%08X", addr);
69 gbeauche 1.16 if (fault_instruction != SIGSEGV_INVALID_PC)
70     fprintf(stderr, " [IP=0x%08X]", fault_instruction);
71 gbeauche 1.11 fprintf(stderr, "\n");
72 gbeauche 1.16 return false;
73 gbeauche 1.1 }
74    
75     /*
76     * Update display for Windowed mode and VOSF
77     */
78    
79 gbeauche 1.13 // From video_blit.cpp
80     extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length);
81     extern bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order);
82    
83 gbeauche 1.12 /* How can we deal with array overrun conditions ?
84    
85     The state of the framebuffer pages that have been touched are maintained
86     in the dirtyPages[] table. That table is (pageCount + 2) bytes long.
87    
88     Terminology
89    
90     "Last Page" denotes the pageCount-nth page, i.e. dirtyPages[pageCount - 1].
91     "CLEAR Page Guard" refers to the page following the Last Page but is always
92     in the CLEAR state. "SET Page Guard" refers to the page following the CLEAR
93     Page Guard but is always in the SET state.
94    
95     Rough process
96    
97 gbeauche 1.13 The update routines must determine which pages have to be blitted to the
98 gbeauche 1.12 screen. This job consists in finding the first_page that was touched.
99     i.e. find the next page that is SET. Then, finding how many pages were
100     touched starting from first_page. i.e. find the next page that is CLEAR.
101    
102 gbeauche 1.13 There are two cases to check:
103 gbeauche 1.12
104     - Last Page is CLEAR: find_next_page_set() will reach the SET Page Guard
105     but it is beyond the valid pageCount value. Therefore, we exit from the
106     update routine.
107    
108     - Last Page is SET: first_page equals (pageCount - 1) and
109     find_next_page_clear() will reach the CLEAR Page Guard. We blit the last
110     page to the screen. On the next iteration, page equals pageCount and
111     find_next_page_set() will reach the SET Page Guard. We still safely exit
112     from the update routine because the SET Page Guard position is greater
113     than pageCount.
114     */
115    
116 gbeauche 1.1 static inline void update_display_window_vosf(void)
117     {
118     int page = 0;
119     for (;;) {
120 gbeauche 1.11 const int first_page = find_next_page_set(page);
121     if (first_page >= mainBuffer.pageCount)
122 gbeauche 1.1 break;
123 gbeauche 1.11
124     page = find_next_page_clear(first_page);
125     PFLAG_CLEAR_RANGE(first_page, page);
126 cebix 1.7
127 gbeauche 1.1 // Make the dirty pages read-only again
128     const int32 offset = first_page << mainBuffer.pageBits;
129     const uint32 length = (page - first_page) << mainBuffer.pageBits;
130     mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
131    
132     // There is at least one line to update
133     const int y1 = mainBuffer.pageInfo[first_page].top;
134     const int y2 = mainBuffer.pageInfo[page - 1].bottom;
135     const int height = y2 - y1 + 1;
136    
137     const int bytes_per_row = VideoMonitor.bytes_per_row;
138     const int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
139 cebix 1.15 int i = y1 * bytes_per_row, j;
140 gbeauche 1.1
141 cebix 1.6 if (depth == 1) {
142    
143     // Update the_host_buffer and copy of the_buffer
144     for (j = y1; j <= y2; j++) {
145 cebix 1.15 Screen_blit(the_host_buffer + i, the_buffer + i, VideoMonitor.x >> 3);
146 cebix 1.6 i += bytes_per_row;
147     }
148    
149     } else {
150    
151     // Update the_host_buffer and copy of the_buffer
152     for (j = y1; j <= y2; j++) {
153 cebix 1.15 Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * VideoMonitor.x);
154 cebix 1.6 i += bytes_per_row;
155     }
156 gbeauche 1.1 }
157 cebix 1.15
158 gbeauche 1.1 if (have_shm)
159 cebix 1.15 XShmPutImage(x_display, the_win, the_gc, img, 0, y1, 0, y1, VideoMonitor.x, height, 0);
160 gbeauche 1.1 else
161 cebix 1.15 XPutImage(x_display, the_win, the_gc, img, 0, y1, 0, y1, VideoMonitor.x, height);
162 gbeauche 1.1 }
163 cebix 1.15
164 gbeauche 1.13 mainBuffer.dirty = false;
165 gbeauche 1.1 }
166    
167    
168     /*
169     * Update display for DGA mode and VOSF
170     * (only in Direct Addressing mode)
171     */
172    
173     #if REAL_ADDRESSING || DIRECT_ADDRESSING
174     static inline void update_display_dga_vosf(void)
175     {
176     int page = 0;
177     for (;;) {
178 gbeauche 1.11 const int first_page = find_next_page_set(page);
179     if (first_page >= mainBuffer.pageCount)
180 gbeauche 1.1 break;
181 gbeauche 1.11
182     page = find_next_page_clear(first_page);
183     PFLAG_CLEAR_RANGE(first_page, page);
184    
185 gbeauche 1.1 // Make the dirty pages read-only again
186     const int32 offset = first_page << mainBuffer.pageBits;
187     const uint32 length = (page - first_page) << mainBuffer.pageBits;
188     mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
189    
190     // I am sure that y2 >= y1 and depth != 1
191     const int y1 = mainBuffer.pageInfo[first_page].top;
192     const int y2 = mainBuffer.pageInfo[page - 1].bottom;
193    
194     const int bytes_per_row = VideoMonitor.bytes_per_row;
195     const int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
196     int i, j;
197    
198     // Check for first column from left and first column
199     // from right that have changed
200     int x1 = VideoMonitor.x * bytes_per_pixel - 1;
201     for (j = y1; j <= y2; j++) {
202     uint8 * const p1 = &the_buffer[j * bytes_per_row];
203     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
204     for (i = 0; i < x1; i++) {
205     if (p1[i] != p2[i]) {
206     x1 = i;
207     break;
208     }
209     }
210     }
211     x1 /= bytes_per_pixel;
212    
213     int x2 = x1 * bytes_per_pixel;
214     for (j = y2; j >= y1; j--) {
215     uint8 * const p1 = &the_buffer[j * bytes_per_row];
216     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
217     for (i = VideoMonitor.x * bytes_per_pixel - 1; i > x2; i--) {
218     if (p1[i] != p2[i]) {
219     x2 = i;
220     break;
221     }
222     }
223     }
224     x2 /= bytes_per_pixel;
225    
226     // Update the_host_buffer and copy of the_buffer
227     // There should be at least one pixel to copy
228     const int width = x2 - x1 + 1;
229     i = y1 * bytes_per_row + x1 * bytes_per_pixel;
230     for (j = y1; j <= y2; j++) {
231 gbeauche 1.13 Screen_blit(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
232 gbeauche 1.1 memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
233     i += bytes_per_row;
234     }
235     }
236 gbeauche 1.13 mainBuffer.dirty = false;
237 gbeauche 1.1 }
238     #endif
239    
240     #endif /* ENABLE_VOSF */
241    
242     #endif /* VIDEO_VOSF_H */