ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.128
Committed: Wed Jul 5 03:01:01 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.127: +1 -1 lines
Log Message:
misc. fixes

File Contents

# User Rev Content
1 root 1.48 #ifdef _WIN32
2 root 1.79 # define _WIN32_WINNT 0x0500 // needed to get win2000 api calls
3 root 1.48 # include <malloc.h>
4 root 1.79 # include <windows.h>
5 root 1.75 # pragma warning(disable:4244)
6 root 1.48 #endif
7    
8 root 1.1 #include "EXTERN.h"
9     #include "perl.h"
10     #include "XSUB.h"
11    
12 root 1.80 #include <math.h>
13 root 1.5 #include <string.h>
14 root 1.25 #include <stdio.h>
15 root 1.111 #include <stdlib.h>
16 root 1.5
17 root 1.2 #include <SDL.h>
18 root 1.76 #include <SDL_endian.h>
19 root 1.23 #include <SDL_image.h>
20 root 1.52 #include <SDL_mixer.h>
21 root 1.3 #include <SDL_opengl.h>
22 root 1.5
23 root 1.124 #define PANGO_ENABLE_BACKEND
24     #define G_DISABLE_CAST_CHECKS
25    
26 root 1.30 #include <glib/gmacros.h>
27    
28 root 1.5 #include <pango/pango.h>
29    
30 root 1.48 #ifndef _WIN32
31     # include <sys/types.h>
32     # include <sys/socket.h>
33     # include <netinet/in.h>
34     # include <netinet/tcp.h>
35     # include <inttypes.h>
36     #else
37     typedef unsigned char uint8_t;
38     typedef unsigned short uint16_t;
39     typedef unsigned int uint32_t;
40     typedef signed char int8_t;
41     typedef signed short int16_t;
42     typedef signed int int32_t;
43     #endif
44 root 1.28
45 root 1.57 #include "glext.h"
46    
47 root 1.121 #define OBJ_STR "\xef\xbf\xbc" /* U+FFFC, objetc replacement character */
48    
49 root 1.29 #define FOW_DARKNESS 32
50    
51     #define MAP_EXTEND_X 32
52     #define MAP_EXTEND_Y 512
53    
54 root 1.63 #define MIN_FONT_HEIGHT 10
55 root 1.58
56 root 1.127 #if 0
57 root 1.124 # define PARACHUTE SDL_INIT_NOPARACHUTE
58     #else
59     # define PARACHUTE 0
60     #endif
61    
62 root 1.103 static struct
63     {
64     #define GL_FUNC(ptr,name) ptr name;
65     #include "glfunc.h"
66     #undef GL_FUNC
67     } gl;
68    
69     static void gl_BlendFuncSeparate (GLenum sa, GLenum da, GLenum saa, GLenum daa)
70     {
71     if (gl.BlendFuncSeparate)
72     gl.BlendFuncSeparate (sa, da, saa, daa);
73     else if (gl.BlendFuncSeparateEXT)
74     gl.BlendFuncSeparateEXT (sa, da, saa, daa);
75     else
76     glBlendFunc (sa, da);
77     }
78 root 1.64
79 root 1.124 #include "texcache.c"
80    
81     #include "pango-font.c"
82     #include "pango-fontmap.c"
83     #include "pango-render.c"
84    
85 root 1.52 typedef Mix_Chunk *CFClient__MixChunk;
86     typedef Mix_Music *CFClient__MixMusic;
87    
88 root 1.61 typedef PangoFontDescription *CFClient__Font;
89 root 1.2
90 root 1.121 static int
91     shape_attr_p (PangoLayoutRun *run)
92     {
93     GSList *attrs = run->item->analysis.extra_attrs;
94    
95     while (attrs)
96     {
97     PangoAttribute *attr = attrs->data;
98    
99     if (attr->klass->type == PANGO_ATTR_SHAPE)
100     return 1;
101    
102     attrs = attrs->next;
103     }
104    
105     return 0;
106     }
107    
108 root 1.14 typedef struct cf_layout {
109 root 1.124 PangoLayout *pl;
110 root 1.76 float r, g, b, a; // default color for rgba mode
111 root 1.14 int base_height;
112 root 1.61 CFClient__Font font;
113 root 1.15 } *CFClient__Layout;
114 root 1.14
115 root 1.61 static CFClient__Font default_font;
116 root 1.124 static PangoContext *opengl_context;
117     static PangoFontMap *opengl_fontmap;
118 root 1.61
119 root 1.14 static void
120 root 1.19 substitute_func (FcPattern *pattern, gpointer data)
121     {
122 root 1.108 FcPatternAddBool (pattern, FC_HINTING, 1);
123 root 1.110 #ifdef FC_HINT_STYLE
124 root 1.109 FcPatternAddBool (pattern, FC_HINT_STYLE, FC_HINT_FULL);
125 root 1.110 #endif
126 root 1.82 FcPatternAddBool (pattern, FC_AUTOHINT, 0);
127 root 1.19 }
128    
129     static void
130 root 1.61 layout_update_font (CFClient__Layout self)
131 root 1.17 {
132 root 1.19 /* use a random scale factor to account for unknown descenders, 0.8 works
133     * reasonably well with bitstream vera
134     */
135 root 1.61 PangoFontDescription *font = self->font ? self->font : default_font;
136 root 1.46
137 root 1.61 pango_font_description_set_absolute_size (font,
138     MAX (MIN_FONT_HEIGHT, self->base_height) * (PANGO_SCALE * 8 / 10));
139 root 1.58
140 root 1.61 pango_layout_set_font_description (self->pl, font);
141 root 1.17 }
142    
143     static void
144 root 1.15 layout_get_pixel_size (CFClient__Layout self, int *w, int *h)
145 root 1.14 {
146     pango_layout_get_pixel_size (self->pl, w, h);
147    
148     if (!*w) *w = 1;
149     if (!*h) *h = 1;
150 root 1.76
151     *w = (*w + 3) & ~3;
152 root 1.14 }
153    
154 root 1.42 typedef uint16_t mapface;
155    
156 root 1.28 typedef struct {
157 root 1.30 GLint name;
158     int w, h;
159     float s, t;
160 root 1.39 uint8_t r, g, b, a;
161 root 1.42 } maptex;
162 root 1.30
163     typedef struct {
164 root 1.29 int16_t darkness;
165 root 1.42 mapface face[3];
166 root 1.28 } mapcell;
167    
168     typedef struct {
169 root 1.30 int32_t c0, c1;
170 root 1.28 mapcell *col;
171     } maprow;
172    
173     typedef struct map {
174     int x, y, w, h;
175 root 1.42 int ox, oy; /* offset to virtual global coordinate system */
176 root 1.28 int faces;
177 root 1.30 mapface *face;
178 root 1.28
179 root 1.42 int texs;
180     maptex *tex;
181    
182 root 1.48 int32_t rows;
183 root 1.28 maprow *row;
184     } *CFClient__Map;
185    
186 root 1.30 static char *
187     prepend (char *ptr, int sze, int inc)
188     {
189     char *p;
190    
191     New (0, p, sze + inc, char);
192     Zero (p, inc, char);
193     Move (ptr, p + inc, sze, char);
194     Safefree (ptr);
195    
196     return p;
197     }
198    
199     static char *
200     append (char *ptr, int sze, int inc)
201     {
202     Renew (ptr, sze + inc, char);
203     Zero (ptr + sze, inc, char);
204    
205     return ptr;
206     }
207    
208     #define Append(type,ptr,sze,inc) (ptr) = (type *)append ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
209     #define Prepend(type,ptr,sze,inc) (ptr) = (type *)prepend ((char *)ptr, (sze) * sizeof (type), (inc) * sizeof (type))
210    
211 root 1.42 static maprow *
212     map_get_row (CFClient__Map self, int y)
213     {
214     if (0 > y)
215     {
216     int extend = - y + MAP_EXTEND_Y;
217     Prepend (maprow, self->row, self->rows, extend);
218    
219     self->rows += extend;
220     self->y += extend;
221     y += extend;
222     }
223     else if (y >= self->rows)
224     {
225     int extend = y - self->rows + MAP_EXTEND_Y;
226     Append (maprow, self->row, self->rows, extend);
227     self->rows += extend;
228     }
229    
230     return self->row + y;
231     }
232    
233     static mapcell *
234     row_get_cell (maprow *row, int x)
235     {
236     if (!row->col)
237     {
238     Newz (0, row->col, MAP_EXTEND_X, mapcell);
239     row->c0 = x - MAP_EXTEND_X / 4;
240     row->c1 = row->c0 + MAP_EXTEND_X;
241     }
242    
243     if (row->c0 > x)
244     {
245     int extend = row->c0 - x + MAP_EXTEND_X;
246     Prepend (mapcell, row->col, row->c1 - row->c0, extend);
247     row->c0 -= extend;
248     }
249     else if (x >= row->c1)
250     {
251     int extend = x - row->c1 + MAP_EXTEND_X;
252     Append (mapcell, row->col, row->c1 - row->c0, extend);
253     row->c1 += extend;
254     }
255    
256     return row->col + (x - row->c0);
257     }
258    
259     static mapcell *
260     map_get_cell (CFClient__Map self, int x, int y)
261     {
262     return row_get_cell (map_get_row (self, y), x);
263     }
264    
265 root 1.30 static void
266     map_clear (CFClient__Map self)
267     {
268     int r;
269    
270     for (r = 0; r < self->rows; r++)
271     Safefree (self->row[r].col);
272    
273     Safefree (self->row);
274    
275     self->x = 0;
276     self->y = 0;
277 root 1.42 self->ox = 0;
278     self->oy = 0;
279 root 1.30 self->row = 0;
280     self->rows = 0;
281     }
282    
283 root 1.29 static void
284     map_blank (CFClient__Map self, int x0, int y0, int w, int h)
285     {
286     int x, y;
287 root 1.48 maprow *row;
288 root 1.29
289     for (y = y0; y < y0 + h; y++)
290 root 1.30 if (y >= 0)
291     {
292     if (y >= self->rows)
293     break;
294    
295 root 1.48 row = self->row + y;
296 root 1.30
297     for (x = x0; x < x0 + w; x++)
298     if (x >= row->c0)
299     {
300     if (x >= row->c1)
301     break;
302 root 1.29
303 root 1.31 row->col[x - row->c0].darkness = -1;
304 root 1.30 }
305     }
306 root 1.29 }
307    
308 root 1.56 static void
309 root 1.75 music_finished (void)
310 root 1.56 {
311     SDL_UserEvent ev;
312    
313     ev.type = SDL_USEREVENT;
314     ev.code = 0;
315     ev.data1 = 0;
316     ev.data2 = 0;
317    
318 root 1.57 SDL_PushEvent ((SDL_Event *)&ev);
319 root 1.56 }
320    
321 root 1.71 static void
322     channel_finished (int channel)
323     {
324     SDL_UserEvent ev;
325    
326     ev.type = SDL_USEREVENT;
327     ev.code = 1;
328 root 1.74 ev.data1 = (void *)(long)channel;
329 root 1.71 ev.data2 = 0;
330    
331     SDL_PushEvent ((SDL_Event *)&ev);
332     }
333    
334 root 1.113 static unsigned int
335     minpot (unsigned int n)
336     {
337     if (!n)
338     return 0;
339    
340     --n;
341    
342     n |= n >> 1;
343     n |= n >> 2;
344     n |= n >> 4;
345     n |= n >> 8;
346     n |= n >> 16;
347    
348     return n + 1;
349     }
350    
351 root 1.15 MODULE = CFClient PACKAGE = CFClient
352 root 1.1
353 root 1.11 PROTOTYPES: ENABLE
354    
355 root 1.5 BOOT:
356     {
357 root 1.51 HV *stash = gv_stashpv ("CFClient", 1);
358     static const struct {
359     const char *name;
360     IV iv;
361     } *civ, const_iv[] = {
362     # define const_iv(name) { # name, (IV)name }
363     const_iv (SDL_ACTIVEEVENT),
364     const_iv (SDL_KEYDOWN),
365     const_iv (SDL_KEYUP),
366     const_iv (SDL_MOUSEMOTION),
367     const_iv (SDL_MOUSEBUTTONDOWN),
368     const_iv (SDL_MOUSEBUTTONUP),
369     const_iv (SDL_JOYAXISMOTION),
370     const_iv (SDL_JOYBALLMOTION),
371     const_iv (SDL_JOYHATMOTION),
372     const_iv (SDL_JOYBUTTONDOWN),
373     const_iv (SDL_JOYBUTTONUP),
374     const_iv (SDL_QUIT),
375     const_iv (SDL_SYSWMEVENT),
376     const_iv (SDL_EVENT_RESERVEDA),
377     const_iv (SDL_EVENT_RESERVEDB),
378     const_iv (SDL_VIDEORESIZE),
379     const_iv (SDL_VIDEOEXPOSE),
380     const_iv (SDL_USEREVENT),
381     const_iv (SDLK_KP0),
382     const_iv (SDLK_KP1),
383     const_iv (SDLK_KP2),
384     const_iv (SDLK_KP3),
385     const_iv (SDLK_KP4),
386     const_iv (SDLK_KP5),
387     const_iv (SDLK_KP6),
388     const_iv (SDLK_KP7),
389     const_iv (SDLK_KP8),
390     const_iv (SDLK_KP9),
391     const_iv (SDLK_KP_PERIOD),
392     const_iv (SDLK_KP_DIVIDE),
393     const_iv (SDLK_KP_MULTIPLY),
394     const_iv (SDLK_KP_MINUS),
395     const_iv (SDLK_KP_PLUS),
396     const_iv (SDLK_KP_ENTER),
397     const_iv (SDLK_KP_EQUALS),
398     const_iv (SDLK_UP),
399     const_iv (SDLK_DOWN),
400     const_iv (SDLK_RIGHT),
401     const_iv (SDLK_LEFT),
402     const_iv (SDLK_INSERT),
403     const_iv (SDLK_HOME),
404     const_iv (SDLK_END),
405     const_iv (SDLK_PAGEUP),
406     const_iv (SDLK_PAGEDOWN),
407     const_iv (SDLK_F1),
408     const_iv (SDLK_F2),
409     const_iv (SDLK_F3),
410     const_iv (SDLK_F4),
411     const_iv (SDLK_F5),
412     const_iv (SDLK_F6),
413     const_iv (SDLK_F7),
414     const_iv (SDLK_F8),
415     const_iv (SDLK_F9),
416     const_iv (SDLK_F10),
417     const_iv (SDLK_F11),
418     const_iv (SDLK_F12),
419     const_iv (SDLK_F13),
420     const_iv (SDLK_F14),
421     const_iv (SDLK_F15),
422     const_iv (SDLK_NUMLOCK),
423     const_iv (SDLK_CAPSLOCK),
424     const_iv (SDLK_SCROLLOCK),
425     const_iv (SDLK_RSHIFT),
426     const_iv (SDLK_LSHIFT),
427     const_iv (SDLK_RCTRL),
428     const_iv (SDLK_LCTRL),
429     const_iv (SDLK_RALT),
430     const_iv (SDLK_LALT),
431     const_iv (SDLK_RMETA),
432     const_iv (SDLK_LMETA),
433     const_iv (SDLK_LSUPER),
434     const_iv (SDLK_RSUPER),
435     const_iv (SDLK_MODE),
436     const_iv (SDLK_COMPOSE),
437     const_iv (SDLK_HELP),
438     const_iv (SDLK_PRINT),
439     const_iv (SDLK_SYSREQ),
440     const_iv (SDLK_BREAK),
441     const_iv (SDLK_MENU),
442     const_iv (SDLK_POWER),
443     const_iv (SDLK_EURO),
444     const_iv (SDLK_UNDO),
445     const_iv (KMOD_NONE),
446     const_iv (KMOD_LSHIFT),
447     const_iv (KMOD_RSHIFT),
448     const_iv (KMOD_LCTRL),
449     const_iv (KMOD_RCTRL),
450     const_iv (KMOD_LALT),
451     const_iv (KMOD_RALT),
452     const_iv (KMOD_LMETA),
453     const_iv (KMOD_RMETA),
454     const_iv (KMOD_NUM),
455     const_iv (KMOD_CAPS),
456     const_iv (KMOD_MODE),
457     const_iv (KMOD_CTRL),
458     const_iv (KMOD_SHIFT),
459     const_iv (KMOD_ALT),
460     const_iv (KMOD_META)
461     # undef const_iv
462     };
463    
464     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
465     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
466 root 1.79 }
467 root 1.51
468 root 1.116 NV floor (NV x)
469    
470     NV ceil (NV x)
471    
472 root 1.79 void
473     pango_init ()
474     CODE:
475     {
476 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
477     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
478     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
479 root 1.5 }
480    
481 root 1.51 int
482 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
483 root 1.51
484     void
485     SDL_Quit ()
486    
487     void
488     SDL_ListModes ()
489     PPCODE:
490     {
491     SDL_Rect **m;
492    
493     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
494     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
495     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
496 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
497 root 1.51
498 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
499 root 1.115 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
500 root 1.85
501 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
502     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
503     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
504     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
505    
506     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
507    
508 root 1.53 SDL_EnableUNICODE (1);
509     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
510    
511 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
512    
513     if (m && m != (SDL_Rect **)-1)
514     while (*m)
515     {
516     AV *av = newAV ();
517     av_push (av, newSViv ((*m)->w));
518     av_push (av, newSViv ((*m)->h));
519     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
520    
521     ++m;
522     }
523     }
524    
525 root 1.88 char *
526     SDL_GetError ()
527    
528 root 1.51 int
529     SDL_SetVideoMode (int w, int h, int fullscreen)
530     CODE:
531     RETVAL = !!SDL_SetVideoMode (
532     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
533     );
534 root 1.103 if (RETVAL)
535     {
536     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
537     # define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
538     # include "glfunc.h"
539     # undef GL_FUNC
540     }
541 root 1.51 OUTPUT:
542     RETVAL
543    
544 root 1.53 void
545 root 1.54 SDL_GL_SwapBuffers ()
546    
547 root 1.94 char *
548     SDL_GetKeyName (int sym)
549    
550 root 1.54 void
551 root 1.53 SDL_PollEvent ()
552     PPCODE:
553     {
554     SDL_Event ev;
555    
556     while (SDL_PollEvent (&ev))
557     {
558     HV *hv = newHV ();
559     hv_store (hv, "type", 4, newSViv (ev.type), 0);
560 root 1.70
561 root 1.53 switch (ev.type)
562     {
563     case SDL_KEYDOWN:
564     case SDL_KEYUP:
565     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
566     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
567     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
568     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
569     break;
570    
571     case SDL_ACTIVEEVENT:
572     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
573     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
574     break;
575    
576     case SDL_MOUSEMOTION:
577 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
578 root 1.93
579 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
580     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
581     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
582     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
583     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
584     break;
585    
586     case SDL_MOUSEBUTTONDOWN:
587     case SDL_MOUSEBUTTONUP:
588 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
589 root 1.93
590 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
591     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
592     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
593     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
594 root 1.70 break;
595 root 1.72
596     case SDL_USEREVENT:
597     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
598     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
599     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
600     break;
601 root 1.53 }
602    
603     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
604     }
605     }
606 root 1.52
607     int
608 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
609 root 1.56 POSTCALL:
610     Mix_HookMusicFinished (music_finished);
611 root 1.71 Mix_ChannelFinished (channel_finished);
612 root 1.52
613     void
614     Mix_CloseAudio ()
615    
616     int
617     Mix_AllocateChannels (int numchans = -1)
618    
619 root 1.10 void
620     lowdelay (int fd, int val = 1)
621     CODE:
622 root 1.48 #ifndef _WIN32
623 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
624 root 1.48 #endif
625 root 1.10
626 root 1.5 void
627 root 1.13 add_font (char *file)
628     CODE:
629     FcConfigAppFontAddFile (0, (const FcChar8 *)file); /* no idea wether this is required */
630    
631     void
632 root 1.23 load_image_inline (SV *image_)
633     ALIAS:
634     load_image_file = 1
635     PPCODE:
636     {
637     STRLEN image_len;
638     char *image = (char *)SvPVbyte (image_, image_len);
639     SDL_Surface *surface, *surface2;
640     SDL_PixelFormat fmt;
641     SDL_RWops *rw = ix
642     ? SDL_RWFromFile (image, "r")
643     : SDL_RWFromConstMem (image, image_len);
644    
645     if (!rw)
646 root 1.41 croak ("load_image: %s", SDL_GetError ());
647 root 1.23
648     surface = IMG_Load_RW (rw, 1);
649     if (!surface)
650 root 1.41 croak ("load_image: %s", SDL_GetError ());
651 root 1.23
652     fmt.palette = NULL;
653     fmt.BitsPerPixel = 32;
654     fmt.BytesPerPixel = 4;
655 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
656 root 1.23 fmt.Rmask = 0x000000ff;
657     fmt.Gmask = 0x0000ff00;
658     fmt.Bmask = 0x00ff0000;
659     fmt.Amask = 0xff000000;
660 root 1.49 #else
661     fmt.Rmask = 0xff000000;
662     fmt.Gmask = 0x00ff0000;
663     fmt.Bmask = 0x0000ff00;
664     fmt.Amask = 0x000000ff;
665     #endif
666 root 1.23 fmt.Rloss = 0;
667     fmt.Gloss = 0;
668     fmt.Bloss = 0;
669     fmt.Aloss = 0;
670     fmt.Rshift = 0;
671     fmt.Gshift = 8;
672     fmt.Bshift = 16;
673     fmt.Ashift = 24;
674     fmt.colorkey = 0;
675     fmt.alpha = 0;
676    
677     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
678    
679 root 1.39 assert (surface2->pitch == surface2->w * 4);
680    
681 root 1.23 EXTEND (SP, 5);
682     PUSHs (sv_2mortal (newSViv (surface2->w)));
683     PUSHs (sv_2mortal (newSViv (surface2->h)));
684     SDL_LockSurface (surface2);
685     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
686     SDL_UnlockSurface (surface2);
687 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
688 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
689 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
690 root 1.23
691     SDL_FreeSurface (surface);
692     SDL_FreeSurface (surface2);
693     }
694    
695 root 1.25 void
696 root 1.39 average (int x, int y, uint32_t *data)
697     PPCODE:
698     {
699     uint32_t r = 0, g = 0, b = 0, a = 0;
700    
701     x = y = x * y;
702    
703     while (x--)
704     {
705     uint32_t p = *data++;
706    
707     r += (p ) & 255;
708     g += (p >> 8) & 255;
709     b += (p >> 16) & 255;
710     a += (p >> 24) & 255;
711     }
712    
713     EXTEND (SP, 4);
714 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
715     PUSHs (sv_2mortal (newSViv (g / y)));
716     PUSHs (sv_2mortal (newSViv (b / y)));
717     PUSHs (sv_2mortal (newSViv (a / y)));
718 root 1.39 }
719    
720     void
721 root 1.66 error (char *message)
722     CODE:
723 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
724 root 1.66 #ifdef _WIN32
725 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
726 root 1.66 #endif
727    
728     void
729 root 1.25 fatal (char *message)
730     CODE:
731 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
732 root 1.50 #ifdef _WIN32
733 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
734 root 1.25 #endif
735 root 1.112 _exit (1);
736 root 1.111
737     void
738     _exit (int retval)
739     CODE:
740 root 1.112 _exit (retval);
741 root 1.25
742 root 1.61 MODULE = CFClient PACKAGE = CFClient::Font
743    
744     CFClient::Font
745 root 1.70 new_from_file (SV *class, char *path, int id = 0)
746 root 1.61 CODE:
747     {
748     int count;
749 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
750 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
751     FcPatternDestroy (pattern);
752     }
753     OUTPUT:
754     RETVAL
755    
756     void
757     DESTROY (CFClient::Font self)
758     CODE:
759     pango_font_description_free (self);
760    
761     void
762     make_default (CFClient::Font self)
763     CODE:
764     default_font = self;
765    
766 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
767 root 1.14
768 root 1.124 void
769     clear_font_cache ()
770     CODE:
771     tc_clear ();
772    
773 root 1.15 CFClient::Layout
774 root 1.128 new (SV *class)
775 root 1.14 CODE:
776     New (0, RETVAL, 1, struct cf_layout);
777 root 1.76
778 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
779 root 1.76 RETVAL->r = 1.;
780     RETVAL->g = 1.;
781     RETVAL->b = 1.;
782     RETVAL->a = 1.;
783     RETVAL->base_height = MIN_FONT_HEIGHT;
784     RETVAL->font = 0;
785    
786 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
787 root 1.76 layout_update_font (RETVAL);
788 root 1.14 OUTPUT:
789     RETVAL
790    
791     void
792 root 1.15 DESTROY (CFClient::Layout self)
793 root 1.14 CODE:
794     g_object_unref (self->pl);
795     Safefree (self);
796 root 1.13
797 root 1.8 void
798 root 1.35 set_text (CFClient::Layout self, SV *text_)
799     CODE:
800     {
801     STRLEN textlen;
802     char *text = SvPVutf8 (text_, textlen);
803    
804     pango_layout_set_text (self->pl, text, textlen);
805     }
806    
807     void
808 root 1.15 set_markup (CFClient::Layout self, SV *text_)
809 root 1.14 CODE:
810 root 1.5 {
811     STRLEN textlen;
812     char *text = SvPVutf8 (text_, textlen);
813 root 1.14
814     pango_layout_set_markup (self->pl, text, textlen);
815     }
816    
817 root 1.121 void
818     set_shapes (CFClient::Layout self, ...)
819     CODE:
820     {
821     PangoAttrList *attrs = 0;
822     const char *text = pango_layout_get_text (self->pl);
823     const char *pos = text;
824 root 1.122 int arg = 4;
825 root 1.121
826     while (arg < items && (pos = strstr (pos, OBJ_STR)))
827     {
828 root 1.122 PangoRectangle inkrect, rect;
829 root 1.121 PangoAttribute *attr;
830    
831 root 1.122 int x = SvIV (ST (arg - 3));
832     int y = SvIV (ST (arg - 2));
833 root 1.121 int w = SvIV (ST (arg - 1));
834 root 1.122 int h = SvIV (ST (arg ));
835 root 1.121
836 root 1.122 inkrect.x = 0;
837     inkrect.y = 0;
838     inkrect.width = 0;
839     inkrect.height = 0;
840    
841     rect.x = x * PANGO_SCALE;
842     rect.y = y * PANGO_SCALE;
843     rect.width = w * PANGO_SCALE;
844 root 1.121 rect.height = h * PANGO_SCALE;
845    
846     if (!attrs)
847     attrs = pango_layout_get_attributes (self->pl);
848    
849 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
850 root 1.121 attr->start_index = pos - text;
851     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
852     pango_attr_list_insert (attrs, attr);
853    
854 root 1.122 arg += 4;
855 root 1.121 pos += sizeof (OBJ_STR) - 1;
856     }
857    
858     if (attrs)
859     pango_layout_set_attributes (self->pl, attrs);
860     }
861    
862     void
863     get_shapes (CFClient::Layout self)
864     PPCODE:
865     {
866     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
867    
868     do
869     {
870     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
871    
872     if (run && shape_attr_p (run))
873     {
874     PangoRectangle extents;
875     pango_layout_iter_get_run_extents (iter, 0, &extents);
876    
877     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
878     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
879     }
880     }
881     while (pango_layout_iter_next_run (iter));
882    
883     pango_layout_iter_free (iter);
884     }
885    
886     int
887     has_wrapped (CFClient::Layout self)
888     CODE:
889     {
890     int lines = 1;
891     const char *text = pango_layout_get_text (self->pl);
892    
893     while (*text)
894     lines += *text++ == '\n';
895    
896     RETVAL = lines < pango_layout_get_line_count (self->pl);
897     }
898     OUTPUT:
899     RETVAL
900    
901 root 1.46 SV *
902     get_text (CFClient::Layout self)
903     CODE:
904 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
905 root 1.107 sv_utf8_decode (RETVAL);
906 root 1.46 OUTPUT:
907     RETVAL
908    
909 root 1.14 void
910 root 1.76 set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.)
911     CODE:
912     self->r = r;
913     self->g = g;
914     self->b = b;
915     self->a = a;
916    
917     void
918 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
919     CODE:
920     if (self->font != font)
921     {
922     self->font = font;
923     layout_update_font (self);
924     }
925    
926     void
927 root 1.16 set_height (CFClient::Layout self, int base_height)
928     CODE:
929 root 1.61 if (self->base_height != base_height)
930     {
931     self->base_height = base_height;
932     layout_update_font (self);
933     }
934 root 1.16
935     void
936 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
937 root 1.14 CODE:
938     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
939    
940     void
941 root 1.84 set_indent (CFClient::Layout self, int indent)
942     CODE:
943     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
944    
945     void
946     set_spacing (CFClient::Layout self, int spacing)
947     CODE:
948     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
949    
950     void
951     set_ellipsise (CFClient::Layout self, int ellipsise)
952     CODE:
953     pango_layout_set_ellipsize (self->pl,
954     ellipsise == 1 ? PANGO_ELLIPSIZE_START
955     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
956     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
957     : PANGO_ELLIPSIZE_NONE
958     );
959    
960     void
961     set_single_paragraph_mode (CFClient::Layout self, int spm)
962     CODE:
963     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
964    
965     void
966 root 1.15 size (CFClient::Layout self)
967 root 1.14 PPCODE:
968     {
969     int w, h;
970    
971     layout_get_pixel_size (self, &w, &h);
972    
973     EXTEND (SP, 2);
974     PUSHs (sv_2mortal (newSViv (w)));
975     PUSHs (sv_2mortal (newSViv (h)));
976     }
977    
978 root 1.17 int
979 root 1.122 descent (CFClient::Layout self)
980     CODE:
981     {
982     PangoRectangle rect;
983     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
984     pango_layout_line_get_pixel_extents (line, 0, &rect);
985     RETVAL = PANGO_DESCENT (rect);
986     }
987     OUTPUT:
988     RETVAL
989    
990     int
991 root 1.17 xy_to_index (CFClient::Layout self, int x, int y)
992     CODE:
993     {
994     int index, trailing;
995     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
996     RETVAL = index;
997     }
998     OUTPUT:
999     RETVAL
1000    
1001     void
1002     cursor_pos (CFClient::Layout self, int index)
1003     PPCODE:
1004     {
1005     PangoRectangle strong_pos;
1006     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1007 root 1.30
1008 root 1.17 EXTEND (SP, 3);
1009     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1010     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1011     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1012     }
1013    
1014 root 1.14 void
1015 root 1.124 render (CFClient::Layout self, float x, float y)
1016 root 1.14 PPCODE:
1017 root 1.124 pango_opengl_render_layout_subpixel (
1018     self->pl,
1019     x * PANGO_SCALE, y * PANGO_SCALE,
1020     self->r, self->g, self->b, self->a
1021     );
1022 root 1.11
1023 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
1024 root 1.11
1025     void
1026 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1027     CODE:
1028     {
1029     int ow = SvIV (w_);
1030     int oh = SvIV (h_);
1031    
1032     if (ow && oh)
1033     {
1034     int nw = minpot (ow);
1035     int nh = minpot (oh);
1036    
1037     if (nw != ow || nh != oh)
1038     {
1039     if (SvOK (data_))
1040     {
1041     STRLEN datalen;
1042     char *data = SvPVbyte (data_, datalen);
1043     int bpp = datalen / (ow * oh);
1044     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1045    
1046     SvPOK_only (result_);
1047     SvCUR_set (result_, nw * nh * bpp);
1048    
1049     memset (SvPVX (result_), 0, nw * nh * bpp);
1050     while (oh--)
1051     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1052    
1053     sv_setsv (data_, result_);
1054     }
1055    
1056     sv_setiv (w_, nw);
1057     sv_setiv (h_, nh);
1058     }
1059     }
1060     }
1061    
1062     void
1063 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1064 root 1.12 PROTOTYPE: $$$;$$
1065 root 1.76 ALIAS:
1066     draw_quad_alpha = 1
1067     draw_quad_alpha_premultiplied = 2
1068 root 1.11 CODE:
1069     {
1070 root 1.12 HV *hv = (HV *)SvRV (self);
1071 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1072     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1073 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1074    
1075     if (items < 5)
1076     {
1077 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1078     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1079 root 1.12 }
1080    
1081 root 1.76 if (ix)
1082     {
1083     glEnable (GL_BLEND);
1084 root 1.103
1085     if (ix == 2)
1086     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1087     else
1088     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1089 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1090 root 1.103
1091 root 1.86 glEnable (GL_ALPHA_TEST);
1092     glAlphaFunc (GL_GREATER, 0.01f);
1093 root 1.76 }
1094    
1095 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1096 root 1.76
1097 root 1.12 glBegin (GL_QUADS);
1098 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1099     glTexCoord2f (0, t); glVertex2f (x , y + h);
1100     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1101     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1102 root 1.12 glEnd ();
1103 root 1.76
1104     if (ix)
1105 root 1.86 {
1106     glDisable (GL_ALPHA_TEST);
1107     glDisable (GL_BLEND);
1108     }
1109 root 1.11 }
1110 root 1.28
1111     MODULE = CFClient PACKAGE = CFClient::Map
1112    
1113     CFClient::Map
1114     new (SV *class, int map_width, int map_height)
1115     CODE:
1116     New (0, RETVAL, 1, struct map);
1117 root 1.42 RETVAL->x = 0;
1118     RETVAL->y = 0;
1119     RETVAL->w = map_width;
1120     RETVAL->h = map_height;
1121     RETVAL->ox = 0;
1122     RETVAL->oy = 0;
1123 root 1.30 RETVAL->faces = 8192;
1124     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1125 root 1.42 RETVAL->texs = 8192;
1126     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1127 root 1.28 RETVAL->rows = 0;
1128     RETVAL->row = 0;
1129     OUTPUT:
1130     RETVAL
1131    
1132     void
1133     DESTROY (CFClient::Map self)
1134     CODE:
1135     {
1136 root 1.30 map_clear (self);
1137 root 1.28 Safefree (self->face);
1138 root 1.111 Safefree (self->tex);
1139 root 1.29 Safefree (self);
1140     }
1141    
1142     void
1143 root 1.30 clear (CFClient::Map self)
1144     CODE:
1145     map_clear (self);
1146    
1147     void
1148 root 1.42 set_face (CFClient::Map self, int face, int texid)
1149 root 1.29 CODE:
1150     {
1151 root 1.42 while (self->faces <= face)
1152 root 1.28 {
1153 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1154 root 1.29 self->faces *= 2;
1155     }
1156 root 1.28
1157 root 1.42 self->face [face] = texid;
1158     }
1159    
1160     void
1161     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)
1162     CODE:
1163     {
1164     while (self->texs <= texid)
1165     {
1166     Append (maptex, self->tex, self->texs, self->texs);
1167     self->texs *= 2;
1168     }
1169    
1170 root 1.48 {
1171     maptex *tex = self->tex + texid;
1172 root 1.39
1173 root 1.48 tex->name = name;
1174     tex->w = w;
1175     tex->h = h;
1176     tex->s = s;
1177     tex->t = t;
1178     tex->r = r;
1179     tex->g = g;
1180     tex->b = b;
1181     tex->a = a;
1182     }
1183 root 1.95
1184     // somewhat hackish, but for textures that require it, it really
1185     // improves the look, and most others don't suffer.
1186     glBindTexture (GL_TEXTURE_2D, name);
1187 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1188     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1189     // use uglier nearest interpolation because linear suffers
1190     // from transparent color bleeding and ugly wrapping effects.
1191     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1192 root 1.29 }
1193    
1194 root 1.42 int
1195     ox (CFClient::Map self)
1196     ALIAS:
1197     oy = 1
1198 root 1.101 x = 2
1199     y = 3
1200 root 1.102 w = 4
1201     h = 5
1202 root 1.42 CODE:
1203     switch (ix)
1204     {
1205     case 0: RETVAL = self->ox; break;
1206     case 1: RETVAL = self->oy; break;
1207 root 1.101 case 2: RETVAL = self->x; break;
1208     case 3: RETVAL = self->y; break;
1209 root 1.102 case 4: RETVAL = self->w; break;
1210     case 5: RETVAL = self->h; break;
1211 root 1.42 }
1212     OUTPUT:
1213     RETVAL
1214    
1215 root 1.29 void
1216 root 1.43 scroll (CFClient::Map self, int dx, int dy)
1217     CODE:
1218     {
1219 root 1.44 if (dx > 0)
1220     map_blank (self, self->x, self->y, dx - 1, self->h);
1221     else if (dx < 0)
1222     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1223    
1224     if (dy > 0)
1225     map_blank (self, self->x, self->y, self->w, dy - 1);
1226     else if (dy < 0)
1227     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1228 root 1.43
1229 root 1.44 self->ox += dx; self->x += dx;
1230     self->oy += dy; self->y += dy;
1231 root 1.43
1232     while (self->y < 0)
1233     {
1234     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1235    
1236     self->rows += MAP_EXTEND_Y;
1237     self->y += MAP_EXTEND_Y;
1238     }
1239 root 1.44 }
1240 root 1.43
1241 root 1.44 void
1242     map1a_update (CFClient::Map self, SV *data_)
1243     CODE:
1244     {
1245 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1246     uint8_t *data_end = (uint8_t *)SvEND (data_);
1247 root 1.48 mapcell *cell;
1248     int x, y, flags;
1249 root 1.43
1250 root 1.29 while (data < data_end)
1251     {
1252 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1253 root 1.30
1254 root 1.120 x = self->x + ((flags >> 10) & 63);
1255     y = self->y + ((flags >> 4) & 63);
1256 root 1.29
1257 root 1.48 cell = map_get_cell (self, x, y);
1258 root 1.29
1259     if (flags & 15)
1260     {
1261 root 1.45 if (cell->darkness < 0)
1262 root 1.29 {
1263     cell->darkness = 0;
1264     cell->face [0] = 0;
1265     cell->face [1] = 0;
1266     cell->face [2] = 0;
1267     }
1268 root 1.45
1269 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1270    
1271 root 1.42 //TODO: don't trust server data to be in-range(!)
1272    
1273 root 1.29 if (flags & 4)
1274     {
1275 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1276 root 1.29 }
1277    
1278     if (flags & 2)
1279     {
1280 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1281 root 1.29 }
1282    
1283     if (flags & 1)
1284     {
1285 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1286 root 1.29 }
1287     }
1288     else
1289 root 1.31 cell->darkness = -1;
1290 root 1.29 }
1291 root 1.28 }
1292    
1293 root 1.40 SV *
1294 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1295 root 1.40 CODE:
1296     {
1297 root 1.55 int x1, x;
1298     int y1, y;
1299 root 1.40 int z;
1300     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1301     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1302    
1303     SvPOK_only (map_sv);
1304     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1305    
1306 root 1.55 x0 += self->x; x1 = x0 + w;
1307     y0 += self->y; y1 = y0 + h;
1308 root 1.40
1309     for (y = y0; y < y1; y++)
1310     {
1311     maprow *row = 0 <= y && y < self->rows
1312     ? self->row + y
1313     : 0;
1314    
1315     for (x = x0; x < x1; x++)
1316     {
1317     int r = 32, g = 32, b = 32, a = 192;
1318    
1319     if (row && row->c0 <= x && x < row->c1)
1320     {
1321     mapcell *cell = row->col + (x - row->c0);
1322    
1323     for (z = 0; z <= 0; z++)
1324     {
1325 root 1.42 mapface face = cell->face [z];
1326 root 1.40
1327     if (face)
1328     {
1329 root 1.42 maptex tex = self->tex [face];
1330 root 1.40 int a0 = 255 - tex.a;
1331     int a1 = tex.a;
1332    
1333     r = (r * a0 + tex.r * a1) / 255;
1334     g = (g * a0 + tex.g * a1) / 255;
1335     b = (b * a0 + tex.b * a1) / 255;
1336     a = (a * a0 + tex.a * a1) / 255;
1337     }
1338     }
1339     }
1340    
1341     *map++ = (r )
1342     | (g << 8)
1343     | (b << 16)
1344     | (a << 24);
1345     }
1346     }
1347    
1348     RETVAL = map_sv;
1349     }
1350     OUTPUT:
1351     RETVAL
1352    
1353 root 1.30 void
1354 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1355 root 1.116 CODE:
1356 root 1.30 {
1357 root 1.48 int vx, vy;
1358     int x, y, z;
1359     int last_name;
1360     mapface face;
1361    
1362 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1363     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1364 root 1.38
1365 root 1.42 /*
1366     int vx = self->vx = self->w >= sw
1367     ? self->x + (self->w - sw) / 2
1368     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1369    
1370     int vy = self->vy = self->h >= sh
1371     ? self->y + (self->h - sh) / 2
1372     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1373     */
1374 root 1.30
1375     glColor4ub (255, 255, 255, 255);
1376    
1377 root 1.117 glEnable (GL_BLEND);
1378 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1379     glEnable (GL_TEXTURE_2D);
1380     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1381    
1382 root 1.48 glBegin (GL_QUADS);
1383 root 1.30
1384 root 1.48 last_name = 0;
1385 root 1.30
1386     for (z = 0; z < 3; z++)
1387     for (y = 0; y < sh; y++)
1388     if (0 <= y + vy && y + vy < self->rows)
1389     {
1390     maprow *row = self->row + (y + vy);
1391    
1392     for (x = 0; x < sw; x++)
1393     if (row->c0 <= x + vx && x + vx < row->c1)
1394     {
1395     mapcell *cell = row->col + (x + vx - row->c0);
1396 root 1.32
1397 root 1.48 face = cell->face [z];
1398 root 1.30
1399     if (face)
1400     {
1401 root 1.42 maptex tex = self->tex [face];
1402 root 1.30
1403     int px = (x + 1) * 32 - tex.w;
1404     int py = (y + 1) * 32 - tex.h;
1405    
1406     if (last_name != tex.name)
1407     {
1408     glEnd ();
1409     last_name = tex.name;
1410     glBindTexture (GL_TEXTURE_2D, last_name);
1411     glBegin (GL_QUADS);
1412     }
1413    
1414     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1415     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1416     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1417     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1418     }
1419     }
1420     }
1421    
1422     glEnd ();
1423 root 1.32
1424 root 1.34 glDisable (GL_TEXTURE_2D);
1425     glDisable (GL_BLEND);
1426 root 1.116 }
1427    
1428     void
1429 root 1.117 draw_magicmap (CFClient::Map self, int dx, int dy, int w, int h, unsigned char *data)
1430     CODE:
1431     {
1432     static float color[16][3] = {
1433 root 1.123 { 0.00F, 0.00F, 0.00F },
1434     { 1.00F, 1.00F, 1.00F },
1435     { 0.00F, 0.00F, 0.55F },
1436     { 1.00F, 0.00F, 0.00F },
1437    
1438     { 1.00F, 0.54F, 0.00F },
1439     { 0.11F, 0.56F, 1.00F },
1440     { 0.93F, 0.46F, 0.00F },
1441     { 0.18F, 0.54F, 0.34F },
1442    
1443     { 0.56F, 0.73F, 0.56F },
1444     { 0.80F, 0.80F, 0.80F },
1445     { 0.55F, 0.41F, 0.13F },
1446     { 0.99F, 0.77F, 0.26F },
1447    
1448     { 0.74F, 0.65F, 0.41F },
1449    
1450     { 0.00F, 1.00F, 1.00F },
1451     { 1.00F, 0.00F, 1.00F },
1452     { 1.00F, 1.00F, 0.00F },
1453 root 1.117 };
1454    
1455     int x, y;
1456    
1457     glEnable (GL_TEXTURE_2D);
1458     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1459     glEnable (GL_BLEND);
1460     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1461     glBegin (GL_QUADS);
1462    
1463     for (y = 0; y < h; y++)
1464     for (x = 0; x < w; x++)
1465     {
1466     unsigned char m = data [x + y * w];
1467    
1468 root 1.118 if (m)
1469     {
1470     float *c = color [m & 15];
1471    
1472     float tx1 = m & 0x40 ? 0.5 : 0.;
1473     float tx2 = tx1 + 0.5;
1474    
1475     glColor4f (c[0], c[1], c[2], 0.75);
1476     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1477     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1478     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1479     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1480     }
1481 root 1.117 }
1482    
1483     glEnd ();
1484     glDisable (GL_BLEND);
1485     glDisable (GL_TEXTURE_2D);
1486     }
1487    
1488     void
1489 root 1.116 fow_texture (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1490     PPCODE:
1491     {
1492     int vx, vy;
1493     int x, y;
1494     int sw4 = (sw + 3) & ~3;
1495     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1496     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1497    
1498     memset (darkness, 255, sw4 * sh);
1499     SvPOK_only (darkness_sv);
1500     SvCUR_set (darkness_sv, sw4 * sh);
1501    
1502     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1503     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1504    
1505     for (y = 0; y < sh; y++)
1506     if (0 <= y + vy && y + vy < self->rows)
1507     {
1508     maprow *row = self->row + (y + vy);
1509    
1510     for (x = 0; x < sw; x++)
1511     if (row->c0 <= x + vx && x + vx < row->c1)
1512     {
1513     mapcell *cell = row->col + (x + vx - row->c0);
1514    
1515     darkness[y * sw4 + x] = cell->darkness < 0
1516     ? 255 - FOW_DARKNESS
1517     : 255 - cell->darkness;
1518     }
1519     }
1520 root 1.34
1521 root 1.32 EXTEND (SP, 3);
1522     PUSHs (sv_2mortal (newSViv (sw4)));
1523     PUSHs (sv_2mortal (newSViv (sh)));
1524     PUSHs (darkness_sv);
1525 root 1.30 }
1526    
1527 root 1.42 SV *
1528     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1529     CODE:
1530     {
1531     int x, y, x1, y1;
1532     SV *data_sv = newSV (w * h * 7 + 5);
1533     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1534    
1535     *data++ = 0; /* version 0 format */
1536     *data++ = w >> 8; *data++ = w;
1537     *data++ = h >> 8; *data++ = h;
1538    
1539     // we need to do this 'cause we don't keep an absolute coord system for rows
1540 root 1.55 // TODO: treat rows as we treat columns
1541 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1542     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1543    
1544     x0 += self->x - self->ox;
1545     y0 += self->y - self->oy;
1546    
1547     x1 = x0 + w;
1548     y1 = y0 + h;
1549    
1550     for (y = y0; y < y1; y++)
1551     {
1552     maprow *row = 0 <= y && y < self->rows
1553     ? self->row + y
1554     : 0;
1555    
1556     for (x = x0; x < x1; x++)
1557     {
1558     if (row && row->c0 <= x && x < row->c1)
1559     {
1560     mapcell *cell = row->col + (x - row->c0);
1561     uint8_t flags = 0;
1562    
1563     if (cell->face [0]) flags |= 1;
1564     if (cell->face [1]) flags |= 2;
1565     if (cell->face [2]) flags |= 4;
1566    
1567     *data++ = flags;
1568    
1569     if (flags & 1)
1570     {
1571     *data++ = cell->face [0] >> 8;
1572     *data++ = cell->face [0];
1573     }
1574    
1575     if (flags & 2)
1576     {
1577     *data++ = cell->face [1] >> 8;
1578     *data++ = cell->face [1];
1579     }
1580    
1581     if (flags & 4)
1582     {
1583     *data++ = cell->face [2] >> 8;
1584     *data++ = cell->face [2];
1585     }
1586     }
1587     else
1588     *data++ = 0;
1589     }
1590     }
1591    
1592     SvPOK_only (data_sv);
1593     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1594     RETVAL = data_sv;
1595     }
1596     OUTPUT:
1597     RETVAL
1598    
1599     void
1600     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1601     PPCODE:
1602     {
1603     int x, y, z;
1604 root 1.48 int w, h;
1605 root 1.42 int x1, y1;
1606    
1607     if (*data++ != 0)
1608     return; /* version mismatch */
1609    
1610 root 1.48 w = *data++ << 8; w |= *data++;
1611     h = *data++ << 8; h |= *data++;
1612 root 1.42
1613     // we need to do this 'cause we don't keep an absolute coord system for rows
1614 root 1.55 // TODO: treat rows as we treat columns
1615 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1616     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1617    
1618     x0 += self->x - self->ox;
1619     y0 += self->y - self->oy;
1620    
1621     x1 = x0 + w;
1622     y1 = y0 + h;
1623    
1624     for (y = y0; y < y1; y++)
1625     {
1626     maprow *row = map_get_row (self, y);
1627    
1628     for (x = x0; x < x1; x++)
1629     {
1630     uint8_t flags = *data++;
1631    
1632     if (flags)
1633     {
1634     mapface face[3] = { 0, 0, 0 };
1635    
1636     mapcell *cell = row_get_cell (row, x);
1637    
1638     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1639     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1640     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1641    
1642     if (cell->darkness <= 0)
1643     {
1644     cell->darkness = -1;
1645    
1646     for (z = 0; z <= 2; z++)
1647     {
1648     cell->face[z] = face[z];
1649    
1650     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1651     XPUSHs (sv_2mortal (newSViv (face[z])));
1652     }
1653     }
1654     }
1655     }
1656     }
1657     }
1658    
1659 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1660    
1661     CFClient::MixChunk
1662     new_from_file (SV *class, char *path)
1663     CODE:
1664     RETVAL = Mix_LoadWAV (path);
1665     OUTPUT:
1666     RETVAL
1667    
1668     void
1669     DESTROY (CFClient::MixChunk self)
1670     CODE:
1671     Mix_FreeChunk (self);
1672    
1673     int
1674     volume (CFClient::MixChunk self, int volume = -1)
1675     CODE:
1676     RETVAL = Mix_VolumeChunk (self, volume);
1677     OUTPUT:
1678     RETVAL
1679    
1680     int
1681     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1682     CODE:
1683     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1684     OUTPUT:
1685     RETVAL
1686    
1687     MODULE = CFClient PACKAGE = CFClient::MixMusic
1688    
1689     int
1690     volume (int volume = -1)
1691     CODE:
1692     RETVAL = Mix_VolumeMusic (volume);
1693     OUTPUT:
1694     RETVAL
1695    
1696     CFClient::MixMusic
1697     new_from_file (SV *class, char *path)
1698     CODE:
1699     RETVAL = Mix_LoadMUS (path);
1700     OUTPUT:
1701     RETVAL
1702    
1703     void
1704     DESTROY (CFClient::MixMusic self)
1705     CODE:
1706     Mix_FreeMusic (self);
1707    
1708     int
1709     play (CFClient::MixMusic self, int loops = -1)
1710     CODE:
1711     RETVAL = Mix_PlayMusic (self, loops);
1712     OUTPUT:
1713     RETVAL
1714    
1715 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1716    
1717     BOOT:
1718     {
1719     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1720     static const struct {
1721     const char *name;
1722     IV iv;
1723     } *civ, const_iv[] = {
1724     # define const_iv(name) { # name, (IV)name }
1725     const_iv (GL_COLOR_MATERIAL),
1726     const_iv (GL_SMOOTH),
1727     const_iv (GL_FLAT),
1728 root 1.69 const_iv (GL_DITHER),
1729 root 1.54 const_iv (GL_BLEND),
1730 root 1.89 const_iv (GL_CULL_FACE),
1731 root 1.69 const_iv (GL_SCISSOR_TEST),
1732 root 1.89 const_iv (GL_DEPTH_TEST),
1733     const_iv (GL_ALPHA_TEST),
1734     const_iv (GL_NORMALIZE),
1735     const_iv (GL_RESCALE_NORMAL),
1736 root 1.119 const_iv (GL_FRONT),
1737     const_iv (GL_BACK),
1738 root 1.54 const_iv (GL_AND),
1739 root 1.67 const_iv (GL_ONE),
1740     const_iv (GL_ZERO),
1741 root 1.54 const_iv (GL_SRC_ALPHA),
1742 root 1.104 const_iv (GL_DST_ALPHA),
1743 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1744 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1745 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1746 root 1.54 const_iv (GL_RGB),
1747     const_iv (GL_RGBA),
1748 root 1.115 const_iv (GL_RGBA4),
1749     const_iv (GL_RGBA8),
1750     const_iv (GL_RGB5_A1),
1751 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1752 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1753     const_iv (GL_UNSIGNED_INT),
1754 root 1.54 const_iv (GL_ALPHA),
1755 root 1.86 const_iv (GL_INTENSITY),
1756 root 1.76 const_iv (GL_LUMINANCE),
1757 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1758 root 1.54 const_iv (GL_FLOAT),
1759     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1760     const_iv (GL_COMPILE),
1761     const_iv (GL_TEXTURE_1D),
1762     const_iv (GL_TEXTURE_2D),
1763     const_iv (GL_TEXTURE_ENV),
1764     const_iv (GL_TEXTURE_MAG_FILTER),
1765     const_iv (GL_TEXTURE_MIN_FILTER),
1766     const_iv (GL_TEXTURE_ENV_MODE),
1767     const_iv (GL_TEXTURE_WRAP_S),
1768     const_iv (GL_TEXTURE_WRAP_T),
1769 root 1.98 const_iv (GL_REPEAT),
1770 root 1.54 const_iv (GL_CLAMP),
1771 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1772 root 1.54 const_iv (GL_NEAREST),
1773     const_iv (GL_LINEAR),
1774 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1775     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1776     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1777     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1778     const_iv (GL_GENERATE_MIPMAP),
1779 root 1.54 const_iv (GL_MODULATE),
1780 root 1.69 const_iv (GL_DECAL),
1781 root 1.54 const_iv (GL_REPLACE),
1782 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1783 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1784     const_iv (GL_PROJECTION),
1785     const_iv (GL_MODELVIEW),
1786     const_iv (GL_COLOR_LOGIC_OP),
1787 root 1.69 const_iv (GL_SEPARABLE_2D),
1788 root 1.54 const_iv (GL_CONVOLUTION_2D),
1789     const_iv (GL_CONVOLUTION_BORDER_MODE),
1790     const_iv (GL_CONSTANT_BORDER),
1791     const_iv (GL_LINES),
1792 root 1.89 const_iv (GL_LINE_LOOP),
1793 root 1.54 const_iv (GL_QUADS),
1794 root 1.89 const_iv (GL_QUAD_STRIP),
1795     const_iv (GL_TRIANGLES),
1796     const_iv (GL_TRIANGLE_STRIP),
1797     const_iv (GL_TRIANGLE_FAN),
1798 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1799     const_iv (GL_FASTEST),
1800 root 1.89 const_iv (GL_V2F),
1801     const_iv (GL_V3F),
1802     const_iv (GL_T2F_V3F),
1803     const_iv (GL_T2F_N3F_V3F),
1804 root 1.54 # undef const_iv
1805     };
1806    
1807     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1808     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1809     }
1810    
1811 root 1.97 char *
1812     gl_vendor ()
1813     CODE:
1814     RETVAL = (char *)glGetString (GL_VENDOR);
1815     OUTPUT:
1816     RETVAL
1817    
1818     char *
1819     gl_version ()
1820     CODE:
1821     RETVAL = (char *)glGetString (GL_VERSION);
1822     OUTPUT:
1823     RETVAL
1824    
1825     char *
1826     gl_extensions ()
1827     CODE:
1828     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1829     OUTPUT:
1830     RETVAL
1831    
1832 root 1.54 int glGetError ()
1833    
1834 root 1.114 void glFinish ()
1835    
1836 root 1.54 void glClear (int mask)
1837    
1838     void glClearColor (float r, float g, float b, float a = 1.0)
1839     PROTOTYPE: @
1840    
1841     void glEnable (int cap)
1842    
1843     void glDisable (int cap)
1844    
1845     void glShadeModel (int mode)
1846    
1847     void glHint (int target, int mode)
1848    
1849     void glBlendFunc (int sfactor, int dfactor)
1850    
1851 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1852     CODE:
1853     gl_BlendFuncSeparate (sa, da, saa, daa);
1854    
1855 root 1.89 void glDepthMask (int flag)
1856    
1857 root 1.54 void glLogicOp (int opcode)
1858    
1859 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1860    
1861 root 1.54 void glMatrixMode (int mode)
1862    
1863     void glPushMatrix ()
1864    
1865     void glPopMatrix ()
1866    
1867     void glLoadIdentity ()
1868    
1869 root 1.119 void glDrawBuffer (int buffer)
1870    
1871     void glReadBuffer (int buffer)
1872    
1873 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1874     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1875    
1876     # near_ and far_ are due to microsofts buggy "c" compiler
1877 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1878 root 1.54
1879     void glViewport (int x, int y, int width, int height)
1880    
1881 root 1.69 void glScissor (int x, int y, int width, int height)
1882    
1883 root 1.54 void glTranslate (float x, float y, float z = 0.)
1884     CODE:
1885     glTranslatef (x, y, z);
1886    
1887 root 1.62 void glScale (float x, float y, float z = 1.)
1888 root 1.54 CODE:
1889     glScalef (x, y, z);
1890    
1891     void glRotate (float angle, float x, float y, float z)
1892     CODE:
1893     glRotatef (angle, x, y, z);
1894    
1895     void glBegin (int mode)
1896    
1897     void glEnd ()
1898    
1899     void glColor (float r, float g, float b, float a = 1.0)
1900     PROTOTYPE: @
1901 root 1.103 ALIAS:
1902     glColor_premultiply = 1
1903 root 1.54 CODE:
1904 root 1.103 if (ix)
1905     {
1906     r *= a;
1907     g *= a;
1908     b *= a;
1909     }
1910 root 1.90 // microsoft visual "c" rounds instead of truncating...
1911 root 1.100 glColor4ub (MIN ((int)(r * 256.f), 255),
1912     MIN ((int)(g * 256.f), 255),
1913     MIN ((int)(b * 256.f), 255),
1914     MIN ((int)(a * 256.f), 255));
1915 root 1.54
1916 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1917    
1918     void glDrawElements (int mode, int count, int type, char *indices)
1919    
1920     # 1.2 void glDrawRangeElements (int mode, int start, int end
1921    
1922 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1923     CODE:
1924     glRasterPos3f (0, 0, z);
1925     glBitmap (0, 0, 0, 0, x, y, 0);
1926    
1927 root 1.54 void glVertex (float x, float y, float z = 0.)
1928     CODE:
1929     glVertex3f (x, y, z);
1930    
1931     void glTexCoord (float s, float t)
1932     CODE:
1933     glTexCoord2f (s, t);
1934    
1935     void glTexEnv (int target, int pname, float param)
1936     CODE:
1937     glTexEnvf (target, pname, param);
1938    
1939     void glTexParameter (int target, int pname, float param)
1940     CODE:
1941     glTexParameterf (target, pname, param);
1942    
1943     void glBindTexture (int target, int name)
1944    
1945     void glConvolutionParameter (int target, int pname, float params)
1946     CODE:
1947 root 1.103 if (gl.ConvolutionParameterf)
1948     gl.ConvolutionParameterf (target, pname, params);
1949 root 1.54
1950     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1951 root 1.64 CODE:
1952 root 1.103 if (gl.ConvolutionFilter2D)
1953     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
1954 root 1.54
1955 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1956     CODE:
1957 root 1.103 if (gl.SeparableFilter2D)
1958     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
1959 root 1.69
1960 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1961    
1962     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1963    
1964 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1965 root 1.68
1966     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1967    
1968 root 1.54 int glGenTexture ()
1969     CODE:
1970     {
1971     GLuint name;
1972     glGenTextures (1, &name);
1973     RETVAL = name;
1974     }
1975     OUTPUT:
1976     RETVAL
1977    
1978     void glDeleteTexture (int name)
1979     CODE:
1980     {
1981     GLuint name_ = name;
1982     glDeleteTextures (1, &name_);
1983     }
1984    
1985     int glGenList ()
1986     CODE:
1987     RETVAL = glGenLists (1);
1988     OUTPUT:
1989     RETVAL
1990    
1991     void glDeleteList (int list)
1992     CODE:
1993     glDeleteLists (list, 1);
1994    
1995     void glNewList (int list, int mode = GL_COMPILE)
1996    
1997     void glEndList ()
1998    
1999     void glCallList (int list)
2000    
2001 root 1.89