ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.124
Committed: Tue Jul 4 23:23:31 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.123: +36 -131 lines
Log Message:
Get rid of cairo completely (yay!) and of ft2 factually (still need the
library as it included pangofc), by introducing a custom pango opengl
renderer.

Text rendering now no longer requires the distinction between rgba and
grayscale modes, requires much less texture space and memory, and is
faster on accelerated hardware (and possibly with software rendering, too).

All at the cost of only 1200 lines or so.

File Contents

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