/[gxemul]/trunk/src/devices/dev_fb.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_fb.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_fb.c,v 1.90 2005/03/29 09:46:06 debug Exp $   *  $Id: dev_fb.c,v 1.127 2006/10/22 04:20:53 debug Exp $
29   *     *  
30   *  Generic framebuffer device.   *  Generic framebuffer device.
31   *   *
32   *      DECstation VFB01 monochrome framebuffer, 1024x864   *      DECstation VFB01 monochrome framebuffer, 1024x864
33   *      DECstation VFB02 8-bit color framebuffer, 1024x864   *      DECstation VFB02 8-bit color framebuffer, 1024x864
34   *      DECstation Maxine, 1024x768 8-bit color   *      DECstation Maxine, 1024x768 8-bit color
  *      HPCmips framebuffer  
35   *      Playstation 2 (24-bit color)   *      Playstation 2 (24-bit color)
36   *      generic (any resolution, several bit depths possible)   *      Generic (any resolution, several bit depths possible, useful for
37     *              testmachines)
38   *   *
39   *   *
40   *  TODO:  There is still a bug when redrawing the cursor. The underlying   *  TODO:  This should actually be independent of X11, but that
  *         image is moved 1 pixel (?), or something like that.  
  *  
  *  TODO:  This should actually be independant of X11, but that  
41   *         might be too hard to do right now.   *         might be too hard to do right now.
42   *   *
43   *  TODO:  playstation 2 pixels are stored in another format, actually   *  TODO:  playstation 2 pixels are stored in another format, actually
# Line 65  Line 62 
62  #endif  #endif
63    
64    
65  #define FB_TICK_SHIFT           18  #define FB_TICK_SHIFT           19
   
 #define LOGO_XSIZE              256  
 #define LOGO_YSIZE              256  
 #define LOGO_BOTTOM_MARGIN      60  
 /*  This must be a 256*256 pixels P4 ppm:  */  
 #include "fb_logo.c"  
 unsigned char *fb_logo = fb_logo_ppm + 11;  
66    
67    
68  /*  #define FB_DEBUG  */  /*  #define FB_DEBUG  */
# Line 114  void set_blackwhite_palette(struct vfb_d Line 104  void set_blackwhite_palette(struct vfb_d
104  }  }
105    
106    
107    static void set_title(struct vfb_data *d)
108    {
109            snprintf(d->title, sizeof(d->title),"GXemul: %ix%ix%i %s framebuffer",
110                d->visible_xsize, d->visible_ysize, d->bit_depth, d->name);
111            d->title[sizeof(d->title)-1] = '\0';
112    }
113    
114    
115    /*
116     *  dev_fb_resize():
117     *
118     *  Resize a framebuffer window. (This functionality is probably a bit buggy,
119     *  because I didn't think of including it from the start.)
120     *
121     *  SUPER-IMPORTANT: Anyone who resizes a framebuffer by calling this function
122     *  must also clear all dyntrans address translations manually, in all cpus
123     *  which might have access to the framebuffer!
124     */
125    void dev_fb_resize(struct vfb_data *d, int new_xsize, int new_ysize)
126    {
127            unsigned char *new_framebuffer;
128            int y, new_bytes_per_line;
129            size_t size;
130    
131            if (d == NULL) {
132                    fatal("dev_fb_resize(): d == NULL\n");
133                    return;
134            }
135    
136            if (new_xsize < 10 || new_ysize < 10) {
137                    fatal("dev_fb_resize(): size too small.\n");
138                    exit(1);
139            }
140    
141            new_bytes_per_line = new_xsize * d->bit_depth / 8;
142            size = new_ysize * new_bytes_per_line;
143    
144            new_framebuffer = malloc(size);
145            if (new_framebuffer == NULL) {
146                    fprintf(stderr, "dev_fb_resize(): out of memory\n");
147                    exit(1);
148            }
149    
150            /*  Copy the old framebuffer to the new:  */
151            if (d->framebuffer != NULL) {
152                    for (y=0; y<new_ysize; y++) {
153                            size_t fromofs = d->bytes_per_line * y;
154                            size_t toofs = new_bytes_per_line * y;
155                            size_t len_to_copy = d->bytes_per_line <
156                                new_bytes_per_line? d->bytes_per_line      
157                                : new_bytes_per_line;
158                            memset(new_framebuffer + toofs, 0, new_bytes_per_line);
159                            if (y < d->x11_ysize)
160                                    memmove(new_framebuffer + toofs,
161                                        d->framebuffer + fromofs, len_to_copy);
162                    }
163    
164                    free(d->framebuffer);
165            }
166    
167            d->framebuffer = new_framebuffer;
168            d->framebuffer_size = size;
169    
170            if (new_xsize > d->xsize || new_ysize > d->ysize) {
171                    d->update_x1 = d->update_y1 = 0;
172                    d->update_x2 = new_xsize - 1;
173                    d->update_y2 = new_ysize - 1;
174            }
175    
176            d->bytes_per_line = new_bytes_per_line;
177            d->xsize = d->visible_xsize = new_xsize;
178            d->ysize = d->visible_ysize = new_ysize;
179    
180            d->x11_xsize = d->xsize / d->vfb_scaledown;
181            d->x11_ysize = d->ysize / d->vfb_scaledown;
182    
183            memory_device_update_data(d->memory, d, d->framebuffer);
184    
185            set_title(d);
186    
187    #ifdef WITH_X11
188            if (d->fb_window != NULL) {
189                    x11_fb_resize(d->fb_window, new_xsize, new_ysize);
190                    x11_set_standard_properties(d->fb_window, d->title);
191            }
192    #endif
193    }
194    
195    
196  /*  /*
197   *  dev_fb_setcursor():   *  dev_fb_setcursor():
198   */   */
# Line 139  void dev_fb_setcursor(struct vfb_data *d Line 218  void dev_fb_setcursor(struct vfb_data *d
218          }          }
219  #endif  #endif
220    
         if (d->fb_window != NULL)  
                 console_set_framebuffer_mouse(cursor_x, cursor_y,  
                     d->fb_window->fb_number);  
   
