OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [graph.c] - Blame information for rev 274

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 hellwig
/*
2
 * graph.c -- graphics controller simulation
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <setjmp.h>
10
 
11
#include "common.h"
12
#include "console.h"
13
#include "error.h"
14
#include "except.h"
15
#include "graph.h"
16
 
17
 
18
static Bool debug = false;
19 251 hellwig
static Bool volatile installed = false;
20 8 hellwig
 
21
 
22
/**************************************************************/
23
/**************************************************************/
24
 
25
/* common definitions, global variables */
26
 
27
 
28
#include <pthread.h>
29
#include <unistd.h>
30
#include <time.h>
31
#include <X11/Xlib.h>
32
#include <X11/Xutil.h>
33
#include <X11/Xatom.h>
34
 
35
 
36
#define WINDOW_SIZE_X           640
37
#define WINDOW_SIZE_Y           480
38
#define WINDOW_POS_X            100
39
#define WINDOW_POS_Y            100
40
 
41
 
42
#define C2B(c,ch)               (((((c) & 0xFF) * ch.scale) >> 8) * ch.factor)
43 251 hellwig
#define RGB2PIXEL(r,g,b)        (0xFF000000 | \
44
                                 C2B(r, vga.red) | \
45 8 hellwig
                                 C2B(g, vga.green) | \
46
                                 C2B(b, vga.blue))
47
 
48
 
49
typedef struct {
50
  unsigned long scale;
51
  unsigned long factor;
52
} ColorChannel;
53
 
54
 
55
typedef struct {
56
  int argc;
57
  char **argv;
58
  Display *display;
59
  Window win;
60
  GC gc;
61
  XImage *image;
62
  ColorChannel red, green, blue;
63
  XExposeEvent expose;
64
  XClientMessageEvent shutdown;
65
} VGA;
66
 
67
 
68
static VGA vga;
69
 
70
 
71
/**************************************************************/
72
 
73
/* monitor server */
74
 
75
 
76
static ColorChannel mask2channel(unsigned long mask) {
77
  unsigned long f;
78
  ColorChannel ch;
79
 
80
  if (mask == 0) {
81
    error("color mask is 0 in mask2channel");
82
  }
83
  for (f = 1; (mask & 1) == 0; f <<= 1) {
84
    mask >>= 1;
85
  }
86
  ch.factor = f;
87
  ch.scale = mask + 1;
88
  while ((mask & 1) != 0) {
89
    mask >>= 1;
90
  }
91
  if (mask != 0) {
92
    error("scattered color mask bits in mask2channel");
93
  }
94
  return ch;
95
}
96
 
97
 
