1 /***********************************************************
2 Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 ******************************************************************/
24 /* $XFree86: xc/lib/Xv/Xv.c,v 1.15 2001/05/11 08:23:22 alanh Exp $ */
28 ** Xv.c --- Xv library extension module.
32 ** David Carver (Digital Workstation Engineering/Project Athena)
37 ** - changed XvFreeAdaptors to XvFreeAdaptorInfo
38 ** - changed XvFreeEncodings to XvFreeEncodingInfo
41 ** - changed SetPortControl to SetPortAttribute
42 ** - changed GetPortControl to GetPortAttribute
43 ** - changed QueryBestSize
46 ** - version 2.0 upgrade
49 ** - version 1.4 upgrade
55 #include "../extensions/Xext.h"
56 #include <X11/extensions/XShm.h>
57 #include "../extensions/extutil.h"
59 static XExtensionInfo _xv_info_data;
60 static XExtensionInfo *xv_info = &_xv_info_data;
61 static char *xv_extension_name = XvName;
63 #define XvCheckExtension(dpy, i, val) \
64 XextCheckExtension(dpy, i, xv_extension_name, val)
66 static char *xv_error_string();
67 static int xv_close_display();
68 static Bool xv_wire_to_event();
70 static XExtensionHooks xv_extension_hooks = {
75 NULL, /* create_font */
77 xv_close_display, /* close_display */
78 xv_wire_to_event, /* wire_to_event */
79 NULL, /* event_to_wire */
81 xv_error_string /* error_string */
85 static char *xv_error_list[] =
87 "BadPort", /* XvBadPort */
88 "BadEncoding", /* XvBadEncoding */
89 "BadControl" /* XvBadControl */
92 static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info)
95 static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info,
101 static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name,
102 XvNumErrors, xv_error_list)
106 SDL_NAME(XvQueryExtension)(
108 unsigned int *p_version,
109 unsigned int *p_revision,
110 unsigned int *p_requestBase,
111 unsigned int *p_eventBase,
112 unsigned int *p_errorBase
114 XExtDisplayInfo *info = xv_find_display(dpy);
115 xvQueryExtensionReq *req;
116 xvQueryExtensionReply rep;
118 XvCheckExtension(dpy, info, XvBadExtension);
122 XvGetReq(QueryExtension, req);
124 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
127 return XvBadExtension;
130 *p_version = rep.version;
131 *p_revision = rep.revision;
132 *p_requestBase = info->codes->major_opcode;
133 *p_eventBase = info->codes->first_event;
134 *p_errorBase = info->codes->first_error;
143 SDL_NAME(XvQueryAdaptors)(
146 unsigned int *p_nAdaptors,
147 SDL_NAME(XvAdaptorInfo) **p_pAdaptors
149 XExtDisplayInfo *info = xv_find_display(dpy);
150 xvQueryAdaptorsReq *req;
151 xvQueryAdaptorsReply rep;
154 SDL_NAME(XvAdaptorInfo) *pas, *pa;
155 SDL_NAME(XvFormat) *pfs, *pf;
165 XvCheckExtension(dpy, info, XvBadExtension);
169 XvGetReq(QueryAdaptors, req);
170 req->window = window;
174 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
180 size = rep.length << 2;
181 if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
186 _XRead (dpy, buffer, size);
190 /* GET INPUT ADAPTORS */
192 if (rep.num_adaptors == 0) {
195 size = rep.num_adaptors*sizeof(SDL_NAME(XvAdaptorInfo));
196 if ((pas=(SDL_NAME(XvAdaptorInfo) *)Xmalloc(size))==NULL) {
204 /* INIT ADAPTOR FIELDS */
207 for (ii=0; ii<rep.num_adaptors; ii++) {
208 pa->num_adaptors = 0;
209 pa->name = (char *)NULL;
210 pa->formats = (SDL_NAME(XvFormat) *)NULL;
215 for (ii=0; ii<rep.num_adaptors; ii++) {
216 pa->type = u.pa->type;
217 pa->base_id = u.pa->base_id;
218 pa->num_ports = u.pa->num_ports;
219 pa->num_formats = u.pa->num_formats;
220 pa->num_adaptors = rep.num_adaptors - ii;
222 /* GET ADAPTOR NAME */
224 size = u.pa->name_size;
225 u.buffer += (sz_xvAdaptorInfo + 3) & ~3;
227 if ( (name = (char *)Xmalloc(size+1)) == NULL)
229 SDL_NAME(XvFreeAdaptorInfo)(pas);
235 SDL_strlcpy(name, u.string, size);
238 u.buffer += (size + 3) & ~3;
242 size = pa->num_formats*sizeof(SDL_NAME(XvFormat));
243 if ((pfs=(SDL_NAME(XvFormat) *)Xmalloc(size))==NULL) {
244 SDL_NAME(XvFreeAdaptorInfo)(pas);
252 for (jj=0; jj<pa->num_formats; jj++) {
253 pf->depth = u.pf->depth;
254 pf->visual_id = u.pf->visual;
257 u.buffer += (sz_xvFormat + 3) & ~3;
266 *p_nAdaptors = rep.num_adaptors;
278 SDL_NAME(XvFreeAdaptorInfo)(SDL_NAME(XvAdaptorInfo) *pAdaptors)
281 SDL_NAME(XvAdaptorInfo) *pa;
284 if (!pAdaptors) return;
288 for (ii=0; ii<pAdaptors->num_adaptors; ii++, pa++)
304 SDL_NAME(XvQueryEncodings)(
307 unsigned int *p_nEncodings,
308 SDL_NAME(XvEncodingInfo) **p_pEncodings
310 XExtDisplayInfo *info = xv_find_display(dpy);
311 xvQueryEncodingsReq *req;
312 xvQueryEncodingsReply rep;
315 SDL_NAME(XvEncodingInfo) *pes, *pe;
324 XvCheckExtension(dpy, info, XvBadExtension);
328 XvGetReq(QueryEncodings, req);
333 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
339 size = rep.length << 2;
340 if ( (buffer = (char *)Xmalloc ((unsigned) size)) == NULL) {
345 _XRead (dpy, buffer, size);
351 size = rep.num_encodings*sizeof(SDL_NAME(XvEncodingInfo));
352 if ( (pes = (SDL_NAME(XvEncodingInfo) *)Xmalloc(size)) == NULL) {
359 /* INITIALIZE THE ENCODING POINTER */
362 for (jj=0; jj<rep.num_encodings; jj++) {
363 pe->name = (char *)NULL;
364 pe->num_encodings = 0;
369 for (jj=0; jj<rep.num_encodings; jj++) {
370 pe->encoding_id = u.pe->encoding;
371 pe->width = u.pe->width;
372 pe->height = u.pe->height;
373 pe->rate.numerator = u.pe->rate.numerator;
374 pe->rate.denominator = u.pe->rate.denominator;
375 pe->num_encodings = rep.num_encodings - jj;
377 size = u.pe->name_size;
378 u.buffer += (sz_xvEncodingInfo + 3) & ~3;
380 if ( (name = (char *)Xmalloc(size+1)) == NULL) {
386 SDL_strlcpy(name, u.string, size);
390 u.buffer += (size + 3) & ~3;
393 *p_nEncodings = rep.num_encodings;
404 SDL_NAME(XvFreeEncodingInfo)(SDL_NAME(XvEncodingInfo) *pEncodings)
407 SDL_NAME(XvEncodingInfo) *pe;
410 if (!pEncodings) return;
414 for (ii=0; ii<pEncodings->num_encodings; ii++, pe++) {
415 if (pe->name) Xfree(pe->name);
422 SDL_NAME(XvPutVideo)(
428 unsigned int vw, unsigned int vh,
430 unsigned int dw, unsigned int dh
432 XExtDisplayInfo *info = xv_find_display(dpy);
435 XvCheckExtension(dpy, info, XvBadExtension);
441 XvGetReq(PutVideo, req);
462 SDL_NAME(XvPutStill)(
468 unsigned int vw, unsigned int vh,
470 unsigned int dw, unsigned int dh
472 XExtDisplayInfo *info = xv_find_display(dpy);
475 XvCheckExtension(dpy, info, XvBadExtension);
481 XvGetReq(PutStill, req);
501 SDL_NAME(XvGetVideo)(
507 unsigned int vw, unsigned int vh,
509 unsigned int dw, unsigned int dh
511 XExtDisplayInfo *info = xv_find_display(dpy);
514 XvCheckExtension(dpy, info, XvBadExtension);
520 XvGetReq(GetVideo, req);
540 SDL_NAME(XvGetStill)(
546 unsigned int vw, unsigned int vh,
548 unsigned int dw, unsigned int dh
550 XExtDisplayInfo *info = xv_find_display(dpy);
553 XvCheckExtension(dpy, info, XvBadExtension);
559 XvGetReq(GetStill, req);
579 SDL_NAME(XvStopVideo)(
584 XExtDisplayInfo *info = xv_find_display(dpy);
587 XvCheckExtension(dpy, info, XvBadExtension);
591 XvGetReq(StopVideo, req);
593 req->drawable = draw;
602 SDL_NAME(XvGrabPort)(
607 XExtDisplayInfo *info = xv_find_display(dpy);
612 XvCheckExtension(dpy, info, XvBadExtension);
616 XvGetReq(GrabPort, req);
620 if (_XReply (dpy, (xReply *) &rep, 0, xTrue) == 0)
621 rep.result = GrabSuccess;
632 SDL_NAME(XvUngrabPort)(
637 XExtDisplayInfo *info = xv_find_display(dpy);
638 xvUngrabPortReq *req;
640 XvCheckExtension(dpy, info, XvBadExtension);
644 XvGetReq(UngrabPort, req);
655 SDL_NAME(XvSelectVideoNotify)(
660 XExtDisplayInfo *info = xv_find_display(dpy);
661 xvSelectVideoNotifyReq *req;
663 XvCheckExtension(dpy, info, XvBadExtension);
667 XvGetReq(SelectVideoNotify, req);
668 req->drawable = drawable;
678 SDL_NAME(XvSelectPortNotify)(
683 XExtDisplayInfo *info = xv_find_display(dpy);
684 xvSelectPortNotifyReq *req;
686 XvCheckExtension(dpy, info, XvBadExtension);
690 XvGetReq(SelectPortNotify, req);
701 SDL_NAME(XvSetPortAttribute) (
708 XExtDisplayInfo *info = xv_find_display(dpy);
709 xvSetPortAttributeReq *req;
711 XvCheckExtension(dpy, info, XvBadExtension);
715 XvGetReq(SetPortAttribute, req);
717 req->attribute = attribute;
727 SDL_NAME(XvGetPortAttribute) (
734 XExtDisplayInfo *info = xv_find_display(dpy);
735 xvGetPortAttributeReq *req;
736 xvGetPortAttributeReply rep;
738 XvCheckExtension(dpy, info, XvBadExtension);
742 XvGetReq(GetPortAttribute, req);
744 req->attribute = attribute;
748 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
754 *p_value = rep.value;
763 SDL_NAME(XvQueryBestSize)(
771 unsigned int *p_actual_width,
772 unsigned int *p_actual_height
775 XExtDisplayInfo *info = xv_find_display(dpy);
776 xvQueryBestSizeReq *req;
777 xvQueryBestSizeReply rep;
779 XvCheckExtension(dpy, info, XvBadExtension);
783 XvGetReq(QueryBestSize, req);
785 req->motion = motion;
793 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
799 *p_actual_width = rep.actual_width;
800 *p_actual_height = rep.actual_height;
809 SDL_NAME(XvAttribute)*
810 SDL_NAME(XvQueryPortAttributes)(Display *dpy, XvPortID port, int *num)
812 XExtDisplayInfo *info = xv_find_display(dpy);
813 xvQueryPortAttributesReq *req;
814 xvQueryPortAttributesReply rep;
815 SDL_NAME(XvAttribute) *ret = NULL;
819 XvCheckExtension(dpy, info, NULL);
823 XvGetReq(QueryPortAttributes, req);
828 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
834 if(rep.num_attributes) {
835 int size = (rep.num_attributes * sizeof(SDL_NAME(XvAttribute))) + rep.text_size;
837 if((ret = Xmalloc(size))) {
838 char* marker = (char*)(&ret[rep.num_attributes]);
839 xvAttributeInfo Info;
842 for(i = 0; i < rep.num_attributes; i++) {
843 _XRead(dpy, (char*)(&Info), sz_xvAttributeInfo);
844 ret[i].flags = (int)Info.flags;
845 ret[i].min_value = Info.min;
846 ret[i].max_value = Info.max;
847 ret[i].name = marker;
848 _XRead(dpy, marker, Info.size);
853 _XEatData(dpy, rep.length << 2);
862 SDL_NAME(XvImageFormatValues) * SDL_NAME(XvListImageFormats) (
867 XExtDisplayInfo *info = xv_find_display(dpy);
868 xvListImageFormatsReq *req;
869 xvListImageFormatsReply rep;
870 SDL_NAME(XvImageFormatValues) *ret = NULL;
874 XvCheckExtension(dpy, info, NULL);
878 XvGetReq(ListImageFormats, req);
883 if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {
889 if(rep.num_formats) {
890 int size = (rep.num_formats * sizeof(SDL_NAME(XvImageFormatValues)));
892 if((ret = Xmalloc(size))) {
893 xvImageFormatInfo Info;
896 for(i = 0; i < rep.num_formats; i++) {
897 _XRead(dpy, (char*)(&Info), sz_xvImageFormatInfo);
899 ret[i].type = Info.type;
900 ret[i].byte_order = Info.byte_order;
901 memcpy(&(ret[i].guid[0]), &(Info.guid[0]), 16);
902 ret[i].bits_per_pixel = Info.bpp;
903 ret[i].format = Info.format;
904 ret[i].num_planes = Info.num_planes;
905 ret[i].depth = Info.depth;
906 ret[i].red_mask = Info.red_mask;
907 ret[i].green_mask = Info.green_mask;
908 ret[i].blue_mask = Info.blue_mask;
909 ret[i].y_sample_bits = Info.y_sample_bits;
910 ret[i].u_sample_bits = Info.u_sample_bits;
911 ret[i].v_sample_bits = Info.v_sample_bits;
912 ret[i].horz_y_period = Info.horz_y_period;
913 ret[i].horz_u_period = Info.horz_u_period;
914 ret[i].horz_v_period = Info.horz_v_period;
915 ret[i].vert_y_period = Info.vert_y_period;
916 ret[i].vert_u_period = Info.vert_u_period;
917 ret[i].vert_v_period = Info.vert_v_period;
918 memcpy(&(ret[i].component_order[0]), &(Info.comp_order[0]), 32);
919 ret[i].scanline_order = Info.scanline_order;
923 _XEatData(dpy, rep.length << 2);
932 SDL_NAME(XvImage) * SDL_NAME(XvCreateImage) (
940 XExtDisplayInfo *info = xv_find_display(dpy);
941 xvQueryImageAttributesReq *req;
942 xvQueryImageAttributesReply rep;
943 SDL_NAME(XvImage) *ret = NULL;
945 XvCheckExtension(dpy, info, NULL);
949 XvGetReq(QueryImageAttributes, req);
953 req->height = height;
957 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
963 if((ret = (SDL_NAME(XvImage)*)Xmalloc(sizeof(SDL_NAME(XvImage)) + (rep.num_planes << 3)))) {
965 ret->width = rep.width;
966 ret->height = rep.height;
967 ret->data_size = rep.data_size;
968 ret->num_planes = rep.num_planes;
969 ret->pitches = (int*)(&ret[1]);
970 ret->offsets = ret->pitches + rep.num_planes;
973 _XRead(dpy, (char*)(ret->pitches), rep.num_planes << 2);
974 _XRead(dpy, (char*)(ret->offsets), rep.num_planes << 2);
976 _XEatData(dpy, rep.length << 2);
983 SDL_NAME(XvImage) * SDL_NAME(XvShmCreateImage) (
990 XShmSegmentInfo *shminfo
992 SDL_NAME(XvImage) *ret;
994 ret = SDL_NAME(XvCreateImage)(dpy, port, id, data, width, height);
996 if(ret) ret->obdata = (XPointer)shminfo;
1001 int SDL_NAME(XvPutImage) (
1006 SDL_NAME(XvImage) *image,
1013 unsigned int dest_w,
1016 XExtDisplayInfo *info = xv_find_display(dpy);
1020 XvCheckExtension(dpy, info, XvBadExtension);
1026 XvGetReq(PutImage, req);
1031 req->id = image->id;
1036 req->drw_x = dest_x;
1037 req->drw_y = dest_y;
1038 req->drw_w = dest_w;
1039 req->drw_h = dest_h;
1040 req->width = image->width;
1041 req->height = image->height;
1043 len = (image->data_size + 3) >> 2;
1044 SetReqLen(req, len, len);
1046 /* Yes it's kindof lame that we are sending the whole thing,
1047 but for video all of it may be needed even if displaying
1048 only a subsection, and I don't want to go through the
1049 trouble of creating subregions to send */
1050 Data(dpy, (char *)image->data, image->data_size);
1058 int SDL_NAME(XvShmPutImage) (
1063 SDL_NAME(XvImage) *image,
1070 unsigned int dest_w,
1071 unsigned int dest_h,
1074 XExtDisplayInfo *info = xv_find_display(dpy);
1075 XShmSegmentInfo *shminfo = (XShmSegmentInfo *)image->obdata;
1076 xvShmPutImageReq *req;
1078 XvCheckExtension(dpy, info, XvBadExtension);
1084 XvGetReq(ShmPutImage, req);
1089 req->shmseg = shminfo->shmseg;
1090 req->id = image->id;
1095 req->drw_x = dest_x;
1096 req->drw_y = dest_y;
1097 req->drw_w = dest_w;
1098 req->drw_h = dest_h;
1099 req->offset = image->data - shminfo->shmaddr;
1100 req->width = image->width;
1101 req->height = image->height;
1102 req->send_event = send_event;
1112 xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire)
1114 XExtDisplayInfo *info = xv_find_display(dpy);
1115 SDL_NAME(XvEvent) *re = (SDL_NAME(XvEvent) *)host;
1116 xvEvent *event = (xvEvent *)wire;
1118 XvCheckExtension(dpy, info, False);
1120 switch((event->u.u.type & 0x7F) - info->codes->first_event)
1123 re->xvvideo.type = event->u.u.type & 0x7f;
1124 re->xvvideo.serial =
1125 _XSetLastRequestRead(dpy, (xGenericReply *)event);
1126 re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0);
1127 re->xvvideo.display = dpy;
1128 re->xvvideo.time = event->u.videoNotify.time;
1129 re->xvvideo.reason = event->u.videoNotify.reason;
1130 re->xvvideo.drawable = event->u.videoNotify.drawable;
1131 re->xvvideo.port_id = event->u.videoNotify.port;
1134 re->xvport.type = event->u.u.type & 0x7f;
1136 _XSetLastRequestRead(dpy, (xGenericReply *)event);
1137 re->xvport.send_event = ((event->u.u.type & 0x80) != 0);
1138 re->xvport.display = dpy;
1139 re->xvport.time = event->u.portNotify.time;
1140 re->xvport.port_id = event->u.portNotify.port;
1141 re->xvport.attribute = event->u.portNotify.attribute;
1142 re->xvport.value = event->u.portNotify.value;