221          /*  debug("dev_fb_setcursor(%i,%i, size %i,%i, on=%i)\n",          /*  debug("dev_fb_setcursor(%i,%i, size %i,%i, on=%i)\n",
222              cursor_x, cursor_y, cursor_xsize, cursor_ysize, on);  */              cursor_x, cursor_y, cursor_xsize, cursor_ysize, on);  */
223  }  }
# Line 155  void dev_fb_setcursor(struct vfb_data *d Line 230  void dev_fb_setcursor(struct vfb_data *d
230   *  block copy/fill.   *  block copy/fill.
231   *   *
232   *  If fillflag is non-zero, then fill_[rgb] should contain the color   *  If fillflag is non-zero, then fill_[rgb] should contain the color
233   *  with which to fill.   *  with which to fill. (In 8-bit mode, only fill_r is used.)
234   *   *
235   *  If fillflag is zero, copy mode is used, and from_[xy] should contain   *  If fillflag is zero, copy mode is used, and from_[xy] should contain
236   *  the offset on the framebuffer where we should copy from.   *  the offset on the framebuffer where we should copy from.
# Line 166  void framebuffer_blockcopyfill(struct vf Line 241  void framebuffer_blockcopyfill(struct vf
241          int fill_g, int fill_b, int x1, int y1, int x2, int y2,          int fill_g, int fill_b, int x1, int y1, int x2, int y2,
242          int from_x, int from_y)          int from_x, int from_y)
243  {  {
244          int y;          int x, y;
245          long from_ofs, dest_ofs, linelen;          long from_ofs, dest_ofs, linelen;
246    
247          if (fillflag)          if (fillflag)
# Line 189  void framebuffer_blockcopyfill(struct vf Line 264  void framebuffer_blockcopyfill(struct vf
264          if (fillflag) {          if (fillflag) {
265                  for (y=y1; y<=y2; y++) {                  for (y=y1; y<=y2; y++) {
266                          if (y>=0 && y<d->ysize) {                          if (y>=0 && y<d->ysize) {
267                                  int x;                                  unsigned char *buf =
268                                  char buf[8192 * 3];                                      d->framebuffer + dest_ofs;
269                                  if (d->bit_depth == 24)  
270                                          for (x=0; x<linelen; x+=3) {                                  if (d->bit_depth == 24) {
271                                            for (x=0; x<linelen && x<sizeof(buf);
272                                                x += 3) {
273                                                  buf[x] = fill_r;                                                  buf[x] = fill_r;
274                                                  buf[x+1] = fill_g;                                                  buf[x+1] = fill_g;
275                                                  buf[x+2] = fill_b;                                                  buf[x+2] = fill_b;
276                                          }                                          }
277                                  else                                  } else if (d->bit_depth == 8) {
278                                          printf("TODO: fill for non-24-bit"                                          memset(buf, fill_r, linelen);
279                                              " modes\n");                                  } else {
280                                            fatal("Unimplemented bit-depth (%i)"
281                                  memmove(d->framebuffer + dest_ofs, buf,                                              " for fb fill\n", d->bit_depth);
282                                      linelen);                                          exit(1);
283                                    }
284                          }                          }
285    
286                          dest_ofs += d->bytes_per_line;                          dest_ofs += d->bytes_per_line;
# Line 210  void framebuffer_blockcopyfill(struct vf Line 288  void framebuffer_blockcopyfill(struct vf
288          } else {          } else {
289                  from_ofs = d->bytes_per_line * from_y +                  from_ofs = d->bytes_per_line * from_y +
290                      (d->bit_depth/8) * from_x;                      (d->bit_depth/8) * from_x;
   
291                  for (y=y1; y<=y2; y++) {                  for (y=y1; y<=y2; y++) {
292                          if (y>=0 && y<d->ysize)                          if (y >= 0 && y < d->ysize) {
293                                  memmove(d->framebuffer + dest_ofs,                                  if (from_y >= 0 && from_y < d->ysize)
294                                      d->framebuffer + from_ofs, linelen);                                          memmove(d->framebuffer + dest_ofs,
295                                                d->framebuffer + from_ofs, linelen);
296                                    else
297                                            memset(d->framebuffer + dest_ofs,
298                                                0, linelen);
299                            }
300                            from_y ++;
301                          from_ofs += d->bytes_per_line;                          from_ofs += d->bytes_per_line;
302                          dest_ofs += d->bytes_per_line;                          dest_ofs += d->bytes_per_line;
303                  }                  }
# Line 234  void framebuffer_blockcopyfill(struct vf Line 316  void framebuffer_blockcopyfill(struct vf
316    
317    
318  #ifdef WITH_X11  #ifdef WITH_X11
 #define macro_put_pixel() {     \  
                         /*  Combine the color into an X11 long and display it:  */      \  
                         /*  TODO:  construct color in a more portable way:  */          \  
                         switch (d->fb_window->x11_screen_depth) {                                       \  
                         case 24:                                                        \  
                                 if (d->fb_window->fb_ximage->byte_order)                \  
                                         color = (b << 16) + (g << 8) + r;               \  
                                 else                                                    \  
                                         color = (r << 16) + (g << 8) + b;               \  
                                 break;                                                  \  
                         case 16:                                                        \  
                                 r >>= 3; g >>= 2; b >>= 3;                              \  
                                 if (d->fb_window->fb_ximage->byte_order) {              \  
                                         /*  Big endian 16-bit X server:  */             \  
                                         static int first = 1;                           \  
                                         if (first) {                                    \  
                                                 fprintf(stderr, "\n*** Please report to the author whether 16-bit X11 colors are rendered correctly or not!\n\n"); \  
                                                 first = 0;                              \  
                                         }                                               \  
                                         color = (b << 11) + (g << 5) + r;               \  
                                 } else {                                                \  
                                         /*  Little endian (eg PC) X servers:  */        \  
                                         color = (r << 11) + (g << 5) + b;               \  
                                 }                                                       \  
                                 break;                                                  \  
                         case 15:                                                        \  
                                 r >>= 3; g >>= 3; b >>= 3;                              \  
                                 if (d->fb_window->fb_ximage->byte_order) {              \  
                                         /*  Big endian 15-bit X server:  */             \  
                                         static int first = 1;                           \  
                                         if (first) {                                    \  
                                                 fprintf(stderr, "\n*** Please report to the author whether 15-bit X11 colors are rendered correctly or not!\n\n"); \  
                                                 first = 0;                              \  
                                         }                                               \  
                                         color = (b << 10) + (g << 5) + r;               \  
                                 } else {                                                \  
                                         /*  Little endian (eg PC) X servers:  */        \  
                                         color = (r << 10) + (g << 5) + b;               \  
                                 }                                                       \  
                                 break;                                                  \  
                         default:                                                        \  
                                 color = d->fb_window->x11_graycolor[15 * (r + g + b) / (255 * 3)].pixel; \  
                         }                                                               \  
                         if (x>=0 && x<d->x11_xsize && y>=0 && y<d->x11_ysize)           \  
                                 XPutPixel(d->fb_window->fb_ximage, x, y, color);        \  
                 }  
 #else  
 /*  If not WITH_X11:  */  
 #define macro_put_pixel() { }  
 #endif  
   
   
 /*  
  *  update_framebuffer():  
  *  
  *  The framebuffer memory has been updated. This function tries to make  
  *  sure that the XImage is also updated (1 or more pixels).  
  */  
 void update_framebuffer(struct vfb_data *d, int addr, int len)  
 {  
         int x, y, pixel, npixels;  
         long color_r, color_g, color_b;  
 #ifdef WITH_X11  
         long color;  
 #endif  
         int scaledown = d->vfb_scaledown;  
         int scaledownXscaledown = 1;  
   
         if (scaledown == 1) {  
                 /*  Which framebuffer pixel does addr correspond to?  */  
                 pixel = addr * 8 / d->bit_depth;  
                 y = pixel / d->xsize;  
                 x = pixel % d->xsize;  
   
                 /*  How many framebuffer pixels?  */  
                 npixels = len * 8 / d->bit_depth;  
                 if (npixels == 0)  
                         npixels = 1;  
   
                 if (d->bit_depth < 8) {  
                         for (pixel=0; pixel<npixels; pixel++) {  
                                 int fb_addr, c, r, g, b;  
                                 color_r = color_g = color_b = 0;  
   
                                 fb_addr = (y * d->xsize + x) * d->bit_depth;  
                                 /*  fb_addr is now which _bit_ in  
                                     the framebuffer  */  
   
                                 c = d->framebuffer[fb_addr >> 3];  
                                 fb_addr &= 7;  
   
                                 /*  HPCmips is reverse:  */  
                                 if (d->vfb_type == VFB_HPCMIPS)  
                                         fb_addr = 8 - d->bit_depth - fb_addr;  
   
                                 c = (c >> fb_addr) & ((1<<d->bit_depth) - 1);  
                                 /*  c <<= (8 - d->bit_depth);  */  
   
                                 r = d->rgb_palette[c*3 + 0];  
                                 g = d->rgb_palette[c*3 + 1];  
                                 b = d->rgb_palette[c*3 + 2];  
   
                                 macro_put_pixel();  
                                 x++;  
                         }  
                 } else if (d->bit_depth == 8) {  
                         for (pixel=0; pixel<npixels; pixel++) {  
                                 int fb_addr, c, r, g, b;  
                                 color_r = color_g = color_b = 0;  
   
                                 fb_addr = y * d->xsize + x;  
                                 /*  fb_addr is now which byte in framebuffer  */  
                                 c = d->framebuffer[fb_addr];  
                                 r = d->rgb_palette[c*3 + 0];  
                                 g = d->rgb_palette[c*3 + 1];  
                                 b = d->rgb_palette[c*3 + 2];  
   
                                 macro_put_pixel();  
                                 x++;  
                         }  
                 } else {        /*  d->bit_depth > 8  */  
                         for (pixel=0; pixel<npixels; pixel++) {  
                                 int fb_addr, r, g, b;  
                                 color_r = color_g = color_b = 0;  
   
                                 fb_addr = (y * d->xsize + x) * d->bit_depth;  
                                 /*  fb_addr is now which byte in framebuffer  */  
   
                                 /*  > 8 bits color.  */  
                                 fb_addr >>= 3;  
                                 switch (d->bit_depth) {  
                                 case 24:  
                                         r = d->framebuffer[fb_addr];  
                                         g = d->framebuffer[fb_addr + 1];  
                                         b = d->framebuffer[fb_addr + 2];  
                                         break;  
                                 /*  TODO: copy to the scaledown code below  */  
                                 case 16:  
                                         if (d->vfb_type == VFB_HPCMIPS) {  
                                                 b = d->framebuffer[fb_addr] +  
                                                     (d->framebuffer[fb_addr+1] << 8);  
   
                                                 if (d->color32k) {  
                                                         r = b >> 11;  
                                                         g = b >> 5;  
                                                         r = r & 31;  
                                                         g = (g & 31) * 2;  
                                                         b = b & 31;  
                                                 } else {  
                                                         r = (b >> 11) & 0x1f;  
                                                         g = (b >>  5) & 0x3f;  
                                                         b = b & 0x1f;  
                                                 }  
                                         } else {  
                                                 r = d->framebuffer[fb_addr] >> 3;  
                                                 g = (d->framebuffer[fb_addr] << 5) +  
                                                     (d->framebuffer[fb_addr + 1] >> 5);  
                                                 b = d->framebuffer[fb_addr + 1] & 0x1f;  
                                         }  
   
                                         r *= 8;  
                                         g *= 4;  
                                         b *= 8;  
                                         break;  
                                 default:  
                                         r = g = b = random() & 255;  
                                 }  
   
                                 macro_put_pixel();  
                                 x++;  
                         }  
                 }  
   
                 return;  
         }  
319    
320          /*  scaledown != 1:  */  #define REDRAW  redraw_fallback
321    #include "fb_include.c"
322    #undef REDRAW
323    
324    #define FB_24
325    #define REDRAW  redraw_24
326    #include "fb_include.c"
327    #undef REDRAW
328    #undef FB_24
329    #define FB_16
330    #define REDRAW  redraw_16
331    #include "fb_include.c"
332    #undef FB_16
333    #undef REDRAW
334    #define FB_15
335    #define REDRAW  redraw_15
336    #include "fb_include.c"
337    #undef REDRAW
338    #undef FB_15
339    
340    #define FB_BO
341    #define FB_24
342    #define REDRAW  redraw_24_bo
343    #include "fb_include.c"
344    #undef REDRAW
345    #undef FB_24
346    #define FB_16
347    #define REDRAW  redraw_16_bo
348    #include "fb_include.c"
349    #undef FB_16
350    #undef REDRAW
351    #define FB_15
352    #define REDRAW  redraw_15_bo
353    #include "fb_include.c"
354    #undef REDRAW
355    #undef FB_15
356    #undef FB_BO
357    
358    #define FB_SCALEDOWN
359    
360    #define REDRAW  redraw_fallback_sd
361    #include "fb_include.c"
362    #undef REDRAW
363    
364    #define FB_24
365    #define REDRAW  redraw_24_sd
366    #include "fb_include.c"
367    #undef REDRAW
368    #undef FB_24
369    #define FB_16
370    #define REDRAW  redraw_16_sd
371    #include "fb_include.c"
372    #undef FB_16
373    #undef REDRAW
374    #define FB_15
375    #define REDRAW  redraw_15_sd
376    #include "fb_include.c"
377    #undef REDRAW
378    #undef FB_15
379    
380    #define FB_BO
381    #define FB_24
382    #define REDRAW  redraw_24_bo_sd
383    #include "fb_include.c"
384    #undef REDRAW
385    #undef FB_24
386    #define FB_16
387    #define REDRAW  redraw_16_bo_sd
388    #include "fb_include.c"
389    #undef FB_16
390    #undef REDRAW
391    #define FB_15
392    #define REDRAW  redraw_15_bo_sd
393    #include "fb_include.c"
394    #undef REDRAW
395    #undef FB_15
396    #undef FB_BO
397    
398    void (*redraw[2 * 4 * 2])(struct vfb_data *, int, int) = {
399            redraw_fallback, redraw_fallback,
400            redraw_15, redraw_15_bo,
401            redraw_16, redraw_16_bo,
402            redraw_24, redraw_24_bo,
403            redraw_fallback_sd, redraw_fallback_sd,
404            redraw_15_sd, redraw_15_bo_sd,
405            redraw_16_sd, redraw_16_bo_sd,
406            redraw_24_sd, redraw_24_bo_sd  };
407    
408          scaledown = d->vfb_scaledown;  #endif  /*  WITH_X11  */
         scaledownXscaledown = scaledown * scaledown;  
409    
         /*  Which framebuffer pixel does addr correspond to?  */  
         pixel = addr * 8 / d->bit_depth;  
         y = pixel / d->xsize;  
         x = pixel % d->xsize;  
   
         /*  How many framebuffer pixels?  */  
         npixels = len * 8 / d->bit_depth;  
   
         /*  Which x11 pixel?  */  
         x /= scaledown;  
         y /= scaledown;  
   
         /*  How many x11 pixels:  */  
         npixels /= scaledown;  
         if (npixels == 0)  
                 npixels = 1;  
   
         if (d->bit_depth < 8) {  
                 for (pixel=0; pixel<npixels; pixel++) {  
                         int subx, suby, r, g, b;  
                         color_r = color_g = color_b = 0;  
                         for (suby=0; suby<scaledown; suby++)  
                             for (subx=0; subx<scaledown; subx++) {  
                                 int fb_x, fb_y, fb_addr, c;  
   
                                 fb_x = x * scaledown + subx;  
                                 fb_y = y * scaledown + suby;  
                                 fb_addr = fb_y * d->xsize + fb_x;  
                                 fb_addr = fb_addr * d->bit_depth;  
                                 /*  fb_addr is now which _bit_ in  
                                     the framebuffer  */  
   
                                 c = d->framebuffer[fb_addr >> 3];  
                                 fb_addr &= 7;  
   
                                 /*  HPCmips is reverse:  */  
                                 if (d->vfb_type == VFB_HPCMIPS)  
                                         fb_addr = 8 - d->bit_depth - fb_addr;  
   
                                 c = (c >> fb_addr) & ((1<<d->bit_depth) - 1);  
                                 /*  c <<= (8 - d->bit_depth);  */  
   
                                 r = d->rgb_palette[c*3 + 0];  
                                 g = d->rgb_palette[c*3 + 1];  
                                 b = d->rgb_palette[c*3 + 2];  
   
                                 color_r += r;  
                                 color_g += g;  
                                 color_b += b;  
                             }  
   
                         r = color_r / scaledownXscaledown;  
                         g = color_g / scaledownXscaledown;  
                         b = color_b / scaledownXscaledown;  
                         macro_put_pixel();  
                         x++;  
                 }  
         } else if (d->bit_depth == 8) {  
                 for (pixel=0; pixel<npixels; pixel++) {  
                         int subx, suby, r, g, b;  
                         color_r = color_g = color_b = 0;  
                         for (suby=0; suby<scaledown; suby++)  
                             for (subx=0; subx<scaledown; subx++) {  
                                 int fb_x, fb_y, fb_addr, c;  
   
                                 fb_x = x * scaledown + subx;  
                                 fb_y = y * scaledown + suby;  
                                 fb_addr = fb_y * d->xsize + fb_x;  
                                 /*  fb_addr is which _byte_ in framebuffer  */  
                                 c = d->framebuffer[fb_addr] * 3;  
                                 r = d->rgb_palette[c + 0];  
                                 g = d->rgb_palette[c + 1];  
                                 b = d->rgb_palette[c + 2];  
                                 color_r += r;  
                                 color_g += g;  
                                 color_b += b;  
                             }  
   
                         r = color_r / scaledownXscaledown;  
                         g = color_g / scaledownXscaledown;  
                         b = color_b / scaledownXscaledown;  
                         macro_put_pixel();  
                         x++;  
                 }  
         } else {  
                 /*  Generic > 8 bit bit-depth:  */  
                 for (pixel=0; pixel<npixels; pixel++) {  
                         int subx, suby, r, g, b;  
                         color_r = color_g = color_b = 0;  
                         for (suby=0; suby<scaledown; suby++)  
                             for (subx=0; subx<scaledown; subx++) {  
                                 int fb_x, fb_y, fb_addr;  
   
                                 fb_x = x * scaledown + subx;  
                                 fb_y = y * scaledown + suby;  
                                 fb_addr = fb_y * d->xsize + fb_x;  
                                 fb_addr = (fb_addr * d->bit_depth) >> 3;  
                                 /*  fb_addr is which _byte_ in framebuffer  */  
   
                                 /*  > 8 bits color.  */  
                                 switch (d->bit_depth) {  
                                 case 24:  
                                         r = d->framebuffer[fb_addr];  
                                         g = d->framebuffer[fb_addr + 1];  
                                         b = d->framebuffer[fb_addr + 2];  
                                         break;  
                                 default:  
                                         r = g = b = random() & 255;  
                                 }  
                                 color_r += r;  
                                 color_g += g;  
                                 color_b += b;  
                             }  
                         r = color_r / scaledownXscaledown;  
                         g = color_g / scaledownXscaledown;  
                         b = color_b / scaledownXscaledown;  
                         macro_put_pixel();  
                         x++;  
                 }  
         }  
 }  
410    
411    DEVICE_TICK(fb)
 /*  
  *  dev_fb_tick():  
  *  
  */  
 void dev_fb_tick(struct cpu *cpu, void *extra)  
412  {  {
413          struct vfb_data *d = extra;          struct vfb_data *d = extra;
414  #ifdef WITH_X11  #ifdef WITH_X11
# Line 553  void dev_fb_tick(struct cpu *cpu, void * Line 419  void dev_fb_tick(struct cpu *cpu, void *
419          if (!cpu->machine->use_x11)          if (!cpu->machine->use_x11)
420                  return;                  return;
421    
 #ifdef BINTRANS  
422          do {          do {
423                  uint64_t low = -1, high;                  uint64_t high, low = (uint64_t)(int64_t) -1;
424                  int x, y;                  int x, y;
425    
426                  memory_device_bintrans_access(cpu, cpu->mem,                  memory_device_dyntrans_access(cpu, cpu->mem,
427                      extra, &low, &high);                      extra, &low, &high);
428                  if ((int64_t)low == -1)                  if ((int64_t)low == -1)
429                          break;                          break;
# Line 619  void dev_fb_tick(struct cpu *cpu, void * Line 484  void dev_fb_tick(struct cpu *cpu, void *
484                          d->update_x2 = d->xsize-1;                          d->update_x2 = d->xsize-1;
485                  }                  }
486          } while (0);          } while (0);
 #endif  
487    
488  #ifdef WITH_X11  #ifdef WITH_X11
489          /*  Do we need to redraw the cursor?  */          /*  Do we need to redraw the cursor?  */
# Line 631  void dev_fb_tick(struct cpu *cpu, void * Line 495  void dev_fb_tick(struct cpu *cpu, void *
495                  need_to_redraw_cursor = 1;                  need_to_redraw_cursor = 1;
496    
497          if (d->update_x2 != -1) {          if (d->update_x2 != -1) {
498                  if ( (d->update_x1 >= d->fb_window->OLD_cursor_x &&                  if (((d->update_x1 >= d->fb_window->OLD_cursor_x &&
499                        d->update_x1 < (d->fb_window->OLD_cursor_x + d->fb_window->OLD_cursor_xsize)) ||                        d->update_x1 < (d->fb_window->OLD_cursor_x +
500                          d->fb_window->OLD_cursor_xsize)) ||
501                       (d->update_x2 >= d->fb_window->OLD_cursor_x &&                       (d->update_x2 >= d->fb_window->OLD_cursor_x &&
502                        d->update_x2 < (d->fb_window->OLD_cursor_x + d->fb_window->OLD_cursor_xsize)) ||                        d->update_x2 < (d->fb_window->OLD_cursor_x +
503                          d->fb_window->OLD_cursor_xsize)) ||
504                       (d->update_x1 <  d->fb_window->OLD_cursor_x &&                       (d->update_x1 <  d->fb_window->OLD_cursor_x &&
505                        d->update_x2 >= (d->fb_window->OLD_cursor_x + d->fb_window->OLD_cursor_xsize)) ) {                        d->update_x2 >= (d->fb_window->OLD_cursor_x +
506                          if ( (d->update_y1 >= d->fb_window->OLD_cursor_y &&                        d->fb_window->OLD_cursor_xsize)) ) &&
507                                d->update_y1 < (d->fb_window->OLD_cursor_y + d->fb_window->OLD_cursor_ysize)) ||                     ( (d->update_y1 >= d->fb_window->OLD_cursor_y &&
508                               (d->update_y2 >= d->fb_window->OLD_cursor_y &&                        d->update_y1 < (d->fb_window->OLD_cursor_y +
509                                d->update_y2 < (d->fb_window->OLD_cursor_y + d->fb_window->OLD_cursor_ysize)) ||                        d->fb_window->OLD_cursor_ysize)) ||
510                               (d->update_y1 <  d->fb_window->OLD_cursor_y &&                       (d->update_y2 >= d->fb_window->OLD_cursor_y &&
511                                d->update_y2 >= (d->fb_window->OLD_cursor_y + d->fb_window->OLD_cursor_ysize)) )                        d->update_y2 < (d->fb_window->OLD_cursor_y +
512                                  need_to_redraw_cursor = 1;                        d->fb_window->OLD_cursor_ysize)) ||
513                  }                       (d->update_y1 <  d->fb_window->OLD_cursor_y &&
514                          d->update_y2 >= (d->fb_window->OLD_cursor_y +
515                         d->fb_window->OLD_cursor_ysize)) ) )
516                            need_to_redraw_cursor = 1;
517          }          }
518    
519          if (need_to_redraw_cursor) {          if (need_to_redraw_cursor) {
# Line 658  void dev_fb_tick(struct cpu *cpu, void * Line 527  void dev_fb_tick(struct cpu *cpu, void *
527                              d->fb_window->OLD_cursor_x/d->vfb_scaledown,                              d->fb_window->OLD_cursor_x/d->vfb_scaledown,
528                              d->fb_window->OLD_cursor_y/d->vfb_scaledown,                              d->fb_window->OLD_cursor_y/d->vfb_scaledown,
529                              d->fb_window->OLD_cursor_xsize/d->vfb_scaledown + 1,                              d->fb_window->OLD_cursor_xsize/d->vfb_scaledown + 1,
530                              d->fb_window->OLD_cursor_ysize/d->vfb_scaledown + 1);                              d->fb_window->OLD_cursor_ysize/d->vfb_scaledown +1);
531                  }                  }
532          }          }
533  #endif  #endif
534    
535          if (d->update_x2 != -1) {          if (d->update_x2 != -1) {
536                  int y, addr, addr2, q = d->vfb_scaledown;  #ifdef WITH_X11
537                    int y;
538    #endif
539                    int addr, addr2, q = d->vfb_scaledown;
540    
541                  if (d->update_x1 >= d->visible_xsize)   d->update_x1 = d->visible_xsize - 1;                  if (d->update_x1 >= d->visible_xsize)
542                  if (d->update_x2 >= d->visible_xsize)   d->update_x2 = d->visible_xsize - 1;                          d->update_x1 = d->visible_xsize - 1;
543                  if (d->update_y1 >= d->visible_ysize)   d->update_y1 = d->visible_ysize - 1;                  if (d->update_x2 >= d->visible_xsize)
544                  if (d->update_y2 >= d->visible_ysize)   d->update_y2 = d->visible_ysize - 1;                          d->update_x2 = d->visible_xsize - 1;
545                    if (d->update_y1 >= d->visible_ysize)
546                            d->update_y1 = d->visible_ysize - 1;
547                    if (d->update_y2 >= d->visible_ysize)
548                            d->update_y2 = d->visible_ysize - 1;
549    
550                  /*  Without these, we might miss the right most / bottom pixel:  */                  /*  Without these, we might miss the rightmost/bottom pixel:  */
551                  d->update_x2 += (q - 1);                  d->update_x2 += (q - 1);
552                  d->update_y2 += (q - 1);                  d->update_y2 += (q - 1);
553    
# Line 680  void dev_fb_tick(struct cpu *cpu, void * Line 556  void dev_fb_tick(struct cpu *cpu, void *
556                  d->update_y1 = d->update_y1 / q * q;                  d->update_y1 = d->update_y1 / q * q;
557                  d->update_y2 = d->update_y2 / q * q;                  d->update_y2 = d->update_y2 / q * q;
558    
559                  addr  = d->update_y1 * d->bytes_per_line + d->update_x1 * d->bit_depth / 8;                  addr  = d->update_y1 * d->bytes_per_line +
560                  addr2 = d->update_y1 * d->bytes_per_line + d->update_x2 * d->bit_depth / 8;                      d->update_x1 * d->bit_depth / 8;
561                    addr2 = d->update_y1 * d->bytes_per_line +
562                        d->update_x2 * d->bit_depth / 8;
563    
564    #ifdef WITH_X11
565                  for (y=d->update_y1; y<=d->update_y2; y+=q) {                  for (y=d->update_y1; y<=d->update_y2; y+=q) {
566                          update_framebuffer(d, addr, addr2 - addr);                          d->redraw_func(d, addr, addr2 - addr);
567                          addr  += d->bytes_per_line * q;                          addr  += d->bytes_per_line * q;
568                          addr2 += d->bytes_per_line * q;                          addr2 += d->bytes_per_line * q;
569                  }                  }
570    
571  #ifdef WITH_X11                  XPutImage(d->fb_window->x11_display, d->fb_window->
572                  XPutImage(d->fb_window->x11_display, d->fb_window->x11_fb_window, d->fb_window->x11_fb_gc, d->fb_window->fb_ximage,                      x11_fb_window, d->fb_window->x11_fb_gc, d->fb_window->
573                      d->update_x1/d->vfb_scaledown, d->update_y1/d->vfb_scaledown,                      fb_ximage, d->update_x1/d->vfb_scaledown, d->update_y1/
574                      d->update_x1/d->vfb_scaledown, d->update_y1/d->vfb_scaledown,                      d->vfb_scaledown, d->update_x1/d->vfb_scaledown,
575                        d->update_y1/d->vfb_scaledown,
576                      (d->update_x2 - d->update_x1)/d->vfb_scaledown + 1,                      (d->update_x2 - d->update_x1)/d->vfb_scaledown + 1,
577                      (d->update_y2 - d->update_y1)/d->vfb_scaledown + 1);                      (d->update_y2 - d->update_y1)/d->vfb_scaledown + 1);
578    
# Line 707  void dev_fb_tick(struct cpu *cpu, void * Line 587  void dev_fb_tick(struct cpu *cpu, void *
587          if (need_to_redraw_cursor) {          if (need_to_redraw_cursor) {
588                  /*  Paint new cursor:  */                  /*  Paint new cursor:  */
589                  if (d->fb_window->cursor_on) {                  if (d->fb_window->cursor_on) {
590                          x11_redraw_cursor(cpu->machine, d->fb_window->fb_number);                          x11_redraw_cursor(cpu->machine,
591                                d->fb_window->fb_number);
592                          d->fb_window->OLD_cursor_on = d->fb_window->cursor_on;                          d->fb_window->OLD_cursor_on = d->fb_window->cursor_on;
593                          d->fb_window->OLD_cursor_x = d->fb_window->cursor_x;                          d->fb_window->OLD_cursor_x = d->fb_window->cursor_x;
594                          d->fb_window->OLD_cursor_y = d->fb_window->cursor_y;                          d->fb_window->OLD_cursor_y = d->fb_window->cursor_y;
595                          d->fb_window->OLD_cursor_xsize = d->fb_window->cursor_xsize;                          d->fb_window->OLD_cursor_xsize = d->fb_window->
596                          d->fb_window->OLD_cursor_ysize = d->fb_window->cursor_ysize;                              cursor_xsize;
597                            d->fb_window->OLD_cursor_ysize = d->fb_window->
598                                cursor_ysize;
599                            need_to_flush_x11 = 1;
600                  }                  }
601          }          }
602  #endif  #endif
# Line 724  void dev_fb_tick(struct cpu *cpu, void * Line 608  void dev_fb_tick(struct cpu *cpu, void *
608  }  }
609    
610    
611  /*  DEVICE_ACCESS(fb)
  *  dev_fb_access():  
  */  
 int dev_fb_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