98
static void initMonitor(int argc, char *argv[]) {
99
  int screenNum;
100
  Window rootWin;
101
  XVisualInfo visualTemp;
102
  XVisualInfo *visualInfo;
103
  int visualCount;
104
  int bestMatch;
105
  int bestDepth;
106
  Visual *visual;
107
  int i;
108
  unsigned long pixel;
109
  int x, y;
110
  Colormap colormap;
111
  XSetWindowAttributes attrib;
112
  XSizeHints *sizeHints;
113
  XWMHints *wmHints;
114
  XClassHint *classHints;
115
  XTextProperty windowName;
116
  XGCValues gcValues;
117
 
118
  /* connect to X server */
119
  if (XInitThreads() == 0) {
120
    error("no thread support for X11");
121
  }
122
  vga.display = XOpenDisplay(NULL);
123
  if (vga.display == NULL) {
124
    error("cannot connect to X server");
125
  }
126
  screenNum = DefaultScreen(vga.display);
127
  rootWin = RootWindow(vga.display, screenNum);
128
  /* find TrueColor visual */
129
  visualTemp.screen = screenNum;
130
  visualTemp.class = TrueColor;
131
  visualInfo = XGetVisualInfo(vga.display,
132
                              VisualClassMask | VisualScreenMask,
133
                              &visualTemp, &visualCount);
134
  if (visualInfo == NULL || visualCount == 0) {
135
    error("no TrueColor visual found");
136
  }
137
  bestMatch = 0;
138
  bestDepth = visualInfo[0].depth;
139
  visual = visualInfo[0].visual;
140
  for (i = 1; i < visualCount; i++) {
141
    if (visualInfo[i].depth > bestDepth) {
142
      bestMatch = i;
143
      bestDepth = visualInfo[i].depth;
144
      visual = visualInfo[i].visual;
145
    }
146
  }
147
  /* build color channels */
148
  vga.red = mask2channel(visualInfo[bestMatch].red_mask);
149
  vga.green = mask2channel(visualInfo[bestMatch].green_mask);
150
  vga.blue = mask2channel(visualInfo[bestMatch].blue_mask);
151
  /* create and initialize image */
152
  vga.image = XCreateImage(vga.display, visual, bestDepth, ZPixmap,
153
                           0, NULL, WINDOW_SIZE_X, WINDOW_SIZE_Y, 32, 0);
154
  if (vga.image == NULL) {
155
    error("cannot allocate image");
156
  }
157
  vga.image->data = malloc(vga.image->height * vga.image->bytes_per_line);
158
  if (vga.image->data == NULL) {
159
    error("cannot allocate image memory");
160
  }
161
  pixel = RGB2PIXEL(0, 0, 0);
162
  for (y = 0; y < WINDOW_SIZE_Y; y++) {
163
    for (x = 0; x < WINDOW_SIZE_X; x++) {
164
      XPutPixel(vga.image, x, y, pixel);
165
    }
166
  }
167
  /* allocate a colormap */
168
  colormap = XCreateColormap(vga.display, rootWin, visual, AllocNone);
169
  /* create the window */
170
  attrib.colormap = colormap;
171
  attrib.event_mask = ExposureMask;
172
  attrib.background_pixel = RGB2PIXEL(0, 0, 0);
173
  attrib.border_pixel = RGB2PIXEL(0, 0, 0);
174
  vga.win =
175
    XCreateWindow(vga.display, rootWin,
176
                  WINDOW_POS_X, WINDOW_POS_Y,
177
                  WINDOW_SIZE_X, WINDOW_SIZE_Y,
178
                  0, bestDepth, InputOutput, visual,
179
                  CWEventMask | CWColormap | CWBackPixel | CWBorderPixel,
180
                  &attrib);
181
  /* give hints to window manager */
182
  sizeHints = XAllocSizeHints();
183
  wmHints = XAllocWMHints();
184
  classHints = XAllocClassHint();
185
  if (sizeHints == NULL ||
186
      wmHints == NULL ||
187
      classHints == NULL) {
188
    error("hint allocation failed");
189
  }
190
  sizeHints->flags = PMinSize | PMaxSize;
191
  sizeHints->min_width = WINDOW_SIZE_X;
192
  sizeHints->min_height = WINDOW_SIZE_Y;
193
  sizeHints->max_width = WINDOW_SIZE_X;
194
  sizeHints->max_height = WINDOW_SIZE_Y;
195
  wmHints->flags = StateHint | InputHint;
196
  wmHints->input = True;
197
  wmHints->initial_state = NormalState;
198
  classHints->res_name = "ECO32";
199
  classHints->res_class = "ECO32";
200
  if (XStringListToTextProperty(&classHints->res_name, 1, &windowName) == 0) {
201
    error("property allocation failed");
202
  }
203
  XSetWMProperties(vga.display, vga.win, &windowName, NULL,
204
                   argv, argc, sizeHints, wmHints, classHints);
205
  /* create a GC */
206
  vga.gc = XCreateGC(vga.display, vga.win, 0, &gcValues);
207
  /* finally get the window displayed */
208
  XMapWindow(vga.display, vga.win);
209
  /* prepare expose event */
210
  vga.expose.type = Expose;
211
  vga.expose.display = vga.display;
212
  vga.expose.window = vga.win;
213
  vga.expose.x = 0;
214
  vga.expose.y = 0;
215
  vga.expose.width = WINDOW_SIZE_X;
216
  vga.expose.height = WINDOW_SIZE_Y;
217
  vga.expose.count = 0;
218
  /* prepare shutdown event */
219
  vga.shutdown.type = ClientMessage;
220
  vga.shutdown.display = vga.display;
221
  vga.shutdown.window = vga.win;
222
  vga.shutdown.message_type = XA_WM_COMMAND;
223 251 hellwig
  vga.shutdown.format = 8;
224 8 hellwig
  /* say that the graphics controller is installed */
225
  XSync(vga.display, False);
226
  installed = true;
227
}
228
 
