File Coverage

blib/lib/X11/Protocol/Ext/XFree86_DGA.pm
Criterion Covered Total %
statement 27 93 29.0
branch 0 18 0.0
condition 0 3 0.0
subroutine 9 20 45.0
pod 0 1 0.0
total 36 135 26.6


line stmt bran cond sub pod time code
1             # Copyright 2011, 2012, 2013, 2014 Kevin Ryde
2              
3             # This file is part of X11-Protocol-Other.
4             #
5             # X11-Protocol-Other is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU General Public License as published
7             # by the Free Software Foundation; either version 3, or (at your option) any
8             # later version.
9             #
10             # X11-Protocol-Other is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13             # Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with X11-Protocol-Other. If not, see .
17              
18              
19             # 2.0 bits:
20             # SetMode two flags fields
21             # byte_order "Significance" ?
22              
23             # Protocol 1.0:
24             # http://cvsweb.xfree86.org/cvsweb/xc/programs/Xserver/hw/xfree86/doc/man/Attic/XF86DGA.man?rev=3.10&hideattic=0&sortby=log&content-type=text/vnd.viewcvs-markup
25             #
26             # /so/xfree/xfree86-3.3.2.3a/programs/Xserver/hw/xfree86/doc/README.DGA
27             # /so/xfree/xfree86-3.3.2.3a/lib/Xxf86dga/XF86DGA.c
28             # Xlib
29             #
30             # /so/xfree/xfree86-3.3.2.3a/include/extensions/xf86dga.h
31             # /so/xfree/xfree86-3.3.2.3a/include/extensions/xf86dgastr.h
32             #
33             # /usr/include/X11/extensions/xf86dga1const.h
34             # /usr/include/X11/extensions/xf86dga1proto.h
35             #
36             # /so/xf86dga/XF86DGA.man
37             #
38             # /so/xfree/xfree86-3.3.2.3a/programs/Xserver/Xext/xf86dga.c
39             # server code
40             #
41             # Protocol 2.0:
42             # /usr/share/doc/xserver-xfree86/README.DGA.gz
43             # /so/xfree4/unpacked/usr/share/doc/xserver-xfree86/README.DGA.gz
44             #
45             # /usr/include/X11/extensions/xf86dgaconst.h
46             # /usr/include/X11/extensions/xf86dgaproto.h
47             #
48             # /so/xorg/xorg-server-1.10.0/hw/xfree86/dixmods/extmod/xf86dga2.c
49             # /so/xorg/xorg-server-1.10.0/hw/xfree86/common/xf86DGA.c
50             # server code
51             #
52             # XDGA(3) man page
53             # /so/xf86dga/libXxf86dga-1.1.2/src/XF86DGA2.c
54             # Xlib
55             #
56             # Other:
57             # /usr/share/doc/x11proto-core-dev/x11protocol.txt.gz
58              
59              
60              
61 1     1   416 BEGIN { require 5 }
62             package X11::Protocol::Ext::XFree86_DGA;
63 1     1   4 use strict;
  1         1  
  1         17  
64 1     1   3 use Carp;
  1         1  
  1         47  
65 1     1   628 use X11::Protocol;
  1         14501  
  1         52  
66              
67 1     1   6 use vars '$VERSION', '@CARP_NOT';
  1         1  
  1         52  
68             $VERSION = 30;
69             @CARP_NOT = ('X11::Protocol');
70              
71             # uncomment this to run the ### lines
72             # use Smart::Comments;
73              
74              
75             # these not documented yet ...
76 1     1   4 use constant CLIENT_MAJOR_VERSION => 1;
  1         1  
  1         70  
77 1     1   3 use constant CLIENT_MINOR_VERSION => 0;
  1         1  
  1         39  
78              
79             #------------------------------------------------------------------------------
80             # symbolic constants
81              
82 1         166 use constant constants_list =>
83             (XDGAPixmapMode => ['Large','Small'],
84 1     1   2 );
  1         2  