612  {  {
613          struct vfb_data *d = extra;          struct vfb_data *d = extra;
614          int i;          size_t i;
615    
616  #ifdef FB_DEBUG  #ifdef FB_DEBUG
617          if (writeflag == MEM_WRITE) { if (data[0]) {          if (writeflag == MEM_WRITE) { if (data[0]) {
# Line 750  int dev_fb_access(struct cpu *cpu, struc Line 629  int dev_fb_access(struct cpu *cpu, struc
629          }          }
630  #endif  #endif
631    
632            if (relative_addr >= d->framebuffer_size)
633                    return 0;
634    
635          /*  See if a write actually modifies the framebuffer contents:  */          /*  See if a write actually modifies the framebuffer contents:  */
636          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
637                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
# Line 758  int dev_fb_access(struct cpu *cpu, struc Line 640  int dev_fb_access(struct cpu *cpu, struc
640    
641                          /*  If all bytes are equal to what is already stored                          /*  If all bytes are equal to what is already stored
642                              in the framebuffer, then simply return:  */                              in the framebuffer, then simply return:  */
643                          if (i==len-1)                          if (i == len-1)
644                                  return 1;                                  return 1;
645                  }                  }
646          }          }
# Line 817  int dev_fb_access(struct cpu *cpu, struc Line 699  int dev_fb_access(struct cpu *cpu, struc
699          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
700                  if (len > 8)                  if (len > 8)
701                          memcpy(d->framebuffer + relative_addr, data, len);                          memcpy(d->framebuffer + relative_addr, data, len);
702                  else                  else {
703                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
704                                  d->framebuffer[relative_addr + i] = data[i];                                  d->framebuffer[relative_addr + i] = data[i];
705                    }
706          } else {          } else {
707                  if (len > 8)                  if (len > 8)
708                          memcpy(data, d->framebuffer + relative_addr, len);                          memcpy(data, d->framebuffer + relative_addr, len);
709                  else                  else {
710                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
711                                  data[i] = d->framebuffer[relative_addr + i];                                  data[i] = d->framebuffer[relative_addr + i];
712                    }
713          }          }
714    
715          return 1;          return 1;
# Line 835  int dev_fb_access(struct cpu *cpu, struc Line 719  int dev_fb_access(struct cpu *cpu, struc
719  /*  /*
720   *  dev_fb_init():   *  dev_fb_init():
721   *   *
722   *  xsize and ysize are ignored if vfb_type is VFB_DEC_VFB01 or 02.   *  This function is big and ugly, but the point is to initialize a framebuffer
723     *  device. :-)
724     *
725     *  visible_xsize and visible_ysize are the sizes of the visible display area.
726     *  xsize and ysize tell how much memory is actually allocated (for example
727     *  visible_xsize could be 640, but xsize could be 1024, for better alignment).
728     *
729     *  vfb_type is useful for selecting special features.
730     *
731     *  type = VFB_GENERIC is the most useful type, especially when bit_depth = 24.
732     *
733     *  VFB_DEC_VFB01, _VFB02, and VFB_DEC_MAXINE are DECstation specific.
734     *
735     *  VFB_HPC is like generic, but the color encoding is done as on HPCmips
736     *  and Dreamcast.
737     *
738     *  If bit_depth = -15 (note the minus sign), then a special hack is used for
739     *  the Playstation Portable's 5-bit R, 5-bit G, 5-bit B.
740   */   */
741  struct vfb_data *dev_fb_init(struct machine *machine, struct memory *mem,  struct vfb_data *dev_fb_init(struct machine *machine, struct memory *mem,
742          uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize,          uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize,
743          int xsize, int ysize, int bit_depth, char *name, int logo)          int xsize, int ysize, int bit_depth, char *name)
744  {  {
745          struct vfb_data *d;          struct vfb_data *d;
746          size_t size;          size_t size, nlen;
         int x, y;  
         char title[400];  
         char *name2;  
747          int flags;          int flags;
748            int reverse_start = 0;
749            char *name2;
750    
751          d = malloc(sizeof(struct vfb_data));          d = malloc(sizeof(struct vfb_data));
752          if (d == NULL) {          if (d == NULL) {
# Line 855  struct vfb_data *dev_fb_init(struct mach Line 755  struct vfb_data *dev_fb_init(struct mach
755          }          }
756          memset(d, 0, sizeof(struct vfb_data));          memset(d, 0, sizeof(struct vfb_data));
757    
758            if (vfb_type & VFB_REVERSE_START) {
759                    vfb_type &= ~VFB_REVERSE_START;
760                    reverse_start = 1;
761            }
762    
763            d->memory = mem;
764          d->vfb_type = vfb_type;          d->vfb_type = vfb_type;
765    
766          /*  Defaults:  */          /*  Defaults:  */
# Line 866  struct vfb_data *dev_fb_init(struct mach Line 772  struct vfb_data *dev_fb_init(struct mach
772          if (bit_depth == 15) {          if (bit_depth == 15) {
773                  d->color32k = 1;                  d->color32k = 1;
774                  bit_depth = d->bit_depth = 16;                  bit_depth = d->bit_depth = 16;
775            } else if (bit_depth == -15) {
776                    d->psp_15bit = 1;
777                    bit_depth = d->bit_depth = 16;
778          }          }
779    
780          /*  Specific types:  */          /*  Specific types:  */
# Line 894  struct vfb_data *dev_fb_init(struct mach Line 803  struct vfb_data *dev_fb_init(struct mach
803                  d->ysize = ysize;  d->visible_ysize = d->ysize;                  d->ysize = ysize;  d->visible_ysize = d->ysize;
804                  d->bit_depth = 24;                  d->bit_depth = 24;
805                  break;                  break;
         default:  
                 ;  
806          }          }
807    
808          if (d->bit_depth == 2 || d->bit_depth == 4)          if (d->bit_depth == 2 || d->bit_depth == 4)
# Line 916  struct vfb_data *dev_fb_init(struct mach Line 823  struct vfb_data *dev_fb_init(struct mach
823    
824          /*  Clear the framebuffer (all black pixels):  */          /*  Clear the framebuffer (all black pixels):  */
825          d->framebuffer_size = size;          d->framebuffer_size = size;
826          memset(d->framebuffer, 0, size);          memset(d->framebuffer, reverse_start? 255 : 0, size);
827    
828          d->x11_xsize = d->visible_xsize / d->vfb_scaledown;          d->x11_xsize = d->visible_xsize / d->vfb_scaledown;
829          d->x11_ysize = d->visible_ysize / d->vfb_scaledown;          d->x11_ysize = d->visible_ysize / d->vfb_scaledown;
830    
831          d->update_x1 = d->update_y1 = 99999;          /*  Only "update" from the start if we need to fill with white.  */
832          d->update_x2 = d->update_y2 = -1;          /*  (The Ximage will be black from the start anyway.)  */
833            if (reverse_start) {
834                    d->update_x1 = d->update_y1 = 0;
835          /*  A nice bootup logo:  */                  d->update_x2 = d->xsize - 1;
836          if (logo) {                  d->update_y2 = d->ysize - 1;
837                  int logo_bottom_margin = LOGO_BOTTOM_MARGIN;          } else {
838                    d->update_x1 = d->update_y1 = 99999;
839                  d->update_x1 = 0;                  d->update_x2 = d->update_y2 = -1;
                 d->update_x2 = LOGO_XSIZE-1;  
                 d->update_y1 = d->visible_ysize-LOGO_YSIZE-logo_bottom_margin;  
                 d->update_y2 = d->visible_ysize-logo_bottom_margin;  
                 for (y=0; y<LOGO_YSIZE; y++)  
                         for (x=0; x<LOGO_XSIZE; x++) {  
                                 int s, a = ((y + d->visible_ysize - LOGO_YSIZE  
                                     - logo_bottom_margin)*d->xsize + x)  
                                     * d->bit_depth / 8;  
                                 int b = fb_logo[(y*LOGO_XSIZE+x) / 8] &  
                                     (128 >> (x&7));  
                                 for (s=0; s<d->bit_depth / 8; s++)  
                                         d->framebuffer[a+s] = b? 0 : 255;  
                         }  
840          }          }
841    
842          snprintf(title, sizeof(title), "GXemul: %ix%ix%i %s framebuffer",          d->name = strdup(name);
843              d->visible_xsize, d->visible_ysize, d->bit_depth, name);          set_title(d);
         title[sizeof(title)-1] = '\0';  