229
 
230
static void exitMonitor(void) {
231
  XFreeGC(vga.display, vga.gc);
232
  XUnmapWindow(vga.display, vga.win);
233
  XDestroyWindow(vga.display, vga.win);
234
  XDestroyImage(vga.image);
235
  XCloseDisplay(vga.display);
236
  installed = false;
237
}
238
 
239
 
240
static int ioErrorHandler(Display *display) {
241
  error("connection to monitor window lost");
242
  /* never reached */
243
  return 0;
244
}
245
 
246
 
247
static void *server(void *ignore) {
248
  Bool run;
249
  XEvent event;
250
 
251
  initMonitor(vga.argc, vga.argv);
252
  XSetIOErrorHandler(ioErrorHandler);
253
  run = true;
254
  while (run) {
255
    XNextEvent(vga.display, &event);
256
    switch (event.type) {
257
      case Expose:
258
        XPutImage(vga.display, vga.win, vga.gc, vga.image,
259
                  event.xexpose.x, event.xexpose.y,
260
                  event.xexpose.x, event.xexpose.y,
261
                  event.xexpose.width, event.xexpose.height);
262
        break;
263
      case ClientMessage:
264
        if (event.xclient.message_type == XA_WM_COMMAND &&
265 251 hellwig
            event.xclient.format == 8) {
266 8 hellwig
          run = false;
267
        }
268
        break;
269
      default:
270
        break;
271
    }
272
  }
273
  exitMonitor();
274
  return NULL;
275
}
276
 
277
 
278
/**************************************************************/
279
 
280
/* refresh timer */
281
 
282
 
283 251 hellwig
static Bool volatile refreshRunning = false;
284 8 hellwig
 
285
 
286
static void *refresh(void *ignore) {
287
  struct timespec delay;
288
 
289
  while (refreshRunning) {
290
    XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.expose);
291
    XFlush(vga.display);
292
    delay.tv_sec = 0;
293
    delay.tv_nsec = 100 * 1000 * 1000;
294
    nanosleep(&delay, &delay);
295
  }
296
  return NULL;
297
}
298
 
299
 
300
/**************************************************************/
301
 
302
/* server interface */
303
 
304
 
305
static int myArgc = 1;
306
static char *myArgv[] = {
307
  "eco32",
308
  NULL
309
};
310
 
311 251 hellwig
static pthread_t monitorThread;
312
static pthread_t refreshThread;
313 8 hellwig
 
314 251 hellwig
 
315 8 hellwig
static void vgaInit(void) {
316
  /* start monitor server in a separate thread */
317
  vga.argc = myArgc;
318
  vga.argv = myArgv;
319 251 hellwig
  if (pthread_create(&monitorThread, NULL, server, NULL) != 0) {
320 8 hellwig
    error("cannot start monitor server");
321
  }
322 251 hellwig
  while (!installed) ;
323 8 hellwig
  /* start refresh timer in another thread */
324
  refreshRunning = true;
325 251 hellwig
  if (pthread_create(&refreshThread, NULL, refresh, NULL) != 0) {
326 8 hellwig
    error("cannot start refresh timer");
327
  }
328
}
329
 
330
 
331
static void vgaExit(void) {
332
  refreshRunning = false;
333 251 hellwig
  pthread_join(refreshThread, NULL);
334 8 hellwig
  XSendEvent(vga.display, vga.win, False, 0, (XEvent *) &vga.shutdown);
335
  XSync(vga.display, False);
336 251 hellwig
  pthread_join(monitorThread, NULL);
337 8 hellwig
}
338
 
