ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.57
Committed: Fri Apr 21 07:09:10 2006 UTC (18 years ago) by root
Branch: MAIN
Changes since 1.56: +9 -1 lines
Log Message:
implement mipmapping

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2     # include <malloc.h>
3     #endif
4    
5 root 1.1 #include "EXTERN.h"
6     #include "perl.h"
7     #include "XSUB.h"
8    
9 root 1.5 #include <string.h>
10 root 1.25 #include <stdio.h>
11 root 1.5
12 root 1.2 #include <SDL.h>
13 root 1.23 #include <SDL_image.h>
14 root 1.52 #include <SDL_mixer.h>
15 root 1.3 #include <SDL_opengl.h>
16 root 1.5
17 root 1.30 #include <glib/gmacros.h>
18    
19 root 1.5 #include <pango/pango.h>
20 root 1.10 #include <pango/pangofc-fontmap.h>
21 root 1.5 #include <pango/pangoft2.h>
22    
23 root 1.48 #ifndef _WIN32
24     # include <sys/types.h>
25     # include <sys/socket.h>
26     # include <netinet/in.h>
27     # include <netinet/tcp.h>
28     # include <inttypes.h>
29     #else
30     typedef unsigned char uint8_t;
31     typedef unsigned short uint16_t;
32     typedef unsigned int uint32_t;
33     typedef signed char int8_t;
34     typedef signed short int16_t;
35     typedef signed int int32_t;
36     #endif
37 root 1.28
38 root 1.57 #include "glext.h"
39    
40 root 1.29 #define FOW_DARKNESS 32
41    
42     #define MAP_EXTEND_X 32
43     #define MAP_EXTEND_Y 512
44    
45 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
46     typedef Mix_Music *CFClient__MixMusic;
47    
48 root 1.5 static PangoContext *context;
49     static PangoFontMap *fontmap;
50 root 1.2
51 root 1.14 typedef struct cf_layout {
52     PangoLayout *pl;
53     int base_height;
54 root 1.15 } *CFClient__Layout;
55 root 1.14
56     static void
57 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
58     {
59 root 1.20 FcPatternAddBool (pattern, FC_HINTING , 1);
60 root 1.35 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
61 root 1.19 }
62    
63     static void
64 root 1.17 layout_update (CFClient__Layout self)
65     {
66 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
67     * reasonably well with bitstream vera
68     */
69 root 1.17 PangoFontDescription *font = pango_context_get_font_description (context);
70 root 1.46
71     int height = self->base_height * (PANGO_SCALE * 8 / 10);
72    
73     if (pango_font_description_get_size (font) != height)
74     {
75     pango_font_description_set_absolute_size (font, height);
76     pango_layout_context_changed (self->pl);
77     }
78 root 1.17 }
79    
80     static void
81 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
82 root 1.14 {
83 root 1.19 layout_update (self);
84 root 1.16
85 root 1.14 pango_layout_get_pixel_size (self->pl, w, h);
86    
87     *w = (*w + 3) & ~3;
88     if (!*w) *w = 1;
89     if (!*h) *h = 1;
90     }
91    
92 root 1.42 typedef uint16_t mapface;
93    
94 root 1.28 typedef struct {
95 root 1.30 GLint name;
96     int w, h;
97     float s, t;
98 root 1.39 uint8_t r, g, b, a;
99 root 1.42 } maptex;
100 root 1.30
101     typedef struct {
102 root 1.29 int16_t darkness;
103 root 1.42 mapface face[3];
104 root 1.28 } mapcell;
105    
106     typedef struct {
107 root 1.30 int32_t c0, c1;
108 root 1.28 mapcell *col;
109     } maprow;
110    
111     typedef struct map {
112     int x, y, w, h;
113 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
114 root 1.28 int faces;
115 root 1.30 mapface *face;
116 root 1.28
117 root 1.42 int texs;
118     maptex *tex;
119    
120 root 1.48 int32_t rows;
121 root 1.28 maprow *row;
122     } *CFClient__Map;
123    
124 root 1.30 static char *
125     prepend (char *ptr, int sze, int inc)
126     {
127     char *p;
128    
129     New (0, p, sze + inc, char);
130     Zero (p, inc, char);
131     Move (ptr, p + inc, sze, char);
132     Safefree (ptr);
133    
134     return p;
135     }
136    
137     static char *
138     append (char *ptr, int sze, int inc)
139     {
140     Renew (ptr, sze + inc, char);
141     Zero (ptr + sze, inc, char);
142    
143     return ptr;
144     }
145    
146     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
147     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
148    
149 root 1.42 static maprow *
150     map_get_row (CFClient__Map self, int y)
151     {
152     if (0 > y)
153     {
154     int extend = - y + MAP_EXTEND_Y;
155     Prepend (maprow, self->row, self->rows, extend);
156    
157     self->rows += extend;
158     self->y += extend;
159     y += extend;
160     }
161     else if (y >= self->rows)
162     {
163     int extend = y - self->rows + MAP_EXTEND_Y;
164     Append (maprow, self->row, self->rows, extend);
165     self->rows += extend;
166     }
167    
168     return self->row + y;
169     }
170    
171     static mapcell *
172     row_get_cell (maprow *row, int x)
173     {
174     if (!row->col)
175     {
176     Newz (0, row->col, MAP_EXTEND_X, mapcell);
177     row->c0 = x - MAP_EXTEND_X / 4;
178     row->c1 = row->c0 + MAP_EXTEND_X;
179     }
180    
181     if (row->c0 > x)
182     {
183     int extend = row->c0 - x + MAP_EXTEND_X;
184     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
185     row->c0 -= extend;
186     }
187     else if (x >= row->c1)
188     {
189     int extend = x - row->c1 + MAP_EXTEND_X;
190     Append (mapcell, row->col, row->c1 - row->c0, extend);
191     row->c1 += extend;
192     }
193    
194     return row->col + (x - row->c0);
195     }
196    
197     static mapcell *
198     map_get_cell (CFClient__Map self, int x, int y)
199     {
200     return row_get_cell (map_get_row (self, y), x);
201     }
202    
203 root 1.30 static void
204     map_clear (CFClient__Map self)
205     {
206     int r;
207    
208     for (r = 0; r < self->rows; r++)
209     Safefree (self->row[r].col);
210    
211     Safefree (self->row);
212    
213     self->x = 0;
214     self->y = 0;
215 root 1.42 self->ox = 0;
216     self->oy = 0;
217 root 1.30 self->row = 0;
218     self->rows = 0;
219     }
220    
221 root 1.29 static void
222     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
223     {
224     int x, y;
225 root 1.48 maprow *row;
226 root 1.29
227     for (y = y0; y < y0 + h; y++)
228 root 1.30 if (y >= 0)
229     {
230     if (y >= self->rows)
231     break;
232    
233 root 1.48 row = self->row + y;
234 root 1.30
235     for (x = x0; x < x0 + w; x++)
236     if (x >= row->c0)
237     {
238     if (x >= row->c1)
239     break;
240 root 1.29
241 root 1.31 row->col[x - row->c0].darkness = -1;
242 root 1.30 }
243     }
244 root 1.29 }
245    
246 root 1.56 static void
247     music_finished ()
248     {
249     SDL_UserEvent ev;
250    
251     ev.type = SDL_USEREVENT;
252     ev.code = 0;
253     ev.data1 = 0;
254     ev.data2 = 0;
255    
256 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
257 root 1.56 }
258    
259 root 1.15 MODULE = CFClient PACKAGE = CFClient
260 root 1.1
261 root 1.11 PROTOTYPES: ENABLE
262    
263 root 1.5 BOOT:
264     {
265 root 1.51 HV *stash = gv_stashpv ("CFClient", 1);
266     static const struct {
267     const char *name;
268     IV iv;
269     } *civ, const_iv[] = {
270     # define const_iv(name) { # name, (IV)name }
271     const_iv (SDL_ACTIVEEVENT),
272     const_iv (SDL_KEYDOWN),
273     const_iv (SDL_KEYUP),
274     const_iv (SDL_MOUSEMOTION),
275     const_iv (SDL_MOUSEBUTTONDOWN),
276     const_iv (SDL_MOUSEBUTTONUP),
277     const_iv (SDL_JOYAXISMOTION),
278     const_iv (SDL_JOYBALLMOTION),
279     const_iv (SDL_JOYHATMOTION),
280     const_iv (SDL_JOYBUTTONDOWN),
281     const_iv (SDL_JOYBUTTONUP),
282     const_iv (SDL_QUIT),
283     const_iv (SDL_SYSWMEVENT),
284     const_iv (SDL_EVENT_RESERVEDA),
285     const_iv (SDL_EVENT_RESERVEDB),
286     const_iv (SDL_VIDEORESIZE),
287     const_iv (SDL_VIDEOEXPOSE),
288     const_iv (SDL_USEREVENT),
289     const_iv (SDLK_KP0),
290     const_iv (SDLK_KP1),
291     const_iv (SDLK_KP2),
292     const_iv (SDLK_KP3),
293     const_iv (SDLK_KP4),
294     const_iv (SDLK_KP5),
295     const_iv (SDLK_KP6),
296     const_iv (SDLK_KP7),
297     const_iv (SDLK_KP8),
298     const_iv (SDLK_KP9),
299     const_iv (SDLK_KP_PERIOD),
300     const_iv (SDLK_KP_DIVIDE),
301     const_iv (SDLK_KP_MULTIPLY),
302     const_iv (SDLK_KP_MINUS),
303     const_iv (SDLK_KP_PLUS),
304     const_iv (SDLK_KP_ENTER),
305     const_iv (SDLK_KP_EQUALS),
306     const_iv (SDLK_UP),
307     const_iv (SDLK_DOWN),
308     const_iv (SDLK_RIGHT),
309     const_iv (SDLK_LEFT),
310     const_iv (SDLK_INSERT),
311     const_iv (SDLK_HOME),
312     const_iv (SDLK_END),
313     const_iv (SDLK_PAGEUP),
314     const_iv (SDLK_PAGEDOWN),
315     const_iv (SDLK_F1),
316     const_iv (SDLK_F2),
317     const_iv (SDLK_F3),
318     const_iv (SDLK_F4),
319     const_iv (SDLK_F5),
320     const_iv (SDLK_F6),
321     const_iv (SDLK_F7),
322     const_iv (SDLK_F8),
323     const_iv (SDLK_F9),
324     const_iv (SDLK_F10),
325     const_iv (SDLK_F11),
326     const_iv (SDLK_F12),
327     const_iv (SDLK_F13),
328     const_iv (SDLK_F14),
329     const_iv (SDLK_F15),
330     const_iv (SDLK_NUMLOCK),
331     const_iv (SDLK_CAPSLOCK),
332     const_iv (SDLK_SCROLLOCK),
333     const_iv (SDLK_RSHIFT),
334     const_iv (SDLK_LSHIFT),
335     const_iv (SDLK_RCTRL),
336     const_iv (SDLK_LCTRL),
337     const_iv (SDLK_RALT),
338     const_iv (SDLK_LALT),
339     const_iv (SDLK_RMETA),
340     const_iv (SDLK_LMETA),
341     const_iv (SDLK_LSUPER),
342     const_iv (SDLK_RSUPER),
343     const_iv (SDLK_MODE),
344     const_iv (SDLK_COMPOSE),
345     const_iv (SDLK_HELP),
346     const_iv (SDLK_PRINT),
347     const_iv (SDLK_SYSREQ),
348     const_iv (SDLK_BREAK),
349     const_iv (SDLK_MENU),
350     const_iv (SDLK_POWER),
351     const_iv (SDLK_EURO),
352     const_iv (SDLK_UNDO),
353     const_iv (KMOD_NONE),
354     const_iv (KMOD_LSHIFT),
355     const_iv (KMOD_RSHIFT),
356     const_iv (KMOD_LCTRL),
357     const_iv (KMOD_RCTRL),
358     const_iv (KMOD_LALT),
359     const_iv (KMOD_RALT),
360     const_iv (KMOD_LMETA),
361     const_iv (KMOD_RMETA),
362     const_iv (KMOD_NUM),
363     const_iv (KMOD_CAPS),
364     const_iv (KMOD_MODE),
365     const_iv (KMOD_CTRL),
366     const_iv (KMOD_SHIFT),
367     const_iv (KMOD_ALT),
368     const_iv (KMOD_META)
369     # undef const_iv
370     };
371    
372     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
373     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
374    
375     fontmap = pango_ft2_font_map_new ();
376     pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, substitute_func, 0, 0);
377     context = pango_ft2_font_map_create_context ((PangoFT2FontMap *)fontmap);
378 root 1.5 }
379    
380 root 1.51 int
381     SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO)
382    
383     void
384     SDL_Quit ()
385    
386     void
387     SDL_ListModes ()
388     PPCODE:
389     {
390     SDL_Rect **m;
391    
392     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
393     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
394     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
395     SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
396    
397     SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
398     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
399     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
400     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
401    
402     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
403     SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
404     SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
405    
406 root 1.53 SDL_EnableUNICODE (1);
407     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
408    
409 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
410    
411     if (m && m != (SDL_Rect **)-1)
412     while (*m)
413     {
414     AV *av = newAV ();
415     av_push (av, newSViv ((*m)->w));
416     av_push (av, newSViv ((*m)->h));
417     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
418    
419     ++m;
420     }
421     }
422    
423     int
424     SDL_SetVideoMode (int w, int h, int fullscreen)
425     CODE:
426     RETVAL = !!SDL_SetVideoMode (
427     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
428     );
429     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
430     OUTPUT:
431     RETVAL
432    
433 root 1.53 void
434 root 1.54 SDL_GL_SwapBuffers ()
435    
436     void
437 root 1.53 SDL_PollEvent ()
438     PPCODE:
439     {
440     SDL_Event ev;
441    
442     while (SDL_PollEvent (&ev))
443     {
444     HV *hv = newHV ();
445     hv_store (hv, "type", 4, newSViv (ev.type), 0);
446     switch (ev.type)
447     {
448     case SDL_KEYDOWN:
449     case SDL_KEYUP:
450     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
451     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
452     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
453     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
454     break;
455    
456     case SDL_ACTIVEEVENT:
457     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
458     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
459     break;
460    
461     case SDL_MOUSEMOTION:
462     hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
463     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
464     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
465     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
466     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
467     break;
468    
469     case SDL_MOUSEBUTTONDOWN:
470     case SDL_MOUSEBUTTONUP:
471     hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
472     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
473     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
474     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
475     }
476    
477     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
478     }
479     }
480 root 1.52
481     int
482     Mix_OpenAudio (int frequency = 22050, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 512)
483 root 1.56 POSTCALL:
484     Mix_HookMusicFinished (music_finished);
485 root 1.52
486     void
487     Mix_CloseAudio ()
488    
489     int
490     Mix_AllocateChannels (int numchans = -1)
491    
492 root 1.10 void
493     lowdelay (int fd, int val = 1)
494     CODE:
495 root 1.48 #ifndef _WIN32
496 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
497 root 1.48 #endif
498 root 1.10
499 root 1.3 char *
500 root 1.4 gl_version ()
501     CODE:
502 root 1.5 RETVAL = (char *)glGetString (GL_VERSION);
503 root 1.4 OUTPUT:
504     RETVAL
505    
506     char *
507 root 1.3 gl_extensions ()
508     CODE:
509 root 1.5 RETVAL = (char *)glGetString (GL_EXTENSIONS);
510 root 1.3 OUTPUT:
511     RETVAL
512    
513 root 1.5 void
514 root 1.13 add_font (char *file)
515     CODE:
516     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
517    
518     void
519 root 1.9 set_font (char *file)
520 root 1.8 CODE:
521     {
522 root 1.9 int count;
523     FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)file, 0, 0, &count);
524 root 1.10 PangoFontDescription *font = pango_fc_font_description_from_pattern (pattern, 0);
525 root 1.9 FcPatternDestroy (pattern);
526 root 1.8 pango_context_set_font_description (context, font);
527     }
528    
529 root 1.23 void
530     load_image_inline (SV *image_)
531     ALIAS:
532     load_image_file = 1
533     PPCODE:
534     {
535     STRLEN image_len;
536     char *image = (char *)SvPVbyte (image_, image_len);
537     SDL_Surface *surface, *surface2;
538     SDL_PixelFormat fmt;
539     SDL_RWops *rw = ix
540     ? SDL_RWFromFile (image, "r")
541     : SDL_RWFromConstMem (image, image_len);
542    
543     if (!rw)
544 root 1.41 croak ("load_image: %s", SDL_GetError ());
545 root 1.23
546     surface = IMG_Load_RW (rw, 1);
547     if (!surface)
548 root 1.41 croak ("load_image: %s", SDL_GetError ());
549 root 1.23
550     fmt.palette = NULL;
551     fmt.BitsPerPixel = 32;
552     fmt.BytesPerPixel = 4;
553 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
554 root 1.23 fmt.Rmask = 0x000000ff;
555     fmt.Gmask = 0x0000ff00;
556     fmt.Bmask = 0x00ff0000;
557     fmt.Amask = 0xff000000;
558 root 1.49 #else
559     fmt.Rmask = 0xff000000;
560     fmt.Gmask = 0x00ff0000;
561     fmt.Bmask = 0x0000ff00;
562     fmt.Amask = 0x000000ff;
563     #endif
564 root 1.23 fmt.Rloss = 0;
565     fmt.Gloss = 0;
566     fmt.Bloss = 0;
567     fmt.Aloss = 0;
568     fmt.Rshift = 0;
569     fmt.Gshift = 8;
570     fmt.Bshift = 16;
571     fmt.Ashift = 24;
572     fmt.colorkey = 0;
573     fmt.alpha = 0;
574    
575     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
576    
577 root 1.39 assert (surface2->pitch == surface2->w * 4);
578    
579 root 1.23 EXTEND (SP, 5);
580     PUSHs (sv_2mortal (newSViv (surface2->w)));
581     PUSHs (sv_2mortal (newSViv (surface2->h)));
582     SDL_LockSurface (surface2);
583     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
584     SDL_UnlockSurface (surface2);
585 root 1.24 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
586 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
587 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
588 root 1.23
589     SDL_FreeSurface (surface);
590     SDL_FreeSurface (surface2);
591     }
592    
593 root 1.25 void
594 root 1.39 average (int x, int y, uint32_t *data)
595     PPCODE:
596     {
597     uint32_t r = 0, g = 0, b = 0, a = 0;
598    
599     x = y = x * y;
600    
601     while (x--)
602     {
603     uint32_t p = *data++;
604    
605     r += (p ) & 255;
606     g += (p >> 8) & 255;
607     b += (p >> 16) & 255;
608     a += (p >> 24) & 255;
609     }
610    
611     EXTEND (SP, 4);
612 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
613     PUSHs (sv_2mortal (newSViv (g / y)));
614     PUSHs (sv_2mortal (newSViv (b / y)));
615     PUSHs (sv_2mortal (newSViv (a / y)));
616 root 1.39 }
617    
618     void
619 root 1.25 fatal (char *message)
620     CODE:
621 root 1.50 #ifdef _WIN32
622 root 1.25 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
623     #else
624 root 1.40 fprintf (stderr, "FATAL: %s\n", message);
625 root 1.25 #endif
626     exit (1);
627    
628 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
629 root 1.14
630 root 1.15 CFClient::Layout
631 root 1.14 new (SV *class, int base_height = 10)
632     CODE:
633     New (0, RETVAL, 1, struct cf_layout);
634     RETVAL->base_height = base_height;
635     RETVAL->pl = pango_layout_new (context);
636     pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
637     OUTPUT:
638     RETVAL
639    
640     void
641 root 1.15 DESTROY (CFClient::Layout self)
642 root 1.14 CODE:
643     g_object_unref (self->pl);
644     Safefree (self);
645 root 1.13
646 root 1.8 void
647 root 1.35 set_text (CFClient::Layout self, SV *text_)
648     CODE:
649     {
650     STRLEN textlen;
651     char *text = SvPVutf8 (text_, textlen);
652    
653     pango_layout_set_text (self->pl, text, textlen);
654     }
655    
656     void
657 root 1.15 set_markup (CFClient::Layout self, SV *text_)
658 root 1.14 CODE:
659 root 1.5 {
660     STRLEN textlen;
661     char *text = SvPVutf8 (text_, textlen);
662 root 1.14
663     pango_layout_set_markup (self->pl, text, textlen);
664     }
665    
666 root 1.46 SV *
667     get_text (CFClient::Layout self)
668     CODE:
669 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
670 root 1.46 SvUTF8_on (RETVAL);
671     OUTPUT:
672     RETVAL
673    
674 root 1.14 void
675 root 1.16 set_height (CFClient::Layout self, int base_height)
676     CODE:
677     self->base_height = base_height;
678    
679     void
680 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
681 root 1.14 CODE:
682     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
683    
684     void
685 root 1.15 size (CFClient::Layout self)
686 root 1.14 PPCODE:
687     {
688     int w, h;
689    
690 root 1.17 layout_update (self);
691 root 1.14 layout_get_pixel_size (self, &w, &h);
692    
693     EXTEND (SP, 2);
694     PUSHs (sv_2mortal (newSViv (w)));
695     PUSHs (sv_2mortal (newSViv (h)));
696     }
697    
698 root 1.17 int
699     xy_to_index (CFClient::Layout self, int x, int y)
700     CODE:
701     {
702     int index, trailing;
703    
704     layout_update (self);
705     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
706    
707     RETVAL = index;
708     }
709     OUTPUT:
710     RETVAL
711    
712     void
713     cursor_pos (CFClient::Layout self, int index)
714     PPCODE:
715     {
716     PangoRectangle strong_pos;
717     layout_update (self);
718     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
719 root 1.30
720 root 1.17 EXTEND (SP, 3);
721     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
722     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
723     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
724     }
725    
726 root 1.14 void
727 root 1.15 render (CFClient::Layout self)
728 root 1.14 PPCODE:
729     {
730 root 1.5 SV *retval;
731     int w, h;
732     FT_Bitmap bitmap;
733    
734 root 1.17 layout_update (self);
735 root 1.14 layout_get_pixel_size (self, &w, &h);
736 root 1.5
737     retval = newSV (w * h);
738     SvPOK_only (retval);
739     SvCUR_set (retval, w * h);
740    
741     bitmap.rows = h;
742     bitmap.width = w;
743     bitmap.pitch = w;
744     bitmap.buffer = (unsigned char*)SvPVX (retval);
745     bitmap.num_grays = 256;
746     bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
747    
748     memset (bitmap.buffer, 0, w * h);
749    
750 root 1.14 pango_ft2_render_layout (&bitmap, self->pl, 0 * PANGO_SCALE, 0 * PANGO_SCALE);
751 root 1.1
752 root 1.5 EXTEND (SP, 3);
753     PUSHs (sv_2mortal (newSViv (w)));
754     PUSHs (sv_2mortal (newSViv (h)));
755     PUSHs (sv_2mortal (retval));
756     }
757 root 1.11
758 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
759 root 1.11
760     void
761 root 1.37 draw_quad (SV *self, float x, float y, float w = 0, float h = 0)
762 root 1.12 PROTOTYPE: $$$;$$
763 root 1.11 CODE:
764     {
765 root 1.12 HV *hv = (HV *)SvRV (self);
766 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
767     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
768 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
769 elmex 1.36 int wrap_mode = SvIV (*hv_fetch (hv, "wrap_mode", 9, 1));
770 root 1.12
771     if (items < 5)
772     {
773 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
774     h = SvNV (*hv_fetch (hv, "h", 1, 1));
775 root 1.12 }
776    
777     glBindTexture (GL_TEXTURE_2D, name);
778 elmex 1.36 if (wrap_mode) {
779     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
780     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
781     }
782 root 1.12 glBegin (GL_QUADS);
783 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
784     glTexCoord2f (0, t); glVertex2f (x , y + h);
785     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
786     glTexCoord2f (s, 0); glVertex2f (x + w, y );
787 root 1.12 glEnd ();
788 root 1.11 }
789 root 1.28
790     MODULE = CFClient PACKAGE = CFClient::Map
791    
792     CFClient::Map
793     new (SV *class, int map_width, int map_height)
794     CODE:
795     New (0, RETVAL, 1, struct map);
796 root 1.42 RETVAL->x = 0;
797     RETVAL->y = 0;
798     RETVAL->w = map_width;
799     RETVAL->h = map_height;
800     RETVAL->ox = 0;
801     RETVAL->oy = 0;
802 root 1.30 RETVAL->faces = 8192;
803     Newz (0, RETVAL->face, RETVAL->faces, mapface);
804 root 1.42 RETVAL->texs = 8192;
805     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
806 root 1.28 RETVAL->rows = 0;
807     RETVAL->row = 0;
808     OUTPUT:
809     RETVAL
810    
811     void
812     DESTROY (CFClient::Map self)
813     CODE:
814     {
815 root 1.30 map_clear (self);
816 root 1.28 Safefree (self->face);
817 root 1.29 Safefree (self);
818     }
819    
820     void
821 root 1.30 clear (CFClient::Map self)
822     CODE:
823     map_clear (self);
824    
825     void
826 root 1.42 set_face (CFClient::Map self, int face, int texid)
827 root 1.29 CODE:
828     {
829 root 1.42 while (self->faces <= face)
830 root 1.28 {
831 root 1.30 Append (mapface, self->face, self->faces, self->faces);
832 root 1.29 self->faces *= 2;
833     }
834 root 1.28
835 root 1.42 self->face [face] = texid;
836     }
837    
838     void
839     set_texture (CFClient::Map self, int texid, int name, int w, int h, float s, float t, int r, int g, int b, int a)
840     CODE:
841     {
842     while (self->texs <= texid)
843     {
844     Append (maptex, self->tex, self->texs, self->texs);
845     self->texs *= 2;
846     }
847    
848 root 1.48 {
849     maptex *tex = self->tex + texid;
850 root 1.39
851 root 1.48 tex->name = name;
852     tex->w = w;
853     tex->h = h;
854     tex->s = s;
855     tex->t = t;
856     tex->r = r;
857     tex->g = g;
858     tex->b = b;
859     tex->a = a;
860     }
861 root 1.29 }
862    
863 root 1.42 int
864     ox (CFClient::Map self)
865     ALIAS:
866     oy = 1
867     CODE:
868     switch (ix)
869     {
870     case 0: RETVAL = self->ox; break;
871     case 1: RETVAL = self->oy; break;
872     }
873     OUTPUT:
874     RETVAL
875    
876 root 1.29 void
877 root 1.43 scroll (CFClient::Map self, int dx, int dy)
878     CODE:
879     {
880 root 1.44 if (dx > 0)
881     map_blank (self, self->x, self->y, dx - 1, self->h);
882     else if (dx < 0)
883     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
884    
885     if (dy > 0)
886     map_blank (self, self->x, self->y, self->w, dy - 1);
887     else if (dy < 0)
888     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
889 root 1.43
890 root 1.44 self->ox += dx; self->x += dx;
891     self->oy += dy; self->y += dy;
892 root 1.43
893     while (self->y < 0)
894     {
895     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
896    
897     self->rows += MAP_EXTEND_Y;
898     self->y += MAP_EXTEND_Y;
899     }
900 root 1.44 }
901 root 1.43
902 root 1.44 void
903     map1a_update (CFClient::Map self, SV *data_)
904     CODE:
905     {
906 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
907     uint8_t *data_end = (uint8_t *)SvEND (data_);
908 root 1.48 mapcell *cell;
909     int x, y, flags;
910 root 1.43
911 root 1.29 while (data < data_end)
912     {
913 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
914 root 1.30
915 root 1.48 x = ((flags >> 10) & 63) + self->x;
916     y = ((flags >> 4) & 63) + self->y;
917 root 1.29
918 root 1.48 cell = map_get_cell (self, x, y);
919 root 1.29
920     if (flags & 15)
921     {
922 root 1.45 if (cell->darkness < 0)
923 root 1.29 {
924     cell->darkness = 0;
925     cell->face [0] = 0;
926     cell->face [1] = 0;
927     cell->face [2] = 0;
928     }
929 root 1.45
930 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
931    
932 root 1.42 //TODO: don't trust server data to be in-range(!)
933    
934 root 1.29 if (flags & 4)
935     {
936 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
937 root 1.29 }
938    
939     if (flags & 2)
940     {
941 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
942 root 1.29 }
943    
944     if (flags & 1)
945     {
946 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
947 root 1.29 }
948     }
949     else
950 root 1.31 cell->darkness = -1;
951 root 1.29 }
952 root 1.28 }
953    
954 root 1.40 SV *
955 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
956 root 1.40 CODE:
957     {
958 root 1.55 int x1, x;
959     int y1, y;
960 root 1.40 int z;
961     SV *map_sv = newSV (w * h * sizeof (uint32_t));
962     uint32_t *map = (uint32_t *)SvPVX (map_sv);
963    
964     SvPOK_only (map_sv);
965     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
966    
967 root 1.55 x0 += self->x; x1 = x0 + w;
968     y0 += self->y; y1 = y0 + h;
969 root 1.40
970     for (y = y0; y < y1; y++)
971     {
972     maprow *row = 0 <= y && y < self->rows
973     ? self->row + y
974     : 0;
975    
976     for (x = x0; x < x1; x++)
977     {
978     int r = 32, g = 32, b = 32, a = 192;
979    
980     if (row && row->c0 <= x && x < row->c1)
981     {
982     mapcell *cell = row->col + (x - row->c0);
983    
984     for (z = 0; z <= 0; z++)
985     {
986 root 1.42 mapface face = cell->face [z];
987 root 1.40
988     if (face)
989     {
990 root 1.42 maptex tex = self->tex [face];
991 root 1.40 int a0 = 255 - tex.a;
992     int a1 = tex.a;
993    
994     r = (r * a0 + tex.r * a1) / 255;
995     g = (g * a0 + tex.g * a1) / 255;
996     b = (b * a0 + tex.b * a1) / 255;
997     a = (a * a0 + tex.a * a1) / 255;
998     }
999     }
1000     }
1001    
1002     *map++ = (r )
1003     | (g << 8)
1004     | (b << 16)
1005     | (a << 24);
1006     }
1007     }
1008    
1009     RETVAL = map_sv;
1010     }
1011     OUTPUT:
1012     RETVAL
1013    
1014 root 1.30 void
1015 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1016 root 1.32 PPCODE:
1017 root 1.30 {
1018 root 1.48 int vx, vy;
1019     int x, y, z;
1020     int last_name;
1021     mapface face;
1022 root 1.32 int sw4 = (sw + 3) & ~3;
1023     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1024 root 1.35 uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1025 root 1.48
1026 root 1.42 memset (darkness, 255, sw4 * sh);
1027 root 1.32 SvPOK_only (darkness_sv);
1028     SvCUR_set (darkness_sv, sw4 * sh);
1029    
1030 root 1.48 vx = self->x + (self->w - sw) / 2 - shift_x;
1031     vy = self->y + (self->h - sh) / 2 - shift_y;
1032 root 1.38
1033 root 1.42 /*
1034     int vx = self->vx = self->w >= sw
1035     ? self->x + (self->w - sw) / 2
1036     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1037    
1038     int vy = self->vy = self->h >= sh
1039     ? self->y + (self->h - sh) / 2
1040     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1041     */
1042 root 1.30
1043     glColor4ub (255, 255, 255, 255);
1044    
1045     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1046     glEnable (GL_BLEND);
1047     glEnable (GL_TEXTURE_2D);
1048     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1049    
1050 root 1.48 glBegin (GL_QUADS);
1051 root 1.30
1052 root 1.48 last_name = 0;
1053 root 1.30
1054     for (z = 0; z < 3; z++)
1055     for (y = 0; y < sh; y++)
1056     if (0 <= y + vy && y + vy < self->rows)
1057     {
1058     maprow *row = self->row + (y + vy);
1059    
1060     for (x = 0; x < sw; x++)
1061     if (row->c0 <= x + vx && x + vx < row->c1)
1062     {
1063     mapcell *cell = row->col + (x + vx - row->c0);
1064 root 1.32
1065     darkness[y * sw4 + x] = cell->darkness < 0
1066 root 1.33 ? 255 - FOW_DARKNESS
1067 root 1.32 : 255 - cell->darkness;
1068    
1069 root 1.48 face = cell->face [z];
1070 root 1.30
1071     if (face)
1072     {
1073 root 1.42 maptex tex = self->tex [face];
1074 root 1.30
1075     int px = (x + 1) * 32 - tex.w;
1076     int py = (y + 1) * 32 - tex.h;
1077    
1078     if (last_name != tex.name)
1079     {
1080     glEnd ();
1081     last_name = tex.name;
1082     glBindTexture (GL_TEXTURE_2D, last_name);
1083     glBegin (GL_QUADS);
1084     }
1085    
1086     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1087     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1088     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1089     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1090     }
1091     }
1092     }
1093    
1094     glEnd ();
1095 root 1.32
1096 root 1.34 glDisable (GL_TEXTURE_2D);
1097     glDisable (GL_BLEND);
1098    
1099 root 1.32 EXTEND (SP, 3);
1100     PUSHs (sv_2mortal (newSViv (sw4)));
1101     PUSHs (sv_2mortal (newSViv (sh)));
1102     PUSHs (darkness_sv);
1103 root 1.30 }
1104    
1105 root 1.42 SV *
1106     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1107     CODE:
1108     {
1109     int x, y, x1, y1;
1110     SV *data_sv = newSV (w * h * 7 + 5);
1111     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1112    
1113     *data++ = 0; /* version 0 format */
1114     *data++ = w >> 8; *data++ = w;
1115     *data++ = h >> 8; *data++ = h;
1116    
1117     // we need to do this 'cause we don't keep an absolute coord system for rows
1118 root 1.55 // TODO: treat rows as we treat columns
1119 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1120     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1121    
1122     x0 += self->x - self->ox;
1123     y0 += self->y - self->oy;
1124    
1125     x1 = x0 + w;
1126     y1 = y0 + h;
1127    
1128     for (y = y0; y < y1; y++)
1129     {
1130     maprow *row = 0 <= y && y < self->rows
1131     ? self->row + y
1132     : 0;
1133    
1134     for (x = x0; x < x1; x++)
1135     {
1136     if (row && row->c0 <= x && x < row->c1)
1137     {
1138     mapcell *cell = row->col + (x - row->c0);
1139     uint8_t flags = 0;
1140    
1141     if (cell->face [0]) flags |= 1;
1142     if (cell->face [1]) flags |= 2;
1143     if (cell->face [2]) flags |= 4;
1144    
1145     *data++ = flags;
1146    
1147     if (flags & 1)
1148     {
1149     *data++ = cell->face [0] >> 8;
1150     *data++ = cell->face [0];
1151     }
1152    
1153     if (flags & 2)
1154     {
1155     *data++ = cell->face [1] >> 8;
1156     *data++ = cell->face [1];
1157     }
1158    
1159     if (flags & 4)
1160     {
1161     *data++ = cell->face [2] >> 8;
1162     *data++ = cell->face [2];
1163     }
1164     }
1165     else
1166     *data++ = 0;
1167     }
1168     }
1169    
1170     SvPOK_only (data_sv);
1171     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1172     RETVAL = data_sv;
1173     }
1174     OUTPUT:
1175     RETVAL
1176    
1177     void
1178     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1179     PPCODE:
1180     {
1181     int x, y, z;
1182 root 1.48 int w, h;
1183 root 1.42 int x1, y1;
1184    
1185     if (*data++ != 0)
1186     return; /* version mismatch */
1187    
1188 root 1.48 w = *data++ << 8; w |= *data++;
1189     h = *data++ << 8; h |= *data++;
1190 root 1.42
1191     // we need to do this 'cause we don't keep an absolute coord system for rows
1192 root 1.55 // TODO: treat rows as we treat columns
1193 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1194     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1195    
1196     x0 += self->x - self->ox;
1197     y0 += self->y - self->oy;
1198    
1199     x1 = x0 + w;
1200     y1 = y0 + h;
1201    
1202     for (y = y0; y < y1; y++)
1203     {
1204     maprow *row = map_get_row (self, y);
1205    
1206     for (x = x0; x < x1; x++)
1207     {
1208     uint8_t flags = *data++;
1209    
1210     if (flags)
1211     {
1212     mapface face[3] = { 0, 0, 0 };
1213    
1214     mapcell *cell = row_get_cell (row, x);
1215    
1216     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1217     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1218     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1219    
1220     if (cell->darkness <= 0)
1221     {
1222     cell->darkness = -1;
1223    
1224     for (z = 0; z <= 2; z++)
1225     {
1226     cell->face[z] = face[z];
1227    
1228     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1229     XPUSHs (sv_2mortal (newSViv (face[z])));
1230     }
1231     }
1232     }
1233     }
1234     }
1235     }
1236    
1237 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1238    
1239     CFClient::MixChunk
1240     new_from_file (SV *class, char *path)
1241     CODE:
1242     RETVAL = Mix_LoadWAV (path);
1243     OUTPUT:
1244     RETVAL
1245    
1246     void
1247     DESTROY (CFClient::MixChunk self)
1248     CODE:
1249     Mix_FreeChunk (self);
1250    
1251     int
1252     volume (CFClient::MixChunk self, int volume = -1)
1253     CODE:
1254     RETVAL = Mix_VolumeChunk (self, volume);
1255     OUTPUT:
1256     RETVAL
1257    
1258     int
1259     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1260     CODE:
1261     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1262     OUTPUT:
1263     RETVAL
1264    
1265     MODULE = CFClient PACKAGE = CFClient::MixMusic
1266    
1267     int
1268     volume (int volume = -1)
1269     CODE:
1270     RETVAL = Mix_VolumeMusic (volume);
1271     OUTPUT:
1272     RETVAL
1273    
1274     CFClient::MixMusic
1275     new_from_file (SV *class, char *path)
1276     CODE:
1277     RETVAL = Mix_LoadMUS (path);
1278     OUTPUT:
1279     RETVAL
1280    
1281     void
1282     DESTROY (CFClient::MixMusic self)
1283     CODE:
1284     Mix_FreeMusic (self);
1285    
1286     int
1287     play (CFClient::MixMusic self, int loops = -1)
1288     CODE:
1289     RETVAL = Mix_PlayMusic (self, loops);
1290     OUTPUT:
1291     RETVAL
1292    
1293 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1294    
1295     BOOT:
1296     {
1297     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1298     static const struct {
1299     const char *name;
1300     IV iv;
1301     } *civ, const_iv[] = {
1302     # define const_iv(name) { # name, (IV)name }
1303     const_iv (GL_COLOR_MATERIAL),
1304     const_iv (GL_SMOOTH),
1305     const_iv (GL_FLAT),
1306     const_iv (GL_BLEND),
1307     const_iv (GL_AND),
1308     const_iv (GL_SRC_ALPHA),
1309     const_iv (GL_ONE_MINUS_SRC_ALPHA),
1310     const_iv (GL_RGB),
1311     const_iv (GL_RGBA),
1312     const_iv (GL_UNSIGNED_BYTE),
1313     const_iv (GL_ALPHA4),
1314     const_iv (GL_ALPHA),
1315     const_iv (GL_FLOAT),
1316     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1317     const_iv (GL_COMPILE),
1318     const_iv (GL_TEXTURE_1D),
1319     const_iv (GL_TEXTURE_2D),
1320     const_iv (GL_TEXTURE_ENV),
1321     const_iv (GL_TEXTURE_MAG_FILTER),
1322     const_iv (GL_TEXTURE_MIN_FILTER),
1323     const_iv (GL_TEXTURE_ENV_MODE),
1324     const_iv (GL_TEXTURE_WRAP_S),
1325     const_iv (GL_TEXTURE_WRAP_T),
1326     const_iv (GL_CLAMP),
1327     const_iv (GL_REPEAT),
1328     const_iv (GL_NEAREST),
1329     const_iv (GL_LINEAR),
1330 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1331     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1332     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1333     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1334     const_iv (GL_GENERATE_MIPMAP),
1335     const_iv (GL_LINEAR),
1336 root 1.54 const_iv (GL_MODULATE),
1337     const_iv (GL_REPLACE),
1338     const_iv (GL_COLOR_BUFFER_BIT),
1339     const_iv (GL_PROJECTION),
1340     const_iv (GL_MODELVIEW),
1341     const_iv (GL_COLOR_LOGIC_OP),
1342     const_iv (GL_CONVOLUTION_2D),
1343     const_iv (GL_CONVOLUTION_BORDER_MODE),
1344     const_iv (GL_CONSTANT_BORDER),
1345     const_iv (GL_LINES),
1346     const_iv (GL_QUADS),
1347 root 1.55 const_iv (GL_LINE_LOOP),
1348 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1349     const_iv (GL_FASTEST),
1350     # undef const_iv
1351     };
1352    
1353     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1354     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1355     }
1356    
1357     int glGetError ()
1358    
1359     void glClear (int mask)
1360    
1361     void glClearColor (float r, float g, float b, float a = 1.0)
1362     PROTOTYPE: @
1363    
1364     void glEnable (int cap)
1365    
1366     void glDisable (int cap)
1367    
1368     void glShadeModel (int mode)
1369    
1370     void glHint (int target, int mode)
1371    
1372     void glBlendFunc (int sfactor, int dfactor)
1373    
1374     void glLogicOp (int opcode)
1375    
1376     void glMatrixMode (int mode)
1377    
1378     void glPushMatrix ()
1379    
1380     void glPopMatrix ()
1381    
1382     void glLoadIdentity ()
1383    
1384     void glOrtho (double left, double right, double bottom, double top, double near, double far)
1385    
1386     void glViewport (int x, int y, int width, int height)
1387    
1388     void glTranslate (float x, float y, float z = 0.)
1389     CODE:
1390     glTranslatef (x, y, z);
1391    
1392     void glScale (float x, float y, float z)
1393     CODE:
1394     glScalef (x, y, z);
1395    
1396     void glRotate (float angle, float x, float y, float z)
1397     CODE:
1398     glRotatef (angle, x, y, z);
1399    
1400     void glBegin (int mode)
1401    
1402     void glEnd ()
1403    
1404     void glColor (float r, float g, float b, float a = 1.0)
1405     PROTOTYPE: @
1406     CODE:
1407     glColor4f (r, g, b, a);
1408    
1409     void glVertex (float x, float y, float z = 0.)
1410     CODE:
1411     glVertex3f (x, y, z);
1412    
1413     void glTexCoord (float s, float t)
1414     CODE:
1415     glTexCoord2f (s, t);
1416    
1417     void glTexEnv (int target, int pname, float param)
1418     CODE:
1419     glTexEnvf (target, pname, param);
1420    
1421     void glTexParameter (int target, int pname, float param)
1422     CODE:
1423     glTexParameterf (target, pname, param);
1424    
1425     void glBindTexture (int target, int name)
1426    
1427     void glConvolutionParameter (int target, int pname, float params)
1428     CODE:
1429     glConvolutionParameterf (target, pname, params);
1430    
1431     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1432    
1433     void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1434    
1435     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1436    
1437     int glGenTexture ()
1438     CODE:
1439     {
1440     GLuint name;
1441     glGenTextures (1, &name);
1442     RETVAL = name;
1443     }
1444     OUTPUT:
1445     RETVAL
1446    
1447     void glDeleteTexture (int name)
1448     CODE:
1449     {
1450     GLuint name_ = name;
1451     glDeleteTextures (1, &name_);
1452     }
1453    
1454     int glGenList ()
1455     CODE:
1456     RETVAL = glGenLists (1);
1457     OUTPUT:
1458     RETVAL
1459    
1460     void glDeleteList (int list)
1461     CODE:
1462     glDeleteLists (list, 1);
1463    
1464     void glNewList (int list, int mode = GL_COMPILE)
1465    
1466     void glEndList ()
1467    
1468     void glCallList (int list)
1469