source: abuse/branches/pd/imlib/port/gl/video.c @ 528

Last change on this file since 528 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 8.5 KB
Line 
1
2#include <sys/time.h>
3#include <sys/types.h>
4#include <unistd.h>
5#include <signal.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9#include <sys/ipc.h>
10#include <sys/shm.h>
11#include <X11/Xlib.h>
12#include <X11/Xutil.h>
13#include <X11/Xatom.h>
14#include <X11/keysym.h>
15#include <X11/extensions/XShm.h>
16#include <GL/gl.h>
17#include <GL/glx.h>
18#include <GL/glu.h>
19
20#include "globals.hpp"
21#include "system.h"
22#include "video.hpp"
23#include "dos.h"
24#include "macs.hpp"
25#include "image.hpp"
26#include "palette.hpp"
27#include "jmalloc.hpp"
28
29image *screen=NULL;
30static ulong *frame_buffer=NULL;
31
32uchar current_background=0;
33
34typedef struct
35{
36        int input;
37        int output;
38} keymap_t;
39
40static float xs;
41static float ys;
42
43Display                 *display;
44static Colormap                 x_cmap;
45Window                  mainwin;
46static GC                               x_gc;
47static Visual                   *my_visual;
48static XVisualInfo              *x_visinfo=0;
49//static XImage                 *x_image;
50static int                              x_screen;
51
52static int                      oktodraw = 0;
53
54static unsigned char    *framebuffer=0;
55
56static int verbose=0;
57
58static short *jcspace=0;
59
60static int                      doGLX;
61static int glX_errorBase, glX_eventBase;
62static GLXContext glX_context;
63
64static int                      glX_scaled=0;
65static GLfloat                  glX_scale_width;
66static GLfloat                  glX_scale_height;
67
68static int config_notify=0;
69static int config_notify_width;
70static int config_notify_height;
71int win_xres,win_yres;
72
73
74void PickVisual()
75{
76  int attribList1[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8,
77                        GLX_BLUE_SIZE, 8, GLX_GREEN_SIZE, 8, None };
78  int attribList2[] = { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8,
79                        GLX_BLUE_SIZE, 8, None };
80
81  doGLX = glXQueryExtension(display, &glX_errorBase, &glX_eventBase);
82  if (!doGLX) { printf("OpenGL not supported\n"); exit(0); }
83
84  x_visinfo = glXChooseVisual(display, x_screen, attribList1);
85  if (!x_visinfo)
86    x_visinfo = glXChooseVisual(display, x_screen, attribList2);
87  else
88    printf("double-buffered\n");
89
90  if (!x_visinfo)
91  { printf("Could not chose an RGB visual.  Use X version.\n");  exit(0); }   
92  else
93    printf("single-buffered\n");
94
95  my_visual = x_visinfo->visual;
96}
97
98
99// ========================================================================
100// makes a null cursor
101// ========================================================================
102
103static Cursor CreateNullCursor(Display *display, Window root)
104{
105    Pixmap cursormask;
106    XGCValues xgc;
107    GC gc;
108    XColor dummycolour;
109    Cursor cursor;
110
111    cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
112    xgc.function = GXclear;
113    gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
114    XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
115    dummycolour.pixel = 0;
116    dummycolour.red = 0;
117    dummycolour.flags = 04;
118    cursor = XCreatePixmapCursor(display, cursormask, cursormask,
119          &dummycolour,&dummycolour, 0,0);
120    XFreePixmap(display,cursormask);
121    XFreeGC(display,gc);
122    return cursor;
123}
124
125void CreateWindow(void)
126{
127
128  // setup attributes for main window
129  int attribmask = CWEventMask  | CWColormap | CWBorderPixel;
130  XSetWindowAttributes attribs;
131  Colormap tmpcmap;
132
133  tmpcmap = XCreateColormap(display, XRootWindow(display,
134                                                x_visinfo->screen), my_visual, AllocNone);
135
136  attribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask;
137  attribs.border_pixel = 0;
138  attribs.colormap = tmpcmap;
139
140  // create the main window
141  mainwin = XCreateWindow(display,
142                        XRootWindow(display, x_visinfo->screen),
143                        0, 0,   // x, y
144                        win_xres+1, win_yres+1,
145                        0, // borderwidth
146                        x_visinfo->depth,
147                        InputOutput,
148                        my_visual,
149                        attribmask,
150                        &attribs );
151
152  XFreeColormap(display, tmpcmap);
153
154}
155
156int *lookup24=NULL;
157
158void palette::load()
159{
160
161  int intensity;
162  int color;
163  int r, g, b;
164
165  lookup24 = (int *)jmalloc(256*4,"24 bit palette lookup");
166  for (color = 0 ; color < 256 ; color++)
167  {
168    r = (int)red(color)<<24;
169    g = (int)green(color)<<16;
170    b = (int)blue(color)<<8;
171    lookup24[color] = r + g + b;
172  }
173}
174
175void palette::load_nice()
176{ load(); }
177
178void image::make_page(short wid, short hi, unsigned char *page_buffer)
179{
180  if (special && !special->static_mem)
181  {
182    data=(uchar *)jmalloc(wid*hi,"image data\n");
183    if (page_buffer)
184      memcpy(data,page_buffer,wid*hi);
185  } else if (page_buffer)
186    data=page_buffer;
187  else data=(uchar *)jmalloc(wid*hi,"image data");
188}
189
190void image::delete_page()
191{
192  if (!special || !special->static_mem)
193    jfree(data);     
194}
195
196void reset_frame()
197{
198  glViewport(0, 0, win_xres+1, win_yres+1);
199  glMatrixMode(GL_PROJECTION);
200  glLoadIdentity();
201  gluOrtho2D(0, xres+1, 0, yres+1);
202  glMatrixMode(GL_MODELVIEW);
203  glLoadIdentity();
204
205  xs=(float)(win_xres+1)/(xres+1);
206  ys=(float)(win_yres+1)/(yres+1);
207
208  if (xs!=1.0 || ys!=1.0)
209    printf("Pixel scaling -> %lfx%lf\n",xs,ys);
210
211  glPixelZoom(xs,ys);                    // top to bottom pixel lines
212  glRasterPos2i(0,0);
213}
214
215
216void Scaled_f(void)
217{
218        config_notify = 1;
219        glX_scaled = 1;
220}
221
222void UnScaled_f(void)
223{
224        config_notify = 1;
225        glX_scaled = 0;
226}
227
228
229void set_mode(int mode, int argc, char **argv)
230{
231//  Cmd_AddCommand("glx_scaled", Scaled_f);
232//  Cmd_AddCommand("glx_unscaled", UnScaled_f);
233
234
235
236  /****************************** Open DISPLAY *************************/
237  char display_name[100];
238  // get the default display name from the enviroment variable DISPLAY
239  char *ds_name=getenv("DISPLAY");
240  if (!ds_name) ds_name="unix:0.0";
241  strcpy(display_name,ds_name);   
242  display=XOpenDisplay(display_name); 
243  if (!display)
244  {
245    printf("Cound not connect to X server named '%s'\n",display_name);
246    exit(1);
247  }
248
249  x_screen = DefaultScreen(display);
250
251
252  win_xres=640; win_yres=400;
253  int i;
254  for (i=1;i<argc;i++)
255  { if (!strcmp(argv[i],"-size"))
256    { i++; sscanf(argv[i],"%d",&win_xres);
257      i++; sscanf(argv[i],"%d",&win_yres);
258    }
259  }
260  xres=320;  yres=200;
261  PickVisual();
262
263
264  frame_buffer=(ulong *)jmalloc(xres*yres*4,"24 bit frame buffer\n");
265  screen=new image(xres,yres,NULL,2);
266  xres--;     yres--;
267  win_xres--; win_yres--;
268
269 
270
271  CreateWindow();
272
273  glX_context = glXCreateContext(display, x_visinfo, 0, True);
274  glXMakeCurrent(display, mainwin, glX_context);
275
276
277  // ****************************  Create the Visual  ****************************
278  XGCValues xgcvalues;
279  int valuemask = GCGraphicsExposures;
280  xgcvalues.graphics_exposures = False;
281  x_gc = XCreateGC(display, mainwin, valuemask, &xgcvalues );
282
283
284  XDefineCursor(display, mainwin, CreateNullCursor(display, mainwin));
285
286  XMapWindow(display, mainwin);
287
288  XEvent event;
289  do
290  {
291    XNextEvent(display, &event);
292    if (event.type == Expose && !event.xexpose.count)
293      oktodraw = 1;
294  } while (!oktodraw);
295
296  reset_frame();
297
298  XSynchronize(display, False);
299}
300
301
302void close_graphics()
303{
304  jfree(frame_buffer);
305  delete screen;
306  XFreeGC(display,x_gc);
307  XFree((char *)my_visual);
308  XCloseDisplay(display);
309}
310
311
312static void refresh_frame_buffer(int x1, int y1, int x2, int y2)
313{
314/*  x1=x1&~3;
315  x2=(x2+3)&~3;*/
316
317//  glRasterPos2i(0,yres);
318
319
320/*  glPixelStorei(GL_UNPACK_ROW_LENGTH,(xres+1));
321  glPixelStorei(GL_UNPACK_SKIP_PIXELS,x1);
322  glPixelStorei(GL_UNPACK_SKIP_ROWS,y1);
323  glRasterPos2i(0,0);*/
324
325//  glDrawPixels(x2-x1+1,y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE,frame_buffer);
326  glRasterPos2i(x1,y1);
327  glDrawPixels(x2-x1+1,y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE,frame_buffer);
328//  glRecti(x1,y1,x2,y2);
329  glFlush();
330  glXSwapBuffers(display,mainwin);
331}
332
333void put_part(image *im, int x, int y, int x1, int y1, int x2, int y2)
334{
335  int width=x2-x1+1,height=y2-y1+1,a,b;
336
337  // first convert to 24 bit 
338  int size1=((long)im->width()*(long)im->height());
339
340 
341//  ulong *page=frame_buffer+y*(xres+1)+x;
342  ulong *page=frame_buffer;
343  uchar *sl=im->scan_line(y1)+x1;
344  int skip=im->width()-(x2-x1+1);
345  int frame_skip=(xres+1)-(x2-x1+1);
346  for (y=y1;y<=y2;y++)
347  {
348    for (x=x1;x<=x2;x++)
349      *(page++)=lookup24[*(sl++)];
350    sl+=skip;
351//    page+=frame_skip;
352  }
353  refresh_frame_buffer(x,y,x+(x2-x1),y+(y2-y1));
354}
355
356
357void put_image(image *im, int x, int y)
358{ put_part(im,x,y,0,0,im->width()-1,im->height()-1); }
359
360
361
362void update_dirty(image *im, int xoff, int yoff)
363{
364
365  int count;
366  dirty_rect *dr,*q;
367  CHECK(im->special);  // make sure the image has the ablity to contain dirty areas
368  if (im->special->keep_dirt==0)
369    put_image(im,0,0);
370  else
371  {
372    count=im->special->dirties.number_nodes();
373    if (!count) return;  // if nothing to update, return
374    (linked_node *) dr=im->special->dirties.first();
375    while (count>0)
376    {
377      put_part(im,dr->dx1+xoff,dr->dy1+yoff,dr->dx1,dr->dy1,dr->dx2,dr->dy2);
378      q=dr;
379      (linked_node *)dr=dr->next();
380      im->special->dirties.unlink((linked_node *)q);
381      delete q;
382      count--;
383    }
384  }
385}
386
387
388
389
390
391
392
393
Note: See TracBrowser for help on using the repository browser.