339
 
340
static void vgaWrite(int x, int y, int r, int g, int b) {
341
  XPutPixel(vga.image, x, y, RGB2PIXEL(r, g, b));
342
}
343
 
344
 
345
/**************************************************************/
346
/**************************************************************/
347
 
348
 
349
#define BACKGROUND              0
350
#define FOREGROUND              1
351
 
352
 
353
static int colors[2] = {
354
  0x007CD4D6,                   /* background */
355
  0x00000000                    /* foreground */
356
};
357
 
358
 
359
static int splashData[] = {
360
#include "grsplash"
361
};
362
 
363
 
364
static void loadSplashScreen(void) {
365
  int sum, i;
366
  int count;
367
  int plane;
368
  int x, y;
369
  int r, g, b;
370
 
371
  /* check splash data */
372
  sum = 0;
373
  for (i = 0; i < sizeof(splashData)/sizeof(splashData[0]); i++) {
374
    sum += splashData[i];
375
  }
376
  if (sum != WINDOW_SIZE_X * WINDOW_SIZE_Y) {
377
    return;
378
  }
379
  /* display splash data */
380
  count = 0;
381
  plane = FOREGROUND;
382
  i = 0;
383
  for (y = 0; y < WINDOW_SIZE_Y; y++) {
384
    for (x = 0; x < WINDOW_SIZE_X; x++) {
385
      while (count == 0) {
386
        plane = (plane == BACKGROUND ? FOREGROUND : BACKGROUND);
387
        r = (colors[plane] >> 16) & 0xFF;
388
        g = (colors[plane] >>  8) & 0xFF;
389
        b = (colors[plane] >>  0) & 0xFF;
390
        count = splashData[i++];
391
      }
392
      count--;
393
      vgaWrite(x, y, r, g, b);
394
    }
395
  }
396
}
397
 
398
 
399
/**************************************************************/
400
 
401
 
402
Word graphRead(Word addr) {
403
  Word data;
404
 
405
  if (debug) {
406
    cPrintf("\n**** GRAPH READ from 0x%08X", addr);
407
  }
408
  if (!installed) {
409
    throwException(EXC_BUS_TIMEOUT);
410
  }
411
  if (addr >= WINDOW_SIZE_X * WINDOW_SIZE_Y * 4) {
412
    throwException(EXC_BUS_TIMEOUT);
413
  }
414
  /* the frame buffer memory yields 0 on every read */
415
  data = 0;
416
  if (debug) {
417
    cPrintf(", data = 0x%08X ****\n", data);
418
  }
419
  return data;
420
}
421
 
422
 
423
void graphWrite(Word addr, Word data) {
424
  if (debug) {
425
    cPrintf("\n**** GRAPH WRITE to 0x%08X, data = 0x%08X ****\n",
426
            addr, data);
427
  }
428
  if (!installed) {
429
    throwException(EXC_BUS_TIMEOUT);
430
  }
431
  if (addr >= WINDOW_SIZE_X * WINDOW_SIZE_Y * 4) {
432
    throwException(EXC_BUS_TIMEOUT);
433
  }
434
  /* write to frame buffer memory */
435
  vgaWrite((addr >> 2) % WINDOW_SIZE_X,
436
           (addr >> 2) / WINDOW_SIZE_X,
437
           (data >> 16) & 0xFF,
438
           (data >>  8) & 0xFF,
439
           (data >>  0) & 0xFF);
440
}
441
 
442
 
443
void graphReset(void) {
444
  if (!installed) {
445
    return;
446
  }
447
  cPrintf("Resetting Graphics...\n");
448
  loadSplashScreen();
449
}
450
 
451
 
452
void graphInit(void) {
453
  vgaInit();
454
  graphReset();
455
}
456
 
457
 
458
void graphExit(void) {
459
  if (!installed) {
460
    return;
461
  }
462
  vgaExit();
463
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.