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

Subversion Repositories eco32

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

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

powered by: WebSVN 2.1.0

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