ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/Client.xs
Revision: 1.131
Committed: Thu Jul 13 01:54:18 2006 UTC (17 years, 10 months ago) by root
Branch: MAIN
Changes since 1.130: +7 -2 lines
Log Message:
remove glext.h, add SDL_GL_ACCELERATED_VISUAL and SDL_GL_SWAP_CONTROL

File Contents

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