ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.130
Committed: Wed Jul 12 17:21:01 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.129: +1 -4 lines
Log Message:
*** empty log message ***

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.129 int
469     in_destruct ()
470     CODE:
471     RETVAL = PL_main_cv == Nullcv;
472     OUTPUT:
473     RETVAL
474    
475 root 1.116 NV floor (NV x)
476    
477     NV ceil (NV x)
478    
479 root 1.79 void
480     pango_init ()
481     CODE:
482     {
483 root 1.124 opengl_fontmap = pango_opengl_font_map_new ();
484     pango_opengl_font_map_set_default_substitute ((PangoOpenGLFontMap *)opengl_fontmap, substitute_func, 0, 0);
485     opengl_context = pango_opengl_font_map_create_context ((PangoOpenGLFontMap *)opengl_fontmap);
486 root 1.5 }
487    
488 root 1.51 int
489 root 1.124 SDL_Init (U32 flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | PARACHUTE)
490 root 1.51
491     void
492     SDL_Quit ()
493    
494     void
495     SDL_ListModes ()
496     PPCODE:
497     {
498     SDL_Rect **m;
499    
500     SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 5);
501     SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 5);
502     SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 5);
503 root 1.88 SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, 1);
504 root 1.51
505 root 1.88 SDL_GL_SetAttribute (SDL_GL_BUFFER_SIZE, 15);
506 root 1.115 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 0);
507 root 1.85
508 root 1.51 SDL_GL_SetAttribute (SDL_GL_ACCUM_RED_SIZE, 0);
509     SDL_GL_SetAttribute (SDL_GL_ACCUM_GREEN_SIZE, 0);
510     SDL_GL_SetAttribute (SDL_GL_ACCUM_BLUE_SIZE, 0);
511     SDL_GL_SetAttribute (SDL_GL_ACCUM_ALPHA_SIZE, 0);
512    
513     SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
514    
515 root 1.53 SDL_EnableUNICODE (1);
516     SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
517    
518 root 1.51 m = SDL_ListModes (0, SDL_FULLSCREEN | SDL_OPENGL);
519    
520     if (m && m != (SDL_Rect **)-1)
521     while (*m)
522     {
523     AV *av = newAV ();
524     av_push (av, newSViv ((*m)->w));
525     av_push (av, newSViv ((*m)->h));
526     XPUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
527    
528     ++m;
529     }
530     }
531    
532 root 1.88 char *
533     SDL_GetError ()
534    
535 root 1.51 int
536     SDL_SetVideoMode (int w, int h, int fullscreen)
537     CODE:
538     RETVAL = !!SDL_SetVideoMode (
539     w, h, 0, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)
540     );
541 root 1.103 if (RETVAL)
542     {
543     SDL_WM_SetCaption ("Crossfire+ Client " VERSION, "Crossfire+");
544     # define GL_FUNC(ptr,name) gl.name = (ptr)SDL_GL_GetProcAddress ("gl" # name);
545     # include "glfunc.h"
546     # undef GL_FUNC
547     }
548 root 1.51 OUTPUT:
549     RETVAL
550    
551 root 1.53 void
552 root 1.54 SDL_GL_SwapBuffers ()
553    
554 root 1.94 char *
555     SDL_GetKeyName (int sym)
556    
557 root 1.54 void
558 root 1.53 SDL_PollEvent ()
559     PPCODE:
560     {
561     SDL_Event ev;
562    
563     while (SDL_PollEvent (&ev))
564     {
565     HV *hv = newHV ();
566     hv_store (hv, "type", 4, newSViv (ev.type), 0);
567 root 1.70
568 root 1.53 switch (ev.type)
569     {
570     case SDL_KEYDOWN:
571     case SDL_KEYUP:
572     hv_store (hv, "state", 5, newSViv (ev.key.state), 0);
573     hv_store (hv, "sym", 3, newSViv (ev.key.keysym.sym), 0);
574     hv_store (hv, "mod", 3, newSViv (ev.key.keysym.mod), 0);
575     hv_store (hv, "unicode", 7, newSViv (ev.key.keysym.unicode), 0);
576     break;
577    
578     case SDL_ACTIVEEVENT:
579     hv_store (hv, "gain", 4, newSViv (ev.active.gain), 0);
580     hv_store (hv, "state", 5, newSViv (ev.active.state), 0);
581     break;
582    
583     case SDL_MOUSEMOTION:
584 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
585 root 1.93
586 root 1.53 hv_store (hv, "state", 5, newSViv (ev.motion.state), 0);
587     hv_store (hv, "x", 1, newSViv (ev.motion.x), 0);
588     hv_store (hv, "y", 1, newSViv (ev.motion.y), 0);
589     hv_store (hv, "xrel", 4, newSViv (ev.motion.xrel), 0);
590     hv_store (hv, "yrel", 4, newSViv (ev.motion.yrel), 0);
591     break;
592    
593     case SDL_MOUSEBUTTONDOWN:
594     case SDL_MOUSEBUTTONUP:
595 root 1.94 hv_store (hv, "mod", 3, newSViv (SDL_GetModState ()), 0);
596 root 1.93
597 root 1.53 hv_store (hv, "button", 6, newSViv (ev.button.button), 0);
598     hv_store (hv, "state", 5, newSViv (ev.button.state), 0);
599     hv_store (hv, "x", 1, newSViv (ev.button.x), 0);
600     hv_store (hv, "y", 1, newSViv (ev.button.y), 0);
601 root 1.70 break;
602 root 1.72
603     case SDL_USEREVENT:
604     hv_store (hv, "code", 4, newSViv (ev.user.code), 0);
605     hv_store (hv, "data1", 5, newSViv ((IV)ev.user.data1), 0);
606     hv_store (hv, "data2", 5, newSViv ((IV)ev.user.data2), 0);
607     break;
608 root 1.53 }
609    
610     XPUSHs (sv_2mortal (newRV_noinc ((SV *)hv)));
611     }
612     }
613 root 1.52
614     int
615 root 1.73 Mix_OpenAudio (int frequency = 48000, int format = MIX_DEFAULT_FORMAT, int channels = 1, int chunksize = 2048)
616 root 1.56 POSTCALL:
617     Mix_HookMusicFinished (music_finished);
618 root 1.71 Mix_ChannelFinished (channel_finished);
619 root 1.52
620     void
621     Mix_CloseAudio ()
622    
623     int
624     Mix_AllocateChannels (int numchans = -1)
625    
626 root 1.10 void
627     lowdelay (int fd, int val = 1)
628     CODE:
629 root 1.48 #ifndef _WIN32
630 root 1.10 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
631 root 1.48 #endif
632 root 1.10
633 root 1.5 void
634 root 1.13 add_font (char *file)
635     CODE:
636 root 1.129 FcConfigAppFontAddFile (0, (const FcChar8 *)file);
637 root 1.13
638     void
639 root 1.23 load_image_inline (SV *image_)
640     ALIAS:
641     load_image_file = 1
642     PPCODE:
643     {
644     STRLEN image_len;
645     char *image = (char *)SvPVbyte (image_, image_len);
646     SDL_Surface *surface, *surface2;
647     SDL_PixelFormat fmt;
648     SDL_RWops *rw = ix
649     ? SDL_RWFromFile (image, "r")
650     : SDL_RWFromConstMem (image, image_len);
651    
652     if (!rw)
653 root 1.41 croak ("load_image: %s", SDL_GetError ());
654 root 1.23
655     surface = IMG_Load_RW (rw, 1);
656     if (!surface)
657 root 1.41 croak ("load_image: %s", SDL_GetError ());
658 root 1.23
659     fmt.palette = NULL;
660     fmt.BitsPerPixel = 32;
661     fmt.BytesPerPixel = 4;
662 root 1.49 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
663 root 1.23 fmt.Rmask = 0x000000ff;
664     fmt.Gmask = 0x0000ff00;
665     fmt.Bmask = 0x00ff0000;
666     fmt.Amask = 0xff000000;
667 root 1.49 #else
668     fmt.Rmask = 0xff000000;
669     fmt.Gmask = 0x00ff0000;
670     fmt.Bmask = 0x0000ff00;
671     fmt.Amask = 0x000000ff;
672     #endif
673 root 1.23 fmt.Rloss = 0;
674     fmt.Gloss = 0;
675     fmt.Bloss = 0;
676     fmt.Aloss = 0;
677     fmt.Rshift = 0;
678     fmt.Gshift = 8;
679     fmt.Bshift = 16;
680     fmt.Ashift = 24;
681     fmt.colorkey = 0;
682     fmt.alpha = 0;
683    
684     surface2 = SDL_ConvertSurface (surface, &fmt, SDL_SWSURFACE);
685    
686 root 1.39 assert (surface2->pitch == surface2->w * 4);
687    
688 root 1.129 SDL_LockSurface (surface2);
689     EXTEND (SP, 6);
690 root 1.23 PUSHs (sv_2mortal (newSViv (surface2->w)));
691     PUSHs (sv_2mortal (newSViv (surface2->h)));
692     PUSHs (sv_2mortal (newSVpvn (surface2->pixels, surface2->h * surface2->pitch)));
693 root 1.116 PUSHs (sv_2mortal (newSViv (surface->flags & (SDL_SRCCOLORKEY | SDL_SRCALPHA) ? GL_RGBA : GL_RGB)));
694 root 1.23 PUSHs (sv_2mortal (newSViv (GL_RGBA)));
695 root 1.49 PUSHs (sv_2mortal (newSViv (GL_UNSIGNED_BYTE)));
696 root 1.129 SDL_UnlockSurface (surface2);
697 root 1.23
698     SDL_FreeSurface (surface);
699     SDL_FreeSurface (surface2);
700     }
701    
702 root 1.25 void
703 root 1.39 average (int x, int y, uint32_t *data)
704     PPCODE:
705     {
706     uint32_t r = 0, g = 0, b = 0, a = 0;
707    
708     x = y = x * y;
709    
710     while (x--)
711     {
712     uint32_t p = *data++;
713    
714     r += (p ) & 255;
715     g += (p >> 8) & 255;
716     b += (p >> 16) & 255;
717     a += (p >> 24) & 255;
718     }
719    
720     EXTEND (SP, 4);
721 root 1.40 PUSHs (sv_2mortal (newSViv (r / y)));
722     PUSHs (sv_2mortal (newSViv (g / y)));
723     PUSHs (sv_2mortal (newSViv (b / y)));
724     PUSHs (sv_2mortal (newSViv (a / y)));
725 root 1.39 }
726    
727     void
728 root 1.66 error (char *message)
729     CODE:
730 root 1.86 fprintf (stderr, "ERROR: %s\n", message);
731 root 1.66 #ifdef _WIN32
732 root 1.86 MessageBox (0, message, "Crossfire+ Error", MB_OK | MB_ICONERROR);
733 root 1.66 #endif
734    
735     void
736 root 1.25 fatal (char *message)
737     CODE:
738 root 1.86 fprintf (stderr, "FATAL: %s\n", message);
739 root 1.50 #ifdef _WIN32
740 root 1.86 MessageBox (0, message, "Crossfire+ Fatal Error", MB_OK | MB_ICONERROR);
741 root 1.25 #endif
742 root 1.112 _exit (1);
743 root 1.111
744     void
745     _exit (int retval)
746     CODE:
747 root 1.112 _exit (retval);
748 root 1.25
749 root 1.61 MODULE = CFClient PACKAGE = CFClient::Font
750    
751     CFClient::Font
752 root 1.70 new_from_file (SV *class, char *path, int id = 0)
753 root 1.61 CODE:
754     {
755     int count;
756 root 1.70 FcPattern *pattern = FcFreeTypeQuery ((const FcChar8 *)path, id, 0, &count);
757 root 1.61 RETVAL = pango_fc_font_description_from_pattern (pattern, 0);
758     FcPatternDestroy (pattern);
759     }
760     OUTPUT:
761     RETVAL
762    
763     void
764     DESTROY (CFClient::Font self)
765     CODE:
766     pango_font_description_free (self);
767    
768     void
769     make_default (CFClient::Font self)
770     CODE:
771     default_font = self;
772    
773 root 1.15 MODULE = CFClient PACKAGE = CFClient::Layout
774 root 1.14
775 root 1.124 void
776 root 1.129 reset_glyph_cache ()
777 root 1.124 CODE:
778     tc_clear ();
779    
780 root 1.15 CFClient::Layout
781 root 1.128 new (SV *class)
782 root 1.14 CODE:
783     New (0, RETVAL, 1, struct cf_layout);
784 root 1.76
785 root 1.124 RETVAL->pl = pango_layout_new (opengl_context);
786 root 1.76 RETVAL->r = 1.;
787     RETVAL->g = 1.;
788     RETVAL->b = 1.;
789     RETVAL->a = 1.;
790     RETVAL->base_height = MIN_FONT_HEIGHT;
791     RETVAL->font = 0;
792    
793 root 1.14 pango_layout_set_wrap (RETVAL->pl, PANGO_WRAP_WORD_CHAR);
794 root 1.76 layout_update_font (RETVAL);
795 root 1.14 OUTPUT:
796     RETVAL
797    
798     void
799 root 1.15 DESTROY (CFClient::Layout self)
800 root 1.14 CODE:
801     g_object_unref (self->pl);
802     Safefree (self);
803 root 1.13
804 root 1.8 void
805 root 1.35 set_text (CFClient::Layout self, SV *text_)
806     CODE:
807     {
808     STRLEN textlen;
809     char *text = SvPVutf8 (text_, textlen);
810    
811     pango_layout_set_text (self->pl, text, textlen);
812     }
813    
814     void
815 root 1.15 set_markup (CFClient::Layout self, SV *text_)
816 root 1.14 CODE:
817 root 1.5 {
818     STRLEN textlen;
819     char *text = SvPVutf8 (text_, textlen);
820 root 1.14
821     pango_layout_set_markup (self->pl, text, textlen);
822     }
823    
824 root 1.121 void
825     set_shapes (CFClient::Layout self, ...)
826     CODE:
827     {
828     PangoAttrList *attrs = 0;
829     const char *text = pango_layout_get_text (self->pl);
830     const char *pos = text;
831 root 1.122 int arg = 4;
832 root 1.121
833     while (arg < items && (pos = strstr (pos, OBJ_STR)))
834     {
835 root 1.122 PangoRectangle inkrect, rect;
836 root 1.121 PangoAttribute *attr;
837    
838 root 1.122 int x = SvIV (ST (arg - 3));
839     int y = SvIV (ST (arg - 2));
840 root 1.121 int w = SvIV (ST (arg - 1));
841 root 1.122 int h = SvIV (ST (arg ));
842 root 1.121
843 root 1.122 inkrect.x = 0;
844     inkrect.y = 0;
845     inkrect.width = 0;
846     inkrect.height = 0;
847    
848     rect.x = x * PANGO_SCALE;
849     rect.y = y * PANGO_SCALE;
850     rect.width = w * PANGO_SCALE;
851 root 1.121 rect.height = h * PANGO_SCALE;
852    
853     if (!attrs)
854     attrs = pango_layout_get_attributes (self->pl);
855    
856 root 1.122 attr = pango_attr_shape_new (&inkrect, &rect);
857 root 1.121 attr->start_index = pos - text;
858     attr->end_index = attr->start_index + sizeof (OBJ_STR) - 1;
859     pango_attr_list_insert (attrs, attr);
860    
861 root 1.122 arg += 4;
862 root 1.121 pos += sizeof (OBJ_STR) - 1;
863     }
864    
865     if (attrs)
866     pango_layout_set_attributes (self->pl, attrs);
867     }
868    
869     void
870     get_shapes (CFClient::Layout self)
871     PPCODE:
872     {
873     PangoLayoutIter *iter = pango_layout_get_iter (self->pl);
874    
875     do
876     {
877     PangoLayoutRun *run = pango_layout_iter_get_run (iter);
878    
879     if (run && shape_attr_p (run))
880     {
881     PangoRectangle extents;
882     pango_layout_iter_get_run_extents (iter, 0, &extents);
883    
884 root 1.129 EXTEND (SP, 2);
885 root 1.121 PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.x))));
886     PUSHs (sv_2mortal (newSViv (PANGO_PIXELS (extents.y))));
887     }
888     }
889     while (pango_layout_iter_next_run (iter));
890    
891     pango_layout_iter_free (iter);
892     }
893    
894     int
895     has_wrapped (CFClient::Layout self)
896     CODE:
897     {
898     int lines = 1;
899     const char *text = pango_layout_get_text (self->pl);
900    
901     while (*text)
902     lines += *text++ == '\n';
903    
904     RETVAL = lines < pango_layout_get_line_count (self->pl);
905     }
906     OUTPUT:
907     RETVAL
908    
909 root 1.46 SV *
910     get_text (CFClient::Layout self)
911     CODE:
912 root 1.47 RETVAL = newSVpv (pango_layout_get_text (self->pl), 0);
913 root 1.107 sv_utf8_decode (RETVAL);
914 root 1.46 OUTPUT:
915     RETVAL
916    
917 root 1.14 void
918 root 1.76 set_foreground (CFClient::Layout self, float r, float g, float b, float a = 1.)
919     CODE:
920     self->r = r;
921     self->g = g;
922     self->b = b;
923     self->a = a;
924    
925     void
926 root 1.61 set_font (CFClient::Layout self, CFClient::Font font = 0)
927     CODE:
928     if (self->font != font)
929     {
930     self->font = font;
931     layout_update_font (self);
932     }
933    
934     void
935 root 1.16 set_height (CFClient::Layout self, int base_height)
936     CODE:
937 root 1.61 if (self->base_height != base_height)
938     {
939     self->base_height = base_height;
940     layout_update_font (self);
941     }
942 root 1.16
943     void
944 root 1.15 set_width (CFClient::Layout self, int max_width = -1)
945 root 1.14 CODE:
946     pango_layout_set_width (self->pl, max_width < 0 ? max_width : max_width * PANGO_SCALE);
947    
948     void
949 root 1.84 set_indent (CFClient::Layout self, int indent)
950     CODE:
951     pango_layout_set_indent (self->pl, indent * PANGO_SCALE);
952    
953     void
954     set_spacing (CFClient::Layout self, int spacing)
955     CODE:
956     pango_layout_set_spacing (self->pl, spacing * PANGO_SCALE);
957    
958     void
959     set_ellipsise (CFClient::Layout self, int ellipsise)
960     CODE:
961     pango_layout_set_ellipsize (self->pl,
962     ellipsise == 1 ? PANGO_ELLIPSIZE_START
963     : ellipsise == 2 ? PANGO_ELLIPSIZE_MIDDLE
964     : ellipsise == 3 ? PANGO_ELLIPSIZE_END
965     : PANGO_ELLIPSIZE_NONE
966     );
967    
968     void
969     set_single_paragraph_mode (CFClient::Layout self, int spm)
970     CODE:
971     pango_layout_set_single_paragraph_mode (self->pl, !!spm);
972    
973     void
974 root 1.15 size (CFClient::Layout self)
975 root 1.14 PPCODE:
976     {
977     int w, h;
978    
979     layout_get_pixel_size (self, &w, &h);
980    
981     EXTEND (SP, 2);
982     PUSHs (sv_2mortal (newSViv (w)));
983     PUSHs (sv_2mortal (newSViv (h)));
984     }
985    
986 root 1.17 int
987 root 1.122 descent (CFClient::Layout self)
988     CODE:
989     {
990     PangoRectangle rect;
991     PangoLayoutLine *line = pango_layout_get_line (self->pl, 0);
992     pango_layout_line_get_pixel_extents (line, 0, &rect);
993     RETVAL = PANGO_DESCENT (rect);
994     }
995     OUTPUT:
996     RETVAL
997    
998     int
999 root 1.17 xy_to_index (CFClient::Layout self, int x, int y)
1000     CODE:
1001     {
1002     int index, trailing;
1003     pango_layout_xy_to_index (self->pl, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing);
1004     RETVAL = index;
1005     }
1006     OUTPUT:
1007     RETVAL
1008    
1009     void
1010     cursor_pos (CFClient::Layout self, int index)
1011     PPCODE:
1012     {
1013     PangoRectangle strong_pos;
1014     pango_layout_get_cursor_pos (self->pl, index, &strong_pos, 0);
1015 root 1.30
1016 root 1.17 EXTEND (SP, 3);
1017     PUSHs (sv_2mortal (newSViv (strong_pos.x / PANGO_SCALE)));
1018     PUSHs (sv_2mortal (newSViv (strong_pos.y / PANGO_SCALE)));
1019     PUSHs (sv_2mortal (newSViv (strong_pos.height / PANGO_SCALE)));
1020     }
1021    
1022 root 1.14 void
1023 root 1.124 render (CFClient::Layout self, float x, float y)
1024 root 1.14 PPCODE:
1025 root 1.124 pango_opengl_render_layout_subpixel (
1026     self->pl,
1027     x * PANGO_SCALE, y * PANGO_SCALE,
1028     self->r, self->g, self->b, self->a
1029     );
1030 root 1.11
1031 root 1.15 MODULE = CFClient PACKAGE = CFClient::Texture
1032 root 1.11
1033     void
1034 root 1.113 pad2pot (SV *data_, SV *w_, SV *h_)
1035     CODE:
1036     {
1037     int ow = SvIV (w_);
1038     int oh = SvIV (h_);
1039    
1040     if (ow && oh)
1041     {
1042     int nw = minpot (ow);
1043     int nh = minpot (oh);
1044    
1045     if (nw != ow || nh != oh)
1046     {
1047     if (SvOK (data_))
1048     {
1049     STRLEN datalen;
1050     char *data = SvPVbyte (data_, datalen);
1051     int bpp = datalen / (ow * oh);
1052     SV *result_ = sv_2mortal (newSV (nw * nh * bpp));
1053    
1054     SvPOK_only (result_);
1055     SvCUR_set (result_, nw * nh * bpp);
1056    
1057     memset (SvPVX (result_), 0, nw * nh * bpp);
1058     while (oh--)
1059     memcpy (SvPVX (result_) + oh * nw * bpp, data + oh * ow * bpp, ow * bpp);
1060    
1061     sv_setsv (data_, result_);
1062     }
1063    
1064     sv_setiv (w_, nw);
1065     sv_setiv (h_, nh);
1066     }
1067     }
1068     }
1069    
1070     void
1071 root 1.114 draw_quad (SV *self, float x, float y, float w = 0., float h = 0.)
1072 root 1.12 PROTOTYPE: $$$;$$
1073 root 1.76 ALIAS:
1074     draw_quad_alpha = 1
1075     draw_quad_alpha_premultiplied = 2
1076 root 1.11 CODE:
1077     {
1078 root 1.12 HV *hv = (HV *)SvRV (self);
1079 root 1.37 float s = SvNV (*hv_fetch (hv, "s", 1, 1));
1080     float t = SvNV (*hv_fetch (hv, "t", 1, 1));
1081 root 1.12 int name = SvIV (*hv_fetch (hv, "name", 4, 1));
1082    
1083     if (items < 5)
1084     {
1085 root 1.18 w = SvNV (*hv_fetch (hv, "w", 1, 1));
1086     h = SvNV (*hv_fetch (hv, "h", 1, 1));
1087 root 1.12 }
1088    
1089 root 1.76 if (ix)
1090     {
1091     glEnable (GL_BLEND);
1092 root 1.103
1093     if (ix == 2)
1094     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1095     else
1096     gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
1097 root 1.104 GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
1098 root 1.103
1099 root 1.86 glEnable (GL_ALPHA_TEST);
1100     glAlphaFunc (GL_GREATER, 0.01f);
1101 root 1.76 }
1102    
1103 root 1.12 glBindTexture (GL_TEXTURE_2D, name);
1104 root 1.76
1105 root 1.12 glBegin (GL_QUADS);
1106 root 1.37 glTexCoord2f (0, 0); glVertex2f (x , y );
1107     glTexCoord2f (0, t); glVertex2f (x , y + h);
1108     glTexCoord2f (s, t); glVertex2f (x + w, y + h);
1109     glTexCoord2f (s, 0); glVertex2f (x + w, y );
1110 root 1.12 glEnd ();
1111 root 1.76
1112     if (ix)
1113 root 1.86 {
1114     glDisable (GL_ALPHA_TEST);
1115     glDisable (GL_BLEND);
1116     }
1117 root 1.11 }
1118 root 1.28
1119     MODULE = CFClient PACKAGE = CFClient::Map
1120    
1121     CFClient::Map
1122     new (SV *class, int map_width, int map_height)
1123     CODE:
1124     New (0, RETVAL, 1, struct map);
1125 root 1.42 RETVAL->x = 0;
1126     RETVAL->y = 0;
1127     RETVAL->w = map_width;
1128     RETVAL->h = map_height;
1129     RETVAL->ox = 0;
1130     RETVAL->oy = 0;
1131 root 1.30 RETVAL->faces = 8192;
1132     Newz (0, RETVAL->face, RETVAL->faces, mapface);
1133 root 1.42 RETVAL->texs = 8192;
1134     Newz (0, RETVAL->tex, RETVAL->texs, maptex);
1135 root 1.28 RETVAL->rows = 0;
1136     RETVAL->row = 0;
1137     OUTPUT:
1138     RETVAL
1139    
1140     void
1141     DESTROY (CFClient::Map self)
1142     CODE:
1143     {
1144 root 1.30 map_clear (self);
1145 root 1.28 Safefree (self->face);
1146 root 1.111 Safefree (self->tex);
1147 root 1.29 Safefree (self);
1148     }
1149    
1150     void
1151 root 1.30 clear (CFClient::Map self)
1152     CODE:
1153     map_clear (self);
1154    
1155     void
1156 root 1.42 set_face (CFClient::Map self, int face, int texid)
1157 root 1.29 CODE:
1158     {
1159 root 1.42 while (self->faces <= face)
1160 root 1.28 {
1161 root 1.30 Append (mapface, self->face, self->faces, self->faces);
1162 root 1.29 self->faces *= 2;
1163     }
1164 root 1.28
1165 root 1.42 self->face [face] = texid;
1166     }
1167    
1168     void
1169     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)
1170     CODE:
1171     {
1172     while (self->texs <= texid)
1173     {
1174     Append (maptex, self->tex, self->texs, self->texs);
1175     self->texs *= 2;
1176     }
1177    
1178 root 1.48 {
1179     maptex *tex = self->tex + texid;
1180 root 1.39
1181 root 1.48 tex->name = name;
1182     tex->w = w;
1183     tex->h = h;
1184     tex->s = s;
1185     tex->t = t;
1186     tex->r = r;
1187     tex->g = g;
1188     tex->b = b;
1189     tex->a = a;
1190     }
1191 root 1.95
1192     // somewhat hackish, but for textures that require it, it really
1193     // improves the look, and most others don't suffer.
1194     glBindTexture (GL_TEXTURE_2D, name);
1195 root 1.99 //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1196     //glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1197     // use uglier nearest interpolation because linear suffers
1198     // from transparent color bleeding and ugly wrapping effects.
1199     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1200 root 1.29 }
1201    
1202 root 1.42 int
1203     ox (CFClient::Map self)
1204     ALIAS:
1205     oy = 1
1206 root 1.101 x = 2
1207     y = 3
1208 root 1.102 w = 4
1209     h = 5
1210 root 1.42 CODE:
1211     switch (ix)
1212     {
1213     case 0: RETVAL = self->ox; break;
1214     case 1: RETVAL = self->oy; break;
1215 root 1.101 case 2: RETVAL = self->x; break;
1216     case 3: RETVAL = self->y; break;
1217 root 1.102 case 4: RETVAL = self->w; break;
1218     case 5: RETVAL = self->h; break;
1219 root 1.42 }
1220     OUTPUT:
1221     RETVAL
1222    
1223 root 1.29 void
1224 root 1.43 scroll (CFClient::Map self, int dx, int dy)
1225     CODE:
1226     {
1227 root 1.44 if (dx > 0)
1228     map_blank (self, self->x, self->y, dx - 1, self->h);
1229     else if (dx < 0)
1230     map_blank (self, self->x + self->w + dx + 1, self->y, 1 - dx, self->h);
1231    
1232     if (dy > 0)
1233     map_blank (self, self->x, self->y, self->w, dy - 1);
1234     else if (dy < 0)
1235     map_blank (self, self->x, self->y + self->h + dy + 1, self->w, 1 - dy);
1236 root 1.43
1237 root 1.44 self->ox += dx; self->x += dx;
1238     self->oy += dy; self->y += dy;
1239 root 1.43
1240     while (self->y < 0)
1241     {
1242     Prepend (maprow, self->row, self->rows, MAP_EXTEND_Y);
1243    
1244     self->rows += MAP_EXTEND_Y;
1245     self->y += MAP_EXTEND_Y;
1246     }
1247 root 1.44 }
1248 root 1.43
1249 root 1.44 void
1250     map1a_update (CFClient::Map self, SV *data_)
1251     CODE:
1252     {
1253 root 1.30 uint8_t *data = (uint8_t *)SvPVbyte_nolen (data_);
1254     uint8_t *data_end = (uint8_t *)SvEND (data_);
1255 root 1.48 mapcell *cell;
1256     int x, y, flags;
1257 root 1.43
1258 root 1.29 while (data < data_end)
1259     {
1260 root 1.48 flags = (data [0] << 8) + data [1]; data += 2;
1261 root 1.30
1262 root 1.120 x = self->x + ((flags >> 10) & 63);
1263     y = self->y + ((flags >> 4) & 63);
1264 root 1.29
1265 root 1.48 cell = map_get_cell (self, x, y);
1266 root 1.29
1267     if (flags & 15)
1268     {
1269 root 1.45 if (cell->darkness < 0)
1270 root 1.29 {
1271     cell->darkness = 0;
1272     cell->face [0] = 0;
1273     cell->face [1] = 0;
1274     cell->face [2] = 0;
1275     }
1276 root 1.45
1277 root 1.29 cell->darkness = flags & 8 ? *data++ : 255;
1278    
1279 root 1.42 //TODO: don't trust server data to be in-range(!)
1280    
1281 root 1.29 if (flags & 4)
1282     {
1283 root 1.42 cell->face [0] = self->face [(data [0] << 8) + data [1]]; data += 2;
1284 root 1.29 }
1285    
1286     if (flags & 2)
1287     {
1288 root 1.42 cell->face [1] = self->face [(data [0] << 8) + data [1]]; data += 2;
1289 root 1.29 }
1290    
1291     if (flags & 1)
1292     {
1293 root 1.42 cell->face [2] = self->face [(data [0] << 8) + data [1]]; data += 2;
1294 root 1.29 }
1295     }
1296     else
1297 root 1.31 cell->darkness = -1;
1298 root 1.29 }
1299 root 1.28 }
1300    
1301 root 1.40 SV *
1302 root 1.55 mapmap (CFClient::Map self, int x0, int y0, int w, int h)
1303 root 1.40 CODE:
1304     {
1305 root 1.55 int x1, x;
1306     int y1, y;
1307 root 1.40 int z;
1308     SV *map_sv = newSV (w * h * sizeof (uint32_t));
1309     uint32_t *map = (uint32_t *)SvPVX (map_sv);
1310    
1311     SvPOK_only (map_sv);
1312     SvCUR_set (map_sv, w * h * sizeof (uint32_t));
1313    
1314 root 1.55 x0 += self->x; x1 = x0 + w;
1315     y0 += self->y; y1 = y0 + h;
1316 root 1.40
1317     for (y = y0; y < y1; y++)
1318     {
1319     maprow *row = 0 <= y && y < self->rows
1320     ? self->row + y
1321     : 0;
1322    
1323     for (x = x0; x < x1; x++)
1324     {
1325     int r = 32, g = 32, b = 32, a = 192;
1326    
1327     if (row && row->c0 <= x && x < row->c1)
1328     {
1329     mapcell *cell = row->col + (x - row->c0);
1330    
1331     for (z = 0; z <= 0; z++)
1332     {
1333 root 1.42 mapface face = cell->face [z];
1334 root 1.40
1335     if (face)
1336     {
1337 root 1.42 maptex tex = self->tex [face];
1338 root 1.40 int a0 = 255 - tex.a;
1339     int a1 = tex.a;
1340    
1341     r = (r * a0 + tex.r * a1) / 255;
1342     g = (g * a0 + tex.g * a1) / 255;
1343     b = (b * a0 + tex.b * a1) / 255;
1344     a = (a * a0 + tex.a * a1) / 255;
1345     }
1346     }
1347     }
1348    
1349     *map++ = (r )
1350     | (g << 8)
1351     | (b << 16)
1352     | (a << 24);
1353     }
1354     }
1355    
1356     RETVAL = map_sv;
1357     }
1358     OUTPUT:
1359     RETVAL
1360    
1361 root 1.30 void
1362 root 1.38 draw (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1363 root 1.116 CODE:
1364 root 1.30 {
1365 root 1.48 int vx, vy;
1366     int x, y, z;
1367     int last_name;
1368     mapface face;
1369    
1370 root 1.120 vx = self->x + self->w / 2 - sw / 2 - shift_x;
1371     vy = self->y + self->h / 2 - sh / 2 - shift_y;
1372 root 1.38
1373 root 1.42 /*
1374     int vx = self->vx = self->w >= sw
1375     ? self->x + (self->w - sw) / 2
1376     : MIN (self->x, MAX (self->x + self->w - sw + 1, self->vx));
1377    
1378     int vy = self->vy = self->h >= sh
1379     ? self->y + (self->h - sh) / 2
1380     : MIN (self->y, MAX (self->y + self->h - sh + 1, self->vy));
1381     */
1382 root 1.30
1383     glColor4ub (255, 255, 255, 255);
1384    
1385 root 1.117 glEnable (GL_BLEND);
1386 root 1.30 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1387     glEnable (GL_TEXTURE_2D);
1388     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1389    
1390 root 1.48 glBegin (GL_QUADS);
1391 root 1.30
1392 root 1.48 last_name = 0;
1393 root 1.30
1394     for (z = 0; z < 3; z++)
1395     for (y = 0; y < sh; y++)
1396     if (0 <= y + vy && y + vy < self->rows)
1397     {
1398     maprow *row = self->row + (y + vy);
1399    
1400     for (x = 0; x < sw; x++)
1401     if (row->c0 <= x + vx && x + vx < row->c1)
1402     {
1403     mapcell *cell = row->col + (x + vx - row->c0);
1404 root 1.32
1405 root 1.48 face = cell->face [z];
1406 root 1.30
1407     if (face)
1408     {
1409 root 1.42 maptex tex = self->tex [face];
1410 root 1.30
1411     int px = (x + 1) * 32 - tex.w;
1412     int py = (y + 1) * 32 - tex.h;
1413    
1414     if (last_name != tex.name)
1415     {
1416     glEnd ();
1417     last_name = tex.name;
1418     glBindTexture (GL_TEXTURE_2D, last_name);
1419     glBegin (GL_QUADS);
1420     }
1421    
1422     glTexCoord2f (0 , 0 ); glVertex2f (px , py );
1423     glTexCoord2f (0 , tex.t); glVertex2f (px , py + tex.h);
1424     glTexCoord2f (tex.s, tex.t); glVertex2f (px + tex.w, py + tex.h);
1425     glTexCoord2f (tex.s, 0 ); glVertex2f (px + tex.w, py );
1426     }
1427     }
1428     }
1429    
1430     glEnd ();
1431 root 1.32
1432 root 1.34 glDisable (GL_TEXTURE_2D);
1433     glDisable (GL_BLEND);
1434 root 1.116 }
1435    
1436     void
1437 root 1.117 draw_magicmap (CFClient::Map self, int dx, int dy, int w, int h, unsigned char *data)
1438     CODE:
1439     {
1440     static float color[16][3] = {
1441 root 1.123 { 0.00F, 0.00F, 0.00F },
1442     { 1.00F, 1.00F, 1.00F },
1443     { 0.00F, 0.00F, 0.55F },
1444     { 1.00F, 0.00F, 0.00F },
1445    
1446     { 1.00F, 0.54F, 0.00F },
1447     { 0.11F, 0.56F, 1.00F },
1448     { 0.93F, 0.46F, 0.00F },
1449     { 0.18F, 0.54F, 0.34F },
1450    
1451     { 0.56F, 0.73F, 0.56F },
1452     { 0.80F, 0.80F, 0.80F },
1453     { 0.55F, 0.41F, 0.13F },
1454     { 0.99F, 0.77F, 0.26F },
1455    
1456     { 0.74F, 0.65F, 0.41F },
1457    
1458     { 0.00F, 1.00F, 1.00F },
1459     { 1.00F, 0.00F, 1.00F },
1460     { 1.00F, 1.00F, 0.00F },
1461 root 1.117 };
1462    
1463     int x, y;
1464    
1465     glEnable (GL_TEXTURE_2D);
1466     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1467     glEnable (GL_BLEND);
1468     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1469     glBegin (GL_QUADS);
1470    
1471     for (y = 0; y < h; y++)
1472     for (x = 0; x < w; x++)
1473     {
1474     unsigned char m = data [x + y * w];
1475    
1476 root 1.118 if (m)
1477     {
1478     float *c = color [m & 15];
1479    
1480     float tx1 = m & 0x40 ? 0.5 : 0.;
1481     float tx2 = tx1 + 0.5;
1482    
1483     glColor4f (c[0], c[1], c[2], 0.75);
1484     glTexCoord2f (tx1, 0.); glVertex2i (x , y );
1485     glTexCoord2f (tx1, 1.); glVertex2i (x , y + 1);
1486     glTexCoord2f (tx2, 1.); glVertex2i (x + 1, y + 1);
1487     glTexCoord2f (tx2, 0.); glVertex2i (x + 1, y );
1488     }
1489 root 1.117 }
1490    
1491     glEnd ();
1492     glDisable (GL_BLEND);
1493     glDisable (GL_TEXTURE_2D);
1494     }
1495    
1496     void
1497 root 1.116 fow_texture (CFClient::Map self, int shift_x, int shift_y, int x0, int y0, int sw, int sh)
1498     PPCODE:
1499     {
1500     int vx, vy;
1501     int x, y;
1502     int sw4 = (sw + 3) & ~3;
1503     SV *darkness_sv = sv_2mortal (newSV (sw4 * sh));
1504     uint8_t *darkness = (uint8_t *)SvPVX (darkness_sv);
1505    
1506     memset (darkness, 255, sw4 * sh);
1507     SvPOK_only (darkness_sv);
1508     SvCUR_set (darkness_sv, sw4 * sh);
1509    
1510     vx = self->x + (self->w - sw + 1) / 2 - shift_x;
1511     vy = self->y + (self->h - sh + 1) / 2 - shift_y;
1512    
1513     for (y = 0; y < sh; y++)
1514     if (0 <= y + vy && y + vy < self->rows)
1515     {
1516     maprow *row = self->row + (y + vy);
1517    
1518     for (x = 0; x < sw; x++)
1519     if (row->c0 <= x + vx && x + vx < row->c1)
1520     {
1521     mapcell *cell = row->col + (x + vx - row->c0);
1522    
1523     darkness[y * sw4 + x] = cell->darkness < 0
1524     ? 255 - FOW_DARKNESS
1525     : 255 - cell->darkness;
1526     }
1527     }
1528 root 1.34
1529 root 1.32 EXTEND (SP, 3);
1530     PUSHs (sv_2mortal (newSViv (sw4)));
1531     PUSHs (sv_2mortal (newSViv (sh)));
1532     PUSHs (darkness_sv);
1533 root 1.30 }
1534    
1535 root 1.42 SV *
1536     get_rect (CFClient::Map self, int x0, int y0, int w, int h)
1537     CODE:
1538     {
1539     int x, y, x1, y1;
1540     SV *data_sv = newSV (w * h * 7 + 5);
1541     uint8_t *data = (uint8_t *)SvPVX (data_sv);
1542    
1543     *data++ = 0; /* version 0 format */
1544     *data++ = w >> 8; *data++ = w;
1545     *data++ = h >> 8; *data++ = h;
1546    
1547     // we need to do this 'cause we don't keep an absolute coord system for rows
1548 root 1.55 // TODO: treat rows as we treat columns
1549 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1550     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1551    
1552     x0 += self->x - self->ox;
1553     y0 += self->y - self->oy;
1554    
1555     x1 = x0 + w;
1556     y1 = y0 + h;
1557    
1558     for (y = y0; y < y1; y++)
1559     {
1560     maprow *row = 0 <= y && y < self->rows
1561     ? self->row + y
1562     : 0;
1563    
1564     for (x = x0; x < x1; x++)
1565     {
1566     if (row && row->c0 <= x && x < row->c1)
1567     {
1568     mapcell *cell = row->col + (x - row->c0);
1569     uint8_t flags = 0;
1570    
1571     if (cell->face [0]) flags |= 1;
1572     if (cell->face [1]) flags |= 2;
1573     if (cell->face [2]) flags |= 4;
1574    
1575     *data++ = flags;
1576    
1577     if (flags & 1)
1578     {
1579     *data++ = cell->face [0] >> 8;
1580     *data++ = cell->face [0];
1581     }
1582    
1583     if (flags & 2)
1584     {
1585     *data++ = cell->face [1] >> 8;
1586     *data++ = cell->face [1];
1587     }
1588    
1589     if (flags & 4)
1590     {
1591     *data++ = cell->face [2] >> 8;
1592     *data++ = cell->face [2];
1593     }
1594     }
1595     else
1596     *data++ = 0;
1597     }
1598     }
1599    
1600     SvPOK_only (data_sv);
1601     SvCUR_set (data_sv, data - (uint8_t *)SvPVX (data_sv));
1602     RETVAL = data_sv;
1603     }
1604     OUTPUT:
1605     RETVAL
1606    
1607     void
1608     set_rect (CFClient::Map self, int x0, int y0, uint8_t *data)
1609     PPCODE:
1610     {
1611     int x, y, z;
1612 root 1.48 int w, h;
1613 root 1.42 int x1, y1;
1614    
1615     if (*data++ != 0)
1616     return; /* version mismatch */
1617    
1618 root 1.48 w = *data++ << 8; w |= *data++;
1619     h = *data++ << 8; h |= *data++;
1620 root 1.42
1621     // we need to do this 'cause we don't keep an absolute coord system for rows
1622 root 1.55 // TODO: treat rows as we treat columns
1623 root 1.42 map_get_row (self, y0 + self->y - self->oy);//D
1624     map_get_row (self, y0 + self->y - self->oy + h - 1);//D
1625    
1626     x0 += self->x - self->ox;
1627     y0 += self->y - self->oy;
1628    
1629     x1 = x0 + w;
1630     y1 = y0 + h;
1631    
1632     for (y = y0; y < y1; y++)
1633     {
1634     maprow *row = map_get_row (self, y);
1635    
1636     for (x = x0; x < x1; x++)
1637     {
1638     uint8_t flags = *data++;
1639    
1640     if (flags)
1641     {
1642     mapface face[3] = { 0, 0, 0 };
1643    
1644     mapcell *cell = row_get_cell (row, x);
1645    
1646     if (flags & 1) { face[0] = *data++ << 8; face[0] |= *data++; }
1647     if (flags & 2) { face[1] = *data++ << 8; face[1] |= *data++; }
1648     if (flags & 4) { face[2] = *data++ << 8; face[2] |= *data++; }
1649    
1650     if (cell->darkness <= 0)
1651     {
1652     cell->darkness = -1;
1653    
1654     for (z = 0; z <= 2; z++)
1655     {
1656     cell->face[z] = face[z];
1657    
1658     if (face[z] && (face[z] >= self->texs || !self->tex[face [z]].name))
1659     XPUSHs (sv_2mortal (newSViv (face[z])));
1660     }
1661     }
1662     }
1663     }
1664     }
1665     }
1666    
1667 root 1.52 MODULE = CFClient PACKAGE = CFClient::MixChunk
1668    
1669     CFClient::MixChunk
1670     new_from_file (SV *class, char *path)
1671     CODE:
1672     RETVAL = Mix_LoadWAV (path);
1673     OUTPUT:
1674     RETVAL
1675    
1676     void
1677     DESTROY (CFClient::MixChunk self)
1678     CODE:
1679     Mix_FreeChunk (self);
1680    
1681     int
1682     volume (CFClient::MixChunk self, int volume = -1)
1683     CODE:
1684     RETVAL = Mix_VolumeChunk (self, volume);
1685     OUTPUT:
1686     RETVAL
1687    
1688     int
1689     play (CFClient::MixChunk self, int channel = -1, int loops = 0, int ticks = -1)
1690     CODE:
1691     RETVAL = Mix_PlayChannelTimed (channel, self, loops, ticks);
1692     OUTPUT:
1693     RETVAL
1694    
1695     MODULE = CFClient PACKAGE = CFClient::MixMusic
1696    
1697     int
1698     volume (int volume = -1)
1699     CODE:
1700     RETVAL = Mix_VolumeMusic (volume);
1701     OUTPUT:
1702     RETVAL
1703    
1704     CFClient::MixMusic
1705     new_from_file (SV *class, char *path)
1706     CODE:
1707     RETVAL = Mix_LoadMUS (path);
1708     OUTPUT:
1709     RETVAL
1710    
1711     void
1712     DESTROY (CFClient::MixMusic self)
1713     CODE:
1714     Mix_FreeMusic (self);
1715    
1716     int
1717     play (CFClient::MixMusic self, int loops = -1)
1718     CODE:
1719     RETVAL = Mix_PlayMusic (self, loops);
1720     OUTPUT:
1721     RETVAL
1722    
1723 root 1.54 MODULE = CFClient PACKAGE = CFClient::OpenGL
1724    
1725     BOOT:
1726     {
1727     HV *stash = gv_stashpv ("CFClient::OpenGL", 1);
1728     static const struct {
1729     const char *name;
1730     IV iv;
1731     } *civ, const_iv[] = {
1732     # define const_iv(name) { # name, (IV)name }
1733     const_iv (GL_COLOR_MATERIAL),
1734     const_iv (GL_SMOOTH),
1735     const_iv (GL_FLAT),
1736 root 1.69 const_iv (GL_DITHER),
1737 root 1.54 const_iv (GL_BLEND),
1738 root 1.89 const_iv (GL_CULL_FACE),
1739 root 1.69 const_iv (GL_SCISSOR_TEST),
1740 root 1.89 const_iv (GL_DEPTH_TEST),
1741     const_iv (GL_ALPHA_TEST),
1742     const_iv (GL_NORMALIZE),
1743     const_iv (GL_RESCALE_NORMAL),
1744 root 1.119 const_iv (GL_FRONT),
1745     const_iv (GL_BACK),
1746 root 1.54 const_iv (GL_AND),
1747 root 1.67 const_iv (GL_ONE),
1748     const_iv (GL_ZERO),
1749 root 1.54 const_iv (GL_SRC_ALPHA),
1750 root 1.104 const_iv (GL_DST_ALPHA),
1751 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1752 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1753 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1754 root 1.54 const_iv (GL_RGB),
1755     const_iv (GL_RGBA),
1756 root 1.115 const_iv (GL_RGBA4),
1757     const_iv (GL_RGBA8),
1758     const_iv (GL_RGB5_A1),
1759 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1760 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1761     const_iv (GL_UNSIGNED_INT),
1762 root 1.54 const_iv (GL_ALPHA),
1763 root 1.86 const_iv (GL_INTENSITY),
1764 root 1.76 const_iv (GL_LUMINANCE),
1765 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1766 root 1.54 const_iv (GL_FLOAT),
1767     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1768     const_iv (GL_COMPILE),
1769     const_iv (GL_TEXTURE_1D),
1770     const_iv (GL_TEXTURE_2D),
1771     const_iv (GL_TEXTURE_ENV),
1772     const_iv (GL_TEXTURE_MAG_FILTER),
1773     const_iv (GL_TEXTURE_MIN_FILTER),
1774     const_iv (GL_TEXTURE_ENV_MODE),
1775     const_iv (GL_TEXTURE_WRAP_S),
1776     const_iv (GL_TEXTURE_WRAP_T),
1777 root 1.98 const_iv (GL_REPEAT),
1778 root 1.54 const_iv (GL_CLAMP),
1779 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1780 root 1.54 const_iv (GL_NEAREST),
1781     const_iv (GL_LINEAR),
1782 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1783     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1784     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1785     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1786     const_iv (GL_GENERATE_MIPMAP),
1787 root 1.54 const_iv (GL_MODULATE),
1788 root 1.69 const_iv (GL_DECAL),
1789 root 1.54 const_iv (GL_REPLACE),
1790 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1791 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1792     const_iv (GL_PROJECTION),
1793     const_iv (GL_MODELVIEW),
1794     const_iv (GL_COLOR_LOGIC_OP),
1795 root 1.69 const_iv (GL_SEPARABLE_2D),
1796 root 1.54 const_iv (GL_CONVOLUTION_2D),
1797     const_iv (GL_CONVOLUTION_BORDER_MODE),
1798     const_iv (GL_CONSTANT_BORDER),
1799     const_iv (GL_LINES),
1800 root 1.89 const_iv (GL_LINE_LOOP),
1801 root 1.54 const_iv (GL_QUADS),
1802 root 1.89 const_iv (GL_QUAD_STRIP),
1803     const_iv (GL_TRIANGLES),
1804     const_iv (GL_TRIANGLE_STRIP),
1805     const_iv (GL_TRIANGLE_FAN),
1806 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1807     const_iv (GL_FASTEST),
1808 root 1.89 const_iv (GL_V2F),
1809     const_iv (GL_V3F),
1810     const_iv (GL_T2F_V3F),
1811     const_iv (GL_T2F_N3F_V3F),
1812 root 1.54 # undef const_iv
1813     };
1814    
1815     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1816     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1817     }
1818    
1819 root 1.97 char *
1820     gl_vendor ()
1821     CODE:
1822     RETVAL = (char *)glGetString (GL_VENDOR);
1823     OUTPUT:
1824     RETVAL
1825    
1826     char *
1827     gl_version ()
1828     CODE:
1829     RETVAL = (char *)glGetString (GL_VERSION);
1830     OUTPUT:
1831     RETVAL
1832    
1833     char *
1834     gl_extensions ()
1835     CODE:
1836     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1837     OUTPUT:
1838     RETVAL
1839    
1840 root 1.54 int glGetError ()
1841    
1842 root 1.114 void glFinish ()
1843    
1844 root 1.54 void glClear (int mask)
1845    
1846     void glClearColor (float r, float g, float b, float a = 1.0)
1847     PROTOTYPE: @
1848    
1849     void glEnable (int cap)
1850    
1851     void glDisable (int cap)
1852    
1853     void glShadeModel (int mode)
1854    
1855     void glHint (int target, int mode)
1856    
1857     void glBlendFunc (int sfactor, int dfactor)
1858    
1859 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1860     CODE:
1861     gl_BlendFuncSeparate (sa, da, saa, daa);
1862    
1863 root 1.89 void glDepthMask (int flag)
1864    
1865 root 1.54 void glLogicOp (int opcode)
1866    
1867 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1868    
1869 root 1.54 void glMatrixMode (int mode)
1870    
1871     void glPushMatrix ()
1872    
1873     void glPopMatrix ()
1874    
1875     void glLoadIdentity ()
1876    
1877 root 1.119 void glDrawBuffer (int buffer)
1878    
1879     void glReadBuffer (int buffer)
1880    
1881 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1882     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1883    
1884     # near_ and far_ are due to microsofts buggy "c" compiler
1885 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1886 root 1.54
1887     void glViewport (int x, int y, int width, int height)
1888    
1889 root 1.69 void glScissor (int x, int y, int width, int height)
1890    
1891 root 1.54 void glTranslate (float x, float y, float z = 0.)
1892     CODE:
1893     glTranslatef (x, y, z);
1894    
1895 root 1.62 void glScale (float x, float y, float z = 1.)
1896 root 1.54 CODE:
1897     glScalef (x, y, z);
1898    
1899     void glRotate (float angle, float x, float y, float z)
1900     CODE:
1901     glRotatef (angle, x, y, z);
1902    
1903     void glBegin (int mode)
1904    
1905     void glEnd ()
1906    
1907     void glColor (float r, float g, float b, float a = 1.0)
1908     PROTOTYPE: @
1909 root 1.103 ALIAS:
1910     glColor_premultiply = 1
1911 root 1.54 CODE:
1912 root 1.103 if (ix)
1913     {
1914     r *= a;
1915     g *= a;
1916     b *= a;
1917     }
1918 root 1.90 // microsoft visual "c" rounds instead of truncating...
1919 root 1.130 glColor4f (r, g, b, a);
1920 root 1.54
1921 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1922    
1923     void glDrawElements (int mode, int count, int type, char *indices)
1924    
1925     # 1.2 void glDrawRangeElements (int mode, int start, int end
1926    
1927 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1928     CODE:
1929     glRasterPos3f (0, 0, z);
1930     glBitmap (0, 0, 0, 0, x, y, 0);
1931    
1932 root 1.54 void glVertex (float x, float y, float z = 0.)
1933     CODE:
1934     glVertex3f (x, y, z);
1935    
1936     void glTexCoord (float s, float t)
1937     CODE:
1938     glTexCoord2f (s, t);
1939    
1940     void glTexEnv (int target, int pname, float param)
1941     CODE:
1942     glTexEnvf (target, pname, param);
1943    
1944     void glTexParameter (int target, int pname, float param)
1945     CODE:
1946     glTexParameterf (target, pname, param);
1947    
1948     void glBindTexture (int target, int name)
1949    
1950     void glConvolutionParameter (int target, int pname, float params)
1951     CODE:
1952 root 1.103 if (gl.ConvolutionParameterf)
1953     gl.ConvolutionParameterf (target, pname, params);
1954 root 1.54
1955     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1956 root 1.64 CODE:
1957 root 1.103 if (gl.ConvolutionFilter2D)
1958     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
1959 root 1.54
1960 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1961     CODE:
1962 root 1.103 if (gl.SeparableFilter2D)
1963     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
1964 root 1.69
1965 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1966    
1967     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1968    
1969 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1970 root 1.68
1971     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1972    
1973 root 1.54 int glGenTexture ()
1974     CODE:
1975     {
1976     GLuint name;
1977     glGenTextures (1, &name);
1978     RETVAL = name;
1979     }
1980     OUTPUT:
1981     RETVAL
1982    
1983     void glDeleteTexture (int name)
1984     CODE:
1985     {
1986     GLuint name_ = name;
1987     glDeleteTextures (1, &name_);
1988     }
1989    
1990     int glGenList ()
1991     CODE:
1992     RETVAL = glGenLists (1);
1993     OUTPUT:
1994     RETVAL
1995    
1996     void glDeleteList (int list)
1997     CODE:
1998     glDeleteLists (list, 1);
1999    
2000     void glNewList (int list, int mode = GL_COMPILE)
2001    
2002     void glEndList ()
2003    
2004     void glCallList (int list)
2005    
2006 root 1.89