85              
86             sub _ext_constants_install {
87 0     0     my ($X, $constants_arrayref) = @_;
88 0           foreach (my $i = 0; $i <= $#$constants_arrayref; $i+=2) {
89 0           my $name = $constants_arrayref->[$i];
90 0           my $aref = $constants_arrayref->[$i+1];
91 0           $X->{'ext_const'}->{$name} = $aref;
92 0           $X->{'ext_const_num'}->{$name} = { X11::Protocol::make_num_hash($aref) };
93             }
94             }
95              
96             #------------------------------------------------------------------------------
97             # events
98              
99             # =head1 EVENTS
100             #
101             # Protocol version 2.0 sends key, button and pointer motion events selected
102             # by C described above.
103             #
104             # Each event has the usual fields
105             #
106             # name "SyncCounterNotify" etc
107             # synthetic true if from a SendEvent
108             # code integer opcode
109             # sequence_number integer
110             #
111             # plus event-specific fields described below.
112             #
113             # =over
114             #
115             # =item C, C
116             #
117             # The "detail", "time" and "state" fields are the same as the core KeyPress
118             # and KeyRelease events,
119             #
120             # detail keycode (integer)
121             # time server timestamp (integer)
122             # screen screen number (integer)
123             # state keyboard modifiers (integer shift, control, etc)
124             #
125             # =item C, C
126             #
127             # The "detail", "time" and "state" fields are the same as the core
128             # ButtonPress and ButtonRelease events,
129             #
130             # detail button number 1 to 5
131             # time server timestamp (integer)
132             # screen screen number (integer)
133             # state keyboard modifiers (integer shift, control, etc)
134             #
135             # =item C
136             #
137             # The "time" and "state" fields are the same as the core key press and
138             # release events,
139             #
140             # dx \ pointer move in pixels, integer + or -
141             # dy /
142             # time server timestamp (integer)
143             # screen screen number (integer)
144             # state keyboard modifiers (integer shift, control, etc)
145             #
146             # =back
147              
148             # xf86dgaproto.h struct dgaEvent has INT16 for screen, so "s" here, though
149             # normally a screen number will be >=0.
150             #
151             use constant events_list =>
152 1         1 do {
153             # struct dgaEvent has dx,dy fields for key and button events, but server
154             # DGAStealButtonEvent() and DGAStealKeyEvent() always puts 0 in them, so
155             # omit.
156             #
157 1         2 my $kb = [ 'xCxxLxxxxsSx16',
158             'detail',
159             'time',
160             'screen',
161             'state',
162             ];
163 1         1452 (XDGAKeyPress => $kb, # +2
164             XDGAKeyRelease => $kb, # +3
165             XDGAButtonPress => $kb, # +4
166             XDGAButtonRelease => $kb, # +5
167              
168             # struct dgaEvent has a "detail" field for motion event, but server
169             # DGAStealMotionEvent() always puts 0 in it, so omit.
170             #
171             XDGAMotionNotify => # +6
172             [ 'xxxxLsssSx16',
173             'time',
174             'dx',
175             'dy',
176             'screen',
177             'state',
178             ])
179 1     1   4 };
  1         1  
