ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_vosf.h
Revision: 1.2
Committed: 2000-09-23T06:51:30Z (23 years, 9 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
Changes since 1.1: +70 -15 lines
Log Message:
- fixed blitters for big endian systems, will probably work now

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * video_vosf.h - Video/graphics emulation, video on SEGV signals support
3     *
4     * Basilisk II (C) 1997-2000 Christian Bauer
5     *
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     static uint32 align_on_page_boundary(uint32 size)
33     {
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    
47     /*
48     * Screen depth identification
49     */
50    
51     enum {
52     ID_DEPTH_UNKNOWN = -1,
53     ID_DEPTH_1,
54     ID_DEPTH_8,
55     ID_DEPTH_15,
56     ID_DEPTH_16,
57     ID_DEPTH_24,
58     ID_DEPTH_32 = ID_DEPTH_24,
59     ID_DEPTH_COUNT
60     };
61    
62     static int depth_id(int depth)
63     {
64     int id;
65     switch (depth) {
66     case 1 : id = ID_DEPTH_1; break;
67     case 8 : id = ID_DEPTH_8; break;
68     case 15 : id = ID_DEPTH_15; break;
69     case 16 : id = ID_DEPTH_16; break;
70     case 24 : id = ID_DEPTH_24; break;
71     case 32 : id = ID_DEPTH_32; break;
72     default : id = ID_DEPTH_UNKNOWN;
73     }
74     return id;
75     }
76    
77    
78     /*
79     * Frame buffer copy function templates
80     */
81    
82     // No conversion required
83    
84     #define MEMCPY_PROFITABLE
85     #ifdef MEMCPY_PROFITABLE
86     static void do_fbcopy_raw(uint8 * dest, const uint8 * source, uint32 length)
87     {
88     memcpy(dest, source, length);
89     }
90     #else
91     #error "incomplete"
92     #define FB_BLIT_1(dst, src) (dst = (src))
93     #define FB_BLIT_2(dst, src) (dst = (src))
94 gbeauche 1.2 #define FB_DEPTH 0
95 gbeauche 1.1 #define FB_FUNC_NAME do_fbcopy_raw
96     #include "video_blit.h"
97     #endif
98    
99    
100     // RGB 555
101    
102 gbeauche 1.2 #ifdef WORDS_BIGENDIAN
103     # define FB_FUNC_NAME do_fbcopy_15_obo
104     #else
105     # define FB_FUNC_NAME do_fbcopy_15_nbo
106     #endif
107    
108 gbeauche 1.1 #define FB_BLIT_1(dst, src) \
109     (dst = (((src) >> 8) & 0xff) | (((src) & 0xff) << 8))
110    
111     #define FB_BLIT_2(dst, src) \
112     (dst = (((src) >> 8) & 0x00ff00ff) | (((src) & 0x00ff00ff) << 8))
113    
114     #define FB_DEPTH 15
115     #include "video_blit.h"
116    
117    
118     // RGB 565
119    
120 gbeauche 1.2 #ifdef WORDS_BIGENDIAN
121    
122     // native byte order
123    
124     #define FB_BLIT_1(dst, src) \
125     (dst = (((src) & 0x1f) | (((src) << 1) & 0xffc0)))
126    
127     #define FB_BLIT_2(dst, src) \
128     (dst = (((src) & 0x001f001f) | (((src) << 1) & 0xffc0ffc0)))
129    
130     #define FB_DEPTH 16
131     #define FB_FUNC_NAME do_fbcopy_16_nbo
132     #include "video_blit.h"
133    
134     // opposite byte order (untested)
135    
136     #define FB_BLIT_1(dst, src) \
137     (dst = ((((src) >> 6) & 0xff) | (((src) & 0x60) << 9)))
138    
139     #define FB_BLIT_2(dst, src) \
140     (dst = ((((src) >> 6) & 0x00ff00ff) | (((src) & 0x00600060) << 9)))
141    
142     #define FB_DEPTH 16
143     #define FB_FUNC_NAME do_fbcopy_16_obo
144     #include "video_blit.h"
145    
146     #else
147    
148     // native byte order
149    
150 gbeauche 1.1 #define FB_BLIT_1(dst, src) \
151     (dst = (((src) >> 8) & 0x001f) | (((src) << 9) & 0xfe00) | (((src) >> 7) & 0x01c0))
152    
153     #define FB_BLIT_2(dst, src) \
154     (dst = (((src) >> 8) & 0x001f001f) | (((src) << 9) & 0xfe00fe00) | (((src) >> 7) & 0x01c001c0))
155    
156     #define FB_DEPTH 16
157 gbeauche 1.2 #define FB_FUNC_NAME do_fbcopy_16_nbo
158 gbeauche 1.1 #include "video_blit.h"
159    
160 gbeauche 1.2 // opposite byte order (untested)
161    
162     #define FB_BLIT_1(dst, src) \
163     (dst = (((src) & 0x1f00) | (((src) << 1) & 0xe0fe) | (((src) >> 15) & 1)))
164    
165     #define FB_BLIT_2(dst, src) \
166     (dst = (((src) & 0x1f001f00) | (((src) << 1) & 0xe0fee0fe) | (((src) >> 15) & 0x10001)))
167    
168     #define FB_DEPTH 16
169     #define FB_FUNC_NAME do_fbcopy_16_obo
170     #include "video_blit.h"
171    
172     #endif
173 gbeauche 1.1
174     // RGB 888
175    
176 gbeauche 1.2 #ifdef WORDS_BIGENDIAN
177     # define FB_FUNC_NAME do_fbcopy_24_obo
178     #else
179     # define FB_FUNC_NAME do_fbcopy_24_nbo
180     #endif
181    
182 gbeauche 1.1 #define FB_BLIT_1(dst, src) \
183     (dst = (src))
184    
185     #define FB_BLIT_2(dst, src) \
186     (dst = (((src) >> 24) & 0xff) | (((src) >> 16) & 0xff00) | (((src) & 0xff00) << 16) | (((src) & 0xff) << 24))
187    
188     #define FB_DEPTH 24
189     #include "video_blit.h"
190    
191    
192     /*
193     * Frame buffer copy functions map table
194     */
195    
196     typedef void (*fbcopy_func)(uint8 *, const uint8 *, uint32);
197     static fbcopy_func do_update_framebuffer;
198    
199     #define FBCOPY_FUNC(aHandler) do_ ## aHandler
200    
201     #if REAL_ADDRESSING || DIRECT_ADDRESSING
202     #define WD(X) { FBCOPY_FUNC(X), FBCOPY_FUNC(X) }
203     #else
204     #define WD(X) { FBCOPY_FUNC(fbcopy_raw), FBCOPY_FUNC(fbcopy_raw) }
205     #endif
206    
207     // fb_copy_funcs[depth_id][native_byte_order][dga_mode]
208     // NT : not tested
209     // OK : has been successfully tested
210     // NBO : native byte order
211 gbeauche 1.2 // OBO : opposite byte order
212 gbeauche 1.1 static fbcopy_func fbcopy_funcs[ID_DEPTH_COUNT][2][2] = {
213     #ifdef WORDS_BIGENDIAN
214 gbeauche 1.2 /* opposite byte order native byte order */
215     /* 1 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // NT
216     /* 8 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // OK (NBO)
217     /* 15 bpp */ { WD(fbcopy_15_obo) , WD(fbcopy_raw) }, // NT
218     /* 16 bpp */ { WD(fbcopy_16_obo) , WD(fbcopy_16_nbo) }, // NT
219     /* 24 bpp */ { WD(fbcopy_24_obo) , WD(fbcopy_raw) } // NT
220 gbeauche 1.1 #else
221 gbeauche 1.2 /* opposite byte order native byte order */
222     /* 1 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // NT
223     /* 8 bpp */ { WD(fbcopy_raw) , WD(fbcopy_raw) }, // OK (NBO)
224     /* 15 bpp */ { WD(fbcopy_raw) , WD(fbcopy_15_nbo) }, // OK (NBO)
225     /* 16 bpp */ { WD(fbcopy_16_obo) , WD(fbcopy_16_nbo) }, // OK (NBO)
226     /* 24 bpp */ { WD(fbcopy_raw) , WD(fbcopy_24_nbo) } // NT
227 gbeauche 1.1 #endif
228     };
229    
230     #undef WD
231    
232     #define FBCOPY_FUNC_ERROR \
233     ErrorAlert("Invalid screen depth")
234    
235     #define GET_FBCOPY_FUNC(aDepth, aNativeByteOrder, aDisplay) \
236     ((depth_id(aDepth) == ID_DEPTH_UNKNOWN) ? ( FBCOPY_FUNC_ERROR, (fbcopy_func)0 ) : \
237     fbcopy_funcs[depth_id(aDepth)][(aNativeByteOrder)][(aDisplay) == DISPLAY_DGA ? 1 : 0])
238    
239    
240     /*
241     * Screen fault handler
242     */
243    
244     static inline void do_handle_screen_fault(unsigned long addr)
245     {
246     if ((addr < mainBuffer.memStart) || (addr >= mainBuffer.memEnd)) {
247     fprintf(stderr, "Segmentation fault at 0x%08X\n", addr);
248     abort();
249     }
250    
251     const int page = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
252     caddr_t page_ad = (caddr_t)(addr & ~(mainBuffer.pageSize - 1));
253     #ifdef HAVE_PTHREADS
254     pthread_mutex_lock(&Screen_draw_lock);
255     #endif
256     PFLAG_SET(page);
257     mprotect(page_ad, mainBuffer.pageSize, PROT_READ | PROT_WRITE);
258     #ifdef HAVE_PTHREADS
259     pthread_mutex_unlock(&Screen_draw_lock);
260     #endif
261     }
262    
263     #if defined(HAVE_SIGINFO_T)
264     static void Screen_fault_handler(int, siginfo_t * sip, void *)
265     {
266     D(bug("Screen_fault_handler: ADDR=0x%08X\n", sip->si_addr));
267     do_handle_screen_fault((unsigned long)sip->si_addr);
268     }
269     #elif defined(HAVE_SIGCONTEXT_SUBTERFUGE)
270     # if defined(__i386__) && defined(__linux__)
271     static void Screen_fault_handler(int, struct sigcontext scs)
272     {
273     D(bug("Screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", scs.cr2, scs.eip));
274     do_handle_screen_fault((unsigned long)scs.cr2);
275     }
276     # else
277     # error "No suitable subterfuge for Video on SEGV signals"
278     # endif
279     #else
280     # error "Can't do Video on SEGV signals"
281     #endif
282    
283    
284     /*
285     * Screen fault handler initialization
286     */
287    
288     #if defined(HAVE_SIGINFO_T)
289     static bool Screen_fault_handler_init()
290     {
291     // Setup SIGSEGV handler to process writes to frame buffer
292     sigemptyset(&vosf_sa.sa_mask);
293     vosf_sa.sa_sigaction = Screen_fault_handler;
294     vosf_sa.sa_flags = 0;
295     return (sigaction(SIGSEGV, &vosf_sa, NULL) == 0);
296     }
297     #elif defined(HAVE_SIGCONTEXT_SUBTERFUGE)
298     static bool Screen_fault_handler_init()
299     {
300     // Setup SIGSEGV handler to process writes to frame buffer
301     sigemptyset(&vosf_sa.sa_mask);
302     vosf_sa.sa_handler = (void (*)(int)) Screen_fault_handler;
303     vosf_sa.sa_flags = 0;
304     return (sigaction(SIGSEGV, &vosf_sa, NULL) == 0);
305     }
306     #endif
307    
308    
309     /*
310     * Update display for Windowed mode and VOSF
311     */
312    
313     static inline void update_display_window_vosf(void)
314     {
315     int page = 0;
316     for (;;) {
317     while (PFLAG_ISCLEAR_4(page))
318     page += 4;
319    
320     while (PFLAG_ISCLEAR(page))
321     page++;
322    
323     if (page >= mainBuffer.pageCount)
324     break;
325    
326     const int first_page = page;
327     PFLAG_CLEAR(first_page);
328     while ((++page < mainBuffer.pageCount) && PFLAG_ISSET(page))
329     PFLAG_CLEAR(page);
330    
331     // Make the dirty pages read-only again
332     const int32 offset = first_page << mainBuffer.pageBits;
333     const uint32 length = (page - first_page) << mainBuffer.pageBits;
334     mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
335    
336     // There is at least one line to update
337     const int y1 = mainBuffer.pageInfo[first_page].top;
338     const int y2 = mainBuffer.pageInfo[page - 1].bottom;
339     const int height = y2 - y1 + 1;
340    
341     const int bytes_per_row = VideoMonitor.bytes_per_row;
342     const int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
343     int i, j;
344    
345     // Check for first column from left and first column
346     // from right that have changed
347     int x1 = VideoMonitor.x * bytes_per_pixel - 1;
348     for (j = y1; j <= y2; j++) {
349     uint8 * const p1 = &the_buffer[j * bytes_per_row];
350     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
351     for (i = 0; i < x1; i++) {
352     if (p1[i] != p2[i]) {
353     x1 = i;
354     break;
355     }
356     }
357     }
358     x1 /= bytes_per_pixel;
359    
360     int x2 = x1 * bytes_per_pixel;
361     for (j = y2; j >= y1; j--) {
362     uint8 * const p1 = &the_buffer[j * bytes_per_row];
363     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
364     for (i = VideoMonitor.x * bytes_per_pixel - 1; i > x2; i--) {
365     if (p1[i] != p2[i]) {
366     x2 = i;
367     break;
368     }
369     }
370     }
371     x2 /= bytes_per_pixel;
372    
373     // Update the_host_buffer and copy of the_buffer
374     // There is at least one pixel to copy
375     const int width = x2 - x1 + 1;
376     i = y1 * bytes_per_row + x1 * bytes_per_pixel;
377     for (j = y1; j <= y2; j++) {
378     do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
379     memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
380     i += bytes_per_row;
381     }
382    
383     if (have_shm)
384     XShmPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, width, height, 0);
385     else
386     XPutImage(x_display, the_win, the_gc, img, x1, y1, x1, y1, width, height);
387     }
388     }
389    
390    
391     /*
392     * Update display for DGA mode and VOSF
393     * (only in Direct Addressing mode)
394     */
395    
396     #if REAL_ADDRESSING || DIRECT_ADDRESSING
397     static inline void update_display_dga_vosf(void)
398     {
399     int page = 0;
400     for (;;) {
401     while (PFLAG_ISCLEAR_4(page))
402     page += 4;
403    
404     while (PFLAG_ISCLEAR(page))
405     page++;
406    
407     if (page >= mainBuffer.pageCount)
408     break;
409    
410     const int first_page = page;
411     PFLAG_CLEAR(first_page);
412     while ((++page < mainBuffer.pageCount) && PFLAG_ISSET(page))
413     PFLAG_CLEAR(page);
414    
415     // Make the dirty pages read-only again
416     const int32 offset = first_page << mainBuffer.pageBits;
417     const uint32 length = (page - first_page) << mainBuffer.pageBits;
418     mprotect((caddr_t)(mainBuffer.memStart + offset), length, PROT_READ);
419    
420     // I am sure that y2 >= y1 and depth != 1
421     const int y1 = mainBuffer.pageInfo[first_page].top;
422     const int y2 = mainBuffer.pageInfo[page - 1].bottom;
423    
424     const int bytes_per_row = VideoMonitor.bytes_per_row;
425     const int bytes_per_pixel = VideoMonitor.bytes_per_row / VideoMonitor.x;
426     int i, j;
427    
428     // Check for first column from left and first column
429     // from right that have changed
430     int x1 = VideoMonitor.x * bytes_per_pixel - 1;
431     for (j = y1; j <= y2; j++) {
432     uint8 * const p1 = &the_buffer[j * bytes_per_row];
433     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
434     for (i = 0; i < x1; i++) {
435     if (p1[i] != p2[i]) {
436     x1 = i;
437     break;
438     }
439     }
440     }
441     x1 /= bytes_per_pixel;
442    
443     int x2 = x1 * bytes_per_pixel;
444     for (j = y2; j >= y1; j--) {
445     uint8 * const p1 = &the_buffer[j * bytes_per_row];
446     uint8 * const p2 = &the_buffer_copy[j * bytes_per_row];
447     for (i = VideoMonitor.x * bytes_per_pixel - 1; i > x2; i--) {
448     if (p1[i] != p2[i]) {
449     x2 = i;
450     break;
451     }
452     }
453     }
454     x2 /= bytes_per_pixel;
455    
456     // Update the_host_buffer and copy of the_buffer
457     // There should be at least one pixel to copy
458     const int width = x2 - x1 + 1;
459     i = y1 * bytes_per_row + x1 * bytes_per_pixel;
460     for (j = y1; j <= y2; j++) {
461     do_update_framebuffer(the_host_buffer + i, the_buffer + i, bytes_per_pixel * width);
462     memcpy(the_buffer_copy + i, the_buffer + i, bytes_per_pixel * width);
463     i += bytes_per_row;
464     }
465     }
466     }
467     #endif
468    
469     #endif /* ENABLE_VOSF */
470    
471     #endif /* VIDEO_VOSF_H */