ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.118
Committed: Thu Jun 15 15:47:35 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.117: +13 -10 lines
Log Message:
implemented preliminary magic mapping support

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