844    
845  #ifdef WITH_X11  #ifdef WITH_X11
846          if (machine->use_x11)          if (machine->use_x11) {
847                    int i = 0;
848                  d->fb_window = x11_fb_init(d->x11_xsize, d->x11_ysize,                  d->fb_window = x11_fb_init(d->x11_xsize, d->x11_ysize,
849                      title, machine->x11_scaledown, machine);                      d->title, machine->x11_scaledown, machine);
850          else                  switch (d->fb_window->x11_screen_depth) {
851                    case 15: i = 2; break;
852                    case 16: i = 4; break;
853                    case 24: i = 6; break;
854                    }
855                    if (d->fb_window->fb_ximage->byte_order)
856                            i ++;
857                    if (d->vfb_scaledown > 1)
858                            i += 8;
859                    d->redraw_func = redraw[i];
860            } else
861  #endif  #endif
862                  d->fb_window = NULL;                  d->fb_window = NULL;
863    
864          name2 = malloc(strlen(name) + 10);          nlen = strlen(name) + 10;
865            name2 = malloc(nlen);
866          if (name2 == NULL) {          if (name2 == NULL) {
867                  fprintf(stderr, "out of memory in dev_fb_init()\n");                  fprintf(stderr, "out of memory in dev_fb_init()\n");
868                  exit(1);                  exit(1);
869          }          }
870          sprintf(name2, "fb [%s]", name);          snprintf(name2, nlen, "fb [%s]", name);
871    
872          flags = MEM_DEFAULT;          flags = DM_DEFAULT;
873          if ((baseaddr & 0xfff) == 0)          if ((baseaddr & 0xfff) == 0)
874                  flags = MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK;                  flags = DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK;
875    
876            flags |= DM_READS_HAVE_NO_SIDE_EFFECTS;
877    
878          memory_device_register(mem, name2, baseaddr, size, dev_fb_access,          memory_device_register(mem, name2, baseaddr, size, dev_fb_access,
879              d, flags, d->framebuffer);              d, flags, d->framebuffer);
880    
881          machine_add_tickfunction(machine, dev_fb_tick, d, FB_TICK_SHIFT);          machine_add_tickfunction(machine, dev_fb_tick, d, FB_TICK_SHIFT, 0.0);
882          return d;          return d;
883  }  }
884    

Legend:
Removed from v.4  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26