180              
181             sub _ext_events_install {
182 0     0     my ($X, $event_num, $events_arrayref) = @_;
183 0           foreach (my $i = 0; $i <= $#$events_arrayref; $i += 2) {
184 0           my $name = $events_arrayref->[$i];
185 0 0         if (defined (my $already = $X->{'ext_const'}->{'Events'}->[$event_num])) {
186 0           carp "Event $event_num $already overwritten with $name";
187             }
188 0           $X->{'ext_const'}->{'Events'}->[$event_num] = $name;
189 0           $X->{'ext_events'}->[$event_num] = $events_arrayref->[$i+1]; # pack/unpack
190 0           $event_num++;
191             }
192             }
193              
194             #------------------------------------------------------------------------------
195             # requests
196              
197             my $reqs =
198             [
199             ['XF86DGAQueryVersion', # 0
200             \&_request_empty,
201             sub {
202             my ($X, $data) = @_;
203             ### XF86DGAQueryVersion() reply ...
204             return unpack 'x8SS', $data;
205             }],
206              
207             ['XF86DGAGetVideoLL', # 1
208             \&_request_screen16,
209             sub {
210             my ($X, $data) = @_;
211             return unpack 'x8L4', $data; # (address,width,bank_size,ram_size)
212             },
213             ],
214              
215             ['XF86DGADirectVideo', # 2
216             sub {
217             my ($X, $screen, $enable) = @_;
218             return pack 'SS', $screen, $enable;
219             } ],
220              
221             ['XF86DGAGetViewPortSize', # 3
222             \&_request_screen16,
223             sub {
224             my ($X, $data) = @_;
225             return unpack 'x8LL', $data; # (width,height)
226             },
227             ],
228              
229             ['XF86DGASetViewPort', # 4
230             sub {
231             shift; # ($X, $screen, $x, $y)
232             return pack 'SxxLL', @_;
233             },
234             ],
235              
236             ['XF86DGAGetVidPage', # 5
237             \&_request_screen16,
238             sub {
239             my ($X, $data) = @_;
240             return unpack 'x8L', $data; # (vidpage)
241             },
242             ],
243              
244             ['XF86DGASetVidPage', # 6
245             sub {
246             shift; # ($X, $screen, $vidpage)
247             return pack 'SS', @_;
248             },
249             ],
250              
251             ['XF86DGAInstallColormap', # 7
252             sub {
253             my ($X, $screen, $colormap) = @_;
254             return pack 'SxxL', $screen, $colormap;
255             }],
256              
257             ['XF86DGAQueryDirectVideo', # 8
258             \&_request_screen16,
259             sub {
260             my ($X, $data) = @_;
261             return unpack 'x8L', $data; # (flags)
262             },
263             ],
264              
265             ['XF86DGAViewPortChanged', # 9
266             sub {
267             shift; # ($X, $screen, $num_pages)
268             return pack 'SS', @_;
269             },
270             sub {
271             my ($X, $data) = @_;
272             return unpack 'x8L', $data; # (bool)
273             } ],
274              
275              
276             #---------------------------------------------------------------------------
277             # version 2.0
278              
279             undef, # 10
280             undef, # 11
281              
282             # =item C<($mode_num =E $hashref, ...) = $X-EXDGAQueryModes($screen_num)>
283             #
284             # Return a list of available DGA modes and information. Each mode is
285             # returned as a pair
286             #
287             # $mode_num => $hashref
288             #
289             # where C<$hashref> contains the following fields
290             #
291             # mode_num
292             # byte_order Significance enum
293             # "LeastSignificant" or "MostSignificant"
294             # depth bits per pixel with usable data, eg. 24
295             # bpp bits per pixel including padding, eg. 32
296             # name string name of mode from xorg.conf
297             # vsync_num \ vertical refresh rate as fraction num/den
298             # vsync_den / retraces per second (Hertz)
299             # flags bits
300             # 1 Concurrent Access
301             # 2 Solid Fill Rect
302             # 4 Blit Rect
303             # 8 Blit Trans Rect
304             # 16 Pixmap
305             # image_width \
306             # image_height /
307             # pixmap_width \ size of the video part accessible by
308             # pixmap_height / pixmap of XDGASetMode()
309             # bytes_per_scanline
310             # red_mask \ pixel bit-masks as per a visual
311             # green_mask |
312             # blue_mask /
313             # visual_class VisualClass enum "TrueColor", "PseudoColor", etc
314             # viewport_width \ size of the visible part of the video
315             # viewport_height /
316             # viewport_xstep \ granularity of X,Y position
317             # viewport_ystep / for XDGASetViewport()
318             # viewport_xmax \ maximum X,Y position
319             # viewport_ymax / for XDGASetViewport()
320             # viewport_flags
321             #
322             # The return list can be put into a hash to lookup by mode number,
323             #
324             # my %h = $X->XDGAQueryModes($screen_num);
325             # my $info = $h{$mode_num};
326             # print "$mode_num name is ",$info->{'name'},"\n";
327             #
328              
329             ['XDGAQueryModes', # 12
330             \&_request_card32s,
331             sub {
332             my ($X, $data) = @_;
333             my ($num_modes) = unpack 'x8L', $data;
334             my $pos = 32;
335              
336             # use Data::HexDump::XXD;
337             # print scalar(Data::HexDump::XXD::xxd($data));
338             # print "\n";
339              
340             return map {my $h = _unpack_info($X,$data,$pos);
341             $pos += 72;
342             ($h->{'num'} => $h)
343             } 1 .. $num_modes;
344             } ],
345              
346             # =item C<(key=Evalue,...) = $X-EXDGASetMode($screen_num, $mode_num, $pixmap)>
347             #
348             # Put screen C<$screen_num> into DGA mode C<$mode_num>. Or if
349             # C<$mode_num> is 0 then leave DGA mode.
350             #
351             # C<$pixmap> is a new integer XID which is for X protocol access to the
352             # video memory while in DGA mode. This is only possible if the "Pixmap"
353             # bit is set in the mode flags (C above).
354             #
355             # The return is a list of key/value pairs with mode information. The
356             # fields are C above for C<$mode_num>, and in addition
357             #
358             # offset => offset into video memory (integer)
359             # set_flags => ... (integer)
360             #
361             ['XDGASetMode', # 13
362             sub {
363             shift; # ($X, $screen_num, $mode_num, $pixmap)
364             return pack 'L3', @_;
365             },
366             sub {
367             my ($X, $data) = @_;
368             my ($offset, $flags) = unpack 'x8LL', $data;
369             my $h = _unpack_info($X, $data, 32);
370             return (offset => $offset,
371             set_flags => $flags,
372             %$h);
373             },
374             ],
375              
376             # =item C<$X-EXDGASetViewport($screen_num, $x, $y, $flags)>
377             #
378             # Set the C<$x,$y> position of the top-left corner of the visible part of
379             # the video memory.
380             #
381             # The hardware might support only certain positions, as per
382             # C,C fields of C
383             # above. C<$x,$y> will round them to the next step if necessary.
384             #
385             # C<$flags> (an integer) can be bits
386             #
387             # 1 Flip Immediate
388             # 2 Flip Retrace
389             #
390             # Flip retrace means to queue the viewport change to occur on the next
391             # vertical retrace, so as not to flicker in the middle of the screen.
392             #
393             [ 'XDGASetViewport', # 14
394             sub {
395             shift; # ($X, $screen, $x, $y, $flags)
396             return pack 'LSSL', @_;
397             },
398             ],
399              
400             # =item C<$X-EXDGAInstallColormap($screen_num, $colormap)>
401             #
402             # Install C<$colormap> in DGA mode. The core
403             # C<$X-EInstallColormap()> cannot be used in DGA mode.
404             #
405             [ 'XDGAInstallColormap', # 15
406             sub {
407             shift; # ($X, $screen, $colormap)
408             return pack 'SxxL', @_;
409             } ],
410              
411             # =item C<$X-EXDGASelectInput($screen_num, $event_mask)>
412             #
413             # Select key, button and mouse motion events while in DGA mode.
414             # C<$event_mask> is as per the core C<$X-Epack_event()> with mask
415             # bits
416             #
417             # KeyPress
418             # KeyRelease
419             # ButtonPress
420             # ButtonRelease
421             # PointerMotion
422             # Button1Motion
423             # Button2Motion
424             # Button3Motion
425             # Button4Motion
426             # Button5Motion
427             # ButtonMotion
428             #
429             [ 'XDGASelectInput', # 16
430             \&_request_card32s ], # ($X, $screen, $mask)
431              
432             # =item C<$X-EXDGAFillRectangle($screen_num, $x,$y, $width,$height, $pixel)>
433             #
434             # Fill the rectangle C<$x,$y, $width,$height> with pixel value C<$pixel>.
435             #
436             # This request is supported if the "Solid Fill Rect" bit is set in the
437             # mode flags (C above).
438             #
439             [ 'XDGAFillRectangle', # 17
440             sub {
441             shift; # ($X, $screen, $x, $y, $width, $height, $color)
442             return pack 'LSSSSL', @_;
443             } ],
444              
445             # =item C<$X-EXDGACopyArea($screen_num, $src_x,$src_y, $width,$height, $dst_x,$dst_y)>
446             #
447             # Copy the rectangle C<$src_x,$src_y, $width,$height> to
448             # C<$dst_x,$dst_y>.
449             #
450             # This request is supported if the "Blit Rect" bit is set in the mode
451             # flags (C above).
452             #
453             [ 'XDGACopyArea', # 18
454             sub {
455             shift; # ($X, $screen, $src_x,$src_y, $width,$height, $dst_x,$dst_y)
456             return pack 'LS*', @_; # x,y's are CARD16s, so unsigned
457             } ],
458              
459             # This request is supported if the "Blit Trans Rect" bit is set in the
460             # mode flags (C above).
461             #
462             [ 'XDGACopyTransparentArea', # 19
463             sub {
464             shift;
465             # ($X, $screen, $src_x,$src_y, $width,$height, $dst_x,$dst_y, $key)
466             return pack 'LS6L', @_; # x,y's are CARD16s, so unsigned
467             } ],
468              
469             # =item C<$status = $X-EXDGAGetViewportStatus($screen_num)>
470             #
471             [ 'XDGAGetViewportStatus', # 20
472             \&_request_card32s, # ($X,$screen_num)
473             sub {
474             my ($X, $data) = @_;
475             return unpack 'x8L', $data;
476             } ],
477              
478             # =item C<$X-EXDGASync($screen_num)>
479             #
480             # Block until all server drawing to the video memory is complete, either
481             # ordinary X drawing or the Copy and Fill requests above.
482             #
483             # The server or hardware might queue drawing requests. C is
484             # a round-trip which ensures the video memory contains all drawing
485             # requested.
486             #
487             # If "Concurrent Access" is set in the mode flags (C
488             # above) then a client and the server can act on the video concurrently,
489             # though care would be needed not to make a mess of each other's drawing.
490             #
491             # If "Concurrent Access" is not set then the client and server must not
492             # act on the video concurrently. The client must C to ensure
493             # the server has finished.
494             #
495             [ 'XDGASync', # 21
496             \&_request_card32s, # ($X,$screen_num)
497             sub { # ($X, $data) empty
498             return;
499             } ],
500              
501             # =item C<($device_name, $addr, $size, $offset, $extra) = $X-EXDGAOpenFramebuffer($screen_num)>
502             #
503             # Get the location of the video RAM memory framebuffer. The client can
504             # use this to open the framebuffer by an C or other means for use
505             # when in DGA mode.
506             #
507             # C<$device_name> (a string) is the name of a device file to access the
508             # framebuffer. If it's an empty string then the framebuffer is in
509             # physical memory (so whatever system-dependent device F or
510             # F etc).
511             #
512             # C<$addr> (an integer) is the address within the device or physical
513             # memory. This might be 64-bits on a 64-bit system. If Perl has only
514             # 32-bit UV when the address is 64-bits then C<$addr> is returned as a
515             # C.
516             #
517             # C<$offset> is an offset from C<$addr>. C<$size> is the size of the
518             # framebuffer memory, in bytes, at that C<$addr+$offset> location.
519             #
520             # C<$extra> is extra information. It can be a bit
521             #
522             # 1 client will need root permissions
523             #
524             [ 'XDGAOpenFramebuffer', # 22
525             \&_request_card32s,
526             sub {
527             my ($X, $data) = @_;
528             ### head: unpack('CCSL', $data)
529             ### data: unpack('x8L5', $data)
530             ### devname: substr($data,32)
531              
532             # (devlen,mem1,mem2,size,offset,extra)
533             my ($length, $mem_lo, $mem_hi, @rest) = unpack 'x4L6', $data;
534              
535             # "\0" terminated within $length many CARD32s
536             (my $devname = substr($data,32,4*$length)) =~ s/\0.*//;
537              
538             return ($devname,
539             _hilo_to_card64($mem_hi,$mem_lo),
540             @rest);
541             } ],
542              
543             # =item C<$X-EXDGACloseFramebuffer($screen_num)>
544             #
545             # Tell the server that the client is no longer accessing the framebuffer
546             # memory of C above.
547             #
548             [ 'XDGACloseFramebuffer', # 23
549             \&_request_card32s ],
550              
551             # =item C<$X-EXDGASetClientVersion($client_major, $client_minor)>
552             #
553             [ 'XDGASetClientVersion', # 24
554             sub {
555             shift; # ($X, $client_major, $client_minor)
556             return pack 'SS', @_;
557             } ],
558              
559             # =item C<($x,$y) = $X-EXDGAChangePixmapMode($screen_num, $x,$y, $mode)>
560             #
561             # Change the position of the C<$pixmap> of C within the
562             # video memory.
563             #
564             # C<$mode> is a XDGAPixmapMode enum,
565             #
566             # "Large" (0) pixmap_width,pixmap_height
567             # "Small" (1) viewport_width,viewport_height and $x,$y
568             #
569             # Large mode means the pixmap is as big as possible, the C
570             # and C per the mode info.
571             #
572             # Small mode means the pixmap is only the size of the viewport,
573             # C and C per the mode info. In this
574             # case C<$x> and C<$y> are the top-left corner of the pixmap within the
575             # full memory. The position can be different from the visible viewport,
576             # but it must be within the C,C limit.
577             #
578             [ 'XDGAChangePixmapMode', # 25
579             sub {
580             my ($X, $screen_num, $x, $y, $mode) = @_;
581             return pack 'LSSL',
582             $screen_num, $x, $y, $X->interp('XDGAPixmapMode',$mode);
583             },
584             sub {
585             my ($X, $data) = @_;
586             return unpack 'x8SS', $data; # (x,y)
587             },
588             ],
589              
590             # =item C<$X-EXDGACreateColormap($screen_num, $colormap, $mode_num, $alloc)>
591             #
592             # Create C<$colormap> (a new XID) as a colormap for use with DGA
593             # C<$screen_num> and C<$mode_num>.
594             #
595             # This is similar to the core C, but there might not
596             # be a core visual corresponding to C<$mode_num> depth etc, hence this
597             # separate way to create a colormap.
598             #
599             # C<$colormap> can be used the same as core protocol colormaps and can
600             # be freed with C<$X-EFreeColormap($colormap)>.
601             #
602             #
603             [ 'XDGACreateColormap', # 26
604             sub {
605             shift; # ($X, $screen, $id, $mode, $alloc)
606             return pack 'LLLCxxx', @_;
607             } ],
608             ];
609              
610             sub new {
611 0     0 0   my ($class, $X, $request_num, $event_num, $error_num) = @_;
612             ### XF86DGA new() ...
613              
614 0           my $self = bless { }, $class;
615 0           _ext_requests_install ($X, $request_num, $reqs);
616 0           _ext_constants_install ($X, [ $self->constants_list ]);
617              
618 0           my ($server_major, $server_minor) = $X->XF86DGAQueryVersion;
619 0           $self->{'major'} = $server_major;
620 0           $self->{'minor'} = $server_minor;
621              
622 0 0         _ext_const_error_install ($X, $error_num,
623             'XF86DGAClientNotLocal', # 0
624             'XF86DGANoDirectVideoMode', # 1
625             'XF86DGAScreenNotActive', # 2
626             'XF86DGADirectNotActivated', # 3
627             ($server_major >= 2
628             ? 'XF86DGAOperationNotSupported' # 4
629             : ()));
630 0 0         if ($server_major >= 2) {
631 0           _ext_events_install ($X,
632             $event_num+2, # to start at $event_num+2
633             [ $self->events_list ]);
634             }
635              
636 0           return $self;
637             }
638              
639             sub _unpack_info {
640 0     0     my ($X, $data, $pos) = @_;
641 0           my %h;
642 0           @h{qw(byte_order depth
643             num bpp name_len
644             vsync_num vsync_den flags
645             image_width image_height pixmap_width pixmap_height
646             bytes_per_scanline red_mask green_mask blue_mask
647             visual_class
648             viewport_width viewport_height
649             viewport_xstep viewport_ystep
650             viewport_xmax viewport_ymax
651             viewport_flags
652             )}
653             = unpack 'C2S3L3S4L4SxxS6L', substr($data,$pos,72);
654 0           $pos += 72;
655             ### %h
656              
657             # name_len a multiple of 4, string \0 nul-terminated
658             # within that length
659 0           my $name_len = delete $h{'name_len'};
660 0           ($h{'name'} = substr($data, $pos, $name_len)) =~ s/\0.*//;
661             # cf unpack 'Z', new in perl 5.6
662             # $h{'name'} = unpack 'Z*', substr($data, $pos, $name_len);
663 0           $pos += $name_len;
664             ### $name_len
665             ### name: $h{'name'}
666              
667 0           $h{'byte_order'} = $X->interp('Significance', $h{'byte_order'});
668 0           $h{'visual_class'} = $X->interp('VisualClass', $h{'visual_class'});
669              
670 0           return \%h;
671             }
672              
673             #------------------------------------------------------------------------------
674             # 64-bits
675              
676             {
677             my $uv = ~0;
678             my $bits = 0;
679             while ($uv && $bits < 64) {
680             $uv >>= 1;
681             $bits++;
682             }
683              
684             if ($bits >= 64) {
685             eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE' or die;
686             sub _hilo_to_card64 {
687 0     0     my ($hi,$lo) = @_;
688             ### _hilo_to_sv(): "$hi $lo, result ".(($hi << 32) + $lo)
689 0           return ($hi << 32) + $lo;
690             }
691             1;
692             HERE
693             } else {
694             eval "\n#line ".(__LINE__+1)." \"".__FILE__."\"\n" . <<'HERE' or die;
695             sub _hilo_to_card64 {
696             my ($hi,$lo) = @_;
697             if ($hi) {
698             require Math::BigInt;
699             return Math::BigInt->new($hi)->blsft(32)->badd($lo);
700             } else {
701             return $lo;
702             }
703             }
704             1;
705             HERE
706             }
707             }
708              
709             #------------------------------------------------------------------------------
710             # generic
711              
712             sub _request_card32s {
713 0     0     shift;
714             ### _request_card32s(): @_
715 0           return pack 'L*', @_;
716             }
717              
718             sub _request_screen16 {
719 0     0     shift; # ($X, $screen)
720 0 0         @_ == 1 or croak "Single screen number parameter expected";
721 0           return pack 'Sxx', @_;
722             }
723              
724             sub _num_none {
725 0     0     my ($xid) = @_;
726 0 0 0       if (defined $xid && $xid eq "None") {
727 0           return 0;
728             } else {
729 0           return $xid;
730             }
731             }
732              
733             sub _request_empty {
734             # ($X)
735             ### _request_empty() ...
736 0 0   0     if (@_ > 1) {
737 0           croak "No parameters in this request";
738             }
739 0           return '';
740             }
741              
742             sub _ext_requests_install {
743 0     0     my ($X, $request_num, $reqs) = @_;
744              
745 0           $X->{'ext_request'}->{$request_num} = $reqs;
746 0           my $href = $X->{'ext_request_num'};
747 0           my $i;
748 0           foreach $i (0 .. $#$reqs) {
749 0 0         if (defined $reqs->[$i]) {
750 0           $href->{$reqs->[$i]->[0]} = [$request_num, $i];
751             }
752             }
753             }
754             sub _ext_const_error_install {
755 0     0     my $X = shift; # ($X, $errname1,$errname2,...)
756             ### _ext_const_error_install: @_
757 0           my $error_num = shift;
758             my $aref = $X->{'ext_const'}{'Error'} # copy
759 0 0         = [ @{$X->{'ext_const'}{'Error'} || []} ];
  0            
760             my $href = $X->{'ext_const_num'}{'Error'} # copy
761 0 0         = { %{$X->{'ext_const_num'}{'Error'} || {}} };
  0            
762 0           my $i;
763 0           foreach $i (0 .. $#_) {
764 0           $aref->[$error_num + $i] = $_[$i];
765 0           $href->{$_[$i]} = $error_num + $i;
766             }
767             }
768              
769             1;
770             __END__