ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.119
Committed: Sat Jun 17 15:07:52 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.118: +6 -0 lines
Log Message:
free textures on vidoe shutdown, seems useless, but maybe fixes scaras problem

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.119 const_iv (GL_FRONT),
1721     const_iv (GL_BACK),
1722 root 1.54 const_iv (GL_AND),
1723 root 1.67 const_iv (GL_ONE),
1724     const_iv (GL_ZERO),
1725 root 1.54 const_iv (GL_SRC_ALPHA),
1726 root 1.104 const_iv (GL_DST_ALPHA),
1727 root 1.54 const_iv (GL_ONE_MINUS_SRC_ALPHA),
1728 root 1.67 const_iv (GL_ONE_MINUS_DST_ALPHA),
1729 root 1.104 const_iv (GL_SRC_ALPHA_SATURATE),
1730 root 1.54 const_iv (GL_RGB),
1731     const_iv (GL_RGBA),
1732 root 1.115 const_iv (GL_RGBA4),
1733     const_iv (GL_RGBA8),
1734     const_iv (GL_RGB5_A1),
1735 root 1.54 const_iv (GL_UNSIGNED_BYTE),
1736 root 1.89 const_iv (GL_UNSIGNED_SHORT),
1737     const_iv (GL_UNSIGNED_INT),
1738 root 1.54 const_iv (GL_ALPHA),
1739 root 1.86 const_iv (GL_INTENSITY),
1740 root 1.76 const_iv (GL_LUMINANCE),
1741 root 1.86 const_iv (GL_LUMINANCE_ALPHA),
1742 root 1.54 const_iv (GL_FLOAT),
1743     const_iv (GL_UNSIGNED_INT_8_8_8_8_REV),
1744     const_iv (GL_COMPILE),
1745     const_iv (GL_TEXTURE_1D),
1746     const_iv (GL_TEXTURE_2D),
1747     const_iv (GL_TEXTURE_ENV),
1748     const_iv (GL_TEXTURE_MAG_FILTER),
1749     const_iv (GL_TEXTURE_MIN_FILTER),
1750     const_iv (GL_TEXTURE_ENV_MODE),
1751     const_iv (GL_TEXTURE_WRAP_S),
1752     const_iv (GL_TEXTURE_WRAP_T),
1753 root 1.98 const_iv (GL_REPEAT),
1754 root 1.54 const_iv (GL_CLAMP),
1755 root 1.98 const_iv (GL_CLAMP_TO_EDGE),
1756 root 1.54 const_iv (GL_NEAREST),
1757     const_iv (GL_LINEAR),
1758 root 1.57 const_iv (GL_NEAREST_MIPMAP_NEAREST),
1759     const_iv (GL_LINEAR_MIPMAP_NEAREST),
1760     const_iv (GL_NEAREST_MIPMAP_LINEAR),
1761     const_iv (GL_LINEAR_MIPMAP_LINEAR),
1762     const_iv (GL_GENERATE_MIPMAP),
1763 root 1.54 const_iv (GL_MODULATE),
1764 root 1.69 const_iv (GL_DECAL),
1765 root 1.54 const_iv (GL_REPLACE),
1766 root 1.89 const_iv (GL_DEPTH_BUFFER_BIT),
1767 root 1.54 const_iv (GL_COLOR_BUFFER_BIT),
1768     const_iv (GL_PROJECTION),
1769     const_iv (GL_MODELVIEW),
1770     const_iv (GL_COLOR_LOGIC_OP),
1771 root 1.69 const_iv (GL_SEPARABLE_2D),
1772 root 1.54 const_iv (GL_CONVOLUTION_2D),
1773     const_iv (GL_CONVOLUTION_BORDER_MODE),
1774     const_iv (GL_CONSTANT_BORDER),
1775     const_iv (GL_LINES),
1776 root 1.89 const_iv (GL_LINE_LOOP),
1777 root 1.54 const_iv (GL_QUADS),
1778 root 1.89 const_iv (GL_QUAD_STRIP),
1779     const_iv (GL_TRIANGLES),
1780     const_iv (GL_TRIANGLE_STRIP),
1781     const_iv (GL_TRIANGLE_FAN),
1782 root 1.54 const_iv (GL_PERSPECTIVE_CORRECTION_HINT),
1783     const_iv (GL_FASTEST),
1784 root 1.89 const_iv (GL_V2F),
1785     const_iv (GL_V3F),
1786     const_iv (GL_T2F_V3F),
1787     const_iv (GL_T2F_N3F_V3F),
1788 root 1.54 # undef const_iv
1789     };
1790    
1791     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
1792     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
1793     }
1794    
1795 root 1.97 char *
1796     gl_vendor ()
1797     CODE:
1798     RETVAL = (char *)glGetString (GL_VENDOR);
1799     OUTPUT:
1800     RETVAL
1801    
1802     char *
1803     gl_version ()
1804     CODE:
1805     RETVAL = (char *)glGetString (GL_VERSION);
1806     OUTPUT:
1807     RETVAL
1808    
1809     char *
1810     gl_extensions ()
1811     CODE:
1812     RETVAL = (char *)glGetString (GL_EXTENSIONS);
1813     OUTPUT:
1814     RETVAL
1815    
1816 root 1.54 int glGetError ()
1817    
1818 root 1.114 void glFinish ()
1819    
1820 root 1.54 void glClear (int mask)
1821    
1822     void glClearColor (float r, float g, float b, float a = 1.0)
1823     PROTOTYPE: @
1824    
1825     void glEnable (int cap)
1826    
1827     void glDisable (int cap)
1828    
1829     void glShadeModel (int mode)
1830    
1831     void glHint (int target, int mode)
1832    
1833     void glBlendFunc (int sfactor, int dfactor)
1834    
1835 root 1.103 void glBlendFuncSeparate (int sa, int da, int saa, int daa)
1836     CODE:
1837     gl_BlendFuncSeparate (sa, da, saa, daa);
1838    
1839 root 1.89 void glDepthMask (int flag)
1840    
1841 root 1.54 void glLogicOp (int opcode)
1842    
1843 root 1.68 void glColorMask (int red, int green, int blue, int alpha)
1844    
1845 root 1.54 void glMatrixMode (int mode)
1846    
1847     void glPushMatrix ()
1848    
1849     void glPopMatrix ()
1850    
1851     void glLoadIdentity ()
1852    
1853 root 1.119 void glDrawBuffer (int buffer)
1854    
1855     void glReadBuffer (int buffer)
1856    
1857 root 1.90 # near_ and far_ are due to microsofts buggy "c" compiler
1858     void glFrustum (double left, double right, double bottom, double top, double near_, double far_)
1859    
1860     # near_ and far_ are due to microsofts buggy "c" compiler
1861 root 1.64 void glOrtho (double left, double right, double bottom, double top, double near_, double far_)
1862 root 1.54
1863     void glViewport (int x, int y, int width, int height)
1864    
1865 root 1.69 void glScissor (int x, int y, int width, int height)
1866    
1867 root 1.54 void glTranslate (float x, float y, float z = 0.)
1868     CODE:
1869     glTranslatef (x, y, z);
1870    
1871 root 1.62 void glScale (float x, float y, float z = 1.)
1872 root 1.54 CODE:
1873     glScalef (x, y, z);
1874    
1875     void glRotate (float angle, float x, float y, float z)
1876     CODE:
1877     glRotatef (angle, x, y, z);
1878    
1879     void glBegin (int mode)
1880    
1881     void glEnd ()
1882    
1883     void glColor (float r, float g, float b, float a = 1.0)
1884     PROTOTYPE: @
1885 root 1.103 ALIAS:
1886     glColor_premultiply = 1
1887 root 1.54 CODE:
1888 root 1.103 if (ix)
1889     {
1890     r *= a;
1891     g *= a;
1892     b *= a;
1893     }
1894 root 1.90 // microsoft visual "c" rounds instead of truncating...
1895 root 1.100 glColor4ub (MIN ((int)(r * 256.f), 255),
1896     MIN ((int)(g * 256.f), 255),
1897     MIN ((int)(b * 256.f), 255),
1898     MIN ((int)(a * 256.f), 255));
1899 root 1.54
1900 root 1.89 void glInterleavedArrays (int format, int stride, char *data)
1901    
1902     void glDrawElements (int mode, int count, int type, char *indices)
1903    
1904     # 1.2 void glDrawRangeElements (int mode, int start, int end
1905    
1906 root 1.91 void glRasterPos (float x, float y, float z = 0.)
1907     CODE:
1908     glRasterPos3f (0, 0, z);
1909     glBitmap (0, 0, 0, 0, x, y, 0);
1910    
1911 root 1.54 void glVertex (float x, float y, float z = 0.)
1912     CODE:
1913     glVertex3f (x, y, z);
1914    
1915     void glTexCoord (float s, float t)
1916     CODE:
1917     glTexCoord2f (s, t);
1918    
1919     void glTexEnv (int target, int pname, float param)
1920     CODE:
1921     glTexEnvf (target, pname, param);
1922    
1923     void glTexParameter (int target, int pname, float param)
1924     CODE:
1925     glTexParameterf (target, pname, param);
1926    
1927     void glBindTexture (int target, int name)
1928    
1929     void glConvolutionParameter (int target, int pname, float params)
1930     CODE:
1931 root 1.103 if (gl.ConvolutionParameterf)
1932     gl.ConvolutionParameterf (target, pname, params);
1933 root 1.54
1934     void glConvolutionFilter2D (int target, int internalformat, int width, int height, int format, int type, char *data)
1935 root 1.64 CODE:
1936 root 1.103 if (gl.ConvolutionFilter2D)
1937     gl.ConvolutionFilter2D (target, internalformat, width, height, format, type, data);
1938 root 1.54
1939 root 1.69 void glSeparableFilter2D (int target, int internalformat, int width, int height, int format, int type, char *row, char *column)
1940     CODE:
1941 root 1.103 if (gl.SeparableFilter2D)
1942     gl.SeparableFilter2D (target, internalformat, width, height, format, type, row, column);
1943 root 1.69
1944 root 1.54 void glTexImage2D (int target, int level, int internalformat, int width, int height, int border, int format, int type, char *data)
1945    
1946     void glCopyTexImage2D (int target, int level, int internalformat, int x, int y, int width, int height, int border)
1947    
1948 root 1.91 void glDrawPixels (int width, int height, int format, int type, char *pixels)
1949 root 1.68
1950     void glCopyPixels (int x, int y, int width, int height, int type = GL_COLOR)
1951    
1952 root 1.54 int glGenTexture ()
1953     CODE:
1954     {
1955     GLuint name;
1956     glGenTextures (1, &name);
1957     RETVAL = name;
1958     }
1959     OUTPUT:
1960     RETVAL
1961    
1962     void glDeleteTexture (int name)
1963     CODE:
1964     {
1965     GLuint name_ = name;
1966     glDeleteTextures (1, &name_);
1967     }
1968    
1969     int glGenList ()
1970     CODE:
1971     RETVAL = glGenLists (1);
1972     OUTPUT:
1973     RETVAL
1974    
1975     void glDeleteList (int list)
1976     CODE:
1977     glDeleteLists (list, 1);
1978    
1979     void glNewList (int list, int mode = GL_COMPILE)
1980    
1981     void glEndList ()
1982    
1983     void glCallList (int list)
1984    
1985 root 1.89