source: golgotha/src/i4/video/x11/x11_display.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.2 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "video/x11/x11_display.hh"
10#include "image/context.hh"
11#define DEPTH 16
12
13x11_display_class x11_display_instance;
14
15
16x11_display_class::x11_display_class()
17{
18  shm_extension=0;
19  mouse_save=screen=0;
20  context=0;
21
22  shm_image=0;
23  ximage=0;
24}
25
26
27
28void x11_display_input_class::resize(int w, int h)
29{
30  x11_display_class *d=(x11_display_class *)i4_display;
31  if (w!=d->width() || h!=d->height())
32  {
33    d->destroy_X_image();
34    d->create_X_image(w,h);
35  }
36}
37
38void x11_display_input_class::note_event(XEvent &xev)
39{
40  x11_display_class *d=(x11_display_class *)i4_display;
41  if (d->shm_extension)
42    d->shm_extension->note_event(xev);
43}
44
45
46i4_image_class *x11_display_class::get_back_buffer(int x1, int y1, int x2, int y2)
47{
48  if (x2<x1 || y2<y1) return 0;
49
50  i4_image_class *im=i4_create_image(x2-x1+1, y2-y1+1, screen->pal);
51  screen->put_part(im, 0,0, x1,y1,x2,y2);
52  return im;
53}
54
55i4_bool x11_display_class::open_X_window(w32 width, w32 height, i4_display_class::mode *mode)
56
57  if (input.create_window(0,0,width,height, this, i4_F, get_visual(input.display)))
58  {
59    i4_pixel_format f;
60    f.red_mask   = mode->red_mask;
61    f.green_mask = mode->green_mask;
62    f.blue_mask  = mode->blue_mask;
63    f.alpha_mask = 0;
64
65    f.calc_shift();
66
67    f.lookup      = 0;
68    f.pixel_depth = I4_16BIT;
69
70    pal = i4_pal_man.register_pal(&f);
71
72
73    if (shm_extension)
74    {
75      char *ds_name=getenv("DISPLAY");
76      if (!ds_name)
77        ds_name="unix:0.0";
78   
79      if (!shm_extension->available(input.display,ds_name))
80        shm_extension=0;
81    }
82
83    create_X_image(width, height);
84    return i4_T;
85  }
86  else
87    return i4_F;
88}
89
90
91
92void x11_display_class::close_X_window()
93{
94  destroy_X_image();
95  if (shm_extension)
96    shm_extension->shutdown(input.display);
97
98
99  if (mouse_save)
100  {
101    delete mouse_save;
102    mouse_save=0;
103  }
104
105  if (mouse_pict)
106  {
107    delete mouse_pict;
108    mouse_pict=0;
109  }
110}
111
112
113i4_bool x11_display_class::close()
114{
115  if (screen)
116    close_X_window();
117
118  return i4_T;
119}
120
121void x11_display_class::init()
122{
123  if (input.display || input.open_display())
124  {
125    me.add_to_list("X Windows", 0, this, i4_display_list);
126    input.close_display();
127  }
128}
129
130  // initialize_mode need not call close() to switch to another mode
131i4_bool x11_display_class::initialize_mode()
132
133  memcpy(&cur_mode, &amode, sizeof(cur_mode));
134
135  // this should open an X window
136  return open_X_window(cur_mode.xres, cur_mode.yres, &cur_mode);
137}
138
139
140XVisualInfo *x11_display_class::get_visual(Display *display)
141{
142  return input.find_visual_with_depth(DEPTH); 
143}
144
145i4_display_class::mode *x11_display_class::get_first_mode(int driver_id)
146{
147  if (!input.open_display())
148    return 0;
149  else
150  {
151    XVisualInfo *v = get_visual(input.display);
152    if (v)
153    {
154      strcpy(amode.name,"Standard X11 window");
155      amode.flags=mode::RESOLUTION_DETERMINED_ON_OPEN;
156      amode.bits_per_pixel=DEPTH;
157
158      amode.red_mask    = v->red_mask;
159      amode.green_mask  = v->green_mask;
160      amode.blue_mask   = v->blue_mask;
161      XFree((char *)v);
162
163      Window root;
164      int x,y;
165      unsigned w,h,bord,depth;
166      if (XGetGeometry(input.display,
167                       RootWindow(input.display,DefaultScreen(input.display)),&root,
168                       &x,&y,&w,&h,&bord,&depth)==0)
169        i4_error("can't get root window attributes");
170
171      amode.xres=w;
172      amode.yres=h;
173
174      amode.assoc=this;          // so we know in 'initialize_mode' that we created this mode
175      return &amode;
176    }
177    return 0;
178  }
179}
180
181
182
183
184
185void x11_display_class::destroy_X_image()
186{
187  if (shm_extension)
188  {
189    if (shm_image)
190      shm_extension->destroy_shm_image(input.display, shm_image);
191    shm_image=0;
192  }
193  else
194  {
195    if (ximage)
196      XDestroyImage(ximage);
197    ximage=0;
198  }
199  if (screen)
200  {
201    delete screen;
202    screen=0;
203  }
204
205  if (context)
206  {
207    delete context;
208    context=0;
209  }
210}
211
212void x11_display_class::create_X_image(w32 width, w32 height)
213{
214  destroy_X_image();
215
216  if (shm_extension)
217  {         
218    w16 w=width,h=height;
219    shm_image=shm_extension->create_shm_image(input.display,
220                                              input.mainwin,
221                                              input.gc,
222                                              input.my_visual->visual,
223                                              input.my_visual->depth,
224                                              w,h);   // actual width and height from X
225    screen=i4_create_image(w,h,pal,
226                           (w8 *)shm_image->data,
227                           w*(DEPTH/8));
228  }
229  else
230  {
231
232    ximage = XCreateImage(input.display,
233                          input.my_visual->visual,
234                          input.my_visual->depth,
235                          ZPixmap,
236                          0,
237                          (char *)i4_malloc(width*height*(DEPTH/8),"Ximage"),
238                          width,
239                          height,
240                          32,
241                          0 );
242
243    screen=i4_create_image(width, height, pal,
244                           (w8 *)ximage->data,
245                           width*(DEPTH/8));            // bytes per line
246
247  }
248
249  if (context)
250    delete context;
251
252  context=new i4_draw_context_class(0,0,screen->width()-1,screen->height()-1);
253  context->both_dirty=new i4_rect_list_class;
254  context->single_dirty=new i4_rect_list_class;
255}
256
257
258void x11_display_class::flush()   // the actual work of the function is in copy_part_to_vram
259
260  int mw,mh;
261  i4_coord rmx,rmy;
262  sw32 mx=input.mouse_x, my=input.mouse_y;
263  if (mx<0) mx=0;
264  if (my<0) my=0;
265
266  rmx=mx-mouse_hot_x;
267  rmy=my-mouse_hot_y; 
268
269  if (mouse_pict)
270  {
271    mw=mouse_pict->width();
272    mh=mouse_pict->height();
273
274    if (pal->source.pixel_depth==I4_8BIT)
275      mouse_save->set_pal(pal);
276     
277
278    i4_draw_context_class save_context(0,0,mw-1,mh-1);
279    screen->put_part(mouse_save,0,0,rmx,rmy,rmx+mw-1,rmy+mh-1,
280        save_context);  // save area behind mouse
281
282    mouse_pict->put_image_trans(screen,rmx,rmy,mouse_trans,*context);
283  }
284
285  i4_rect_list_class::area_iter a;
286  for (a=context->single_dirty->list.begin();
287       a!=context->single_dirty->list.end();
288       ++a)
289    context->both_dirty->add_area(a->x1, a->y1, a->x2, a->y2);
290
291  context->single_dirty->delete_list();
292
293
294  context->both_dirty->intersect_area(0,0,width()-1,height()-1);
295
296  a=context->both_dirty->list.begin();
297  i4_bool error=i4_F;
298  for (;a!=context->both_dirty->list.end();++a)
299    error=(i4_bool)(error & copy_part_to_vram(a->x1,a->y1,a->x1,a->y1,a->x2,a->y2));
300 
301  if (!error)
302    context->both_dirty->delete_list();
303
304  if (mouse_pict)
305    mouse_save->put_part(screen,rmx,rmy,0,0,mw-1,mh-1,*context);   // restore area behind mouse
306
307
308}
309
310
311i4_bool x11_display_class::copy_part_to_vram(i4_coord x, i4_coord y,
312                                             i4_coord x1, i4_coord y1,
313                                             i4_coord x2, i4_coord y2)
314// this should copy a portion of an image to the actual screen at offset x, y
315{
316  if (shm_image)
317    return shm_image->copy_part_to_vram(shm_extension,x,y,x1,y1,x2,y2);
318  else
319  {
320    XPutImage(input.display, input.mainwin, input.gc, ximage,x1,y1,x,y,x2-x1+1,y2-y1+1);
321    return i4_T;
322  }
323}
324
325
326i4_bool x11_display_class::set_mouse_shape(i4_cursor_class *cursor)
327{
328  if (mouse_pict)
329  {
330    delete mouse_pict;
331    delete mouse_save;
332  }
333
334  mouse_trans=cursor->trans;
335  mouse_pict=cursor->pict->copy();
336
337  mouse_save=i4_create_image(mouse_pict->width(),mouse_pict->height(),screen->get_pal());
338
339  mouse_hot_x=cursor->hot_x;
340  mouse_hot_y=cursor->hot_y;
341  return i4_T;
342}
343
344
Note: See TracBrowser for help on using the repository browser.