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

File Contents

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