From 71372d36e1a3f0230b88808f70d35446fda12260 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 15 Apr 2011 14:48:46 +0000 Subject: xserver xkeyboard-config libX11 mesa git update 15 April 2011 --- libX11/modules/im/ximcp/imCallbk.c | 2 + libX11/modules/im/ximcp/imDefIc.c | 3164 ++++++------ libX11/modules/im/ximcp/imDefIm.c | 4089 ++++++++-------- libX11/modules/im/ximcp/imDefLkup.c | 2338 ++++----- libX11/modules/im/ximcp/imLcIm.c | 1461 +++--- libX11/modules/im/ximcp/imRmAttr.c | 8 +- libX11/modules/om/generic/omGeneric.c | 40 +- libX11/src/FSWrap.c | 2 +- libX11/src/RdBitF.c | 5 + libX11/src/xcms/LRGB.c | 8 +- mesalib/configure.ac | 3889 +++++++-------- mesalib/docs/GL3.txt | 6 +- mesalib/docs/relnotes-7.11.html | 16 +- mesalib/src/glsl/glcpp/glcpp-parse.y | 76 +- mesalib/src/mesa/main/extensions.c | 3 +- mesalib/src/mesa/main/fbobject.c | 5022 ++++++++++---------- mesalib/src/mesa/main/formats.c | 44 +- mesalib/src/mesa/main/formats.h | 4 + mesalib/src/mesa/main/framebuffer.c | 2182 ++++----- mesalib/src/mesa/main/texfetch.c | 28 + mesalib/src/mesa/main/texfetch_tmp.h | 104 + mesalib/src/mesa/main/texformat.c | 16 + mesalib/src/mesa/main/texstore.c | 20 +- mesalib/src/mesa/state_tracker/st_cb_readpixels.c | 21 +- mesalib/src/mesa/state_tracker/st_cb_texture.c | 7 +- mesalib/src/mesa/state_tracker/st_extensions.c | 12 + mesalib/src/mesa/state_tracker/st_format.c | 237 + xorg-server/hw/xfree86/dri2/dri2.c | 22 +- .../xkeyboard-config/rules/base.extras.xml.in | 24 + xorg-server/xkeyboard-config/rules/base.xml.in | 14 - xorg-server/xkeyboard-config/symbols/ca | 61 +- xorg-server/xkeyboard-config/symbols/lv | 18 +- 32 files changed, 11761 insertions(+), 11182 deletions(-) diff --git a/libX11/modules/im/ximcp/imCallbk.c b/libX11/modules/im/ximcp/imCallbk.c index 866b27c64..6275bbf00 100644 --- a/libX11/modules/im/ximcp/imCallbk.c +++ b/libX11/modules/im/ximcp/imCallbk.c @@ -247,6 +247,8 @@ _XimCbDispatch(Xim xim, /* status = XimCbQueued; */ } else { /* status = XimCbError; */ + Xfree(pcb); + Xfree(proto_buf); } } else { diff --git a/libX11/modules/im/ximcp/imDefIc.c b/libX11/modules/im/ximcp/imDefIc.c index 6e7519a28..9283c49c3 100644 --- a/libX11/modules/im/ximcp/imDefIc.c +++ b/libX11/modules/im/ximcp/imDefIc.c @@ -1,1582 +1,1582 @@ -/* - * Copyright 1991, 1992 Oracle and/or its affiliates. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -/****************************************************************** - - Copyright 1992, 1993, 1994 by FUJITSU LIMITED - -Permission to use, copy, modify, distribute, and sell this software -and its documentation for any purpose is hereby granted without fee, -provided that the above copyright notice appear in all copies and -that both that copyright notice and this permission notice appear -in supporting documentation, and that the name of FUJITSU LIMITED -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. -FUJITSU LIMITED makes no representations about the suitability of -this software for any purpose. -It is provided "as is" without express or implied warranty. - -FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc. - Takashi Fujiwara FUJITSU LIMITED - fujiwara@a80.tech.yk.fujitsu.co.jp - -******************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include "Xlibint.h" -#include "Xlcint.h" -#include "Ximint.h" - -Private Bool -_XimCreateICCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - - if ((major_opcode == XIM_CREATE_IC_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid)) - return True; - return False; -} - -#ifdef XIM_CONNECTABLE -Public Bool -_XimReCreateIC(ic) - Xic ic; -{ - Xim im = (Xim)ic->core.im; - Xic save_ic; - XIMResourceList res; - unsigned int num; - XIMStyle input_style = ic->core.input_style; - XimDefICValues ic_values; - INT16 len; - CARD16 *buf_s; - char *tmp; - CARD32 tmp_buf32[BUFSIZE/4]; - char *tmp_buf = (char *)tmp_buf32; - char *buf; - int buf_size; - char *data; - int data_len; - int ret_len; - int total; - int idx; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int ret_code; - - if (!(save_ic = (Xic)Xmalloc(sizeof(XicRec)))) - return False; - memcpy((char *)save_ic, (char *)ic, sizeof(XicRec)); - - ic->core.filter_events = im->private.proto.forward_event_mask; - ic->private.proto.forward_event_mask = - im->private.proto.forward_event_mask; - ic->private.proto.synchronous_event_mask = - im->private.proto.synchronous_event_mask; - - num = im->core.ic_num_resources; - buf_size = sizeof(XIMResource) * num; - if (!(res = (XIMResourceList)Xmalloc(buf_size))) - goto ErrorOnReCreateIC; - (void)memcpy((char *)res, (char *)im->core.ic_resources, buf_size); - ic->private.proto.ic_resources = res; - ic->private.proto.ic_num_resources = num; - - num = im->private.proto.ic_num_inner_resources; - buf_size = sizeof(XIMResource) * num; - if (!(res = (XIMResourceList)Xmalloc(buf_size))) - goto ErrorOnReCreateIC; - (void)memcpy((char *)res, - (char *)im->private.proto.ic_inner_resources, buf_size); - ic->private.proto.ic_inner_resources = res; - ic->private.proto.ic_num_inner_resources = num; - - _XimSetICMode(ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, input_style); - - _XimSetICMode(ic->private.proto.ic_inner_resources, - ic->private.proto.ic_num_inner_resources, input_style); - - _XimGetCurrentICValues(ic, &ic_values); - buf = tmp_buf; - buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); - data_len = BUFSIZE - buf_size; - total = 0; - idx = 0; - for (;;) { - data = &buf[buf_size]; - if (!_XimEncodeSavedICATTRIBUTE(ic, ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, &idx, data, data_len, - &ret_len, (XPointer)&ic_values, XIM_CREATEIC)) { - if (buf != tmp_buf) - Xfree(buf); - goto ErrorOnReCreateIC; - } - - total += ret_len; - if (idx == -1) { - break; - } - - buf_size += ret_len; - if (buf == tmp_buf) { - if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { - goto ErrorOnReCreateIC; - } - memcpy(tmp, buf, buf_size); - buf = tmp; - } else { - if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { - Xfree(buf); - goto ErrorOnReCreateIC; - } - buf = tmp; - } - } - - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - buf_s[0] = im->private.proto.imid; - buf_s[1] = (INT16)total; - - len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); - _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - if (buf != tmp_buf) - Xfree(buf); - goto ErrorOnReCreateIC; - } - _XimFlush(im); - if (buf != tmp_buf) - Xfree(buf); - ic->private.proto.waitCallback = True; - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimCreateICCheck, 0); - if (ret_code == XIM_TRUE) { - preply = reply; - } else if (ret_code == XIM_OVERFLOW) { - if (len <= 0) { - preply = reply; - } else { - buf_size = (int)len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimCreateICCheck, 0); - if (ret_code != XIM_TRUE) { - Xfree(preply); - ic->private.proto.waitCallback = False; - goto ErrorOnReCreateIC; - } - } - } else { - ic->private.proto.waitCallback = False; - goto ErrorOnReCreateIC; - } - ic->private.proto.waitCallback = False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if (reply != preply) - Xfree(preply); - goto ErrorOnReCreateIC; - } - - ic->private.proto.icid = buf_s[1]; /* icid */ - if (reply != preply) - Xfree(preply); - - _XimRegisterFilter(ic); - MARK_IC_CONNECTED(ic); - if (save_ic->private.proto.ic_resources) - Xfree(save_ic->private.proto.ic_resources); - if (save_ic->private.proto.ic_inner_resources) - Xfree(save_ic->private.proto.ic_inner_resources); - Xfree(save_ic); - return True; - -ErrorOnReCreateIC: - memcpy((char *)ic, (char *)save_ic, sizeof(XicRec)); - Xfree(save_ic); - return False; -} - -Private char * -_XimDelayModeGetICValues(ic, arg) - Xic ic; - XIMArg *arg; -{ - XimDefICValues ic_values; - - _XimGetCurrentICValues(ic, &ic_values); - return _XimGetICValueData(ic, (XPointer)&ic_values, - ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, - arg, XIM_GETICVALUES); -} -#endif /* XIM_CONNECTABLE */ - -Private Bool -_XimGetICValuesCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - - if ((major_opcode == XIM_GET_IC_VALUES_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - return True; - return False; -} - -Private char * -_XimProtoGetICValues( - XIC xic, - XIMArg *arg) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - register XIMArg *p; - register XIMArg *pp; - register int n; - CARD8 *buf; - CARD16 *buf_s; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply = NULL; - int buf_size; - int ret_code; - char *makeid_name; - char *decode_name; - CARD16 *data = NULL; - INT16 data_len = 0; - -#ifndef XIM_CONNECTABLE - if (!IS_IC_CONNECTED(ic)) - return arg->name; -#else - if (!IS_IC_CONNECTED(ic)) { - if (IS_CONNECTABLE(im)) { - if (_XimConnectServer(im)) { - if (!_XimReCreateIC(ic)) { - _XimDelayModeSetAttr(im); - return _XimDelayModeGetICValues(ic, arg); - } - } else { - return _XimDelayModeGetICValues(ic, arg); - } - } else { - return arg->name; - } - } -#endif /* XIM_CONNECTABLE */ - - for (n = 0, p = arg; p && p->name; p++) { - n++; - if ((strcmp(p->name, XNPreeditAttributes) == 0) - || (strcmp(p->name, XNStatusAttributes) == 0)) { - n++; - for (pp = (XIMArg *)p->value; pp && pp->name; pp++) - n++; - } - } - - if (!n) - return (char *)NULL; - - buf_size = sizeof(CARD16) * n; - buf_size += XIM_HEADER_SIZE - + sizeof(CARD16) - + sizeof(CARD16) - + sizeof(INT16) - + XIM_PAD(2 + buf_size); - - if (!(buf = (CARD8 *)Xmalloc(buf_size))) - return arg->name; - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - - makeid_name = _XimMakeICAttrIDList(ic, ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, arg, - &buf_s[3], &len, XIM_GETICVALUES); - - if (len > 0) { - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - buf_s[2] = len; /* length of ic-attr-id */ - len += sizeof(INT16); /* sizeof length of attr */ - XIM_SET_PAD(&buf_s[2], len); /* pad */ - len += sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_GET_IC_VALUES, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - Xfree(buf); - return arg->name; - } - _XimFlush(im); - Xfree(buf); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimGetICValuesCheck, (XPointer)ic); - if (ret_code == XIM_TRUE) { - preply = reply; - } else if (ret_code == XIM_OVERFLOW) { - if (len <= 0) { - preply = reply; - } else { - buf_size = (int)len; - preply = (XPointer)Xmalloc(len); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimGetICValuesCheck, (XPointer)ic); - if (ret_code != XIM_TRUE) { - if (preply != reply) - Xfree(preply); - return arg->name; - } - } - } else { - return arg->name; - } - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if (reply != preply) - Xfree(preply); - return arg->name; - } - data = &buf_s[4]; - data_len = buf_s[2]; - } - else if (len < 0) { - return arg->name; - } - - decode_name = _XimDecodeICATTRIBUTE(ic, ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, data, data_len, - arg, XIM_GETICVALUES); - if (reply != preply) - Xfree(preply); - - if (decode_name) - return decode_name; - else - return makeid_name; -} - -#ifdef XIM_CONNECTABLE -Private Bool -_XimCheckNestQuarkList(quark_list, num_quark, quark, separator) - XrmQuark *quark_list; - int num_quark; - XrmQuark quark; - XrmQuark separator; -{ - register int i; - - for (i = 0; i < num_quark; i++) { - if (quark_list[i] == separator) { - break; - } - if (quark_list[i] == quark) { - return True; - } - } - return False; -} - -Private Bool -_XimCheckNestedQuarkList(quark_list, idx, num_quark, arg, separator) - XrmQuark **quark_list; - int idx; - int *num_quark; - XIMArg *arg; - XrmQuark separator; -{ - XrmQuark *q_list = *quark_list; - int n_quark = *num_quark; - register XIMArg *p; - XrmQuark quark; - XrmQuark *tmp; - register int i; - - for (p = arg; p && p->name; p++) { - quark = XrmStringToQuark(p->name); - if (_XimCheckNestQuarkList(&q_list[idx], n_quark - idx, - quark, separator)) { - continue; - } - if (!(tmp = (XrmQuark *)Xmalloc((sizeof(XrmQuark) * (n_quark + 1))))) { - *quark_list = q_list; - *num_quark = n_quark; - return False; - } - n_quark++; - for (i = 0; i < idx; i++) { - tmp[i] = q_list[i]; - } - tmp[i] = quark; - for (i = idx + 1; i < n_quark; i++) { - tmp[i] = q_list[i - 1]; - } - q_list = tmp; - } - *quark_list = q_list; - *num_quark = n_quark; - return True; -} - -Private Bool -_XimCheckICQuarkList(quark_list, num_quark, quark, idx) - XrmQuark *quark_list; - int num_quark; - XrmQuark quark; - int *idx; -{ - register int i; - - for (i = 0; i < num_quark; i++) { - if (quark_list[i] == quark) { - *idx = i; - return True; - } - } - return False; -} - -Private Bool -_XimSaveICValues(ic, arg) - Xic ic; - XIMArg *arg; -{ - register XIMArg *p; - register int n; - XrmQuark *quark_list; - XrmQuark *tmp; - XrmQuark quark; - int num_quark; - XrmQuark pre_quark; - XrmQuark sts_quark; - XrmQuark separator; - int idx; - - pre_quark = XrmStringToQuark(XNPreeditAttributes); - sts_quark = XrmStringToQuark(XNStatusAttributes); - separator = XrmStringToQuark(XNSeparatorofNestedList); - - if (quark_list = ic->private.proto.saved_icvalues) { - num_quark = ic->private.proto.num_saved_icvalues; - for (p = arg; p && p->name; p++) { - quark = XrmStringToQuark(p->name); - if ((quark == pre_quark) || (quark == sts_quark)) { - if (!_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) { - register XIMArg *pp; - int nn; - XrmQuark *q_list; - - for (pp = (XIMArg *)p->value, nn = 0; - pp && pp->name; pp++, nn++); - if (!(tmp = (XrmQuark *)Xrealloc(quark_list, - (sizeof(XrmQuark) * (num_quark + nn + 2))))) { - ic->private.proto.saved_icvalues = quark_list; - ic->private.proto.num_saved_icvalues = num_quark; - return False; - } - quark_list = tmp; - q_list = &quark_list[num_quark]; - num_quark += nn + 2; - *q_list++ = quark; - for (pp = (XIMArg *)p->value; - pp && pp->name; pp++, quark_list++) { - *q_list = XrmStringToQuark(pp->name); - } - *q_list = separator; - } else { - if (!_XimCheckNestedQuarkList(&quark_list, idx + 1, - &num_quark, (XIMArg *)p->value, separator)) { - ic->private.proto.saved_icvalues = quark_list; - ic->private.proto.num_saved_icvalues = num_quark; - return False; - } - } - } else { - if (_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) { - continue; - } - if (!(tmp = (XrmQuark *)Xrealloc(quark_list, - (sizeof(XrmQuark) * (num_quark + 1))))) { - ic->private.proto.saved_icvalues = quark_list; - ic->private.proto.num_saved_icvalues = num_quark; - return False; - } - quark_list = tmp; - quark_list[num_quark] = quark; - num_quark++; - } - } - ic->private.proto.saved_icvalues = quark_list; - ic->private.proto.num_saved_icvalues = num_quark; - return True; - } - - for (p = arg, n = 0; p && p->name; p++, n++) { - if ((!strcmp(p->name, XNPreeditAttributes)) - || (!strcmp(p->name, XNStatusAttributes))) { - register XIMArg *pp; - int nn; - - for (pp = (XIMArg *)p->value, nn = 0; pp && pp->name; pp++, nn++); - n += nn + 1; - } - } - - if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) { - return False; - } - - ic->private.proto.saved_icvalues = quark_list; - ic->private.proto.num_saved_icvalues = n; - for (p = arg; p && p->name; p++, quark_list++) { - *quark_list = XrmStringToQuark(p->name); - if ((*quark_list == pre_quark) || (*quark_list == sts_quark)) { - register XIMArg *pp; - - quark_list++; - for (pp = (XIMArg *)p->value; pp && pp->name; pp++, quark_list++) { - *quark_list = XrmStringToQuark(pp->name); - } - *quark_list = separator; - } - } - return True; -} - -Private char * -_XimDelayModeSetICValues(ic, arg) - Xic ic; - XIMArg *arg; -{ - XimDefICValues ic_values; - char *name; - - _XimGetCurrentICValues(ic, &ic_values); - name = _XimSetICValueData(ic, (XPointer)&ic_values, - ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, - arg, XIM_SETICVALUES, False); - _XimSetCurrentICValues(ic, &ic_values); - return name; -} -#endif /* XIM_CONNECTABLE */ - -Private Bool -_XimSetICValuesCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - - if ((major_opcode == XIM_SET_IC_VALUES_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - return True; - return False; -} - -Private char * -_XimProtoSetICValues( - XIC xic, - XIMArg *arg) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - XimDefICValues ic_values; - INT16 len; - CARD16 *buf_s; - char *tmp; - CARD32 tmp_buf32[BUFSIZE/4]; - char *tmp_buf = (char *)tmp_buf32; - char *buf; - int buf_size; - char *data; - int data_len; - int ret_len; - int total; - XIMArg *arg_ret; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply = NULL; - int ret_code; - BITMASK32 flag = 0L; - char *name; - char *tmp_name = (arg) ? arg->name : NULL; - -#ifndef XIM_CONNECTABLE - if (!IS_IC_CONNECTED(ic)) - return tmp_name; -#else - if (!_XimSaveICValues(ic, arg)) - return NULL; - - if (!IS_IC_CONNECTED(ic)) { - if (IS_CONNECTABLE(im)) { - if (_XimConnectServer(im)) { - if (!_XimReCreateIC(ic)) { - _XimDelayModeSetAttr(im); - return _XimDelayModeSetICValues(ic, arg); - } - } else { - return _XimDelayModeSetICValues(ic, arg); - } - } else { - return tmp_name; - } - } -#endif /* XIM_CONNECTABLE */ - - _XimGetCurrentICValues(ic, &ic_values); - buf = tmp_buf; - buf_size = XIM_HEADER_SIZE - + sizeof(CARD16) + sizeof(CARD16) + sizeof(INT16) + sizeof(CARD16); - data_len = BUFSIZE - buf_size; - total = 0; - arg_ret = arg; - for (;;) { - data = &buf[buf_size]; - if ((name = _XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, arg, &arg_ret, - data, data_len, &ret_len, (XPointer)&ic_values, - &flag, XIM_SETICVALUES))) { - break; - } - - total += ret_len; - if (!(arg = arg_ret)) { - break; - } - - buf_size += ret_len; - if (buf == tmp_buf) { - if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { - return tmp_name; - } - memcpy(tmp, buf, buf_size); - buf = tmp; - } else { - if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { - Xfree(buf); - return tmp_name; - } - buf = tmp; - } - } - _XimSetCurrentICValues(ic, &ic_values); - - if (!total) { - return tmp_name; - } - - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - -#ifdef EXT_MOVE - if (_XimExtenMove(im, ic, flag, &buf_s[4], (INT16)total)) - return name; -#endif - - buf_s[0] = im->private.proto.imid; - buf_s[1] = ic->private.proto.icid; - buf_s[2] = (INT16)total; - buf_s[3] = 0; - len = (INT16)(sizeof(CARD16) + sizeof(CARD16) - + sizeof(INT16) + sizeof(CARD16) + total); - - _XimSetHeader((XPointer)buf, XIM_SET_IC_VALUES, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - if (buf != tmp_buf) - Xfree(buf); - return tmp_name; - } - _XimFlush(im); - if (buf != tmp_buf) - Xfree(buf); - ic->private.proto.waitCallback = True; - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimSetICValuesCheck, (XPointer)ic); - if (ret_code == XIM_TRUE) { - preply = reply; - } else if (ret_code == XIM_OVERFLOW) { - buf_size = (int)len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimSetICValuesCheck, (XPointer)ic); - if (ret_code != XIM_TRUE) { - Xfree(preply); - ic->private.proto.waitCallback = False; - return tmp_name; - } - } else { - ic->private.proto.waitCallback = False; - return tmp_name; - } - ic->private.proto.waitCallback = False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if (reply != preply) - Xfree(preply); - return tmp_name; - } - if (reply != preply) - Xfree(preply); - - return name; -} - -Private Bool -_XimDestroyICCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - Bool ret = False; - - if ((major_opcode == XIM_DESTROY_IC_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - ret = True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - ret = False; - return ret; -} - -Private void -_XimProtoICFree( - Xic ic) -{ -#ifdef XIM_CONNECTABLE - Xim im = (Xim)ic->core.im; -#endif - - if (ic->private.proto.preedit_font) { - Xfree(ic->private.proto.preedit_font); - ic->private.proto.preedit_font = NULL; - } - if (ic->private.proto.status_font) { - Xfree(ic->private.proto.status_font); - ic->private.proto.status_font = NULL; - } - if (ic->private.proto.commit_info) { - _XimFreeCommitInfo(ic); - ic->private.proto.commit_info = NULL; - } - if (ic->private.proto.ic_inner_resources) { - Xfree(ic->private.proto.ic_inner_resources); - ic->private.proto.ic_inner_resources = NULL; - } - -#ifdef XIM_CONNECTABLE - if (IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { - return; - } -#endif /* XIM_CONNECTABLE */ - - if (ic->private.proto.saved_icvalues) { - Xfree(ic->private.proto.saved_icvalues); - ic->private.proto.saved_icvalues = NULL; - } - if (ic->private.proto.ic_resources) { - Xfree(ic->private.proto.ic_resources); - ic->private.proto.ic_resources = NULL; - } - if (ic->core.hotkey) { - Xfree(ic->core.hotkey); - ic->core.hotkey = NULL; - } - - return; -} - -Private void -_XimProtoDestroyIC( - XIC xic) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - - if (IS_SERVER_CONNECTED(im)) { - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_DESTROY_IC, 0, &len); - (void)_XimWrite(im, len, (XPointer)buf); - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimDestroyICCheck, (XPointer)ic); - if (ret_code == XIM_OVERFLOW) { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - (void)_XimRead(im, &len, preply, buf_size, - _XimDestroyICCheck, (XPointer)ic); - Xfree(preply); - } - } - UNMARK_IC_CONNECTED(ic); - _XimUnregisterFilter(ic); - _XimProtoICFree(ic); - return; -} - -Private void -_XimProtoSetFocus( - XIC xic) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - -#ifndef XIM_CONNECTABLE - if (!IS_IC_CONNECTED(ic)) - return; -#else - if (!IS_IC_CONNECTED(ic)) { - if (IS_CONNECTABLE(im)) { - if (_XimConnectServer(im)) { - if (!_XimReCreateIC(ic)) { - _XimDelayModeSetAttr(im); - return; - } - } else { - return; - } - } else { - return; - } - } -#endif /* XIM_CONNECTABLE */ - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_SET_IC_FOCUS, 0, &len); - (void)_XimWrite(im, len, (XPointer)buf); - _XimFlush(im); - - MARK_FOCUSED(ic); - - _XimRegisterFilter(ic); - return; -} - -Private void -_XimProtoUnsetFocus( - XIC xic) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - -#ifndef XIM_CONNECTABLE - if (!IS_IC_CONNECTED(ic)) - return; -#else - if (!IS_IC_CONNECTED(ic)) { - if (IS_CONNECTABLE(im)) { - if (_XimConnectServer(im)) { - if (!_XimReCreateIC(ic)) { - _XimDelayModeSetAttr(im); - return; - } - } else { - return; - } - } else { - return; - } - } -#endif /* XIM_CONNECTABLE */ - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_UNSET_IC_FOCUS, 0, &len); - (void)_XimWrite(im, len, (XPointer)buf); - _XimFlush(im); - - UNMARK_FOCUSED(ic); - - _XimUnregisterFilter(ic); - return; -} - -Private Bool -_XimResetICCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - - if ((major_opcode == XIM_RESET_IC_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - return True; - return False; -} - -Private char * -_XimProtoReset( - XIC xic, - char * (*retfunc) (Xim im, Xic ic, XPointer buf) ) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - char *commit; - - if (!IS_IC_CONNECTED(ic)) - return (char *)NULL; - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_RESET_IC, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return NULL; - _XimFlush(im); - ic->private.proto.waitCallback = True; - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimResetICCheck, (XPointer)ic); - if (ret_code == XIM_TRUE) { - preply = reply; - } else if (ret_code == XIM_OVERFLOW) { - if (len < 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimResetICCheck, (XPointer)ic); - if (ret_code != XIM_TRUE) { - Xfree(preply); - ic->private.proto.waitCallback = False; - return NULL; - } - } - } else { - ic->private.proto.waitCallback = False; - return NULL; - } - ic->private.proto.waitCallback = False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if (reply != preply) - free(preply); - return NULL; - } - - commit = retfunc(im, ic, (XPointer)&buf_s[2]); - - if (reply != preply) - Xfree(preply); - return commit; -} - -Private char * -_XimCommitedMbString( - Xim im, - Xic ic, - XPointer buf) -{ - CARD16 *buf_s = (CARD16 *)buf; - XimCommitInfo info; - int len; - int new_len; - char *commit; - char *new_commit = NULL; - char *str; - Status status; - - len = 0; - for (info = ic->private.proto.commit_info; info; info = info->next) - len += info->string_len; - len += buf_s[0]; - if ( len == 0 ) - return( NULL ); - - if (!(commit = (char *)Xmalloc(len + 1))) - goto Error_On_Reset; - - str = commit; - for (info = ic->private.proto.commit_info; info; info = info->next) { - (void)memcpy(str, info->string, info->string_len); - str += info->string_len; - } - (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); - commit[len] = '\0'; - - new_len = im->methods->ctstombs((XIM)im, commit, len, NULL, 0, &status); - if (status != XLookupNone) { - if (!(new_commit = Xmalloc(new_len + 1))) { - Xfree(commit); - goto Error_On_Reset; - } - (void)im->methods->ctstombs((XIM)im, commit, len, - new_commit, new_len, NULL); - new_commit[new_len] = '\0'; - } - Xfree(commit); - -Error_On_Reset: - _XimFreeCommitInfo( ic ); - return new_commit; -} - -Private char * -_XimProtoMbReset( - XIC xic) -{ - return _XimProtoReset(xic, _XimCommitedMbString); -} - -Private wchar_t * -_XimCommitedWcString( - Xim im, - Xic ic, - XPointer buf) -{ - CARD16 *buf_s = (CARD16 *)buf; - XimCommitInfo info; - int len; - int new_len; - char *commit; - wchar_t *new_commit = (wchar_t *)NULL; - char *str; - Status status; - - len = 0; - for (info = ic->private.proto.commit_info; info; info = info->next) - len += info->string_len; - len += buf_s[0]; - if ( len == 0 ) - return( (wchar_t *)NULL ); - - if (!(commit = (char *)Xmalloc(len + 1))) - goto Error_On_Reset; - - str = commit; - for (info = ic->private.proto.commit_info; info; info = info->next) { - (void)memcpy(str, info->string, info->string_len); - str += info->string_len; - } - (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); - commit[len] = '\0'; - - new_len = im->methods->ctstowcs((XIM)im, commit, len, NULL, 0, &status); - if (status != XLookupNone) { - if (!(new_commit = - (wchar_t *)Xmalloc(sizeof(wchar_t) * (new_len + 1)))) { - Xfree(commit); - goto Error_On_Reset; - } - (void)im->methods->ctstowcs((XIM)im, commit, len, - new_commit, new_len, NULL); - new_commit[new_len] = (wchar_t)'\0'; - } - Xfree(commit); - -Error_On_Reset: - _XimFreeCommitInfo( ic ); - return new_commit; -} - -Private wchar_t * -_XimProtoWcReset( - XIC xic) -{ - return (wchar_t *) _XimProtoReset(xic, - (char * (*) (Xim, Xic, XPointer)) _XimCommitedWcString); -} - -Private char * -_XimCommitedUtf8String( - Xim im, - Xic ic, - XPointer buf) -{ - CARD16 *buf_s = (CARD16 *)buf; - XimCommitInfo info; - int len; - int new_len; - char *commit; - char *new_commit = NULL; - char *str; - Status status; - - len = 0; - for (info = ic->private.proto.commit_info; info; info = info->next) - len += info->string_len; - len += buf_s[0]; - if ( len == 0 ) - return( NULL ); - - if (!(commit = (char *)Xmalloc(len + 1))) - goto Error_On_Reset; - - str = commit; - for (info = ic->private.proto.commit_info; info; info = info->next) { - (void)memcpy(str, info->string, info->string_len); - str += info->string_len; - } - (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); - commit[len] = '\0'; - - new_len = im->methods->ctstoutf8((XIM)im, commit, len, NULL, 0, &status); - if (status != XLookupNone) { - if (!(new_commit = Xmalloc(new_len + 1))) { - Xfree(commit); - goto Error_On_Reset; - } - (void)im->methods->ctstoutf8((XIM)im, commit, len, - new_commit, new_len, NULL); - new_commit[new_len] = '\0'; - } - Xfree(commit); - -Error_On_Reset: - _XimFreeCommitInfo( ic ); - return new_commit; -} - -Private char * -_XimProtoUtf8Reset( - XIC xic) -{ - return _XimProtoReset(xic, _XimCommitedUtf8String); -} - -Private XICMethodsRec ic_methods = { - _XimProtoDestroyIC, /* destroy */ - _XimProtoSetFocus, /* set_focus */ - _XimProtoUnsetFocus, /* unset_focus */ - _XimProtoSetICValues, /* set_values */ - _XimProtoGetICValues, /* get_values */ - _XimProtoMbReset, /* mb_reset */ - _XimProtoWcReset, /* wc_reset */ - _XimProtoUtf8Reset, /* utf8_reset */ - _XimProtoMbLookupString, /* mb_lookup_string */ - _XimProtoWcLookupString, /* wc_lookup_string */ - _XimProtoUtf8LookupString /* utf8_lookup_string */ -}; - -Private Bool -_XimGetInputStyle( - XIMArg *arg, - XIMStyle *input_style) -{ - register XIMArg *p; - - for (p = arg; p && p->name; p++) { - if (!(strcmp(p->name, XNInputStyle))) { - *input_style = (XIMStyle)p->value; - return True; - } - } - return False; -} - -#ifdef XIM_CONNECTABLE -Private Bool -_XimDelayModeCreateIC( - Xic ic, - XIMArg *values, - XIMResourceList res, - unsigned int num) -{ - Xim im = (Xim)ic->core.im; - XimDefICValues ic_values; - int len; - XIMStyle input_style; - - bzero((char *)&ic_values, sizeof(XimDefICValues)); - _XimGetCurrentICValues(ic, &ic_values); - if (!(_XimGetInputStyle(values, &input_style))) - return False; - - _XimSetICMode(res, num, input_style); - - if (_XimSetICValueData(ic, (XPointer)&ic_values, res, num, - values, XIM_CREATEIC, False)) { - return False; - } - _XimSetCurrentICValues(ic, &ic_values); - if (!_XimSetICDefaults(ic, (XPointer)&ic_values, - XIM_SETICDEFAULTS, res, num)) { - return False; - } - ic_values.filter_events = KeyPressMask; - _XimSetCurrentICValues(ic, &ic_values); - _XimRegisterFilter(ic); - - return True; -} - -Public Bool -_XimReconnectModeCreateIC(ic) - Xic ic; -{ - Xim im = (Xim)ic->core.im; - int len; - XIMStyle input_style = ic->core.input_style; - XIMResourceList res; - unsigned int num; - - num = im->core.ic_num_resources; - len = sizeof(XIMResource) * num; - if (!(res = (XIMResourceList)Xmalloc(len))) - return False; - (void)memcpy((char *)res, (char *)im->core.ic_resources, len); - ic->private.proto.ic_resources = res; - ic->private.proto.ic_num_resources = num; - - _XimSetICMode(res, num, input_style); - - ic->core.filter_events = KeyPressMask; - - return True; -} -#endif /* XIM_CONNECTABLE */ - -Public XIC -_XimProtoCreateIC( - XIM xim, - XIMArg *arg) -{ - Xim im = (Xim)xim; - Xic ic; - XimDefICValues ic_values; - XIMResourceList res; - unsigned int num; - XIMStyle input_style; - INT16 len; - CARD16 *buf_s; - char *tmp; - CARD32 tmp_buf32[BUFSIZE/4]; - char *tmp_buf = (char *)tmp_buf32; - char *buf; - int buf_size; - char *data; - int data_len; - int ret_len; - int total; - XIMArg *arg_ret; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int ret_code; - -#ifdef XIM_CONNECTABLE - if (!IS_SERVER_CONNECTED(im) && !IS_CONNECTABLE(im)) - return (XIC)NULL; -#else - if (!IS_SERVER_CONNECTED(im)) - return (XIC)NULL; -#endif /* XIM_CONNECTABLE */ - - if (!(_XimGetInputStyle(arg, &input_style))) - return (XIC)NULL; - - if ((ic = (Xic)Xmalloc(sizeof(XicRec))) == (Xic)NULL) - return (XIC)NULL; - - bzero((char *)ic, sizeof(XicRec)); - ic->methods = &ic_methods; - ic->core.im = (XIM)im; - ic->core.input_style = input_style; - - num = im->core.ic_num_resources; - len = sizeof(XIMResource) * num; - if (!(res = (XIMResourceList)Xmalloc(len))) - return (XIC)NULL; - (void)memcpy((char *)res, (char *)im->core.ic_resources, len); - ic->private.proto.ic_resources = res; - ic->private.proto.ic_num_resources = num; - -#ifdef XIM_CONNECTABLE - if (!_XimSaveICValues(ic, arg)) - return False; - - if (!IS_SERVER_CONNECTED(im)) { - if (!_XimConnectServer(im)) { - if (_XimDelayModeCreateIC(ic, arg, res, num)) { - return (XIC)ic; - } - goto ErrorOnCreatingIC; - } - } -#endif /* XIM_CONNECTABLE */ - - ic->core.filter_events = im->private.proto.forward_event_mask; - ic->private.proto.forward_event_mask = - im->private.proto.forward_event_mask; - ic->private.proto.synchronous_event_mask = - im->private.proto.synchronous_event_mask; - - num = im->private.proto.ic_num_inner_resources; - len = sizeof(XIMResource) * num; - if (!(res = (XIMResourceList)Xmalloc(len))) - return (XIC)NULL; - (void)memcpy((char *)res, - (char *)im->private.proto.ic_inner_resources, len); - ic->private.proto.ic_inner_resources = res; - ic->private.proto.ic_num_inner_resources = num; - - _XimSetICMode(ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, input_style); - - _XimSetICMode(ic->private.proto.ic_inner_resources, - ic->private.proto.ic_num_inner_resources, input_style); - - _XimGetCurrentICValues(ic, &ic_values); - buf = tmp_buf; - buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); - data_len = BUFSIZE - buf_size; - total = 0; - arg_ret = arg; - for (;;) { - data = &buf[buf_size]; - if (_XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources, arg, &arg_ret, data, - data_len, &ret_len, (XPointer)&ic_values, 0, XIM_CREATEIC)) { - goto ErrorOnCreatingIC; - } - - total += ret_len; - if (!(arg = arg_ret)) { - break; - } - - buf_size += ret_len; - if (buf == tmp_buf) { - if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { - goto ErrorOnCreatingIC; - } - memcpy(tmp, buf, buf_size); - buf = tmp; - } else { - if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { - Xfree(buf); - goto ErrorOnCreatingIC; - } - buf = tmp; - } - } - _XimSetCurrentICValues(ic, &ic_values); - - if (!(_XimCheckCreateICValues(ic->private.proto.ic_resources, - ic->private.proto.ic_num_resources))) - goto ErrorOnCreatingIC; - - _XimRegisterFilter(ic); - - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - buf_s[0] = im->private.proto.imid; - buf_s[1] = (INT16)total; - - len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); - _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - if (buf != tmp_buf) - Xfree(buf); - goto ErrorOnCreatingIC; - } - _XimFlush(im); - if (buf != tmp_buf) - Xfree(buf); - ic->private.proto.waitCallback = True; - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimCreateICCheck, 0); - if (ret_code == XIM_TRUE) { - preply = reply; - } else if (ret_code == XIM_OVERFLOW) { - if (len <= 0) { - preply = reply; - } else { - buf_size = (int)len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimCreateICCheck, 0); - if (ret_code != XIM_TRUE) { - Xfree(preply); - ic->private.proto.waitCallback = False; - goto ErrorOnCreatingIC; - } - } - } else { - ic->private.proto.waitCallback = False; - goto ErrorOnCreatingIC; - } - ic->private.proto.waitCallback = False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if (reply != preply) - Xfree(preply); - goto ErrorOnCreatingIC; - } - - ic->private.proto.icid = buf_s[1]; /* icid */ - if (reply != preply) - Xfree(preply); - MARK_IC_CONNECTED(ic); - return (XIC)ic; - -ErrorOnCreatingIC: - _XimUnregisterFilter(ic); - if (ic->private.proto.ic_resources) - Xfree(ic->private.proto.ic_resources); - if (ic->private.proto.ic_inner_resources) - Xfree(ic->private.proto.ic_inner_resources); - Xfree(ic); - return (XIC)NULL; -} +/* + * Copyright 1991, 1992 Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/****************************************************************** + + Copyright 1992, 1993, 1994 by FUJITSU LIMITED + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear +in supporting documentation, and that the name of FUJITSU LIMITED +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +FUJITSU LIMITED makes no representations about the suitability of +this software for any purpose. +It is provided "as is" without express or implied warranty. + +FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc. + Takashi Fujiwara FUJITSU LIMITED + fujiwara@a80.tech.yk.fujitsu.co.jp + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "Xlibint.h" +#include "Xlcint.h" +#include "Ximint.h" + +Private Bool +_XimCreateICCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_CREATE_IC_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +#ifdef XIM_CONNECTABLE +Public Bool +_XimReCreateIC(ic) + Xic ic; +{ + Xim im = (Xim)ic->core.im; + Xic save_ic; + XIMResourceList res; + unsigned int num; + XIMStyle input_style = ic->core.input_style; + XimDefICValues ic_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + int idx; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + + if (!(save_ic = (Xic)Xmalloc(sizeof(XicRec)))) + return False; + memcpy((char *)save_ic, (char *)ic, sizeof(XicRec)); + + ic->core.filter_events = im->private.proto.forward_event_mask; + ic->private.proto.forward_event_mask = + im->private.proto.forward_event_mask; + ic->private.proto.synchronous_event_mask = + im->private.proto.synchronous_event_mask; + + num = im->core.ic_num_resources; + buf_size = sizeof(XIMResource) * num; + if (!(res = (XIMResourceList)Xmalloc(buf_size))) + goto ErrorOnReCreateIC; + (void)memcpy((char *)res, (char *)im->core.ic_resources, buf_size); + ic->private.proto.ic_resources = res; + ic->private.proto.ic_num_resources = num; + + num = im->private.proto.ic_num_inner_resources; + buf_size = sizeof(XIMResource) * num; + if (!(res = (XIMResourceList)Xmalloc(buf_size))) + goto ErrorOnReCreateIC; + (void)memcpy((char *)res, + (char *)im->private.proto.ic_inner_resources, buf_size); + ic->private.proto.ic_inner_resources = res; + ic->private.proto.ic_num_inner_resources = num; + + _XimSetICMode(ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, input_style); + + _XimSetICMode(ic->private.proto.ic_inner_resources, + ic->private.proto.ic_num_inner_resources, input_style); + + _XimGetCurrentICValues(ic, &ic_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + idx = 0; + for (;;) { + data = &buf[buf_size]; + if (!_XimEncodeSavedICATTRIBUTE(ic, ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, &idx, data, data_len, + &ret_len, (XPointer)&ic_values, XIM_CREATEIC)) { + if (buf != tmp_buf) + Xfree(buf); + goto ErrorOnReCreateIC; + } + + total += ret_len; + if (idx == -1) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + goto ErrorOnReCreateIC; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + goto ErrorOnReCreateIC; + } + buf = tmp; + } + } + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + goto ErrorOnReCreateIC; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + ic->private.proto.waitCallback = True; + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimCreateICCheck, 0); + if (ret_code == XIM_TRUE) { + preply = reply; + } else if (ret_code == XIM_OVERFLOW) { + if (len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimCreateICCheck, 0); + if (ret_code != XIM_TRUE) { + Xfree(preply); + ic->private.proto.waitCallback = False; + goto ErrorOnReCreateIC; + } + } + } else { + ic->private.proto.waitCallback = False; + goto ErrorOnReCreateIC; + } + ic->private.proto.waitCallback = False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if (reply != preply) + Xfree(preply); + goto ErrorOnReCreateIC; + } + + ic->private.proto.icid = buf_s[1]; /* icid */ + if (reply != preply) + Xfree(preply); + + _XimRegisterFilter(ic); + MARK_IC_CONNECTED(ic); + if (save_ic->private.proto.ic_resources) + Xfree(save_ic->private.proto.ic_resources); + if (save_ic->private.proto.ic_inner_resources) + Xfree(save_ic->private.proto.ic_inner_resources); + Xfree(save_ic); + return True; + +ErrorOnReCreateIC: + memcpy((char *)ic, (char *)save_ic, sizeof(XicRec)); + Xfree(save_ic); + return False; +} + +Private char * +_XimDelayModeGetICValues(ic, arg) + Xic ic; + XIMArg *arg; +{ + XimDefICValues ic_values; + + _XimGetCurrentICValues(ic, &ic_values); + return _XimGetICValueData(ic, (XPointer)&ic_values, + ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, + arg, XIM_GETICVALUES); +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimGetICValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + + if ((major_opcode == XIM_GET_IC_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + return True; + return False; +} + +Private char * +_XimProtoGetICValues( + XIC xic, + XIMArg *arg) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + register XIMArg *p; + register XIMArg *pp; + register int n; + CARD8 *buf; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply = NULL; + int buf_size; + int ret_code; + char *makeid_name; + char *decode_name; + CARD16 *data = NULL; + INT16 data_len = 0; + +#ifndef XIM_CONNECTABLE + if (!IS_IC_CONNECTED(ic)) + return arg->name; +#else + if (!IS_IC_CONNECTED(ic)) { + if (IS_CONNECTABLE(im)) { + if (_XimConnectServer(im)) { + if (!_XimReCreateIC(ic)) { + _XimDelayModeSetAttr(im); + return _XimDelayModeGetICValues(ic, arg); + } + } else { + return _XimDelayModeGetICValues(ic, arg); + } + } else { + return arg->name; + } + } +#endif /* XIM_CONNECTABLE */ + + for (n = 0, p = arg; p && p->name; p++) { + n++; + if ((strcmp(p->name, XNPreeditAttributes) == 0) + || (strcmp(p->name, XNStatusAttributes) == 0)) { + n++; + for (pp = (XIMArg *)p->value; pp && pp->name; pp++) + n++; + } + } + + if (!n) + return (char *)NULL; + + buf_size = sizeof(CARD16) * n; + buf_size += XIM_HEADER_SIZE + + sizeof(CARD16) + + sizeof(CARD16) + + sizeof(INT16) + + XIM_PAD(2 + buf_size); + + if (!(buf = (CARD8 *)Xmalloc(buf_size))) + return arg->name; + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + + makeid_name = _XimMakeICAttrIDList(ic, ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, arg, + &buf_s[3], &len, XIM_GETICVALUES); + + if (len > 0) { + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + buf_s[2] = len; /* length of ic-attr-id */ + len += sizeof(INT16); /* sizeof length of attr */ + XIM_SET_PAD(&buf_s[2], len); /* pad */ + len += sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_GET_IC_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + Xfree(buf); + return arg->name; + } + _XimFlush(im); + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimGetICValuesCheck, (XPointer)ic); + if (ret_code == XIM_TRUE) { + preply = reply; + } else if (ret_code == XIM_OVERFLOW) { + if (len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(len); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimGetICValuesCheck, (XPointer)ic); + if (ret_code != XIM_TRUE) { + if (preply != reply) + Xfree(preply); + return arg->name; + } + } + } else { + return arg->name; + } + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if (reply != preply) + Xfree(preply); + return arg->name; + } + data = &buf_s[4]; + data_len = buf_s[2]; + } + else if (len < 0) { + return arg->name; + } + + decode_name = _XimDecodeICATTRIBUTE(ic, ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, data, data_len, + arg, XIM_GETICVALUES); + if (reply != preply) + Xfree(preply); + + if (decode_name) + return decode_name; + else + return makeid_name; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimCheckNestQuarkList(quark_list, num_quark, quark, separator) + XrmQuark *quark_list; + int num_quark; + XrmQuark quark; + XrmQuark separator; +{ + register int i; + + for (i = 0; i < num_quark; i++) { + if (quark_list[i] == separator) { + break; + } + if (quark_list[i] == quark) { + return True; + } + } + return False; +} + +Private Bool +_XimCheckNestedQuarkList(quark_list, idx, num_quark, arg, separator) + XrmQuark **quark_list; + int idx; + int *num_quark; + XIMArg *arg; + XrmQuark separator; +{ + XrmQuark *q_list = *quark_list; + int n_quark = *num_quark; + register XIMArg *p; + XrmQuark quark; + XrmQuark *tmp; + register int i; + + for (p = arg; p && p->name; p++) { + quark = XrmStringToQuark(p->name); + if (_XimCheckNestQuarkList(&q_list[idx], n_quark - idx, + quark, separator)) { + continue; + } + if (!(tmp = (XrmQuark *)Xmalloc((sizeof(XrmQuark) * (n_quark + 1))))) { + *quark_list = q_list; + *num_quark = n_quark; + return False; + } + n_quark++; + for (i = 0; i < idx; i++) { + tmp[i] = q_list[i]; + } + tmp[i] = quark; + for (i = idx + 1; i < n_quark; i++) { + tmp[i] = q_list[i - 1]; + } + q_list = tmp; + } + *quark_list = q_list; + *num_quark = n_quark; + return True; +} + +Private Bool +_XimCheckICQuarkList(quark_list, num_quark, quark, idx) + XrmQuark *quark_list; + int num_quark; + XrmQuark quark; + int *idx; +{ + register int i; + + for (i = 0; i < num_quark; i++) { + if (quark_list[i] == quark) { + *idx = i; + return True; + } + } + return False; +} + +Private Bool +_XimSaveICValues(ic, arg) + Xic ic; + XIMArg *arg; +{ + register XIMArg *p; + register int n; + XrmQuark *quark_list; + XrmQuark *tmp; + XrmQuark quark; + int num_quark; + XrmQuark pre_quark; + XrmQuark sts_quark; + XrmQuark separator; + int idx; + + pre_quark = XrmStringToQuark(XNPreeditAttributes); + sts_quark = XrmStringToQuark(XNStatusAttributes); + separator = XrmStringToQuark(XNSeparatorofNestedList); + + if (quark_list = ic->private.proto.saved_icvalues) { + num_quark = ic->private.proto.num_saved_icvalues; + for (p = arg; p && p->name; p++) { + quark = XrmStringToQuark(p->name); + if ((quark == pre_quark) || (quark == sts_quark)) { + if (!_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) { + register XIMArg *pp; + int nn; + XrmQuark *q_list; + + for (pp = (XIMArg *)p->value, nn = 0; + pp && pp->name; pp++, nn++); + if (!(tmp = (XrmQuark *)Xrealloc(quark_list, + (sizeof(XrmQuark) * (num_quark + nn + 2))))) { + ic->private.proto.saved_icvalues = quark_list; + ic->private.proto.num_saved_icvalues = num_quark; + return False; + } + quark_list = tmp; + q_list = &quark_list[num_quark]; + num_quark += nn + 2; + *q_list++ = quark; + for (pp = (XIMArg *)p->value; + pp && pp->name; pp++, quark_list++) { + *q_list = XrmStringToQuark(pp->name); + } + *q_list = separator; + } else { + if (!_XimCheckNestedQuarkList(&quark_list, idx + 1, + &num_quark, (XIMArg *)p->value, separator)) { + ic->private.proto.saved_icvalues = quark_list; + ic->private.proto.num_saved_icvalues = num_quark; + return False; + } + } + } else { + if (_XimCheckICQuarkList(quark_list, num_quark, quark, &idx)) { + continue; + } + if (!(tmp = (XrmQuark *)Xrealloc(quark_list, + (sizeof(XrmQuark) * (num_quark + 1))))) { + ic->private.proto.saved_icvalues = quark_list; + ic->private.proto.num_saved_icvalues = num_quark; + return False; + } + quark_list = tmp; + quark_list[num_quark] = quark; + num_quark++; + } + } + ic->private.proto.saved_icvalues = quark_list; + ic->private.proto.num_saved_icvalues = num_quark; + return True; + } + + for (p = arg, n = 0; p && p->name; p++, n++) { + if ((!strcmp(p->name, XNPreeditAttributes)) + || (!strcmp(p->name, XNStatusAttributes))) { + register XIMArg *pp; + int nn; + + for (pp = (XIMArg *)p->value, nn = 0; pp && pp->name; pp++, nn++); + n += nn + 1; + } + } + + if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) { + return False; + } + + ic->private.proto.saved_icvalues = quark_list; + ic->private.proto.num_saved_icvalues = n; + for (p = arg; p && p->name; p++, quark_list++) { + *quark_list = XrmStringToQuark(p->name); + if ((*quark_list == pre_quark) || (*quark_list == sts_quark)) { + register XIMArg *pp; + + quark_list++; + for (pp = (XIMArg *)p->value; pp && pp->name; pp++, quark_list++) { + *quark_list = XrmStringToQuark(pp->name); + } + *quark_list = separator; + } + } + return True; +} + +Private char * +_XimDelayModeSetICValues(ic, arg) + Xic ic; + XIMArg *arg; +{ + XimDefICValues ic_values; + char *name; + + _XimGetCurrentICValues(ic, &ic_values); + name = _XimSetICValueData(ic, (XPointer)&ic_values, + ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, + arg, XIM_SETICVALUES, False); + _XimSetCurrentICValues(ic, &ic_values); + return name; +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimSetICValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + + if ((major_opcode == XIM_SET_IC_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + return True; + return False; +} + +Private char * +_XimProtoSetICValues( + XIC xic, + XIMArg *arg) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + XimDefICValues ic_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + XIMArg *arg_ret; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply = NULL; + int ret_code; + BITMASK32 flag = 0L; + char *name; + char *tmp_name = (arg) ? arg->name : NULL; + +#ifndef XIM_CONNECTABLE + if (!IS_IC_CONNECTED(ic)) + return tmp_name; +#else + if (!_XimSaveICValues(ic, arg)) + return NULL; + + if (!IS_IC_CONNECTED(ic)) { + if (IS_CONNECTABLE(im)) { + if (_XimConnectServer(im)) { + if (!_XimReCreateIC(ic)) { + _XimDelayModeSetAttr(im); + return _XimDelayModeSetICValues(ic, arg); + } + } else { + return _XimDelayModeSetICValues(ic, arg); + } + } else { + return tmp_name; + } + } +#endif /* XIM_CONNECTABLE */ + + _XimGetCurrentICValues(ic, &ic_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + + sizeof(CARD16) + sizeof(CARD16) + sizeof(INT16) + sizeof(CARD16); + data_len = BUFSIZE - buf_size; + total = 0; + arg_ret = arg; + for (;;) { + data = &buf[buf_size]; + if ((name = _XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, arg, &arg_ret, + data, data_len, &ret_len, (XPointer)&ic_values, + &flag, XIM_SETICVALUES))) { + break; + } + + total += ret_len; + if (!(arg = arg_ret)) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + return tmp_name; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + return tmp_name; + } + buf = tmp; + } + } + _XimSetCurrentICValues(ic, &ic_values); + + if (!total) { + return tmp_name; + } + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + +#ifdef EXT_MOVE + if (_XimExtenMove(im, ic, flag, &buf_s[4], (INT16)total)) + return name; +#endif + + buf_s[0] = im->private.proto.imid; + buf_s[1] = ic->private.proto.icid; + buf_s[2] = (INT16)total; + buf_s[3] = 0; + len = (INT16)(sizeof(CARD16) + sizeof(CARD16) + + sizeof(INT16) + sizeof(CARD16) + total); + + _XimSetHeader((XPointer)buf, XIM_SET_IC_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + return tmp_name; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + ic->private.proto.waitCallback = True; + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSetICValuesCheck, (XPointer)ic); + if (ret_code == XIM_TRUE) { + preply = reply; + } else if (ret_code == XIM_OVERFLOW) { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimSetICValuesCheck, (XPointer)ic); + if (ret_code != XIM_TRUE) { + Xfree(preply); + ic->private.proto.waitCallback = False; + return tmp_name; + } + } else { + ic->private.proto.waitCallback = False; + return tmp_name; + } + ic->private.proto.waitCallback = False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if (reply != preply) + Xfree(preply); + return tmp_name; + } + if (reply != preply) + Xfree(preply); + + return name; +} + +Private Bool +_XimDestroyICCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + Bool ret = False; + + if ((major_opcode == XIM_DESTROY_IC_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + ret = True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + ret = False; + return ret; +} + +Private void +_XimProtoICFree( + Xic ic) +{ +#ifdef XIM_CONNECTABLE + Xim im = (Xim)ic->core.im; +#endif + + if (ic->private.proto.preedit_font) { + Xfree(ic->private.proto.preedit_font); + ic->private.proto.preedit_font = NULL; + } + if (ic->private.proto.status_font) { + Xfree(ic->private.proto.status_font); + ic->private.proto.status_font = NULL; + } + if (ic->private.proto.commit_info) { + _XimFreeCommitInfo(ic); + ic->private.proto.commit_info = NULL; + } + if (ic->private.proto.ic_inner_resources) { + Xfree(ic->private.proto.ic_inner_resources); + ic->private.proto.ic_inner_resources = NULL; + } + +#ifdef XIM_CONNECTABLE + if (IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { + return; + } +#endif /* XIM_CONNECTABLE */ + + if (ic->private.proto.saved_icvalues) { + Xfree(ic->private.proto.saved_icvalues); + ic->private.proto.saved_icvalues = NULL; + } + if (ic->private.proto.ic_resources) { + Xfree(ic->private.proto.ic_resources); + ic->private.proto.ic_resources = NULL; + } + if (ic->core.hotkey) { + Xfree(ic->core.hotkey); + ic->core.hotkey = NULL; + } + + return; +} + +Private void +_XimProtoDestroyIC( + XIC xic) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (IS_SERVER_CONNECTED(im)) { + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_DESTROY_IC, 0, &len); + (void)_XimWrite(im, len, (XPointer)buf); + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimDestroyICCheck, (XPointer)ic); + if (ret_code == XIM_OVERFLOW) { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + (void)_XimRead(im, &len, preply, buf_size, + _XimDestroyICCheck, (XPointer)ic); + Xfree(preply); + } + } + UNMARK_IC_CONNECTED(ic); + _XimUnregisterFilter(ic); + _XimProtoICFree(ic); + return; +} + +Private void +_XimProtoSetFocus( + XIC xic) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + +#ifndef XIM_CONNECTABLE + if (!IS_IC_CONNECTED(ic)) + return; +#else + if (!IS_IC_CONNECTED(ic)) { + if (IS_CONNECTABLE(im)) { + if (_XimConnectServer(im)) { + if (!_XimReCreateIC(ic)) { + _XimDelayModeSetAttr(im); + return; + } + } else { + return; + } + } else { + return; + } + } +#endif /* XIM_CONNECTABLE */ + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_SET_IC_FOCUS, 0, &len); + (void)_XimWrite(im, len, (XPointer)buf); + _XimFlush(im); + + MARK_FOCUSED(ic); + + _XimRegisterFilter(ic); + return; +} + +Private void +_XimProtoUnsetFocus( + XIC xic) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + +#ifndef XIM_CONNECTABLE + if (!IS_IC_CONNECTED(ic)) + return; +#else + if (!IS_IC_CONNECTED(ic)) { + if (IS_CONNECTABLE(im)) { + if (_XimConnectServer(im)) { + if (!_XimReCreateIC(ic)) { + _XimDelayModeSetAttr(im); + return; + } + } else { + return; + } + } else { + return; + } + } +#endif /* XIM_CONNECTABLE */ + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_UNSET_IC_FOCUS, 0, &len); + (void)_XimWrite(im, len, (XPointer)buf); + _XimFlush(im); + + UNMARK_FOCUSED(ic); + + _XimUnregisterFilter(ic); + return; +} + +Private Bool +_XimResetICCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + + if ((major_opcode == XIM_RESET_IC_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + return True; + return False; +} + +Private char * +_XimProtoReset( + XIC xic, + char * (*retfunc) (Xim im, Xic ic, XPointer buf) ) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + char *commit; + + if (!IS_IC_CONNECTED(ic)) + return (char *)NULL; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_RESET_IC, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return NULL; + _XimFlush(im); + ic->private.proto.waitCallback = True; + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimResetICCheck, (XPointer)ic); + if (ret_code == XIM_TRUE) { + preply = reply; + } else if (ret_code == XIM_OVERFLOW) { + if (len < 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimResetICCheck, (XPointer)ic); + if (ret_code != XIM_TRUE) { + Xfree(preply); + ic->private.proto.waitCallback = False; + return NULL; + } + } + } else { + ic->private.proto.waitCallback = False; + return NULL; + } + ic->private.proto.waitCallback = False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if (reply != preply) + free(preply); + return NULL; + } + + commit = retfunc(im, ic, (XPointer)&buf_s[2]); + + if (reply != preply) + Xfree(preply); + return commit; +} + +Private char * +_XimCommitedMbString( + Xim im, + Xic ic, + XPointer buf) +{ + CARD16 *buf_s = (CARD16 *)buf; + XimCommitInfo info; + int len; + int new_len; + char *commit; + char *new_commit = NULL; + char *str; + Status status; + + len = 0; + for (info = ic->private.proto.commit_info; info; info = info->next) + len += info->string_len; + len += buf_s[0]; + if ( len == 0 ) + return( NULL ); + + if (!(commit = (char *)Xmalloc(len + 1))) + goto Error_On_Reset; + + str = commit; + for (info = ic->private.proto.commit_info; info; info = info->next) { + (void)memcpy(str, info->string, info->string_len); + str += info->string_len; + } + (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); + commit[len] = '\0'; + + new_len = im->methods->ctstombs((XIM)im, commit, len, NULL, 0, &status); + if (status != XLookupNone) { + if (!(new_commit = Xmalloc(new_len + 1))) { + Xfree(commit); + goto Error_On_Reset; + } + (void)im->methods->ctstombs((XIM)im, commit, len, + new_commit, new_len, NULL); + new_commit[new_len] = '\0'; + } + Xfree(commit); + +Error_On_Reset: + _XimFreeCommitInfo( ic ); + return new_commit; +} + +Private char * +_XimProtoMbReset( + XIC xic) +{ + return _XimProtoReset(xic, _XimCommitedMbString); +} + +Private wchar_t * +_XimCommitedWcString( + Xim im, + Xic ic, + XPointer buf) +{ + CARD16 *buf_s = (CARD16 *)buf; + XimCommitInfo info; + int len; + int new_len; + char *commit; + wchar_t *new_commit = (wchar_t *)NULL; + char *str; + Status status; + + len = 0; + for (info = ic->private.proto.commit_info; info; info = info->next) + len += info->string_len; + len += buf_s[0]; + if ( len == 0 ) + return( (wchar_t *)NULL ); + + if (!(commit = (char *)Xmalloc(len + 1))) + goto Error_On_Reset; + + str = commit; + for (info = ic->private.proto.commit_info; info; info = info->next) { + (void)memcpy(str, info->string, info->string_len); + str += info->string_len; + } + (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); + commit[len] = '\0'; + + new_len = im->methods->ctstowcs((XIM)im, commit, len, NULL, 0, &status); + if (status != XLookupNone) { + if (!(new_commit = + (wchar_t *)Xmalloc(sizeof(wchar_t) * (new_len + 1)))) { + Xfree(commit); + goto Error_On_Reset; + } + (void)im->methods->ctstowcs((XIM)im, commit, len, + new_commit, new_len, NULL); + new_commit[new_len] = (wchar_t)'\0'; + } + Xfree(commit); + +Error_On_Reset: + _XimFreeCommitInfo( ic ); + return new_commit; +} + +Private wchar_t * +_XimProtoWcReset( + XIC xic) +{ + return (wchar_t *) _XimProtoReset(xic, + (char * (*) (Xim, Xic, XPointer)) _XimCommitedWcString); +} + +Private char * +_XimCommitedUtf8String( + Xim im, + Xic ic, + XPointer buf) +{ + CARD16 *buf_s = (CARD16 *)buf; + XimCommitInfo info; + int len; + int new_len; + char *commit; + char *new_commit = NULL; + char *str; + Status status; + + len = 0; + for (info = ic->private.proto.commit_info; info; info = info->next) + len += info->string_len; + len += buf_s[0]; + if ( len == 0 ) + return( NULL ); + + if (!(commit = (char *)Xmalloc(len + 1))) + goto Error_On_Reset; + + str = commit; + for (info = ic->private.proto.commit_info; info; info = info->next) { + (void)memcpy(str, info->string, info->string_len); + str += info->string_len; + } + (void)memcpy(str, (char *)&buf_s[1], buf_s[0]); + commit[len] = '\0'; + + new_len = im->methods->ctstoutf8((XIM)im, commit, len, NULL, 0, &status); + if (status != XLookupNone) { + if (!(new_commit = Xmalloc(new_len + 1))) { + Xfree(commit); + goto Error_On_Reset; + } + (void)im->methods->ctstoutf8((XIM)im, commit, len, + new_commit, new_len, NULL); + new_commit[new_len] = '\0'; + } + Xfree(commit); + +Error_On_Reset: + _XimFreeCommitInfo( ic ); + return new_commit; +} + +Private char * +_XimProtoUtf8Reset( + XIC xic) +{ + return _XimProtoReset(xic, _XimCommitedUtf8String); +} + +Private XICMethodsRec ic_methods = { + _XimProtoDestroyIC, /* destroy */ + _XimProtoSetFocus, /* set_focus */ + _XimProtoUnsetFocus, /* unset_focus */ + _XimProtoSetICValues, /* set_values */ + _XimProtoGetICValues, /* get_values */ + _XimProtoMbReset, /* mb_reset */ + _XimProtoWcReset, /* wc_reset */ + _XimProtoUtf8Reset, /* utf8_reset */ + _XimProtoMbLookupString, /* mb_lookup_string */ + _XimProtoWcLookupString, /* wc_lookup_string */ + _XimProtoUtf8LookupString /* utf8_lookup_string */ +}; + +Private Bool +_XimGetInputStyle( + XIMArg *arg, + XIMStyle *input_style) +{ + register XIMArg *p; + + for (p = arg; p && p->name; p++) { + if (!(strcmp(p->name, XNInputStyle))) { + *input_style = (XIMStyle)p->value; + return True; + } + } + return False; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimDelayModeCreateIC( + Xic ic, + XIMArg *values, + XIMResourceList res, + unsigned int num) +{ + Xim im = (Xim)ic->core.im; + XimDefICValues ic_values; + int len; + XIMStyle input_style; + + bzero((char *)&ic_values, sizeof(XimDefICValues)); + _XimGetCurrentICValues(ic, &ic_values); + if (!(_XimGetInputStyle(values, &input_style))) + return False; + + _XimSetICMode(res, num, input_style); + + if (_XimSetICValueData(ic, (XPointer)&ic_values, res, num, + values, XIM_CREATEIC, False)) { + return False; + } + _XimSetCurrentICValues(ic, &ic_values); + if (!_XimSetICDefaults(ic, (XPointer)&ic_values, + XIM_SETICDEFAULTS, res, num)) { + return False; + } + ic_values.filter_events = KeyPressMask; + _XimSetCurrentICValues(ic, &ic_values); + _XimRegisterFilter(ic); + + return True; +} + +Public Bool +_XimReconnectModeCreateIC(ic) + Xic ic; +{ + Xim im = (Xim)ic->core.im; + int len; + XIMStyle input_style = ic->core.input_style; + XIMResourceList res; + unsigned int num; + + num = im->core.ic_num_resources; + len = sizeof(XIMResource) * num; + if (!(res = (XIMResourceList)Xmalloc(len))) + return False; + (void)memcpy((char *)res, (char *)im->core.ic_resources, len); + ic->private.proto.ic_resources = res; + ic->private.proto.ic_num_resources = num; + + _XimSetICMode(res, num, input_style); + + ic->core.filter_events = KeyPressMask; + + return True; +} +#endif /* XIM_CONNECTABLE */ + +Public XIC +_XimProtoCreateIC( + XIM xim, + XIMArg *arg) +{ + Xim im = (Xim)xim; + Xic ic; + XimDefICValues ic_values; + XIMResourceList res; + unsigned int num; + XIMStyle input_style; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + XIMArg *arg_ret; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + +#ifdef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im) && !IS_CONNECTABLE(im)) + return (XIC)NULL; +#else + if (!IS_SERVER_CONNECTED(im)) + return (XIC)NULL; +#endif /* XIM_CONNECTABLE */ + + if (!(_XimGetInputStyle(arg, &input_style))) + return (XIC)NULL; + + if ((ic = (Xic)Xmalloc(sizeof(XicRec))) == (Xic)NULL) + return (XIC)NULL; + + bzero((char *)ic, sizeof(XicRec)); + ic->methods = &ic_methods; + ic->core.im = (XIM)im; + ic->core.input_style = input_style; + + num = im->core.ic_num_resources; + len = sizeof(XIMResource) * num; + if (!(res = (XIMResourceList)Xmalloc(len))) + goto ErrorOnCreatingIC; + (void)memcpy((char *)res, (char *)im->core.ic_resources, len); + ic->private.proto.ic_resources = res; + ic->private.proto.ic_num_resources = num; + +#ifdef XIM_CONNECTABLE + if (!_XimSaveICValues(ic, arg)) + return False; + + if (!IS_SERVER_CONNECTED(im)) { + if (!_XimConnectServer(im)) { + if (_XimDelayModeCreateIC(ic, arg, res, num)) { + return (XIC)ic; + } + goto ErrorOnCreatingIC; + } + } +#endif /* XIM_CONNECTABLE */ + + ic->core.filter_events = im->private.proto.forward_event_mask; + ic->private.proto.forward_event_mask = + im->private.proto.forward_event_mask; + ic->private.proto.synchronous_event_mask = + im->private.proto.synchronous_event_mask; + + num = im->private.proto.ic_num_inner_resources; + len = sizeof(XIMResource) * num; + if (!(res = (XIMResourceList)Xmalloc(len))) + goto ErrorOnCreatingIC; + (void)memcpy((char *)res, + (char *)im->private.proto.ic_inner_resources, len); + ic->private.proto.ic_inner_resources = res; + ic->private.proto.ic_num_inner_resources = num; + + _XimSetICMode(ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, input_style); + + _XimSetICMode(ic->private.proto.ic_inner_resources, + ic->private.proto.ic_num_inner_resources, input_style); + + _XimGetCurrentICValues(ic, &ic_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + arg_ret = arg; + for (;;) { + data = &buf[buf_size]; + if (_XimEncodeICATTRIBUTE(ic, ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources, arg, &arg_ret, data, + data_len, &ret_len, (XPointer)&ic_values, 0, XIM_CREATEIC)) { + goto ErrorOnCreatingIC; + } + + total += ret_len; + if (!(arg = arg_ret)) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + goto ErrorOnCreatingIC; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + goto ErrorOnCreatingIC; + } + buf = tmp; + } + } + _XimSetCurrentICValues(ic, &ic_values); + + if (!(_XimCheckCreateICValues(ic->private.proto.ic_resources, + ic->private.proto.ic_num_resources))) + goto ErrorOnCreatingIC; + + _XimRegisterFilter(ic); + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_CREATE_IC, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + goto ErrorOnCreatingIC; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + ic->private.proto.waitCallback = True; + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimCreateICCheck, 0); + if (ret_code == XIM_TRUE) { + preply = reply; + } else if (ret_code == XIM_OVERFLOW) { + if (len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimCreateICCheck, 0); + if (ret_code != XIM_TRUE) { + Xfree(preply); + ic->private.proto.waitCallback = False; + goto ErrorOnCreatingIC; + } + } + } else { + ic->private.proto.waitCallback = False; + goto ErrorOnCreatingIC; + } + ic->private.proto.waitCallback = False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if (reply != preply) + Xfree(preply); + goto ErrorOnCreatingIC; + } + + ic->private.proto.icid = buf_s[1]; /* icid */ + if (reply != preply) + Xfree(preply); + MARK_IC_CONNECTED(ic); + return (XIC)ic; + +ErrorOnCreatingIC: + _XimUnregisterFilter(ic); + if (ic->private.proto.ic_resources) + Xfree(ic->private.proto.ic_resources); + if (ic->private.proto.ic_inner_resources) + Xfree(ic->private.proto.ic_inner_resources); + Xfree(ic); + return (XIC)NULL; +} diff --git a/libX11/modules/im/ximcp/imDefIm.c b/libX11/modules/im/ximcp/imDefIm.c index 936ce12b2..18a3cc85f 100644 --- a/libX11/modules/im/ximcp/imDefIm.c +++ b/libX11/modules/im/ximcp/imDefIm.c @@ -1,2045 +1,2044 @@ -/* - * Copyright 1990, 1991, 1992 Oracle and/or its affiliates. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/****************************************************************** - Copyright 1992, 1993, 1994 by FUJITSU LIMITED - Copyright 1993, 1994 by Sony Corporation - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital, FUJITSU -LIMITED and Sony Corporation not be used in advertising or publicity -pertaining to distribution of the software without specific, written -prior permission. - -DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED -AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc. - Takashi Fujiwara FUJITSU LIMITED - fujiwara@a80.tech.yk.fujitsu.co.jp - Makoto Wakamatsu Sony Corporation - makoto@sm.sony.co.jp - -******************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include "Xlibint.h" -#include "Xlcint.h" -#include "XlcPublic.h" -#include "XlcPubI.h" -#include "XimTrInt.h" -#include "Ximint.h" - - -Public int -_XimCheckDataSize( - XPointer buf, - int len) -{ - CARD16 *buf_s = (CARD16 *)buf; - - if(len < XIM_HEADER_SIZE) - return -1; - return buf_s[1]; -} - -Public void -_XimSetHeader( - XPointer buf, - CARD8 major_opcode, - CARD8 minor_opcode, - INT16 *len -) -{ - CARD8 *buf_b = (CARD8 *)buf; - CARD16 *buf_s = (CARD16 *)buf; - - buf_b[0] = major_opcode; - buf_b[1] = minor_opcode; - buf_s[1] = ((*len) / 4); - *len += XIM_HEADER_SIZE; - return; -} - -Public char -_XimGetMyEndian(void) -{ - CARD16 test_card = 1; - - if(*((char *)&test_card)) - return LITTLEENDIAN; - else - return BIGENDIAN; -} - -Private Bool -_XimCheckServerName( - Xim im, - char *str) -{ - char *server_name = im->core.im_name; - int len; - int str_len; - int category_len = strlen(XIM_SERVER_CATEGORY); - char *pp; - register char *p; - - if(server_name && *server_name) - len = strlen(server_name); - else - return True; - - if((int)strlen(str) < category_len) - return False; - - if(strncmp(str, XIM_SERVER_CATEGORY, category_len)) - return False; - - pp = &str[category_len]; - - for(;;) { - for(p = pp; (*p != ',') && (*p); p++); - str_len = (int)(p - pp); - - if((len == str_len) && (!strncmp(pp, server_name, len))) - break; - if(!(*p)) - return False; - pp = p + 1; - } - return True; -} - -Private char * -_XimCheckLocaleName( - Xim im, - char *address, - int address_len, - char *locale_name[], - int len) -{ - int category_len; - char *pp; - register char *p; - register int n; - Bool finish = False; - - category_len = strlen(XIM_LOCAL_CATEGORY); - if(address_len < category_len) - return (char*)NULL; - - if(strncmp(address, XIM_LOCAL_CATEGORY, category_len)) - return (char*)NULL; - - pp = &address[category_len]; - - for(;;) { - for( p = pp; *p && *p != ','; p++); - if (!*p) - finish = True; - address_len = (int)(p - pp); - *p = '\0'; - - for( n = 0; n < len; n++ ) - if( locale_name[n] && !_XlcCompareISOLatin1( pp, locale_name[n] ) ) - return locale_name[n]; - if (finish) - break; - pp = p + 1; - } - return (char *)NULL; -} - -Private Bool -_XimCheckTransport( - char *address, - int address_len, - const char *transport, - int len, - char **trans_addr) -{ - int category_len = strlen(XIM_TRANSPORT_CATEGORY); - char *pp; - register char *p; - - if(address_len < category_len) - return False; - - if(strncmp(address, XIM_TRANSPORT_CATEGORY, category_len)) - return False; - - pp = &address[category_len]; - - for(;;) { - *trans_addr = pp; - - for(p = pp; (*p != '/') && (*p != ',') && (*p); p++); - if(*p == ',') { - pp = p + 1; - continue; - } - if(!(*p)) - return False; - - address_len = (int)(p - pp); - - if((len == address_len) && (!strncmp(pp, transport, len))) - break; - pp = p + 1; - } - pp = p + 1; - for(p = pp; (*p != ',') && (*p); p++); - if (*p) - *p = '\0'; - return True; -} - -Private Bool -_CheckSNEvent( - Display *display, - XEvent *xevent, - XPointer arg) -{ - XSelectionEvent *event = (XSelectionEvent *)xevent; - Window window = *(Window*)arg; - - if((event->type == SelectionNotify) && (window == event->requestor)) - return True; - return False; -} - -Private Bool -_XimGetSelectionNotify( - Display *display, - Window window, - Atom target, - char **ret_address) -{ - XEvent event; - XSelectionEvent *ev = (XSelectionEvent *)&event; - Atom actual_type; - int actual_format; - unsigned long nitems, bytes_after; - - for(;;) { - XIfEvent(display, &event, _CheckSNEvent, (XPointer)&window); - if((ev->type == SelectionNotify) && (window == ev->requestor)) - break; - } - - if(ev->property == (Atom)None) - return False; - if( XGetWindowProperty( display, window, target, 0L, 1000000L, - True, target, &actual_type, &actual_format, - &nitems, &bytes_after, - (unsigned char **)&*ret_address ) != Success ) - return False; - return True; -} - -Private Bool -_XimPreConnectionIM( - Xim im, - Atom selection) -{ - Display *display = im->core.display; - Atom locales, transport; - char *address; - XLCd lcd; - char *language; - char *territory; - char *codeset; - char *trans_addr; - char *locale_name[4], *locale; - int llen, tlen, clen; - register int i; - Window window; - char *str; - - if(!(lcd = im->core.lcd)) - return False; - - for( i = 0; i < 4; i++ ) - locale_name[i] = NULL; - /* requestor window */ - if(!(window = XCreateSimpleWindow(display, DefaultRootWindow(display), - 0, 0, 1, 1, 1, 0, 0))) - return False; - - /* server name check */ - if( !(str = XGetAtomName( display, selection )) ) - return False; - if(!_XimCheckServerName(im, str)) { - XFree( (XPointer)str ); - goto Error; - } - XFree( (XPointer)str ); - - /* locale name check */ - _XGetLCValues(lcd, XlcNLanguage, &language, XlcNTerritory, &territory, - XlcNCodeset, &codeset, NULL); - llen = strlen( language ); - tlen = territory ? strlen( territory ): 0; - clen = codeset ? strlen( codeset ): 0; - - if( tlen != 0 && clen != 0 ) { - if( (locale_name[0] = Xmalloc(llen+tlen+clen+3)) != NULL ) - sprintf( locale_name[0], "%s_%s.%s", language, territory, codeset ); - } - if( clen != 0 ) { - if( (locale_name[1] = Xmalloc(llen+clen+2)) != NULL ) - sprintf( locale_name[1], "%s.%s", language, codeset ); - else - goto Error; - } - if( tlen != 0 ) { - if( (locale_name[2] = Xmalloc(llen+tlen+2)) != NULL ) - sprintf( locale_name[2], "%s_%s", language, territory ); - else - goto Error; - } - if( (locale_name[3] = Xmalloc(llen+1)) != NULL ) - strcpy( locale_name[3], language ); - else - goto Error; - if((locales = XInternAtom(display, XIM_LOCALES, True)) == (Atom)None) - goto Error; - - XConvertSelection(display, selection, locales, locales, window, - CurrentTime); - if(!(_XimGetSelectionNotify(display, window, locales, &address))) - goto Error; - - if((locale = _XimCheckLocaleName(im, address, strlen(address), locale_name, - 4)) == NULL) { - XFree((XPointer)address); - goto Error; - } - im->private.proto.locale_name = locale; - for( i = 0; i < 4; i++ ) { - if( locale_name[i] != NULL && locale_name[i] != locale ) { - XFree( locale_name[i] ); - locale_name[i] = NULL; - } - } - XFree((XPointer)address); - - /* transport check */ - if((transport = XInternAtom(display, XIM_TRANSPORT, True)) == (Atom)None) - goto Error; - - XConvertSelection(display, selection, transport, transport, window, - CurrentTime); - if(!_XimGetSelectionNotify(display, window, transport, &address)) - goto Error; - - for(i = 0; _XimTransportRec[i].transportname ; i++) { - if( _XimCheckTransport(address, strlen(address), - _XimTransportRec[i].transportname, - strlen(_XimTransportRec[i].transportname), - &trans_addr)) { - if( _XimTransportRec[i].config(im, trans_addr) ) { - XFree((XPointer)address); - XDestroyWindow(display, window); - return True; - } - } - } - - XFree((XPointer)address); -Error: - for( i = 0; i < 4; i++ ) - if( locale_name[i] != NULL ) - XFree( locale_name[i] ); - XDestroyWindow(display, window); - return False; -} - -Private Bool -_XimPreConnect( - Xim im) -{ - Display *display = im->core.display; - Atom imserver; - Atom actual_type; - int actual_format; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop_return; - Atom *atoms; - Window im_window = 0; - register int i; - - if((imserver = XInternAtom(display, XIM_SERVERS, True)) == (Atom)None) - return False; - - if(XGetWindowProperty(display, RootWindow(display, 0), - imserver, 0L, 1000000L, False, XA_ATOM, &actual_type, - &actual_format, &nitems, &bytes_after, - &prop_return) != Success) - return False; - - if( (actual_type != XA_ATOM) || (actual_format != 32) ) { - if( nitems ) - XFree((XPointer)prop_return); - return False; - } - - atoms = (Atom *)prop_return; - for(i = 0; i < nitems; i++) { - if((im_window = XGetSelectionOwner(display, atoms[i])) == (Window)None) - continue; - - if(_XimPreConnectionIM(im, atoms[i])) - break; - } - - XFree((XPointer)prop_return); - if(i >= nitems) - return False; - - im->private.proto.im_window = im_window; - return True; -} - -Private Bool -_XimGetAuthProtocolNames( - Xim im, - CARD16 *buf, - CARD8 *num, - INT16 *len) -{ - if (!IS_USE_AUTHORIZATION_FUNC(im)) { - *num = 0; - *len = 0; - return True; - } - /* - * Not yet - */ - return True; -} - -Private Bool -_XimSetAuthReplyData( - Xim im, - XPointer buf, - INT16 *len) -{ - /* - * Not yet - */ - *len = 0; - return True; -} - -Private Bool -_XimSetAuthNextData( - Xim im, - XPointer buf, - INT16 *len) -{ - /* - * Not yet - */ - *len = 0; - return True; -} - -Private Bool -_XimSetAuthRequiredData( - Xim im, - XPointer buf, - INT16 *len) -{ - /* - * Not yet - */ - *len = 0; - return True; -} - -Private Bool -_XimCheckAuthSetupData( - Xim im, - XPointer buf) -{ - /* - * Not yet - */ - return True; -} - -Private Bool -_XimCheckAuthNextData( - Xim im, - XPointer buf) -{ - /* - * Not yet - */ - return True; -} - -#define NO_MORE_AUTH 2 -#define GOOD_AUTH 1 -#define BAD_AUTH 0 - -Private int -_XimClientAuthCheck( - Xim im, - XPointer buf) -{ - /* - * Not yet - */ - return NO_MORE_AUTH; -} - -Private void -_XimAuthNG( - Xim im) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - INT16 len = 0; - - _XimSetHeader((XPointer)buf, XIM_AUTH_NG, 0, &len); - (void)_XimWrite(im, len, (XPointer)buf); - _XimFlush(im); - return; -} - -Private Bool -_XimAllRecv( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - return True; -} - -#define CLIENT_WAIT1 1 -#define CLIENT_WAIT2 2 - -Private Bool -_XimConnection( - Xim im) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; - CARD16 *buf_s = (CARD16 *)((XPointer)buf_b); - INT16 len; - CARD8 num; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - CARD8 major_opcode; - int wait_mode; - int ret; - - if(!(_XimConnect(im))) /* Transport Connect */ - return False; - - if(!_XimDispatchInit(im)) - return False; - - _XimRegProtoIntrCallback(im, XIM_ERROR, 0, _XimErrorCallback, (XPointer)im); - - if(!_XimGetAuthProtocolNames(im, &buf_s[4], &num, &len)) - return False; - - im->private.proto.protocol_major_version = PROTOCOLMAJORVERSION; - im->private.proto.protocol_minor_version = PROTOCOLMINORVERSION; - - buf_b[0] = _XimGetMyEndian(); - buf_b[1] = 0; - buf_s[1] = PROTOCOLMAJORVERSION; - buf_s[2] = PROTOCOLMINORVERSION; - buf_s[3] = num; - len += sizeof(CARD8) - + sizeof(CARD8) - + sizeof(CARD16) - + sizeof(CARD16) - + sizeof(CARD16); - - major_opcode = XIM_CONNECT; - wait_mode = (IS_USE_AUTHORIZATION_FUNC(im)) ? CLIENT_WAIT1 : CLIENT_WAIT2; - - for(;;) { - _XimSetHeader((XPointer)buf, major_opcode, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, reply, buf_size, _XimAllRecv, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, _XimAllRecv, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else - return False; - - major_opcode = *((CARD8 *)preply); - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - - if (wait_mode == CLIENT_WAIT1) { - if (major_opcode == XIM_AUTH_REQUIRED) { - ret = _XimClientAuthCheck(im, (XPointer)buf_s); - if(reply != preply) - Xfree(preply); - if (ret == NO_MORE_AUTH) { - if (!(_XimSetAuthReplyData(im, - (XPointer)&buf[XIM_HEADER_SIZE], &len))) { - _XimAuthNG(im); - return False; - } - major_opcode = XIM_AUTH_REPLY; - wait_mode = CLIENT_WAIT2; - } else if (ret == GOOD_AUTH) { - if (!(_XimSetAuthNextData(im, - (XPointer)&buf[XIM_HEADER_SIZE], &len))) { - _XimAuthNG(im); - return False; - } - major_opcode = XIM_AUTH_NEXT; - } else { /* BAD_AUTH */ - _XimAuthNG(im); - return False; - } - } else { - if(reply != preply) - Xfree(preply); - _XimAuthNG(im); - return False; - } - } else { /* CLIENT_WAIT2 */ - if (major_opcode == XIM_CONNECT_REPLY) { - break; - } else if (major_opcode == XIM_AUTH_SETUP) { - if (!(_XimCheckAuthSetupData(im, (XPointer)buf_s))) { - _XimAuthNG(im); - return False; - } - if(reply != preply) - Xfree(preply); - if (!(_XimSetAuthRequiredData(im, - (XPointer)&buf[XIM_HEADER_SIZE], &len))) { - _XimAuthNG(im); - return False; - } - major_opcode = XIM_AUTH_REQUIRED; - } else if (major_opcode == XIM_AUTH_NEXT) { - if (!(_XimCheckAuthNextData(im, (XPointer)buf_s))) { - _XimAuthNG(im); - return False; - } - if(reply != preply) - Xfree(preply); - if (!(_XimSetAuthRequiredData(im, - (XPointer)&buf[XIM_HEADER_SIZE], &len))) { - _XimAuthNG(im); - return False; - } - major_opcode = XIM_AUTH_REQUIRED; - } else if (major_opcode == XIM_AUTH_NG) { - if(reply != preply) - Xfree(preply); - return False; - } else { - _XimAuthNG(im); - if(reply != preply) - Xfree(preply); - return False; - } - } - } - - if (!( buf_s[0] == im->private.proto.protocol_major_version - && buf_s[1] == im->private.proto.protocol_minor_version)) { - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - MARK_SERVER_CONNECTED(im); - - _XimRegProtoIntrCallback(im, XIM_REGISTER_TRIGGERKEYS, 0, - _XimRegisterTriggerKeysCallback, (XPointer)im); - return True; -} - -Private Bool -_XimDisconnectCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - - if ((major_opcode == XIM_DISCONNECT_REPLY) - && (minor_opcode == 0)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0)) - return True; - return False; -} - -Private Bool -_XimDisconnect( - Xim im) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - INT16 len = 0; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - - if (IS_SERVER_CONNECTED(im)) { - _XimSetHeader((XPointer)buf, XIM_DISCONNECT, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimDisconnectCheck, 0); - if(ret_code == XIM_OVERFLOW) { - if(len > 0) { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimDisconnectCheck, 0); - Xfree(preply); - if(ret_code != XIM_TRUE) - return False; - } - } else if(ret_code == XIM_FALSE) - return False; - - } - if (!(_XimShutdown(im))) /* Transport shutdown */ - return False; - return True; -} - -Private Bool -_XimOpenCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - - if ((major_opcode == XIM_OPEN_REPLY) - && (minor_opcode == 0)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0)) - return True; - return False; -} - -Private Bool -_XimOpen( - Xim im) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; - CARD16 *buf_s; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - char *locale_name; - - locale_name = im->private.proto.locale_name; - len = strlen(locale_name); - buf_b[0] = (BYTE)len; /* length of locale name */ - (void)strcpy((char *)&buf_b[1], locale_name); /* locale name */ - len += sizeof(BYTE); /* sizeof length */ - XIM_SET_PAD(buf_b, len); /* pad */ - - _XimSetHeader((XPointer)buf, XIM_OPEN, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, reply, buf_size, - _XimOpenCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimOpenCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else - return False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - - im->private.proto.imid = buf_s[0]; /* imid */ - - if (!(_XimGetAttributeID(im, &buf_s[1]))) { - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - - if (!(_XimSetInnerIMResourceList(&(im->private.proto.im_inner_resources), - &(im->private.proto.im_num_inner_resources)))) - return False; - - if (!(_XimSetInnerICResourceList(&(im->private.proto.ic_inner_resources), - &(im->private.proto.ic_num_inner_resources)))) - return False; - - _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); - _XimSetIMMode(im->private.proto.im_inner_resources, - im->private.proto.im_num_inner_resources); - - /* Transport Callbak */ - _XimRegProtoIntrCallback(im, XIM_SET_EVENT_MASK, 0, - _XimSetEventMaskCallback, (XPointer)im); - _XimRegProtoIntrCallback(im, XIM_FORWARD_EVENT, 0, - _XimForwardEventCallback, (XPointer)im); - _XimRegProtoIntrCallback(im, XIM_COMMIT, 0, - _XimCommitCallback, (XPointer)im); - _XimRegProtoIntrCallback(im, XIM_SYNC, 0, - _XimSyncCallback, (XPointer)im); - - if(!_XimExtension(im)) - return False; - - /* register a hook for callback protocols */ - _XimRegisterDispatcher(im, _XimCbDispatch, (XPointer)im); - - return True; -} - -Private Bool -_XimCloseCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - - if ((major_opcode == XIM_CLOSE_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid)) - return True; - return False; -} - -Private Bool -_XimClose( - Xim im) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - - if (!IS_SERVER_CONNECTED(im)) - return True; - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = 0; /* unused */ - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof unused */ - - _XimSetHeader((XPointer)buf, XIM_CLOSE, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimCloseCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, _XimCloseCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else - return False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - - if(reply != preply) - Xfree(preply); - return True; -} - -Public void -_XimProtoIMFree( - Xim im) -{ - /* XIMPrivateRec */ - if (im->private.proto.im_onkeylist) { - Xfree(im->private.proto.im_onkeylist); - im->private.proto.im_onkeylist = NULL; - } - if (im->private.proto.im_offkeylist) { - Xfree(im->private.proto.im_offkeylist); - im->private.proto.im_offkeylist = NULL; - } - if (im->private.proto.intrproto) { - _XimFreeProtoIntrCallback(im); - im->private.proto.intrproto = NULL; - } - if (im->private.proto.im_inner_resources) { - Xfree(im->private.proto.im_inner_resources); - im->private.proto.im_inner_resources = NULL; - } - if (im->private.proto.ic_inner_resources) { - Xfree(im->private.proto.ic_inner_resources); - im->private.proto.ic_inner_resources = NULL; - } - if (im->private.proto.hold_data) { - Xfree(im->private.proto.hold_data); - im->private.proto.hold_data = NULL; - } - if (im->private.proto.locale_name) { - Xfree(im->private.proto.locale_name); - im->private.proto.locale_name = NULL; - } - if (im->private.proto.ctom_conv) { - _XlcCloseConverter(im->private.proto.ctom_conv); - im->private.proto.ctom_conv = NULL; - } - if (im->private.proto.ctow_conv) { - _XlcCloseConverter(im->private.proto.ctow_conv); - im->private.proto.ctow_conv = NULL; - } - if (im->private.proto.ctoutf8_conv) { - _XlcCloseConverter(im->private.proto.ctoutf8_conv); - im->private.proto.ctoutf8_conv = NULL; - } - if (im->private.proto.cstomb_conv) { - _XlcCloseConverter(im->private.proto.cstomb_conv); - im->private.proto.cstomb_conv = NULL; - } - if (im->private.proto.cstowc_conv) { - _XlcCloseConverter(im->private.proto.cstowc_conv); - im->private.proto.cstowc_conv = NULL; - } - if (im->private.proto.cstoutf8_conv) { - _XlcCloseConverter(im->private.proto.cstoutf8_conv); - im->private.proto.cstoutf8_conv = NULL; - } - if (im->private.proto.ucstoc_conv) { - _XlcCloseConverter(im->private.proto.ucstoc_conv); - im->private.proto.ucstoc_conv = NULL; - } - if (im->private.proto.ucstoutf8_conv) { - _XlcCloseConverter(im->private.proto.ucstoutf8_conv); - im->private.proto.ucstoutf8_conv = NULL; - } - -#ifdef XIM_CONNECTABLE - if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { - return; - } -#endif /* XIM_CONNECTABLE */ - - if (im->private.proto.saved_imvalues) { - Xfree(im->private.proto.saved_imvalues); - im->private.proto.saved_imvalues = NULL; - } - if (im->private.proto.default_styles) { - Xfree(im->private.proto.default_styles); - im->private.proto.default_styles = NULL; - } - - /* core */ - if (im->core.res_name) { - Xfree(im->core.res_name); - im->core.res_name = NULL; - } - if (im->core.res_class) { - Xfree(im->core.res_class); - im->core.res_class = NULL; - } - if (im->core.im_values_list) { - Xfree(im->core.im_values_list); - im->core.im_values_list = NULL; - } - if (im->core.ic_values_list) { - Xfree(im->core.ic_values_list); - im->core.ic_values_list = NULL; - } - if (im->core.im_name) { - Xfree(im->core.im_name); - im->core.im_name = NULL; - } - if (im->core.styles) { - Xfree(im->core.styles); - im->core.styles = NULL; - } - if (im->core.im_resources) { - Xfree(im->core.im_resources); - im->core.im_resources = NULL; - } - if (im->core.ic_resources) { - Xfree(im->core.ic_resources); - im->core.ic_resources = NULL; - } - - return; -} - -Private Status -_XimProtoCloseIM( - XIM xim) -{ - Xim im = (Xim)xim; - XIC ic; - XIC next; - Status status; - - ic = im->core.ic_chain; - while (ic) { - (*ic->methods->destroy) (ic); - next = ic->core.next; -#ifdef XIM_CONNECTABLE - if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) { - Xfree ((char *) ic); - } -#else - Xfree ((char *) ic); -#endif /* XIM_CONNECTABLE */ - ic = next; - } -#ifdef XIM_CONNECTABLE - if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) - im->core.ic_chain = NULL; -#else - im->core.ic_chain = NULL; -#endif - - _XimUnregisterServerFilter(im); - _XimResetIMInstantiateCallback(im); - status = (Status)_XimClose(im); - status = (Status)_XimDisconnect(im) && status; - _XimProtoIMFree(im); -#ifdef XIM_CONNECTABLE - if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { - _XimReconnectModeSetAttr(im); - for (ic = im->core.ic_chain; ic; ic = ic->core.next) { - _XimReconnectModeCreateIC(ic); - } - return 0; - } -#endif /* XIM_CONNECTABLE */ - _XimDestroyIMStructureList(im); - return status; -} - -#ifdef XIM_CONNECTABLE -Private Bool -_XimCheckIMQuarkList( - XrmQuark *quark_list, - int num_quark, - XrmQuark quark) -{ - register int i; - - for (i = 0; i < num_quark; i++) { - if (quark_list[i] == quark) { - return True; - } - } - return False; -} - -Private Bool -_XimSaveIMValues( - Xim im, - XIMArg *arg) -{ - register XIMArg *p; - register int n; - XrmQuark *quark_list; - XrmQuark *tmp; - XrmQuark quark; - int num_quark; - - if (quark_list = im->private.proto.saved_imvalues) { - num_quark = im->private.proto.num_saved_imvalues; - for (p = arg; p && p->name; p++) { - quark = XrmStringToQuark(p->name); - if (_XimCheckIMQuarkList(quark_list, num_quark, quark)) { - continue; - } - if (!(tmp = (XrmQuark *)Xrealloc(quark_list, - (sizeof(XrmQuark) * (num_quark + 1))))) { - im->private.proto.saved_imvalues = quark_list; - im->private.proto.num_saved_imvalues = num_quark; - return False; - } - num_quark++; - quark_list = tmp; - quark_list[num_quark] = quark; - } - im->private.proto.saved_imvalues = quark_list; - im->private.proto.num_saved_imvalues = num_quark; - return True; - } - - for (p = arg, n = 0; p && p->name; p++, n++); - - if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) { - return False; - } - - im->private.proto.saved_imvalues = quark_list; - im->private.proto.num_saved_imvalues = n; - for (p = arg; p && p->name; p++, quark_list++) { - *quark_list = XrmStringToQuark(p->name); - } - - return True; -} - -Private char * -_XimDelayModeSetIMValues( - Xim im, - XIMArg *arg) -{ - XimDefIMValues im_values; - char *name; - XIMArg *values; - - _XimGetCurrentIMValues(im, &im_values); - name = _XimSetIMValueData(im, (XPointer)&im_values, values, - im->core.im_resources, im->core.im_num_resources); - _XimSetCurrentIMValues(im, &im_values); - - return name; -} -#endif /* XIM_CONNECTABLE */ - -Private Bool -_XimSetIMValuesCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - - if ((major_opcode == XIM_SET_IM_VALUES_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid)) - return True; - return False; -} - -Private char * -_XimProtoSetIMValues( - XIM xim, - XIMArg *arg) -{ - Xim im = (Xim)xim; - XimDefIMValues im_values; - INT16 len; - CARD16 *buf_s; - char *tmp; - CARD32 tmp_buf32[BUFSIZE/4]; - char *tmp_buf = (char *)tmp_buf32; - char *buf; - int buf_size; - char *data; - int data_len; - int ret_len; - int total; - XIMArg *arg_ret; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int ret_code; - char *name; - -#ifndef XIM_CONNECTABLE - if (!IS_SERVER_CONNECTED(im)) - return arg->name; -#else - if (!_XimSaveIMValues(im, arg)) - return arg->name; - - if (!IS_SERVER_CONNECTED(im)) { - if (IS_CONNECTABLE(im)) { - if (!_XimConnectServer(im)) { - return _XimDelayModeSetIMValues(im, arg); - } - } else { - return arg->name; - } - } -#endif /* XIM_CONNECTABLE */ - - _XimGetCurrentIMValues(im, &im_values); - buf = tmp_buf; - buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); - data_len = BUFSIZE - buf_size; - total = 0; - arg_ret = arg; - for (;;) { - data = &buf[buf_size]; - if ((name = _XimEncodeIMATTRIBUTE(im, im->core.im_resources, - im->core.im_num_resources, arg, &arg_ret, data, data_len, - &ret_len, (XPointer)&im_values, XIM_SETIMVALUES))) { - if (buf != tmp_buf) - Xfree(buf); - break; - } - - total += ret_len; - if (!(arg = arg_ret)) { - break; - } - - buf_size += ret_len; - if (buf == tmp_buf) { - if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { - return arg->name; - } - memcpy(tmp, buf, buf_size); - buf = tmp; - } else { - if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { - Xfree(buf); - return arg->name; - } - buf = tmp; - } - } - _XimSetCurrentIMValues(im, &im_values); - - if (!total) - return (char *)NULL; - - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - buf_s[0] = im->private.proto.imid; - buf_s[1] = (INT16)total; - - len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); - _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - if (buf != tmp_buf) - Xfree(buf); - return arg->name; - } - _XimFlush(im); - if (buf != tmp_buf) - Xfree(buf); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimSetIMValuesCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = (int)len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, reply, buf_size, - _XimSetIMValuesCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return arg->name; - } - } - } else - return arg->name; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return arg->name; - } - if(reply != preply) - Xfree(preply); - - return name; -} - -#ifdef XIM_CONNECTABLE -Private char * -_XimDelayModeGetIMValues( - Xim im, - XIMArg *arg) -{ - XimDefIMValues im_values; - - _XimGetCurrentIMValues(im, &im_values); - return(_XimGetIMValueData(im, (XPointer)&im_values, arg, - im->core.im_resources, im->core.im_num_resources)); -} -#endif /* XIM_CONNECTABLE */ - -Private Bool -_XimGetIMValuesCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - - if ((major_opcode == XIM_GET_IM_VALUES_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid)) - return True; - return False; -} - -Private char * -_XimProtoGetIMValues( - XIM xim, - XIMArg *arg) -{ - Xim im = (Xim)xim; - register XIMArg *p; - register int n; - CARD8 *buf; - CARD16 *buf_s; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply = NULL; - int buf_size; - int ret_code; - char *makeid_name; - char *decode_name; - CARD16 *data = NULL; - INT16 data_len = 0; - -#ifndef XIM_CONNECTABLE - if (!IS_SERVER_CONNECTED(im)) - return arg->name; -#else - if (!IS_SERVER_CONNECTED(im)) { - if (IS_CONNECTABLE(im)) { - if (!_XimConnectServer(im)) { - return _XimDelayModeGetIMValues(im, arg); - } - } else { - return arg->name; - } - } -#endif /* XIM_CONNECTABLE */ - - for (n = 0, p = arg; p->name; p++) - n++; - - if (!n) - return (char *)NULL; - - buf_size = sizeof(CARD16) * n; - buf_size += XIM_HEADER_SIZE - + sizeof(CARD16) - + sizeof(INT16) - + XIM_PAD(buf_size); - - if (!(buf = (CARD8 *)Xmalloc(buf_size))) - return arg->name; - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - - makeid_name = _XimMakeIMAttrIDList(im, im->core.im_resources, - im->core.im_num_resources, arg, - &buf_s[2], &len, XIM_GETIMVALUES); - - if (len) { - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = len; /* length of im-attr-id */ - XIM_SET_PAD(&buf_s[2], len); /* pad */ - len += sizeof(CARD16) /* sizeof imid */ - + sizeof(INT16); /* sizeof length of attr */ - - _XimSetHeader((XPointer)buf, XIM_GET_IM_VALUES, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - Xfree(buf); - return arg->name; - } - _XimFlush(im); - Xfree(buf); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimGetIMValuesCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimGetIMValuesCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return arg->name; - } - } - } else - return arg->name; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return arg->name; - } - data = &buf_s[2]; - data_len = buf_s[1]; - } - decode_name = _XimDecodeIMATTRIBUTE(im, im->core.im_resources, - im->core.im_num_resources, data, data_len, - arg, XIM_GETIMVALUES); - if (reply != preply) - Xfree(preply); - - if (decode_name) - return decode_name; - else - return makeid_name; -} - -Private XIMMethodsRec im_methods = { - _XimProtoCloseIM, /* close */ - _XimProtoSetIMValues, /* set_values */ - _XimProtoGetIMValues, /* get_values */ - _XimProtoCreateIC, /* create_ic */ - _Ximctstombs, /* ctstombs */ - _Ximctstowcs, /* ctstowcs */ - _Ximctstoutf8 /* ctstoutf8 */ -}; - -Private Bool -_XimSetEncodingByName( - Xim im, - char **buf, - int *len) -{ - char *encoding = (char *)NULL; - int encoding_len; - int compound_len; - BYTE *ret; - - _XGetLCValues(im->core.lcd, XlcNCodeset, &encoding, NULL); - if (!encoding) { - *buf = (char *)NULL; - *len = 0; - return True; - } - encoding_len = strlen(encoding); - compound_len = strlen("COMPOUND_TEXT"); - *len = encoding_len + sizeof(BYTE) + compound_len + sizeof(BYTE); - if (!(ret = (BYTE *)Xmalloc(*len))) { - return False; - } - *buf = (char *)ret; - - ret[0] = (BYTE)encoding_len; - (void)strncpy((char *)&ret[1], encoding, encoding_len); - ret += (encoding_len + sizeof(BYTE)); - ret[0] = (BYTE)compound_len; - (void)strncpy((char *)&ret[1], "COMPOUND_TEXT", compound_len); - return True; -} - -Private Bool -_XimSetEncodingByDetail( - Xim im, - char **buf, - int *len) -{ - *len = 0; - *buf = NULL; - return True; -} - -Private Bool -_XimGetEncoding( - Xim im, - CARD16 *buf, - char *name, - int name_len, - char *detail, - int detail_len) -{ - XLCd lcd = im->core.lcd; - CARD16 category = buf[0]; - CARD16 idx = buf[1]; - int len; - XlcConv ctom_conv = NULL; - XlcConv ctow_conv = NULL; - XlcConv ctoutf8_conv = NULL; - XlcConv conv; - XimProtoPrivateRec *private = &im->private.proto; - - if (idx == (CARD16)XIM_Default_Encoding_IDX) { /* XXX */ - if (!(ctom_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNMultiByte))) - return False; - if (!(ctow_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNWideChar))) - return False; - if (!(ctoutf8_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNUtf8String))) - return False; - } - - if (category == XIM_Encoding_NameCategory) { - while (name_len > 0) { - len = (int)name[0]; - if (!strncmp(&name[1], "COMPOUND_TEXT", len)) { - if (!(ctom_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNMultiByte))) - return False; - if (!(ctow_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNWideChar))) - return False; - if (!(ctoutf8_conv = _XlcOpenConverter(lcd, - XlcNCompoundText, lcd, XlcNUtf8String))) - return False; - break; - } else { - /* - * Not yet - */ - } - len += sizeof(BYTE); - name_len -= len; - name += len; - } - } else if (category == XIM_Encoding_DetailCategory) { - /* - * Not yet - */ - } else { - return False; - } - - private->ctom_conv = ctom_conv; - private->ctow_conv = ctow_conv; - private->ctoutf8_conv = ctoutf8_conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) - return False; - private->cstomb_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) - return False; - private->cstowc_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) - return False; - private->cstoutf8_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) - return False; - private->ucstoc_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) - return False; - private->ucstoutf8_conv = conv; - - return True; -} - -Private Bool -_XimEncodingNegoCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - - if ((major_opcode == XIM_ENCODING_NEGOTIATION_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid)) - return True; - return False; -} - -Private Bool -_XimEncodingNegotiation( - Xim im) -{ - char *name_ptr = 0; - int name_len = 0; - char *detail_ptr = 0; - int detail_len = 0; - CARD8 *buf; - CARD16 *buf_s; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - - if (!(_XimSetEncodingByName(im, &name_ptr, &name_len))) - return False; - - if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len))) { - if (name_ptr) - Xfree(name_ptr); - return False; - } - - len = sizeof(CARD16) - + sizeof(INT16) - + name_len - + XIM_PAD(name_len) - + sizeof(INT16) - + sizeof(CARD16) - + detail_len; - - if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len))) { - if (name_ptr) - Xfree(name_ptr); - if (detail_ptr) - Xfree(detail_ptr); - return False; - } - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - - buf_s[0] = im->private.proto.imid; - buf_s[1] = (INT16)name_len; - if (name_ptr) - (void)memcpy((char *)&buf_s[2], name_ptr, name_len); - XIM_SET_PAD(&buf_s[2], name_len); - buf_s = (CARD16 *)((char *)&buf_s[2] + name_len); - buf_s[0] = detail_len; - buf_s[1] = 0; - if (detail_ptr) - (void)memcpy((char *)&buf_s[2], detail_ptr, detail_len); - - _XimSetHeader((XPointer)buf, XIM_ENCODING_NEGOTIATION, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - Xfree(buf); - return False; - } - _XimFlush(im); - Xfree(buf); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimEncodingNegoCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimEncodingNegoCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else - return False; - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - - if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len, - detail_ptr, detail_len))) { - if(reply != preply) - Xfree(preply); - return False; - } - if (name_ptr) - Xfree(name_ptr); - if (detail_ptr) - Xfree(detail_ptr); - - if(reply != preply) - Xfree(preply); - - return True; -} - -#ifdef XIM_CONNECTABLE -Private Bool -_XimSendSavedIMValues( - Xim im) -{ - XimDefIMValues im_values; - INT16 len; - CARD16 *buf_s; - char *tmp; - CARD32 tmp_buf32[BUFSIZE/4]; - char *tmp_buf = (char *)tmp_buf32; - char *buf; - int buf_size; - char *data; - int data_len; - int ret_len; - int total; - int idx; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int ret_code; - - _XimGetCurrentIMValues(im, &im_values); - buf = tmp_buf; - buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); - data_len = BUFSIZE - buf_size; - total = 0; - idx = 0; - for (;;) { - data = &buf[buf_size]; - if (!_XimEncodeSavedIMATTRIBUTE(im, im->core.im_resources, - im->core.im_num_resources, &idx, data, data_len, - &ret_len, (XPointer)&im_values, XIM_SETIMVALUES)) { - if (buf != tmp_buf) - Xfree(buf); - return False; - } - - total += ret_len; - if (idx == -1) { - break; - } - - buf_size += ret_len; - if (buf == tmp_buf) { - if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { - return False; - } - memcpy(tmp, buf, buf_size); - buf = tmp; - } else { - if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { - Xfree(buf); - return False; - } - buf = tmp; - } - } - - if (!total) - return True; - - buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - buf_s[0] = im->private.proto.imid; - buf_s[1] = (INT16)total; - - len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); - _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) { - if (buf != tmp_buf) - Xfree(buf); - return False; - } - _XimFlush(im); - if (buf != tmp_buf) - Xfree(buf); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimSetIMValuesCheck, 0); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = (int)len; - preply = (XPointer)Xmalloc(buf_size); - ret_code = _XimRead(im, &len, reply, buf_size, - _XimSetIMValuesCheck, 0); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else - return False; - - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - - return True; -} - -Private void -_XimDelayModeIMFree( - Xim im) -{ - if (im->core.im_resources) { - Xfree(im->core.im_resources); - im->core.im_resources = NULL; - } - if (im->core.ic_resources) { - Xfree(im->core.ic_resources); - im->core.ic_resources = NULL; - } - if (im->core.im_values_list) { - Xfree(im->core.im_values_list); - im->core.im_values_list = NULL; - } - if (im->core.ic_values_list) { - Xfree(im->core.ic_values_list); - im->core.ic_values_list = NULL; - } - return; -} - -Public Bool -_XimConnectServer( - Xim im) -{ - Xim save_im; - - if (!(save_im = (Xim)Xmalloc(sizeof(XimRec)))) - return False; - memcpy((char *)save_im, (char *)im, sizeof(XimRec)); - - if (_XimPreConnect(im) && _XimConnection(im) - && _XimOpen(im) && _XimEncodingNegotiation(im)) { - if (_XimSendSavedIMValues(im)) { - _XimDelayModeIMFree(save_im); - _XimRegisterServerFilter(im); - Xfree(save_im); - return True; - } - } - memcpy((char *)im, (char *)save_im, sizeof(XimRec)); - Xfree(save_im); - return False; -} - -Public Bool -_XimDelayModeSetAttr( - Xim im) -{ - XimDefIMValues im_values; - - if(!_XimSetIMResourceList(&im->core.im_resources, - &im->core.im_num_resources)) { - return False; - } - if(!_XimSetICResourceList(&im->core.ic_resources, - &im->core.ic_num_resources)) { - return False; - } - - _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); - - _XimGetCurrentIMValues(im, &im_values); - if(!_XimSetLocalIMDefaults(im, (XPointer)&im_values, - im->core.im_resources, im->core.im_num_resources)) { - return False; - } - _XimSetCurrentIMValues(im, &im_values); - if (im->private.proto.default_styles) { - if (im->core.styles) - Xfree(im->core.styles); - im->core.styles = im->private.proto.default_styles; - } - - return True; -} - -Private Bool -_XimReconnectModeSetAttr( - Xim im) -{ - XimDefIMValues im_values; - - if(!_XimSetIMResourceList(&im->core.im_resources, - &im->core.im_num_resources)) { - return False; - } - if(!_XimSetICResourceList(&im->core.ic_resources, - &im->core.ic_num_resources)) { - return False; - } - - _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); - - if (im->private.proto.default_styles) { - if (im->core.styles) - Xfree(im->core.styles); - im->core.styles = im->private.proto.default_styles; - } - - return True; -} -#endif /* XIM_CONNECTABLE */ - -Public Bool -_XimProtoOpenIM( - Xim im) -{ - _XimInitialResourceInfo(); - - im->methods = &im_methods; - -#ifdef XIM_CONNECTABLE - _XimSetProtoResource(im); -#endif /* XIM_CONNECTABLE */ - - if (_XimPreConnect(im)) { - if (_XimConnection(im) && _XimOpen(im) && _XimEncodingNegotiation(im)) { - _XimRegisterServerFilter(im); - return True; - } - _XimShutdown(im); -#ifdef XIM_CONNECTABLE - } else if (IS_DELAYBINDABLE(im)) { - if (_XimDelayModeSetAttr(im)) - return True; -#endif /* XIM_CONNECTABLE */ - } - _XimProtoIMFree(im); - return False; -} +/* + * Copyright 1990, 1991, 1992 Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/****************************************************************** + Copyright 1992, 1993, 1994 by FUJITSU LIMITED + Copyright 1993, 1994 by Sony Corporation + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital, FUJITSU +LIMITED and Sony Corporation not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. + +DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED +AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + Author: Hideki Hiura (hhiura@Sun.COM) Sun Microsystems, Inc. + Takashi Fujiwara FUJITSU LIMITED + fujiwara@a80.tech.yk.fujitsu.co.jp + Makoto Wakamatsu Sony Corporation + makoto@sm.sony.co.jp + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "Xlibint.h" +#include "Xlcint.h" +#include "XlcPublic.h" +#include "XlcPubI.h" +#include "XimTrInt.h" +#include "Ximint.h" + + +Public int +_XimCheckDataSize( + XPointer buf, + int len) +{ + CARD16 *buf_s = (CARD16 *)buf; + + if(len < XIM_HEADER_SIZE) + return -1; + return buf_s[1]; +} + +Public void +_XimSetHeader( + XPointer buf, + CARD8 major_opcode, + CARD8 minor_opcode, + INT16 *len +) +{ + CARD8 *buf_b = (CARD8 *)buf; + CARD16 *buf_s = (CARD16 *)buf; + + buf_b[0] = major_opcode; + buf_b[1] = minor_opcode; + buf_s[1] = ((*len) / 4); + *len += XIM_HEADER_SIZE; + return; +} + +Public char +_XimGetMyEndian(void) +{ + CARD16 test_card = 1; + + if(*((char *)&test_card)) + return LITTLEENDIAN; + else + return BIGENDIAN; +} + +Private Bool +_XimCheckServerName( + Xim im, + char *str) +{ + char *server_name = im->core.im_name; + int len; + int str_len; + int category_len = strlen(XIM_SERVER_CATEGORY); + char *pp; + register char *p; + + if(server_name && *server_name) + len = strlen(server_name); + else + return True; + + if((int)strlen(str) < category_len) + return False; + + if(strncmp(str, XIM_SERVER_CATEGORY, category_len)) + return False; + + pp = &str[category_len]; + + for(;;) { + for(p = pp; (*p != ',') && (*p); p++); + str_len = (int)(p - pp); + + if((len == str_len) && (!strncmp(pp, server_name, len))) + break; + if(!(*p)) + return False; + pp = p + 1; + } + return True; +} + +Private char * +_XimCheckLocaleName( + Xim im, + char *address, + int address_len, + char *locale_name[], + int len) +{ + int category_len; + char *pp; + register char *p; + register int n; + Bool finish = False; + + category_len = strlen(XIM_LOCAL_CATEGORY); + if(address_len < category_len) + return (char*)NULL; + + if(strncmp(address, XIM_LOCAL_CATEGORY, category_len)) + return (char*)NULL; + + pp = &address[category_len]; + + for(;;) { + for( p = pp; *p && *p != ','; p++); + if (!*p) + finish = True; + address_len = (int)(p - pp); + *p = '\0'; + + for( n = 0; n < len; n++ ) + if( locale_name[n] && !_XlcCompareISOLatin1( pp, locale_name[n] ) ) + return locale_name[n]; + if (finish) + break; + pp = p + 1; + } + return (char *)NULL; +} + +Private Bool +_XimCheckTransport( + char *address, + int address_len, + const char *transport, + int len, + char **trans_addr) +{ + int category_len = strlen(XIM_TRANSPORT_CATEGORY); + char *pp; + register char *p; + + if(address_len < category_len) + return False; + + if(strncmp(address, XIM_TRANSPORT_CATEGORY, category_len)) + return False; + + pp = &address[category_len]; + + for(;;) { + *trans_addr = pp; + + for(p = pp; (*p != '/') && (*p != ',') && (*p); p++); + if(*p == ',') { + pp = p + 1; + continue; + } + if(!(*p)) + return False; + + address_len = (int)(p - pp); + + if((len == address_len) && (!strncmp(pp, transport, len))) + break; + pp = p + 1; + } + pp = p + 1; + for(p = pp; (*p != ',') && (*p); p++); + if (*p) + *p = '\0'; + return True; +} + +Private Bool +_CheckSNEvent( + Display *display, + XEvent *xevent, + XPointer arg) +{ + XSelectionEvent *event = (XSelectionEvent *)xevent; + Window window = *(Window*)arg; + + if((event->type == SelectionNotify) && (window == event->requestor)) + return True; + return False; +} + +Private Bool +_XimGetSelectionNotify( + Display *display, + Window window, + Atom target, + char **ret_address) +{ + XEvent event; + XSelectionEvent *ev = (XSelectionEvent *)&event; + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + + for(;;) { + XIfEvent(display, &event, _CheckSNEvent, (XPointer)&window); + if((ev->type == SelectionNotify) && (window == ev->requestor)) + break; + } + + if(ev->property == (Atom)None) + return False; + if( XGetWindowProperty( display, window, target, 0L, 1000000L, + True, target, &actual_type, &actual_format, + &nitems, &bytes_after, + (unsigned char **)&*ret_address ) != Success ) + return False; + return True; +} + +Private Bool +_XimPreConnectionIM( + Xim im, + Atom selection) +{ + Display *display = im->core.display; + Atom locales, transport; + char *address; + XLCd lcd; + char *language; + char *territory; + char *codeset; + char *trans_addr; + char *locale_name[4], *locale; + int llen, tlen, clen; + register int i; + Window window; + char *str; + + if(!(lcd = im->core.lcd)) + return False; + + for( i = 0; i < 4; i++ ) + locale_name[i] = NULL; + /* requestor window */ + if(!(window = XCreateSimpleWindow(display, DefaultRootWindow(display), + 0, 0, 1, 1, 1, 0, 0))) + return False; + + /* server name check */ + if( !(str = XGetAtomName( display, selection )) ) + return False; + if(!_XimCheckServerName(im, str)) { + XFree( (XPointer)str ); + goto Error; + } + XFree( (XPointer)str ); + + /* locale name check */ + _XGetLCValues(lcd, XlcNLanguage, &language, XlcNTerritory, &territory, + XlcNCodeset, &codeset, NULL); + llen = strlen( language ); + tlen = territory ? strlen( territory ): 0; + clen = codeset ? strlen( codeset ): 0; + + if( tlen != 0 && clen != 0 ) { + if( (locale_name[0] = Xmalloc(llen+tlen+clen+3)) != NULL ) + sprintf( locale_name[0], "%s_%s.%s", language, territory, codeset ); + } + if( clen != 0 ) { + if( (locale_name[1] = Xmalloc(llen+clen+2)) != NULL ) + sprintf( locale_name[1], "%s.%s", language, codeset ); + else + goto Error; + } + if( tlen != 0 ) { + if( (locale_name[2] = Xmalloc(llen+tlen+2)) != NULL ) + sprintf( locale_name[2], "%s_%s", language, territory ); + else + goto Error; + } + if( (locale_name[3] = Xmalloc(llen+1)) != NULL ) + strcpy( locale_name[3], language ); + else + goto Error; + if((locales = XInternAtom(display, XIM_LOCALES, True)) == (Atom)None) + goto Error; + + XConvertSelection(display, selection, locales, locales, window, + CurrentTime); + if(!(_XimGetSelectionNotify(display, window, locales, &address))) + goto Error; + + if((locale = _XimCheckLocaleName(im, address, strlen(address), locale_name, + 4)) == NULL) { + XFree((XPointer)address); + goto Error; + } + im->private.proto.locale_name = locale; + for( i = 0; i < 4; i++ ) { + if( locale_name[i] != NULL && locale_name[i] != locale ) { + XFree( locale_name[i] ); + locale_name[i] = NULL; + } + } + XFree((XPointer)address); + + /* transport check */ + if((transport = XInternAtom(display, XIM_TRANSPORT, True)) == (Atom)None) + goto Error; + + XConvertSelection(display, selection, transport, transport, window, + CurrentTime); + if(!_XimGetSelectionNotify(display, window, transport, &address)) + goto Error; + + for(i = 0; _XimTransportRec[i].transportname ; i++) { + if( _XimCheckTransport(address, strlen(address), + _XimTransportRec[i].transportname, + strlen(_XimTransportRec[i].transportname), + &trans_addr)) { + if( _XimTransportRec[i].config(im, trans_addr) ) { + XFree((XPointer)address); + XDestroyWindow(display, window); + return True; + } + } + } + + XFree((XPointer)address); +Error: + for( i = 0; i < 4; i++ ) + if( locale_name[i] != NULL ) + XFree( locale_name[i] ); + XDestroyWindow(display, window); + return False; +} + +Private Bool +_XimPreConnect( + Xim im) +{ + Display *display = im->core.display; + Atom imserver; + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop_return; + Atom *atoms; + Window im_window = 0; + register int i; + + if((imserver = XInternAtom(display, XIM_SERVERS, True)) == (Atom)None) + return False; + + if(XGetWindowProperty(display, RootWindow(display, 0), + imserver, 0L, 1000000L, False, XA_ATOM, &actual_type, + &actual_format, &nitems, &bytes_after, + &prop_return) != Success) + return False; + + if( (actual_type != XA_ATOM) || (actual_format != 32) ) { + if( nitems ) + XFree((XPointer)prop_return); + return False; + } + + atoms = (Atom *)prop_return; + for(i = 0; i < nitems; i++) { + if((im_window = XGetSelectionOwner(display, atoms[i])) == (Window)None) + continue; + + if(_XimPreConnectionIM(im, atoms[i])) + break; + } + + XFree((XPointer)prop_return); + if(i >= nitems) + return False; + + im->private.proto.im_window = im_window; + return True; +} + +Private Bool +_XimGetAuthProtocolNames( + Xim im, + CARD16 *buf, + CARD8 *num, + INT16 *len) +{ + if (!IS_USE_AUTHORIZATION_FUNC(im)) { + *num = 0; + *len = 0; + return True; + } + /* + * Not yet + */ + return True; +} + +Private Bool +_XimSetAuthReplyData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimSetAuthNextData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimSetAuthRequiredData( + Xim im, + XPointer buf, + INT16 *len) +{ + /* + * Not yet + */ + *len = 0; + return True; +} + +Private Bool +_XimCheckAuthSetupData( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return True; +} + +Private Bool +_XimCheckAuthNextData( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return True; +} + +#define NO_MORE_AUTH 2 +#define GOOD_AUTH 1 +#define BAD_AUTH 0 + +Private int +_XimClientAuthCheck( + Xim im, + XPointer buf) +{ + /* + * Not yet + */ + return NO_MORE_AUTH; +} + +Private void +_XimAuthNG( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + INT16 len = 0; + + _XimSetHeader((XPointer)buf, XIM_AUTH_NG, 0, &len); + (void)_XimWrite(im, len, (XPointer)buf); + _XimFlush(im); + return; +} + +Private Bool +_XimAllRecv( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + return True; +} + +#define CLIENT_WAIT1 1 +#define CLIENT_WAIT2 2 + +Private Bool +_XimConnection( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; + CARD16 *buf_s = (CARD16 *)((XPointer)buf_b); + INT16 len; + CARD8 num; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + CARD8 major_opcode; + int wait_mode; + int ret; + + if(!(_XimConnect(im))) /* Transport Connect */ + return False; + + if(!_XimDispatchInit(im)) + return False; + + _XimRegProtoIntrCallback(im, XIM_ERROR, 0, _XimErrorCallback, (XPointer)im); + + if(!_XimGetAuthProtocolNames(im, &buf_s[4], &num, &len)) + return False; + + im->private.proto.protocol_major_version = PROTOCOLMAJORVERSION; + im->private.proto.protocol_minor_version = PROTOCOLMINORVERSION; + + buf_b[0] = _XimGetMyEndian(); + buf_b[1] = 0; + buf_s[1] = PROTOCOLMAJORVERSION; + buf_s[2] = PROTOCOLMINORVERSION; + buf_s[3] = num; + len += sizeof(CARD8) + + sizeof(CARD8) + + sizeof(CARD16) + + sizeof(CARD16) + + sizeof(CARD16); + + major_opcode = XIM_CONNECT; + wait_mode = (IS_USE_AUTHORIZATION_FUNC(im)) ? CLIENT_WAIT1 : CLIENT_WAIT2; + + for(;;) { + _XimSetHeader((XPointer)buf, major_opcode, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, reply, buf_size, _XimAllRecv, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, _XimAllRecv, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + + major_opcode = *((CARD8 *)preply); + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + + if (wait_mode == CLIENT_WAIT1) { + if (major_opcode == XIM_AUTH_REQUIRED) { + ret = _XimClientAuthCheck(im, (XPointer)buf_s); + if(reply != preply) + Xfree(preply); + if (ret == NO_MORE_AUTH) { + if (!(_XimSetAuthReplyData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REPLY; + wait_mode = CLIENT_WAIT2; + } else if (ret == GOOD_AUTH) { + if (!(_XimSetAuthNextData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_NEXT; + } else { /* BAD_AUTH */ + _XimAuthNG(im); + return False; + } + } else { + if(reply != preply) + Xfree(preply); + _XimAuthNG(im); + return False; + } + } else { /* CLIENT_WAIT2 */ + if (major_opcode == XIM_CONNECT_REPLY) { + break; + } else if (major_opcode == XIM_AUTH_SETUP) { + if (!(_XimCheckAuthSetupData(im, (XPointer)buf_s))) { + _XimAuthNG(im); + return False; + } + if(reply != preply) + Xfree(preply); + if (!(_XimSetAuthRequiredData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REQUIRED; + } else if (major_opcode == XIM_AUTH_NEXT) { + if (!(_XimCheckAuthNextData(im, (XPointer)buf_s))) { + _XimAuthNG(im); + return False; + } + if(reply != preply) + Xfree(preply); + if (!(_XimSetAuthRequiredData(im, + (XPointer)&buf[XIM_HEADER_SIZE], &len))) { + _XimAuthNG(im); + return False; + } + major_opcode = XIM_AUTH_REQUIRED; + } else if (major_opcode == XIM_AUTH_NG) { + if(reply != preply) + Xfree(preply); + return False; + } else { + _XimAuthNG(im); + if(reply != preply) + Xfree(preply); + return False; + } + } + } + + if (!( buf_s[0] == im->private.proto.protocol_major_version + && buf_s[1] == im->private.proto.protocol_minor_version)) { + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + MARK_SERVER_CONNECTED(im); + + _XimRegProtoIntrCallback(im, XIM_REGISTER_TRIGGERKEYS, 0, + _XimRegisterTriggerKeysCallback, (XPointer)im); + return True; +} + +Private Bool +_XimDisconnectCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + + if ((major_opcode == XIM_DISCONNECT_REPLY) + && (minor_opcode == 0)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0)) + return True; + return False; +} + +Private Bool +_XimDisconnect( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + INT16 len = 0; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (IS_SERVER_CONNECTED(im)) { + _XimSetHeader((XPointer)buf, XIM_DISCONNECT, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimDisconnectCheck, 0); + if(ret_code == XIM_OVERFLOW) { + if(len > 0) { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimDisconnectCheck, 0); + Xfree(preply); + if(ret_code != XIM_TRUE) + return False; + } + } else if(ret_code == XIM_FALSE) + return False; + + } + if (!(_XimShutdown(im))) /* Transport shutdown */ + return False; + return True; +} + +Private Bool +_XimOpenCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + + if ((major_opcode == XIM_OPEN_REPLY) + && (minor_opcode == 0)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0)) + return True; + return False; +} + +Private Bool +_XimOpen( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + char *locale_name; + + locale_name = im->private.proto.locale_name; + len = strlen(locale_name); + buf_b[0] = (BYTE)len; /* length of locale name */ + (void)strcpy((char *)&buf_b[1], locale_name); /* locale name */ + len += sizeof(BYTE); /* sizeof length */ + XIM_SET_PAD(buf_b, len); /* pad */ + + _XimSetHeader((XPointer)buf, XIM_OPEN, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, reply, buf_size, + _XimOpenCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimOpenCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + + im->private.proto.imid = buf_s[0]; /* imid */ + + if (!(_XimGetAttributeID(im, &buf_s[1]))) { + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + + if (!(_XimSetInnerIMResourceList(&(im->private.proto.im_inner_resources), + &(im->private.proto.im_num_inner_resources)))) + return False; + + if (!(_XimSetInnerICResourceList(&(im->private.proto.ic_inner_resources), + &(im->private.proto.ic_num_inner_resources)))) + return False; + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + _XimSetIMMode(im->private.proto.im_inner_resources, + im->private.proto.im_num_inner_resources); + + /* Transport Callbak */ + _XimRegProtoIntrCallback(im, XIM_SET_EVENT_MASK, 0, + _XimSetEventMaskCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_FORWARD_EVENT, 0, + _XimForwardEventCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_COMMIT, 0, + _XimCommitCallback, (XPointer)im); + _XimRegProtoIntrCallback(im, XIM_SYNC, 0, + _XimSyncCallback, (XPointer)im); + + if(!_XimExtension(im)) + return False; + + /* register a hook for callback protocols */ + _XimRegisterDispatcher(im, _XimCbDispatch, (XPointer)im); + + return True; +} + +Private Bool +_XimCloseCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_CLOSE_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private Bool +_XimClose( + Xim im) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (!IS_SERVER_CONNECTED(im)) + return True; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = 0; /* unused */ + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof unused */ + + _XimSetHeader((XPointer)buf, XIM_CLOSE, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimCloseCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, _XimCloseCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + + if(reply != preply) + Xfree(preply); + return True; +} + +Public void +_XimProtoIMFree( + Xim im) +{ + /* XIMPrivateRec */ + if (im->private.proto.im_onkeylist) { + Xfree(im->private.proto.im_onkeylist); + im->private.proto.im_onkeylist = NULL; + } + if (im->private.proto.im_offkeylist) { + Xfree(im->private.proto.im_offkeylist); + im->private.proto.im_offkeylist = NULL; + } + if (im->private.proto.intrproto) { + _XimFreeProtoIntrCallback(im); + im->private.proto.intrproto = NULL; + } + if (im->private.proto.im_inner_resources) { + Xfree(im->private.proto.im_inner_resources); + im->private.proto.im_inner_resources = NULL; + } + if (im->private.proto.ic_inner_resources) { + Xfree(im->private.proto.ic_inner_resources); + im->private.proto.ic_inner_resources = NULL; + } + if (im->private.proto.hold_data) { + Xfree(im->private.proto.hold_data); + im->private.proto.hold_data = NULL; + } + if (im->private.proto.locale_name) { + Xfree(im->private.proto.locale_name); + im->private.proto.locale_name = NULL; + } + if (im->private.proto.ctom_conv) { + _XlcCloseConverter(im->private.proto.ctom_conv); + im->private.proto.ctom_conv = NULL; + } + if (im->private.proto.ctow_conv) { + _XlcCloseConverter(im->private.proto.ctow_conv); + im->private.proto.ctow_conv = NULL; + } + if (im->private.proto.ctoutf8_conv) { + _XlcCloseConverter(im->private.proto.ctoutf8_conv); + im->private.proto.ctoutf8_conv = NULL; + } + if (im->private.proto.cstomb_conv) { + _XlcCloseConverter(im->private.proto.cstomb_conv); + im->private.proto.cstomb_conv = NULL; + } + if (im->private.proto.cstowc_conv) { + _XlcCloseConverter(im->private.proto.cstowc_conv); + im->private.proto.cstowc_conv = NULL; + } + if (im->private.proto.cstoutf8_conv) { + _XlcCloseConverter(im->private.proto.cstoutf8_conv); + im->private.proto.cstoutf8_conv = NULL; + } + if (im->private.proto.ucstoc_conv) { + _XlcCloseConverter(im->private.proto.ucstoc_conv); + im->private.proto.ucstoc_conv = NULL; + } + if (im->private.proto.ucstoutf8_conv) { + _XlcCloseConverter(im->private.proto.ucstoutf8_conv); + im->private.proto.ucstoutf8_conv = NULL; + } + +#ifdef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { + return; + } +#endif /* XIM_CONNECTABLE */ + + if (im->private.proto.saved_imvalues) { + Xfree(im->private.proto.saved_imvalues); + im->private.proto.saved_imvalues = NULL; + } + if (im->private.proto.default_styles) { + Xfree(im->private.proto.default_styles); + im->private.proto.default_styles = NULL; + } + + /* core */ + if (im->core.res_name) { + Xfree(im->core.res_name); + im->core.res_name = NULL; + } + if (im->core.res_class) { + Xfree(im->core.res_class); + im->core.res_class = NULL; + } + if (im->core.im_values_list) { + Xfree(im->core.im_values_list); + im->core.im_values_list = NULL; + } + if (im->core.ic_values_list) { + Xfree(im->core.ic_values_list); + im->core.ic_values_list = NULL; + } + if (im->core.im_name) { + Xfree(im->core.im_name); + im->core.im_name = NULL; + } + if (im->core.styles) { + Xfree(im->core.styles); + im->core.styles = NULL; + } + if (im->core.im_resources) { + Xfree(im->core.im_resources); + im->core.im_resources = NULL; + } + if (im->core.ic_resources) { + Xfree(im->core.ic_resources); + im->core.ic_resources = NULL; + } + + return; +} + +Private Status +_XimProtoCloseIM( + XIM xim) +{ + Xim im = (Xim)xim; + XIC ic; + XIC next; + Status status; + + ic = im->core.ic_chain; + while (ic) { + (*ic->methods->destroy) (ic); + next = ic->core.next; +#ifdef XIM_CONNECTABLE + if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) { + Xfree ((char *) ic); + } +#else + Xfree ((char *) ic); +#endif /* XIM_CONNECTABLE */ + ic = next; + } +#ifdef XIM_CONNECTABLE + if (!(!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im))) + im->core.ic_chain = NULL; +#else + im->core.ic_chain = NULL; +#endif + + _XimUnregisterServerFilter(im); + _XimResetIMInstantiateCallback(im); + status = (Status)_XimClose(im); + status = (Status)_XimDisconnect(im) && status; + _XimProtoIMFree(im); +#ifdef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) { + _XimReconnectModeSetAttr(im); + for (ic = im->core.ic_chain; ic; ic = ic->core.next) { + _XimReconnectModeCreateIC(ic); + } + return 0; + } +#endif /* XIM_CONNECTABLE */ + _XimDestroyIMStructureList(im); + return status; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimCheckIMQuarkList( + XrmQuark *quark_list, + int num_quark, + XrmQuark quark) +{ + register int i; + + for (i = 0; i < num_quark; i++) { + if (quark_list[i] == quark) { + return True; + } + } + return False; +} + +Private Bool +_XimSaveIMValues( + Xim im, + XIMArg *arg) +{ + register XIMArg *p; + register int n; + XrmQuark *quark_list; + XrmQuark *tmp; + XrmQuark quark; + int num_quark; + + if (quark_list = im->private.proto.saved_imvalues) { + num_quark = im->private.proto.num_saved_imvalues; + for (p = arg; p && p->name; p++) { + quark = XrmStringToQuark(p->name); + if (_XimCheckIMQuarkList(quark_list, num_quark, quark)) { + continue; + } + if (!(tmp = (XrmQuark *)Xrealloc(quark_list, + (sizeof(XrmQuark) * (num_quark + 1))))) { + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = num_quark; + return False; + } + num_quark++; + quark_list = tmp; + quark_list[num_quark] = quark; + } + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = num_quark; + return True; + } + + for (p = arg, n = 0; p && p->name; p++, n++); + + if (!(quark_list = (XrmQuark *)Xmalloc(sizeof(XrmQuark) * n))) { + return False; + } + + im->private.proto.saved_imvalues = quark_list; + im->private.proto.num_saved_imvalues = n; + for (p = arg; p && p->name; p++, quark_list++) { + *quark_list = XrmStringToQuark(p->name); + } + + return True; +} + +Private char * +_XimDelayModeSetIMValues( + Xim im, + XIMArg *arg) +{ + XimDefIMValues im_values; + char *name; + XIMArg *values; + + _XimGetCurrentIMValues(im, &im_values); + name = _XimSetIMValueData(im, (XPointer)&im_values, values, + im->core.im_resources, im->core.im_num_resources); + _XimSetCurrentIMValues(im, &im_values); + + return name; +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimSetIMValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_SET_IM_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private char * +_XimProtoSetIMValues( + XIM xim, + XIMArg *arg) +{ + Xim im = (Xim)xim; + XimDefIMValues im_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + XIMArg *arg_ret; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + char *name; + +#ifndef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im)) + return arg->name; +#else + if (!_XimSaveIMValues(im, arg)) + return arg->name; + + if (!IS_SERVER_CONNECTED(im)) { + if (IS_CONNECTABLE(im)) { + if (!_XimConnectServer(im)) { + return _XimDelayModeSetIMValues(im, arg); + } + } else { + return arg->name; + } + } +#endif /* XIM_CONNECTABLE */ + + _XimGetCurrentIMValues(im, &im_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + arg_ret = arg; + for (;;) { + data = &buf[buf_size]; + if ((name = _XimEncodeIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, arg, &arg_ret, data, data_len, + &ret_len, (XPointer)&im_values, XIM_SETIMVALUES))) { + if (buf != tmp_buf) + Xfree(buf); + break; + } + + total += ret_len; + if (!(arg = arg_ret)) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + return arg->name; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + return arg->name; + } + buf = tmp; + } + } + _XimSetCurrentIMValues(im, &im_values); + + if (!total) + return (char *)NULL; + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + return arg->name; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return arg->name; + } + } + } else + return arg->name; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return arg->name; + } + if(reply != preply) + Xfree(preply); + + return name; +} + +#ifdef XIM_CONNECTABLE +Private char * +_XimDelayModeGetIMValues( + Xim im, + XIMArg *arg) +{ + XimDefIMValues im_values; + + _XimGetCurrentIMValues(im, &im_values); + return(_XimGetIMValueData(im, (XPointer)&im_values, arg, + im->core.im_resources, im->core.im_num_resources)); +} +#endif /* XIM_CONNECTABLE */ + +Private Bool +_XimGetIMValuesCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_GET_IM_VALUES_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private char * +_XimProtoGetIMValues( + XIM xim, + XIMArg *arg) +{ + Xim im = (Xim)xim; + register XIMArg *p; + register int n; + CARD8 *buf; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply = NULL; + int buf_size; + int ret_code; + char *makeid_name; + char *decode_name; + CARD16 *data = NULL; + INT16 data_len = 0; + +#ifndef XIM_CONNECTABLE + if (!IS_SERVER_CONNECTED(im)) + return arg->name; +#else + if (!IS_SERVER_CONNECTED(im)) { + if (IS_CONNECTABLE(im)) { + if (!_XimConnectServer(im)) { + return _XimDelayModeGetIMValues(im, arg); + } + } else { + return arg->name; + } + } +#endif /* XIM_CONNECTABLE */ + + for (n = 0, p = arg; p->name; p++) + n++; + + if (!n) + return (char *)NULL; + + buf_size = sizeof(CARD16) * n; + buf_size += XIM_HEADER_SIZE + + sizeof(CARD16) + + sizeof(INT16) + + XIM_PAD(buf_size); + + if (!(buf = (CARD8 *)Xmalloc(buf_size))) + return arg->name; + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + + makeid_name = _XimMakeIMAttrIDList(im, im->core.im_resources, + im->core.im_num_resources, arg, + &buf_s[2], &len, XIM_GETIMVALUES); + + if (len) { + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = len; /* length of im-attr-id */ + XIM_SET_PAD(&buf_s[2], len); /* pad */ + len += sizeof(CARD16) /* sizeof imid */ + + sizeof(INT16); /* sizeof length of attr */ + + _XimSetHeader((XPointer)buf, XIM_GET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + Xfree(buf); + return arg->name; + } + _XimFlush(im); + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimGetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimGetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return arg->name; + } + } + } else + return arg->name; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return arg->name; + } + data = &buf_s[2]; + data_len = buf_s[1]; + } + decode_name = _XimDecodeIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, data, data_len, + arg, XIM_GETIMVALUES); + if (reply != preply) + Xfree(preply); + + if (decode_name) + return decode_name; + else + return makeid_name; +} + +Private XIMMethodsRec im_methods = { + _XimProtoCloseIM, /* close */ + _XimProtoSetIMValues, /* set_values */ + _XimProtoGetIMValues, /* get_values */ + _XimProtoCreateIC, /* create_ic */ + _Ximctstombs, /* ctstombs */ + _Ximctstowcs, /* ctstowcs */ + _Ximctstoutf8 /* ctstoutf8 */ +}; + +Private Bool +_XimSetEncodingByName( + Xim im, + char **buf, + int *len) +{ + char *encoding = (char *)NULL; + int encoding_len; + int compound_len; + BYTE *ret; + + _XGetLCValues(im->core.lcd, XlcNCodeset, &encoding, NULL); + if (!encoding) { + *buf = (char *)NULL; + *len = 0; + return True; + } + encoding_len = strlen(encoding); + compound_len = strlen("COMPOUND_TEXT"); + *len = encoding_len + sizeof(BYTE) + compound_len + sizeof(BYTE); + if (!(ret = (BYTE *)Xmalloc(*len))) { + return False; + } + *buf = (char *)ret; + + ret[0] = (BYTE)encoding_len; + (void)strncpy((char *)&ret[1], encoding, encoding_len); + ret += (encoding_len + sizeof(BYTE)); + ret[0] = (BYTE)compound_len; + (void)strncpy((char *)&ret[1], "COMPOUND_TEXT", compound_len); + return True; +} + +Private Bool +_XimSetEncodingByDetail( + Xim im, + char **buf, + int *len) +{ + *len = 0; + *buf = NULL; + return True; +} + +Private Bool +_XimGetEncoding( + Xim im, + CARD16 *buf, + char *name, + int name_len, + char *detail, + int detail_len) +{ + XLCd lcd = im->core.lcd; + CARD16 category = buf[0]; + CARD16 idx = buf[1]; + int len; + XlcConv ctom_conv = NULL; + XlcConv ctow_conv = NULL; + XlcConv ctoutf8_conv = NULL; + XlcConv conv; + XimProtoPrivateRec *private = &im->private.proto; + + if (idx == (CARD16)XIM_Default_Encoding_IDX) { /* XXX */ + if (!(ctom_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNMultiByte))) + return False; + if (!(ctow_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNWideChar))) + return False; + if (!(ctoutf8_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNUtf8String))) + return False; + } + + if (category == XIM_Encoding_NameCategory) { + while (name_len > 0) { + len = (int)name[0]; + if (!strncmp(&name[1], "COMPOUND_TEXT", len)) { + if (!(ctom_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNMultiByte))) + return False; + if (!(ctow_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNWideChar))) + return False; + if (!(ctoutf8_conv = _XlcOpenConverter(lcd, + XlcNCompoundText, lcd, XlcNUtf8String))) + return False; + break; + } else { + /* + * Not yet + */ + } + len += sizeof(BYTE); + name_len -= len; + name += len; + } + } else if (category == XIM_Encoding_DetailCategory) { + /* + * Not yet + */ + } else { + return False; + } + + private->ctom_conv = ctom_conv; + private->ctow_conv = ctow_conv; + private->ctoutf8_conv = ctoutf8_conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) + return False; + private->cstomb_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) + return False; + private->cstowc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) + return False; + private->cstoutf8_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) + return False; + private->ucstoc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) + return False; + private->ucstoutf8_conv = conv; + + return True; +} + +Private Bool +_XimEncodingNegoCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + + if ((major_opcode == XIM_ENCODING_NEGOTIATION_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid)) + return True; + return False; +} + +Private Bool +_XimEncodingNegotiation( + Xim im) +{ + char *name_ptr = 0; + int name_len = 0; + char *detail_ptr = 0; + int detail_len = 0; + CARD8 *buf; + CARD16 *buf_s; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + if (!(_XimSetEncodingByName(im, &name_ptr, &name_len))) + return False; + + if (!(_XimSetEncodingByDetail(im, &detail_ptr, &detail_len))) + goto free_name_ptr; + + len = sizeof(CARD16) + + sizeof(INT16) + + name_len + + XIM_PAD(name_len) + + sizeof(INT16) + + sizeof(CARD16) + + detail_len; + + if (!(buf = (CARD8 *)Xmalloc(XIM_HEADER_SIZE + len))) + goto free_detail_ptr; + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)name_len; + if (name_ptr) + (void)memcpy((char *)&buf_s[2], name_ptr, name_len); + XIM_SET_PAD(&buf_s[2], name_len); + buf_s = (CARD16 *)((char *)&buf_s[2] + name_len); + buf_s[0] = detail_len; + buf_s[1] = 0; + if (detail_ptr) + (void)memcpy((char *)&buf_s[2], detail_ptr, detail_len); + + _XimSetHeader((XPointer)buf, XIM_ENCODING_NEGOTIATION, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + Xfree(buf); + goto free_detail_ptr; + } + _XimFlush(im); + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimEncodingNegoCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimEncodingNegoCheck, 0); + if(ret_code != XIM_TRUE) + goto free_preply; + } + } else + goto free_detail_ptr; + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + goto free_preply; + } + + if (!(_XimGetEncoding(im, &buf_s[1], name_ptr, name_len, + detail_ptr, detail_len))) + goto free_preply; + + if (name_ptr) + Xfree(name_ptr); + if (detail_ptr) + Xfree(detail_ptr); + + if(reply != preply) + Xfree(preply); + + return True; + +free_preply: + if (reply != preply) + Xfree(preply); + +free_detail_ptr: + Xfree(detail_ptr); + +free_name_ptr: + Xfree(name_ptr); + + return False; +} + +#ifdef XIM_CONNECTABLE +Private Bool +_XimSendSavedIMValues( + Xim im) +{ + XimDefIMValues im_values; + INT16 len; + CARD16 *buf_s; + char *tmp; + CARD32 tmp_buf32[BUFSIZE/4]; + char *tmp_buf = (char *)tmp_buf32; + char *buf; + int buf_size; + char *data; + int data_len; + int ret_len; + int total; + int idx; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int ret_code; + + _XimGetCurrentIMValues(im, &im_values); + buf = tmp_buf; + buf_size = XIM_HEADER_SIZE + sizeof(CARD16) + sizeof(INT16); + data_len = BUFSIZE - buf_size; + total = 0; + idx = 0; + for (;;) { + data = &buf[buf_size]; + if (!_XimEncodeSavedIMATTRIBUTE(im, im->core.im_resources, + im->core.im_num_resources, &idx, data, data_len, + &ret_len, (XPointer)&im_values, XIM_SETIMVALUES)) { + if (buf != tmp_buf) + Xfree(buf); + return False; + } + + total += ret_len; + if (idx == -1) { + break; + } + + buf_size += ret_len; + if (buf == tmp_buf) { + if (!(tmp = (char *)Xmalloc(buf_size + data_len))) { + return False; + } + memcpy(tmp, buf, buf_size); + buf = tmp; + } else { + if (!(tmp = (char *)Xrealloc(buf, (buf_size + data_len)))) { + Xfree(buf); + return False; + } + buf = tmp; + } + } + + if (!total) + return True; + + buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + buf_s[0] = im->private.proto.imid; + buf_s[1] = (INT16)total; + + len = (INT16)(sizeof(CARD16) + sizeof(INT16) + total); + _XimSetHeader((XPointer)buf, XIM_SET_IM_VALUES, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) { + if (buf != tmp_buf) + Xfree(buf); + return False; + } + _XimFlush(im); + if (buf != tmp_buf) + Xfree(buf); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = (int)len; + preply = (XPointer)Xmalloc(buf_size); + ret_code = _XimRead(im, &len, reply, buf_size, + _XimSetIMValuesCheck, 0); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else + return False; + + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + + return True; +} + +Private void +_XimDelayModeIMFree( + Xim im) +{ + if (im->core.im_resources) { + Xfree(im->core.im_resources); + im->core.im_resources = NULL; + } + if (im->core.ic_resources) { + Xfree(im->core.ic_resources); + im->core.ic_resources = NULL; + } + if (im->core.im_values_list) { + Xfree(im->core.im_values_list); + im->core.im_values_list = NULL; + } + if (im->core.ic_values_list) { + Xfree(im->core.ic_values_list); + im->core.ic_values_list = NULL; + } + return; +} + +Public Bool +_XimConnectServer( + Xim im) +{ + Xim save_im; + + if (!(save_im = (Xim)Xmalloc(sizeof(XimRec)))) + return False; + memcpy((char *)save_im, (char *)im, sizeof(XimRec)); + + if (_XimPreConnect(im) && _XimConnection(im) + && _XimOpen(im) && _XimEncodingNegotiation(im)) { + if (_XimSendSavedIMValues(im)) { + _XimDelayModeIMFree(save_im); + _XimRegisterServerFilter(im); + Xfree(save_im); + return True; + } + } + memcpy((char *)im, (char *)save_im, sizeof(XimRec)); + Xfree(save_im); + return False; +} + +Public Bool +_XimDelayModeSetAttr( + Xim im) +{ + XimDefIMValues im_values; + + if(!_XimSetIMResourceList(&im->core.im_resources, + &im->core.im_num_resources)) { + return False; + } + if(!_XimSetICResourceList(&im->core.ic_resources, + &im->core.ic_num_resources)) { + return False; + } + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + + _XimGetCurrentIMValues(im, &im_values); + if(!_XimSetLocalIMDefaults(im, (XPointer)&im_values, + im->core.im_resources, im->core.im_num_resources)) { + return False; + } + _XimSetCurrentIMValues(im, &im_values); + if (im->private.proto.default_styles) { + if (im->core.styles) + Xfree(im->core.styles); + im->core.styles = im->private.proto.default_styles; + } + + return True; +} + +Private Bool +_XimReconnectModeSetAttr( + Xim im) +{ + XimDefIMValues im_values; + + if(!_XimSetIMResourceList(&im->core.im_resources, + &im->core.im_num_resources)) { + return False; + } + if(!_XimSetICResourceList(&im->core.ic_resources, + &im->core.ic_num_resources)) { + return False; + } + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + + if (im->private.proto.default_styles) { + if (im->core.styles) + Xfree(im->core.styles); + im->core.styles = im->private.proto.default_styles; + } + + return True; +} +#endif /* XIM_CONNECTABLE */ + +Public Bool +_XimProtoOpenIM( + Xim im) +{ + _XimInitialResourceInfo(); + + im->methods = &im_methods; + +#ifdef XIM_CONNECTABLE + _XimSetProtoResource(im); +#endif /* XIM_CONNECTABLE */ + + if (_XimPreConnect(im)) { + if (_XimConnection(im) && _XimOpen(im) && _XimEncodingNegotiation(im)) { + _XimRegisterServerFilter(im); + return True; + } + _XimShutdown(im); +#ifdef XIM_CONNECTABLE + } else if (IS_DELAYBINDABLE(im)) { + if (_XimDelayModeSetAttr(im)) + return True; +#endif /* XIM_CONNECTABLE */ + } + _XimProtoIMFree(im); + return False; +} diff --git a/libX11/modules/im/ximcp/imDefLkup.c b/libX11/modules/im/ximcp/imDefLkup.c index a269df062..996d36aef 100644 --- a/libX11/modules/im/ximcp/imDefLkup.c +++ b/libX11/modules/im/ximcp/imDefLkup.c @@ -1,1168 +1,1170 @@ -/****************************************************************** - - Copyright 1992, 1993, 1994 by FUJITSU LIMITED - -Permission to use, copy, modify, distribute, and sell this software -and its documentation for any purpose is hereby granted without fee, -provided that the above copyright notice appear in all copies and -that both that copyright notice and this permission notice appear -in supporting documentation, and that the name of FUJITSU LIMITED -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. -FUJITSU LIMITED makes no representations about the suitability of -this software for any purpose. -It is provided "as is" without express or implied warranty. - -FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - Author: Takashi Fujiwara FUJITSU LIMITED - fujiwara@a80.tech.yk.fujitsu.co.jp - -******************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include "Xlibint.h" -#include "Xlcint.h" -#include "Ximint.h" - -Public Xic -_XimICOfXICID( - Xim im, - XICID icid) -{ - Xic pic; - - for (pic = (Xic)im->core.ic_chain; pic; pic = (Xic)pic->core.next) { - if (pic->private.proto.icid == icid) - return pic; - } - return (Xic)0; -} - -Private void -_XimProcIMSetEventMask( - Xim im, - XPointer buf) -{ - EVENTMASK *buf_l = (EVENTMASK *)buf; - - im->private.proto.forward_event_mask = buf_l[0]; - im->private.proto.synchronous_event_mask = buf_l[1]; - return; -} - -Private void -_XimProcICSetEventMask( - Xic ic, - XPointer buf) -{ - EVENTMASK *buf_l = (EVENTMASK *)buf; - - ic->private.proto.forward_event_mask = buf_l[0]; - ic->private.proto.synchronous_event_mask = buf_l[1]; - _XimReregisterFilter(ic); - return; -} - -Public Bool -_XimSetEventMaskCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - Xim im = (Xim)call_data; - Xic ic; - - if (imid == im->private.proto.imid) { - if (icid) { - ic = _XimICOfXICID(im, icid); - _XimProcICSetEventMask(ic, (XPointer)&buf_s[2]); - } else { - _XimProcIMSetEventMask(im, (XPointer)&buf_s[2]); - } - return True; - } - return False; -} - -Private Bool -_XimSyncCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - - if ((major_opcode == XIM_SYNC_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - return True; - return False; -} - -Public Bool -_XimSync( - Xim im, - Xic ic) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_SYNC, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimSyncCheck, (XPointer)ic); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(len); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimSyncCheck, (XPointer)ic); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else { - return False; - } - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - return True; -} - -Public Bool -_XimProcSyncReply( - Xim im, - Xic ic) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len; - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16); /* sizeof icid */ - - _XimSetHeader((XPointer)buf, XIM_SYNC_REPLY, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - return True; -} - -Public Bool -_XimRespSyncReply( - Xic ic, - BITMASK16 mode) -{ - if (mode & XimSYNCHRONUS) /* SYNC Request */ { - if (IS_FOCUSED(ic)) - MARK_NEED_SYNC_REPLY(ic); - else - _XimProcSyncReply((Xim)ic->core.im, ic); - } - - return True; -} - -Public Bool -_XimSyncCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - Xim im = (Xim)call_data; - Xic ic; - - if ((imid == im->private.proto.imid) - && (ic = _XimICOfXICID(im, icid))) { - (void)_XimProcSyncReply(im, ic); - return True; - } - return False; -} - -Private INT16 -_XimSetEventToWire( - XEvent *ev, - xEvent *event) -{ - if (!(_XimProtoEventToWire(ev, event, False))) - return 0; - event->u.u.sequenceNumber = - ((XAnyEvent *)ev)->serial & (unsigned long)0xffff; - return sz_xEvent; -} - -Private Bool -_XimForwardEventCore( - Xic ic, - XEvent *ev, - Bool sync) -{ - Xim im = (Xim)ic->core.im; - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - INT16 len; - - if (!(len = _XimSetEventToWire(ev, (xEvent *)&buf_s[4]))) - return False; /* X event */ - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - buf_s[2] = sync ? XimSYNCHRONUS : 0; /* flag */ - buf_s[3] = - (CARD16)((((XAnyEvent *)ev)->serial & ~((unsigned long)0xffff)) >> 16); - /* serial number */ - - len += sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16) /* sizeof icid */ - + sizeof(BITMASK16) /* sizeof flag */ - + sizeof(CARD16); /* sizeof serila number */ - - _XimSetHeader((XPointer)buf, XIM_FORWARD_EVENT, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - - if (sync) { - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimSyncCheck, (XPointer)ic); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(len); - ret_code = _XimRead(im, &len, preply, buf_size, - _XimSyncCheck, (XPointer)ic); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else { - return False; - } - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - } - return True; -} - -Public Bool -_XimForwardEvent( - Xic ic, - XEvent *ev, - Bool sync) -{ -#ifdef EXT_FORWARD - if (((ev->type == KeyPress) || (ev->type == KeyRelease))) - if (_XimExtForwardKeyEvent(ic, (XKeyEvent *)ev, sync)) - return True; -#endif - return _XimForwardEventCore(ic, ev, sync); -} - -Private void -_XimProcEvent( - Display *d, - Xic ic, - XEvent *ev, - CARD16 *buf) -{ - INT16 serial = buf[0]; - xEvent *xev = (xEvent *)&buf[1]; - - _XimProtoWireToEvent(ev, xev, False); - ev->xany.serial |= serial << 16; - ev->xany.send_event = False; - ev->xany.display = d; - MARK_FABLICATED(ic); - return; -} - -Private Bool -_XimForwardEventRecv( - Xim im, - Xic ic, - XPointer buf) -{ - CARD16 *buf_s = (CARD16 *)buf; - Display *d = im->core.display; - XEvent ev; - - _XimProcEvent(d, ic, &ev, &buf_s[1]); - - (void)_XimRespSyncReply(ic, buf_s[0]); - - XPutBackEvent(d, &ev); - - return True; -} - -Public Bool -_XimForwardEventCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - Xim im = (Xim)call_data; - Xic ic; - - if ((imid == im->private.proto.imid) - && (ic = _XimICOfXICID(im, icid))) { - (void)_XimForwardEventRecv(im, ic, (XPointer)&buf_s[2]); - return True; - } - return False; -} - -Private Bool -_XimRegisterTriggerkey( - Xim im, - XPointer buf) -{ - CARD32 *buf_l = (CARD32 *)buf; - CARD32 len; - CARD32 *key; - - if (IS_DYNAMIC_EVENT_FLOW(im)) /* already Dynamic event flow mode */ - return True; - - /* - * register onkeylist - */ - - len = buf_l[0]; /* length of on-keys */ - len += sizeof(INT32); /* sizeof length of on-keys */ - - if (!(key = (CARD32 *)Xmalloc(len))) { - _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); - return False; - } - memcpy((char *)key, (char *)buf_l, len); - im->private.proto.im_onkeylist = key; - - MARK_DYNAMIC_EVENT_FLOW(im); - - /* - * register offkeylist - */ - - buf_l = (CARD32 *)((char *)buf + len); - len = buf_l[0]; /* length of off-keys */ - len += sizeof(INT32); /* sizeof length of off-keys */ - - if (!(key = (CARD32 *)Xmalloc(len))) { - _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); - return False; - } - - memcpy((char *)key, (char *)buf_l, len); - im->private.proto.im_offkeylist = key; - - return True; -} - -Public Bool -_XimRegisterTriggerKeysCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - Xim im = (Xim)call_data; - - (void )_XimRegisterTriggerkey(im, (XPointer)&buf_s[2]); - return True; -} - -Public EVENTMASK -_XimGetWindowEventmask( - Xic ic) -{ - Xim im = (Xim )ic->core.im; - XWindowAttributes atr; - - if (!XGetWindowAttributes(im->core.display, ic->core.focus_window, &atr)) - return 0; - return (EVENTMASK)atr.your_event_mask; -} - - -Private Bool -_XimTriggerNotifyCheck( - Xim im, - INT16 len, - XPointer data, - XPointer arg) -{ - Xic ic = (Xic)arg; - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - CARD8 major_opcode = *((CARD8 *)data); - CARD8 minor_opcode = *((CARD8 *)data + 1); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - - if ((major_opcode == XIM_TRIGGER_NOTIFY_REPLY) - && (minor_opcode == 0) - && (imid == im->private.proto.imid) - && (icid == ic->private.proto.icid)) - return True; - if ((major_opcode == XIM_ERROR) - && (minor_opcode == 0) - && (buf_s[2] & XIM_IMID_VALID) - && (imid == im->private.proto.imid) - && (buf_s[2] & XIM_ICID_VALID) - && (icid == ic->private.proto.icid)) - return True; - return False; -} - -Public Bool -_XimTriggerNotify( - Xim im, - Xic ic, - int mode, - CARD32 idx) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - CARD32 *buf_l = (CARD32 *)&buf[XIM_HEADER_SIZE]; - CARD32 reply32[BUFSIZE/4]; - char *reply = (char *)reply32; - XPointer preply; - int buf_size; - int ret_code; - INT16 len; - EVENTMASK mask = _XimGetWindowEventmask(ic); - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[1] = ic->private.proto.icid; /* icid */ - buf_l[1] = mode; /* flag */ - buf_l[2] = idx; /* index of keys list */ - buf_l[3] = mask; /* select-event-mask */ - - len = sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16) /* sizeof icid */ - + sizeof(CARD32) /* sizeof flag */ - + sizeof(CARD32) /* sizeof index of key list */ - + sizeof(EVENTMASK); /* sizeof select-event-mask */ - - _XimSetHeader((XPointer)buf, XIM_TRIGGER_NOTIFY, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - buf_size = BUFSIZE; - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimTriggerNotifyCheck, (XPointer)ic); - if(ret_code == XIM_TRUE) { - preply = reply; - } else if(ret_code == XIM_OVERFLOW) { - if(len <= 0) { - preply = reply; - } else { - buf_size = len; - preply = (XPointer)Xmalloc(len); - ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, - _XimTriggerNotifyCheck, (XPointer)ic); - if(ret_code != XIM_TRUE) { - Xfree(preply); - return False; - } - } - } else { - return False; - } - buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); - if (*((CARD8 *)preply) == XIM_ERROR) { - _XimProcError(im, 0, (XPointer)&buf_s[3]); - if(reply != preply) - Xfree(preply); - return False; - } - if(reply != preply) - Xfree(preply); - return True; -} - -Private Bool -_XimRegCommitInfo( - Xic ic, - char *string, - int string_len, - KeySym *keysym, - int keysym_len) -{ - XimCommitInfo info; - - if (!(info = (XimCommitInfo)Xmalloc(sizeof(XimCommitInfoRec)))) - return False; - info->string = string; - info->string_len = string_len; - info->keysym = keysym; - info->keysym_len = keysym_len; - info->next = ic->private.proto.commit_info; - ic->private.proto.commit_info = info; - return True; -} - -Private void -_XimUnregCommitInfo( - Xic ic) -{ - XimCommitInfo info; - - if (!(info = ic->private.proto.commit_info)) - return; - - if (info->string) - Xfree(info->string); - if (info->keysym) - Xfree(info->keysym); - ic->private.proto.commit_info = info->next; - Xfree(info); - return; -} - -Public void -_XimFreeCommitInfo( - Xic ic) -{ - while (ic->private.proto.commit_info) - _XimUnregCommitInfo(ic); - return; -} - -Private Bool -_XimProcKeySym( - Xic ic, - CARD32 sym, - KeySym **xim_keysym, - int *xim_keysym_len) -{ - Xim im = (Xim)ic->core.im; - - if (!(*xim_keysym = (KeySym *)Xmalloc(sizeof(KeySym)))) { - _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); - return False; - } - - **xim_keysym = (KeySym)sym; - *xim_keysym_len = 1; - - return True; -} - -Private Bool -_XimProcCommit( - Xic ic, - BYTE *buf, - int len, - char **xim_string, - int *xim_string_len) -{ - Xim im = (Xim)ic->core.im; - char *string; - - if (!(string = (char *)Xmalloc(len + 1))) { - _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); - return False; - } - - (void)memcpy(string, (char *)buf, len); - string[len] = '\0'; - - *xim_string = string; - *xim_string_len = len; - return True; -} - -Private Bool -_XimCommitRecv( - Xim im, - Xic ic, - XPointer buf) -{ - CARD16 *buf_s = (CARD16 *)buf; - BITMASK16 flag = buf_s[0]; - XKeyEvent ev; - char *string = NULL; - int string_len = 0; - KeySym *keysym = NULL; - int keysym_len = 0; - - if ((flag & XimLookupBoth) == XimLookupChars) { - if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2], - (int)buf_s[1], &string, &string_len))) - return False; - - } else if ((flag & XimLookupBoth) == XimLookupKeySym) { - if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) - return False; - - } else if ((flag & XimLookupBoth) == XimLookupBoth) { - if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) - return False; - - if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5], - (int)buf_s[4], &string, &string_len))) - return False; - } - - if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) { - if (string) - Xfree(string); - if (keysym) - Xfree(keysym); - _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); - return False; - } - - (void)_XimRespSyncReply(ic, flag); - - MARK_FABLICATED(ic); - - ev.type = KeyPress; - ev.send_event = False; - ev.display = im->core.display; - ev.window = ic->core.focus_window; - ev.keycode = 0; - ev.state = 0; - - XPutBackEvent(im->core.display, (XEvent *)&ev); - - return True; -} - -Public Bool -_XimCommitCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - XIMID imid = buf_s[0]; - XICID icid = buf_s[1]; - Xim im = (Xim)call_data; - Xic ic; - - if ((imid == im->private.proto.imid) - && (ic = _XimICOfXICID(im, icid))) { - (void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]); - return True; - } - return False; -} - -Public void -_XimProcError( - Xim im, - Xic ic, - XPointer data) -{ - return; -} - -Public Bool -_XimErrorCallback( - Xim xim, - INT16 len, - XPointer data, - XPointer call_data) -{ - CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); - BITMASK16 flag = buf_s[2]; - XIMID imid; - XICID icid; - Xim im = (Xim)call_data; - Xic ic = NULL; - - if (flag & XIM_IMID_VALID) { - imid = buf_s[0]; - if (imid != im->private.proto.imid) - return False; - } - if (flag & XIM_ICID_VALID) { - icid = buf_s[1]; - if (!(ic = _XimICOfXICID(im, icid))) - return False; - } - _XimProcError(im, ic, (XPointer)&buf_s[3]); - - return True; -} - -Public Bool -_XimError( - Xim im, - Xic ic, - CARD16 error_code, - INT16 detail_length, - CARD16 type, - char *detail) -{ - CARD32 buf32[BUFSIZE/4]; - CARD8 *buf = (CARD8 *)buf32; - CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; - INT16 len = 0; - - buf_s[0] = im->private.proto.imid; /* imid */ - buf_s[2] = XIM_IMID_VALID; /* flag */ - if (ic) { - buf_s[1] = ic->private.proto.icid; /* icid */ - buf_s[2] |= XIM_ICID_VALID; /* flag */ - } - buf_s[3] = error_code; /* Error Code */ - buf_s[4] = detail_length; /* length of error detail */ - buf_s[5] = type; /* type of error detail */ - - if (detail_length && detail) { - len = detail_length; - memcpy((char *)&buf_s[6], detail, len); - XIM_SET_PAD(&buf_s[6], len); - } - - len += sizeof(CARD16) /* sizeof imid */ - + sizeof(CARD16) /* sizeof icid */ - + sizeof(BITMASK16) /* sizeof flag */ - + sizeof(CARD16) /* sizeof error_code */ - + sizeof(INT16) /* sizeof length of detail */ - + sizeof(CARD16); /* sizeof type */ - - _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len); - if (!(_XimWrite(im, len, (XPointer)buf))) - return False; - _XimFlush(im); - return True; -} - -Private int -_Ximctsconvert( - XlcConv conv, - char *from, - int from_len, - char *to, - int to_len, - Status *state) -{ - int from_left; - int to_left; - int from_savelen; - int to_savelen; - int from_cnvlen; - int to_cnvlen; - char *from_buf; - char *to_buf; - char scratchbuf[BUFSIZ]; - Status tmp_state; - - if (!state) - state = &tmp_state; - - if (!conv || !from || !from_len) { - *state = XLookupNone; - return 0; - } - - /* Reset the converter. The CompoundText at 'from' starts in - initial state. */ - _XlcResetConverter(conv); - - from_left = from_len; - to_left = BUFSIZ; - from_cnvlen = 0; - to_cnvlen = 0; - for (;;) { - from_buf = &from[from_cnvlen]; - from_savelen = from_left; - to_buf = &scratchbuf[to_cnvlen]; - to_savelen = to_left; - if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, - (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { - *state = XLookupNone; - return 0; - } - from_cnvlen += (from_savelen - from_left); - to_cnvlen += (to_savelen - to_left); - if (from_left == 0) { - if (!to_cnvlen) { - *state = XLookupNone; - return 0; - } - break; - } - } - - if (!to || !to_len || (to_len < to_cnvlen)) { - *state = XBufferOverflow; - } else { - memcpy(to, scratchbuf, to_cnvlen); - *state = XLookupChars; - } - return to_cnvlen; -} - -Public int -_Ximctstombs(XIM xim, char *from, int from_len, - char *to, int to_len, Status *state) -{ - return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv, - from, from_len, to, to_len, state); -} - -Public int -_Ximctstowcs( - XIM xim, - char *from, - int from_len, - wchar_t *to, - int to_len, - Status *state) -{ - Xim im = (Xim)xim; - XlcConv conv = im->private.proto.ctow_conv; - int from_left; - int to_left; - int from_savelen; - int to_savelen; - int from_cnvlen; - int to_cnvlen; - char *from_buf; - wchar_t *to_buf; - wchar_t scratchbuf[BUFSIZ]; - Status tmp_state; - - if (!state) - state = &tmp_state; - - if (!conv || !from || !from_len) { - *state = XLookupNone; - return 0; - } - - /* Reset the converter. The CompoundText at 'from' starts in - initial state. */ - _XlcResetConverter(conv); - - from_left = from_len; - to_left = BUFSIZ; - from_cnvlen = 0; - to_cnvlen = 0; - for (;;) { - from_buf = &from[from_cnvlen]; - from_savelen = from_left; - to_buf = &scratchbuf[to_cnvlen]; - to_savelen = to_left; - if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, - (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { - *state = XLookupNone; - return 0; - } - from_cnvlen += (from_savelen - from_left); - to_cnvlen += (to_savelen - to_left); - if (from_left == 0) { - if (!to_cnvlen){ - *state = XLookupNone; - return 0; - } - break; - } - } - - if (!to || !to_len || (to_len < to_cnvlen)) { - *state = XBufferOverflow; - } else { - memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t)); - *state = XLookupChars; - } - return to_cnvlen; -} - -Public int -_Ximctstoutf8( - XIM xim, - char *from, - int from_len, - char *to, - int to_len, - Status *state) -{ - return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv, - from, from_len, to, to_len, state); -} - -Public int -_XimProtoMbLookupString( - XIC xic, - XKeyEvent *ev, - char *buffer, - int bytes, - KeySym *keysym, - Status *state) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - int ret; - Status tmp_state; - XimCommitInfo info; - - if (!IS_SERVER_CONNECTED(im)) - return 0; - - if (!state) - state = &tmp_state; - - if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */ - if (!(info = ic->private.proto.commit_info)) { - *state = XLookupNone; - return 0; - } - - ret = im->methods->ctstombs((XIM)im, info->string, - info->string_len, buffer, bytes, state); - if (*state == XBufferOverflow) - return ret; - if (keysym && (info->keysym && *(info->keysym))) { - *keysym = *(info->keysym); - if (*state == XLookupChars) - *state = XLookupBoth; - else - *state = XLookupKeySym; - } - _XimUnregCommitInfo(ic); - - } else if (ev->type == KeyPress) { - ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL); - if (ret > 0) { - if (ret > bytes) - *state = XBufferOverflow; - else if (keysym && *keysym != NoSymbol) - *state = XLookupBoth; - else - *state = XLookupChars; - } else { - if (keysym && *keysym != NoSymbol) - *state = XLookupKeySym; - else - *state = XLookupNone; - } - } else { - *state = XLookupNone; - ret = 0; - } - - return ret; -} - -Public int -_XimProtoWcLookupString( - XIC xic, - XKeyEvent *ev, - wchar_t *buffer, - int bytes, - KeySym *keysym, - Status *state) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - int ret; - Status tmp_state; - XimCommitInfo info; - - if (!IS_SERVER_CONNECTED(im)) - return 0; - - if (!state) - state = &tmp_state; - - if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ - if (!(info = ic->private.proto.commit_info)) { - *state = XLookupNone; - return 0; - } - - ret = im->methods->ctstowcs((XIM)im, info->string, - info->string_len, buffer, bytes, state); - if (*state == XBufferOverflow) - return ret; - if (keysym && (info->keysym && *(info->keysym))) { - *keysym = *(info->keysym); - if (*state == XLookupChars) - *state = XLookupBoth; - else - *state = XLookupKeySym; - } - _XimUnregCommitInfo(ic); - - } else if (ev->type == KeyPress) { - ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL); - if (ret > 0) { - if (ret > bytes) - *state = XBufferOverflow; - else if (keysym && *keysym != NoSymbol) - *state = XLookupBoth; - else - *state = XLookupChars; - } else { - if (keysym && *keysym != NoSymbol) - *state = XLookupKeySym; - else - *state = XLookupNone; - } - } else { - *state = XLookupNone; - ret = 0; - } - - return ret; -} - -Public int -_XimProtoUtf8LookupString( - XIC xic, - XKeyEvent *ev, - char *buffer, - int bytes, - KeySym *keysym, - Status *state) -{ - Xic ic = (Xic)xic; - Xim im = (Xim)ic->core.im; - int ret; - Status tmp_state; - XimCommitInfo info; - - if (!IS_SERVER_CONNECTED(im)) - return 0; - - if (!state) - state = &tmp_state; - - if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ - if (!(info = ic->private.proto.commit_info)) { - *state = XLookupNone; - return 0; - } - - ret = im->methods->ctstoutf8((XIM)im, info->string, - info->string_len, buffer, bytes, state); - if (*state == XBufferOverflow) - return ret; - if (keysym && (info->keysym && *(info->keysym))) { - *keysym = *(info->keysym); - if (*state == XLookupChars) - *state = XLookupBoth; - else - *state = XLookupKeySym; - } - _XimUnregCommitInfo(ic); - - } else if (ev->type == KeyPress) { - ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL); - if (ret > 0) { - if (ret > bytes) - *state = XBufferOverflow; - else if (keysym && *keysym != NoSymbol) - *state = XLookupBoth; - else - *state = XLookupChars; - } else { - if (keysym && *keysym != NoSymbol) - *state = XLookupKeySym; - else - *state = XLookupNone; - } - } else { - *state = XLookupNone; - ret = 0; - } - - return ret; -} +/****************************************************************** + + Copyright 1992, 1993, 1994 by FUJITSU LIMITED + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear +in supporting documentation, and that the name of FUJITSU LIMITED +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +FUJITSU LIMITED makes no representations about the suitability of +this software for any purpose. +It is provided "as is" without express or implied warranty. + +FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + Author: Takashi Fujiwara FUJITSU LIMITED + fujiwara@a80.tech.yk.fujitsu.co.jp + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "Xlibint.h" +#include "Xlcint.h" +#include "Ximint.h" + +Public Xic +_XimICOfXICID( + Xim im, + XICID icid) +{ + Xic pic; + + for (pic = (Xic)im->core.ic_chain; pic; pic = (Xic)pic->core.next) { + if (pic->private.proto.icid == icid) + return pic; + } + return (Xic)0; +} + +Private void +_XimProcIMSetEventMask( + Xim im, + XPointer buf) +{ + EVENTMASK *buf_l = (EVENTMASK *)buf; + + im->private.proto.forward_event_mask = buf_l[0]; + im->private.proto.synchronous_event_mask = buf_l[1]; + return; +} + +Private void +_XimProcICSetEventMask( + Xic ic, + XPointer buf) +{ + EVENTMASK *buf_l = (EVENTMASK *)buf; + + ic->private.proto.forward_event_mask = buf_l[0]; + ic->private.proto.synchronous_event_mask = buf_l[1]; + _XimReregisterFilter(ic); + return; +} + +Public Bool +_XimSetEventMaskCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + Xim im = (Xim)call_data; + Xic ic; + + if (imid == im->private.proto.imid) { + if (icid) { + ic = _XimICOfXICID(im, icid); + _XimProcICSetEventMask(ic, (XPointer)&buf_s[2]); + } else { + _XimProcIMSetEventMask(im, (XPointer)&buf_s[2]); + } + return True; + } + return False; +} + +Private Bool +_XimSyncCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + + if ((major_opcode == XIM_SYNC_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + return True; + return False; +} + +Public Bool +_XimSync( + Xim im, + Xic ic) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_SYNC, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSyncCheck, (XPointer)ic); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(len); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimSyncCheck, (XPointer)ic); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else { + return False; + } + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + return True; +} + +Public Bool +_XimProcSyncReply( + Xim im, + Xic ic) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16); /* sizeof icid */ + + _XimSetHeader((XPointer)buf, XIM_SYNC_REPLY, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + return True; +} + +Public Bool +_XimRespSyncReply( + Xic ic, + BITMASK16 mode) +{ + if (mode & XimSYNCHRONUS) /* SYNC Request */ { + if (IS_FOCUSED(ic)) + MARK_NEED_SYNC_REPLY(ic); + else + _XimProcSyncReply((Xim)ic->core.im, ic); + } + + return True; +} + +Public Bool +_XimSyncCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + Xim im = (Xim)call_data; + Xic ic; + + if ((imid == im->private.proto.imid) + && (ic = _XimICOfXICID(im, icid))) { + (void)_XimProcSyncReply(im, ic); + return True; + } + return False; +} + +Private INT16 +_XimSetEventToWire( + XEvent *ev, + xEvent *event) +{ + if (!(_XimProtoEventToWire(ev, event, False))) + return 0; + event->u.u.sequenceNumber = + ((XAnyEvent *)ev)->serial & (unsigned long)0xffff; + return sz_xEvent; +} + +Private Bool +_XimForwardEventCore( + Xic ic, + XEvent *ev, + Bool sync) +{ + Xim im = (Xim)ic->core.im; + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + INT16 len; + + if (!(len = _XimSetEventToWire(ev, (xEvent *)&buf_s[4]))) + return False; /* X event */ + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + buf_s[2] = sync ? XimSYNCHRONUS : 0; /* flag */ + buf_s[3] = + (CARD16)((((XAnyEvent *)ev)->serial & ~((unsigned long)0xffff)) >> 16); + /* serial number */ + + len += sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16) /* sizeof icid */ + + sizeof(BITMASK16) /* sizeof flag */ + + sizeof(CARD16); /* sizeof serila number */ + + _XimSetHeader((XPointer)buf, XIM_FORWARD_EVENT, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + + if (sync) { + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimSyncCheck, (XPointer)ic); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(len); + ret_code = _XimRead(im, &len, preply, buf_size, + _XimSyncCheck, (XPointer)ic); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else { + return False; + } + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + } + return True; +} + +Public Bool +_XimForwardEvent( + Xic ic, + XEvent *ev, + Bool sync) +{ +#ifdef EXT_FORWARD + if (((ev->type == KeyPress) || (ev->type == KeyRelease))) + if (_XimExtForwardKeyEvent(ic, (XKeyEvent *)ev, sync)) + return True; +#endif + return _XimForwardEventCore(ic, ev, sync); +} + +Private void +_XimProcEvent( + Display *d, + Xic ic, + XEvent *ev, + CARD16 *buf) +{ + INT16 serial = buf[0]; + xEvent *xev = (xEvent *)&buf[1]; + + _XimProtoWireToEvent(ev, xev, False); + ev->xany.serial |= serial << 16; + ev->xany.send_event = False; + ev->xany.display = d; + MARK_FABLICATED(ic); + return; +} + +Private Bool +_XimForwardEventRecv( + Xim im, + Xic ic, + XPointer buf) +{ + CARD16 *buf_s = (CARD16 *)buf; + Display *d = im->core.display; + XEvent ev; + + _XimProcEvent(d, ic, &ev, &buf_s[1]); + + (void)_XimRespSyncReply(ic, buf_s[0]); + + XPutBackEvent(d, &ev); + + return True; +} + +Public Bool +_XimForwardEventCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + Xim im = (Xim)call_data; + Xic ic; + + if ((imid == im->private.proto.imid) + && (ic = _XimICOfXICID(im, icid))) { + (void)_XimForwardEventRecv(im, ic, (XPointer)&buf_s[2]); + return True; + } + return False; +} + +Private Bool +_XimRegisterTriggerkey( + Xim im, + XPointer buf) +{ + CARD32 *buf_l = (CARD32 *)buf; + CARD32 len; + CARD32 *key; + + if (IS_DYNAMIC_EVENT_FLOW(im)) /* already Dynamic event flow mode */ + return True; + + /* + * register onkeylist + */ + + len = buf_l[0]; /* length of on-keys */ + len += sizeof(INT32); /* sizeof length of on-keys */ + + if (!(key = (CARD32 *)Xmalloc(len))) { + _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); + return False; + } + memcpy((char *)key, (char *)buf_l, len); + im->private.proto.im_onkeylist = key; + + MARK_DYNAMIC_EVENT_FLOW(im); + + /* + * register offkeylist + */ + + buf_l = (CARD32 *)((char *)buf + len); + len = buf_l[0]; /* length of off-keys */ + len += sizeof(INT32); /* sizeof length of off-keys */ + + if (!(key = (CARD32 *)Xmalloc(len))) { + _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); + return False; + } + + memcpy((char *)key, (char *)buf_l, len); + im->private.proto.im_offkeylist = key; + + return True; +} + +Public Bool +_XimRegisterTriggerKeysCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + Xim im = (Xim)call_data; + + (void )_XimRegisterTriggerkey(im, (XPointer)&buf_s[2]); + return True; +} + +Public EVENTMASK +_XimGetWindowEventmask( + Xic ic) +{ + Xim im = (Xim )ic->core.im; + XWindowAttributes atr; + + if (!XGetWindowAttributes(im->core.display, ic->core.focus_window, &atr)) + return 0; + return (EVENTMASK)atr.your_event_mask; +} + + +Private Bool +_XimTriggerNotifyCheck( + Xim im, + INT16 len, + XPointer data, + XPointer arg) +{ + Xic ic = (Xic)arg; + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + CARD8 major_opcode = *((CARD8 *)data); + CARD8 minor_opcode = *((CARD8 *)data + 1); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + + if ((major_opcode == XIM_TRIGGER_NOTIFY_REPLY) + && (minor_opcode == 0) + && (imid == im->private.proto.imid) + && (icid == ic->private.proto.icid)) + return True; + if ((major_opcode == XIM_ERROR) + && (minor_opcode == 0) + && (buf_s[2] & XIM_IMID_VALID) + && (imid == im->private.proto.imid) + && (buf_s[2] & XIM_ICID_VALID) + && (icid == ic->private.proto.icid)) + return True; + return False; +} + +Public Bool +_XimTriggerNotify( + Xim im, + Xic ic, + int mode, + CARD32 idx) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + CARD32 *buf_l = (CARD32 *)&buf[XIM_HEADER_SIZE]; + CARD32 reply32[BUFSIZE/4]; + char *reply = (char *)reply32; + XPointer preply; + int buf_size; + int ret_code; + INT16 len; + EVENTMASK mask = _XimGetWindowEventmask(ic); + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[1] = ic->private.proto.icid; /* icid */ + buf_l[1] = mode; /* flag */ + buf_l[2] = idx; /* index of keys list */ + buf_l[3] = mask; /* select-event-mask */ + + len = sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16) /* sizeof icid */ + + sizeof(CARD32) /* sizeof flag */ + + sizeof(CARD32) /* sizeof index of key list */ + + sizeof(EVENTMASK); /* sizeof select-event-mask */ + + _XimSetHeader((XPointer)buf, XIM_TRIGGER_NOTIFY, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + buf_size = BUFSIZE; + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimTriggerNotifyCheck, (XPointer)ic); + if(ret_code == XIM_TRUE) { + preply = reply; + } else if(ret_code == XIM_OVERFLOW) { + if(len <= 0) { + preply = reply; + } else { + buf_size = len; + preply = (XPointer)Xmalloc(len); + ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, + _XimTriggerNotifyCheck, (XPointer)ic); + if(ret_code != XIM_TRUE) { + Xfree(preply); + return False; + } + } + } else { + return False; + } + buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); + if (*((CARD8 *)preply) == XIM_ERROR) { + _XimProcError(im, 0, (XPointer)&buf_s[3]); + if(reply != preply) + Xfree(preply); + return False; + } + if(reply != preply) + Xfree(preply); + return True; +} + +Private Bool +_XimRegCommitInfo( + Xic ic, + char *string, + int string_len, + KeySym *keysym, + int keysym_len) +{ + XimCommitInfo info; + + if (!(info = (XimCommitInfo)Xmalloc(sizeof(XimCommitInfoRec)))) + return False; + info->string = string; + info->string_len = string_len; + info->keysym = keysym; + info->keysym_len = keysym_len; + info->next = ic->private.proto.commit_info; + ic->private.proto.commit_info = info; + return True; +} + +Private void +_XimUnregCommitInfo( + Xic ic) +{ + XimCommitInfo info; + + if (!(info = ic->private.proto.commit_info)) + return; + + if (info->string) + Xfree(info->string); + if (info->keysym) + Xfree(info->keysym); + ic->private.proto.commit_info = info->next; + Xfree(info); + return; +} + +Public void +_XimFreeCommitInfo( + Xic ic) +{ + while (ic->private.proto.commit_info) + _XimUnregCommitInfo(ic); + return; +} + +Private Bool +_XimProcKeySym( + Xic ic, + CARD32 sym, + KeySym **xim_keysym, + int *xim_keysym_len) +{ + Xim im = (Xim)ic->core.im; + + if (!(*xim_keysym = (KeySym *)Xmalloc(sizeof(KeySym)))) { + _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); + return False; + } + + **xim_keysym = (KeySym)sym; + *xim_keysym_len = 1; + + return True; +} + +Private Bool +_XimProcCommit( + Xic ic, + BYTE *buf, + int len, + char **xim_string, + int *xim_string_len) +{ + Xim im = (Xim)ic->core.im; + char *string; + + if (!(string = (char *)Xmalloc(len + 1))) { + _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); + return False; + } + + (void)memcpy(string, (char *)buf, len); + string[len] = '\0'; + + *xim_string = string; + *xim_string_len = len; + return True; +} + +Private Bool +_XimCommitRecv( + Xim im, + Xic ic, + XPointer buf) +{ + CARD16 *buf_s = (CARD16 *)buf; + BITMASK16 flag = buf_s[0]; + XKeyEvent ev; + char *string = NULL; + int string_len = 0; + KeySym *keysym = NULL; + int keysym_len = 0; + + if ((flag & XimLookupBoth) == XimLookupChars) { + if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2], + (int)buf_s[1], &string, &string_len))) + return False; + + } else if ((flag & XimLookupBoth) == XimLookupKeySym) { + if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) + return False; + + } else if ((flag & XimLookupBoth) == XimLookupBoth) { + if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) + return False; + + if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5], + (int)buf_s[4], &string, &string_len))) { + Xfree(keysym); + return False; + } + } + + if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) { + if (string) + Xfree(string); + if (keysym) + Xfree(keysym); + _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); + return False; + } + + (void)_XimRespSyncReply(ic, flag); + + MARK_FABLICATED(ic); + + ev.type = KeyPress; + ev.send_event = False; + ev.display = im->core.display; + ev.window = ic->core.focus_window; + ev.keycode = 0; + ev.state = 0; + + XPutBackEvent(im->core.display, (XEvent *)&ev); + + return True; +} + +Public Bool +_XimCommitCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + XIMID imid = buf_s[0]; + XICID icid = buf_s[1]; + Xim im = (Xim)call_data; + Xic ic; + + if ((imid == im->private.proto.imid) + && (ic = _XimICOfXICID(im, icid))) { + (void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]); + return True; + } + return False; +} + +Public void +_XimProcError( + Xim im, + Xic ic, + XPointer data) +{ + return; +} + +Public Bool +_XimErrorCallback( + Xim xim, + INT16 len, + XPointer data, + XPointer call_data) +{ + CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); + BITMASK16 flag = buf_s[2]; + XIMID imid; + XICID icid; + Xim im = (Xim)call_data; + Xic ic = NULL; + + if (flag & XIM_IMID_VALID) { + imid = buf_s[0]; + if (imid != im->private.proto.imid) + return False; + } + if (flag & XIM_ICID_VALID) { + icid = buf_s[1]; + if (!(ic = _XimICOfXICID(im, icid))) + return False; + } + _XimProcError(im, ic, (XPointer)&buf_s[3]); + + return True; +} + +Public Bool +_XimError( + Xim im, + Xic ic, + CARD16 error_code, + INT16 detail_length, + CARD16 type, + char *detail) +{ + CARD32 buf32[BUFSIZE/4]; + CARD8 *buf = (CARD8 *)buf32; + CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; + INT16 len = 0; + + buf_s[0] = im->private.proto.imid; /* imid */ + buf_s[2] = XIM_IMID_VALID; /* flag */ + if (ic) { + buf_s[1] = ic->private.proto.icid; /* icid */ + buf_s[2] |= XIM_ICID_VALID; /* flag */ + } + buf_s[3] = error_code; /* Error Code */ + buf_s[4] = detail_length; /* length of error detail */ + buf_s[5] = type; /* type of error detail */ + + if (detail_length && detail) { + len = detail_length; + memcpy((char *)&buf_s[6], detail, len); + XIM_SET_PAD(&buf_s[6], len); + } + + len += sizeof(CARD16) /* sizeof imid */ + + sizeof(CARD16) /* sizeof icid */ + + sizeof(BITMASK16) /* sizeof flag */ + + sizeof(CARD16) /* sizeof error_code */ + + sizeof(INT16) /* sizeof length of detail */ + + sizeof(CARD16); /* sizeof type */ + + _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len); + if (!(_XimWrite(im, len, (XPointer)buf))) + return False; + _XimFlush(im); + return True; +} + +Private int +_Ximctsconvert( + XlcConv conv, + char *from, + int from_len, + char *to, + int to_len, + Status *state) +{ + int from_left; + int to_left; + int from_savelen; + int to_savelen; + int from_cnvlen; + int to_cnvlen; + char *from_buf; + char *to_buf; + char scratchbuf[BUFSIZ]; + Status tmp_state; + + if (!state) + state = &tmp_state; + + if (!conv || !from || !from_len) { + *state = XLookupNone; + return 0; + } + + /* Reset the converter. The CompoundText at 'from' starts in + initial state. */ + _XlcResetConverter(conv); + + from_left = from_len; + to_left = BUFSIZ; + from_cnvlen = 0; + to_cnvlen = 0; + for (;;) { + from_buf = &from[from_cnvlen]; + from_savelen = from_left; + to_buf = &scratchbuf[to_cnvlen]; + to_savelen = to_left; + if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, + (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { + *state = XLookupNone; + return 0; + } + from_cnvlen += (from_savelen - from_left); + to_cnvlen += (to_savelen - to_left); + if (from_left == 0) { + if (!to_cnvlen) { + *state = XLookupNone; + return 0; + } + break; + } + } + + if (!to || !to_len || (to_len < to_cnvlen)) { + *state = XBufferOverflow; + } else { + memcpy(to, scratchbuf, to_cnvlen); + *state = XLookupChars; + } + return to_cnvlen; +} + +Public int +_Ximctstombs(XIM xim, char *from, int from_len, + char *to, int to_len, Status *state) +{ + return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv, + from, from_len, to, to_len, state); +} + +Public int +_Ximctstowcs( + XIM xim, + char *from, + int from_len, + wchar_t *to, + int to_len, + Status *state) +{ + Xim im = (Xim)xim; + XlcConv conv = im->private.proto.ctow_conv; + int from_left; + int to_left; + int from_savelen; + int to_savelen; + int from_cnvlen; + int to_cnvlen; + char *from_buf; + wchar_t *to_buf; + wchar_t scratchbuf[BUFSIZ]; + Status tmp_state; + + if (!state) + state = &tmp_state; + + if (!conv || !from || !from_len) { + *state = XLookupNone; + return 0; + } + + /* Reset the converter. The CompoundText at 'from' starts in + initial state. */ + _XlcResetConverter(conv); + + from_left = from_len; + to_left = BUFSIZ; + from_cnvlen = 0; + to_cnvlen = 0; + for (;;) { + from_buf = &from[from_cnvlen]; + from_savelen = from_left; + to_buf = &scratchbuf[to_cnvlen]; + to_savelen = to_left; + if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, + (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { + *state = XLookupNone; + return 0; + } + from_cnvlen += (from_savelen - from_left); + to_cnvlen += (to_savelen - to_left); + if (from_left == 0) { + if (!to_cnvlen){ + *state = XLookupNone; + return 0; + } + break; + } + } + + if (!to || !to_len || (to_len < to_cnvlen)) { + *state = XBufferOverflow; + } else { + memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t)); + *state = XLookupChars; + } + return to_cnvlen; +} + +Public int +_Ximctstoutf8( + XIM xim, + char *from, + int from_len, + char *to, + int to_len, + Status *state) +{ + return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv, + from, from_len, to, to_len, state); +} + +Public int +_XimProtoMbLookupString( + XIC xic, + XKeyEvent *ev, + char *buffer, + int bytes, + KeySym *keysym, + Status *state) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + int ret; + Status tmp_state; + XimCommitInfo info; + + if (!IS_SERVER_CONNECTED(im)) + return 0; + + if (!state) + state = &tmp_state; + + if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */ + if (!(info = ic->private.proto.commit_info)) { + *state = XLookupNone; + return 0; + } + + ret = im->methods->ctstombs((XIM)im, info->string, + info->string_len, buffer, bytes, state); + if (*state == XBufferOverflow) + return ret; + if (keysym && (info->keysym && *(info->keysym))) { + *keysym = *(info->keysym); + if (*state == XLookupChars) + *state = XLookupBoth; + else + *state = XLookupKeySym; + } + _XimUnregCommitInfo(ic); + + } else if (ev->type == KeyPress) { + ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL); + if (ret > 0) { + if (ret > bytes) + *state = XBufferOverflow; + else if (keysym && *keysym != NoSymbol) + *state = XLookupBoth; + else + *state = XLookupChars; + } else { + if (keysym && *keysym != NoSymbol) + *state = XLookupKeySym; + else + *state = XLookupNone; + } + } else { + *state = XLookupNone; + ret = 0; + } + + return ret; +} + +Public int +_XimProtoWcLookupString( + XIC xic, + XKeyEvent *ev, + wchar_t *buffer, + int bytes, + KeySym *keysym, + Status *state) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + int ret; + Status tmp_state; + XimCommitInfo info; + + if (!IS_SERVER_CONNECTED(im)) + return 0; + + if (!state) + state = &tmp_state; + + if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ + if (!(info = ic->private.proto.commit_info)) { + *state = XLookupNone; + return 0; + } + + ret = im->methods->ctstowcs((XIM)im, info->string, + info->string_len, buffer, bytes, state); + if (*state == XBufferOverflow) + return ret; + if (keysym && (info->keysym && *(info->keysym))) { + *keysym = *(info->keysym); + if (*state == XLookupChars) + *state = XLookupBoth; + else + *state = XLookupKeySym; + } + _XimUnregCommitInfo(ic); + + } else if (ev->type == KeyPress) { + ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL); + if (ret > 0) { + if (ret > bytes) + *state = XBufferOverflow; + else if (keysym && *keysym != NoSymbol) + *state = XLookupBoth; + else + *state = XLookupChars; + } else { + if (keysym && *keysym != NoSymbol) + *state = XLookupKeySym; + else + *state = XLookupNone; + } + } else { + *state = XLookupNone; + ret = 0; + } + + return ret; +} + +Public int +_XimProtoUtf8LookupString( + XIC xic, + XKeyEvent *ev, + char *buffer, + int bytes, + KeySym *keysym, + Status *state) +{ + Xic ic = (Xic)xic; + Xim im = (Xim)ic->core.im; + int ret; + Status tmp_state; + XimCommitInfo info; + + if (!IS_SERVER_CONNECTED(im)) + return 0; + + if (!state) + state = &tmp_state; + + if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ + if (!(info = ic->private.proto.commit_info)) { + *state = XLookupNone; + return 0; + } + + ret = im->methods->ctstoutf8((XIM)im, info->string, + info->string_len, buffer, bytes, state); + if (*state == XBufferOverflow) + return ret; + if (keysym && (info->keysym && *(info->keysym))) { + *keysym = *(info->keysym); + if (*state == XLookupChars) + *state = XLookupBoth; + else + *state = XLookupKeySym; + } + _XimUnregCommitInfo(ic); + + } else if (ev->type == KeyPress) { + ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL); + if (ret > 0) { + if (ret > bytes) + *state = XBufferOverflow; + else if (keysym && *keysym != NoSymbol) + *state = XLookupBoth; + else + *state = XLookupChars; + } else { + if (keysym && *keysym != NoSymbol) + *state = XLookupKeySym; + else + *state = XLookupNone; + } + } else { + *state = XLookupNone; + ret = 0; + } + + return ret; +} diff --git a/libX11/modules/im/ximcp/imLcIm.c b/libX11/modules/im/ximcp/imLcIm.c index 430e318d2..904169830 100644 --- a/libX11/modules/im/ximcp/imLcIm.c +++ b/libX11/modules/im/ximcp/imLcIm.c @@ -1,729 +1,732 @@ -/****************************************************************** - - Copyright 1992, 1993, 1994 by FUJITSU LIMITED - Copyright 1993 by Digital Equipment Corporation - -Permission to use, copy, modify, distribute, and sell this software -and its documentation for any purpose is hereby granted without fee, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of FUJITSU LIMITED and -Digital Equipment Corporation not be used in advertising or publicity -pertaining to distribution of the software without specific, written -prior permission. FUJITSU LIMITED and Digital Equipment Corporation -makes no representations about the suitability of this software for -any purpose. It is provided "as is" without express or implied -warranty. - -FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR -ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - - Author: Takashi Fujiwara FUJITSU LIMITED - fujiwara@a80.tech.yk.fujitsu.co.jp - Modifier: Franky Ling Digital Equipment Corporation - frankyling@hgrd01.enet.dec.com - -******************************************************************/ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include - -#include -#include -#include -#include "Xlibint.h" -#include "Xlcint.h" -#include "XlcPublic.h" -#include "XlcPubI.h" -#include "Ximint.h" -#include -#include - -#ifdef COMPOSECACHE -# include -# include -# include -# include -#endif - - -#ifdef COMPOSECACHE - -/* include trailing '/' for cache directory, file prefix otherwise */ -#define XIM_GLOBAL_CACHE_DIR "/var/cache/libx11/compose/" -#define XIM_HOME_CACHE_DIR "/.compose-cache/" -#define XIM_CACHE_MAGIC ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24) -#define XIM_CACHE_VERSION 4 -#define XIM_CACHE_TREE_ALIGNMENT 4 - -#define XIM_HASH_PRIME_1 13 -#define XIM_HASH_PRIME_2 1234096939 - -typedef INT32 DTStructIndex; -struct _XimCacheStruct { - INT32 id; - INT32 version; - DTStructIndex tree; - DTStructIndex mb; - DTStructIndex wc; - DTStructIndex utf8; - DTStructIndex size; - DTIndex top; - DTIndex treeused; - DTCharIndex mbused; - DTCharIndex wcused; - DTCharIndex utf8used; - char fname[1]; - /* char encoding[1] */ -}; - -Private struct _XimCacheStruct* _XimCache_mmap = NULL; -Private DefTreeBase _XimCachedDefaultTreeBase; -Private int _XimCachedDefaultTreeRefcount = 0; - -#endif - - -Public Bool -_XimCheckIfLocalProcessing(Xim im) -{ - FILE *fp; - char *name; - - if(strcmp(im->core.im_name, "") == 0) { - name = _XlcFileName(im->core.lcd, COMPOSE_FILE); - if (name != (char *)NULL) { - fp = _XFopenFile (name, "r"); - Xfree(name); - if (fp != (FILE *)NULL) { - fclose(fp); - return(True); - } - } - return(False); - } else if(strcmp(im->core.im_name, "local") == 0 || - strcmp(im->core.im_name, "none" ) == 0 ) { - return(True); - } - return(False); -} - -Private void -XimFreeDefaultTree( - DefTreeBase *b) -{ - if (!b) return; - if (b->tree == NULL) return; -#ifdef COMPOSECACHE - if (b->tree == _XimCachedDefaultTreeBase.tree) { - _XimCachedDefaultTreeRefcount--; - /* No deleting, it's a cache after all. */ - return; - } -#endif - Xfree (b->tree); - if (b->mb) Xfree (b->mb); - if (b->wc) Xfree (b->wc); - if (b->utf8) Xfree (b->utf8); - b->tree = NULL; - b->mb = NULL; - b->wc = NULL; - b->utf8 = NULL; - b->treeused = b->treesize = 0; - b->mbused = b->mbsize = 0; - b->wcused = b->wcsize = 0; - b->utf8used = b->utf8size = 0; -} - -Public void -_XimLocalIMFree( - Xim im) -{ - XimFreeDefaultTree(&im->private.local.base); - im->private.local.top = 0; - - if(im->core.im_resources) { - Xfree(im->core.im_resources); - im->core.im_resources = NULL; - } - if(im->core.ic_resources) { - Xfree(im->core.ic_resources); - im->core.ic_resources = NULL; - } - if(im->core.im_values_list) { - Xfree(im->core.im_values_list); - im->core.im_values_list = NULL; - } - if(im->core.ic_values_list) { - Xfree(im->core.ic_values_list); - im->core.ic_values_list = NULL; - } - if(im->core.styles) { - Xfree(im->core.styles); - im->core.styles = NULL; - } - if(im->core.res_name) { - Xfree(im->core.res_name); - im->core.res_name = NULL; - } - if(im->core.res_class) { - Xfree(im->core.res_class); - im->core.res_class = NULL; - } - if(im->core.im_name) { - Xfree(im->core.im_name); - im->core.im_name = NULL; - } - if (im->private.local.ctom_conv) { - _XlcCloseConverter(im->private.local.ctom_conv); - im->private.local.ctom_conv = NULL; - } - if (im->private.local.ctow_conv) { - _XlcCloseConverter(im->private.local.ctow_conv); - im->private.local.ctow_conv = NULL; - } - if (im->private.local.ctoutf8_conv) { - _XlcCloseConverter(im->private.local.ctoutf8_conv); - im->private.local.ctoutf8_conv = NULL; - } - if (im->private.local.cstomb_conv) { - _XlcCloseConverter(im->private.local.cstomb_conv); - im->private.local.cstomb_conv = NULL; - } - if (im->private.local.cstowc_conv) { - _XlcCloseConverter(im->private.local.cstowc_conv); - im->private.local.cstowc_conv = NULL; - } - if (im->private.local.cstoutf8_conv) { - _XlcCloseConverter(im->private.local.cstoutf8_conv); - im->private.local.cstoutf8_conv = NULL; - } - if (im->private.local.ucstoc_conv) { - _XlcCloseConverter(im->private.local.ucstoc_conv); - im->private.local.ucstoc_conv = NULL; - } - if (im->private.local.ucstoutf8_conv) { - _XlcCloseConverter(im->private.local.ucstoutf8_conv); - im->private.local.ucstoutf8_conv = NULL; - } - return; -} - -Private Status -_XimLocalCloseIM( - XIM xim) -{ - Xim im = (Xim)xim; - XIC ic; - XIC next; - - ic = im->core.ic_chain; - im->core.ic_chain = NULL; - while (ic) { - (*ic->methods->destroy) (ic); - next = ic->core.next; - Xfree ((char *) ic); - ic = next; - } - _XimLocalIMFree(im); - _XimDestroyIMStructureList(im); - return(True); -} - -Public char * -_XimLocalGetIMValues( - XIM xim, - XIMArg *values) -{ - Xim im = (Xim)xim; - XimDefIMValues im_values; - - _XimGetCurrentIMValues(im, &im_values); - return(_XimGetIMValueData(im, (XPointer)&im_values, values, - im->core.im_resources, im->core.im_num_resources)); -} - -Public char * -_XimLocalSetIMValues( - XIM xim, - XIMArg *values) -{ - Xim im = (Xim)xim; - XimDefIMValues im_values; - char *name = (char *)NULL; - - _XimGetCurrentIMValues(im, &im_values); - name = _XimSetIMValueData(im, (XPointer)&im_values, values, - im->core.im_resources, im->core.im_num_resources); - _XimSetCurrentIMValues(im, &im_values); - return(name); -} - - -#ifdef COMPOSECACHE - -Private Bool -_XimReadCachedDefaultTree( - int fd_cache, - const char *name, - const char *encoding, - DTStructIndex size) -{ - struct _XimCacheStruct* m; - int namelen = strlen (name) + 1; - int encodinglen = strlen (encoding) + 1; - - m = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd_cache, 0); - if (m == NULL || m == MAP_FAILED) - return False; - assert (m->id == XIM_CACHE_MAGIC); - assert (m->version == XIM_CACHE_VERSION); - if (size != m->size || - size < XOffsetOf (struct _XimCacheStruct, fname) + namelen + encodinglen) { - fprintf (stderr, "Ignoring broken XimCache %s [%s]\n", name, encoding); - munmap (m, size); - return False; - } - if (strncmp (name, m->fname, namelen) != 0) { - /* m->fname may *not* be terminated - but who cares here */ - fprintf (stderr, "Filename hash clash - expected %s, got %s\n", - name, m->fname); - munmap (m, size); - return False; - } - if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) { - /* m->fname+namelen may *not* be terminated - but who cares here */ - fprintf (stderr, "Enoding hash clash - expected %s, got %s\n", - encoding, m->fname + namelen); - munmap (m, size); - return False; - } - _XimCache_mmap = m; - _XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree); - _XimCachedDefaultTreeBase.mb = (((char *) m) + m->mb); - _XimCachedDefaultTreeBase.wc = (wchar_t *) (((char *) m) + m->wc); - _XimCachedDefaultTreeBase.utf8 = (((char *) m) + m->utf8); - _XimCachedDefaultTreeBase.treeused = m->treeused; - _XimCachedDefaultTreeBase.mbused = m->mbused; - _XimCachedDefaultTreeBase.wcused = m->wcused; - _XimCachedDefaultTreeBase.utf8used = m->utf8used; - /* treesize etc. is ignored because only used during parsing */ - _XimCachedDefaultTreeRefcount = 0; -/* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */ - return True; -} - -Private unsigned int strToHash ( - const char *name) -{ - unsigned int hash = 0; - while (*name) - hash = hash * XIM_HASH_PRIME_1 + *(unsigned const char *)name++; - return hash % XIM_HASH_PRIME_2; -} - - -/* Returns read-only fd of cache file, -1 if none. - * Sets *res to cache filename if safe. Sets *size to file size of cache. */ -Private int _XimCachedFileName ( - const char *dir, const char *name, - const char *intname, const char *encoding, - uid_t uid, int isglobal, char **res, off_t *size) -{ - struct stat st_name, st; - int fd; - unsigned int len, hash, hash2; - struct _XimCacheStruct *m; - /* There are some races here with 'dir', but we are either in our own home - * or the global cache dir, and not inside some public writable dir */ -/* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */ - if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode) - || stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode) || st.st_uid != uid - || (st.st_mode & 0022) != 0000) { - *res = NULL; - return -1; - } - len = strlen (dir); - hash = strToHash (intname); - hash2 = strToHash (encoding); - *res = Xmalloc (len + 1 + 27 + 1); /* Max VERSION 9999 */ - - if (len == 0 || dir [len-1] != '/') - sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), - XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2); - else - sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), - XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2); - -/* fprintf (stderr, "-> %s\n", *res); */ - if ( (fd = _XOpenFile (*res, O_RDONLY)) == -1) - return -1; - - if (fstat (fd, &st) == -1) { - Xfree (*res); - *res = NULL; - close (fd); - return -1; - } - *size = st.st_size; - - if (! S_ISREG (st.st_mode) || st.st_uid != uid - || (st.st_mode & 0022) != 0000 || st.st_mtime <= st_name.st_mtime - || (st.st_mtime < time (NULL) - 24*60*60 && ! isglobal)) { - - close (fd); - if (unlink (*res) != 0) { - Xfree (*res); - *res = NULL; /* cache is not safe */ - } - return -1; - } - - m = mmap (NULL, sizeof (struct _XimCacheStruct), PROT_READ, MAP_PRIVATE, - fd, 0); - if (m == NULL || m == MAP_FAILED) { - close (fd); - Xfree (*res); - *res = NULL; - return -1; - } - if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC) { - munmap (m, sizeof (struct _XimCacheStruct)); - close (fd); - fprintf (stderr, "Ignoring broken XimCache %s\n", *res); - Xfree (*res); - *res = NULL; - return -1; - } - if (m->version != XIM_CACHE_VERSION) { - munmap (m, sizeof (struct _XimCacheStruct)); - close (fd); - if (unlink (*res) != 0) { - Xfree (*res); - *res = NULL; /* cache is not safe */ - } - return -1; - } - munmap (m, sizeof (struct _XimCacheStruct)); - - return fd; -} - - -Private Bool _XimLoadCache ( - int fd, - const char *name, - const char *encoding, - off_t size, - Xim im) -{ - if (_XimCache_mmap || - _XimReadCachedDefaultTree (fd, name, encoding, size)) { - _XimCachedDefaultTreeRefcount++; - memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase, - sizeof (_XimCachedDefaultTreeBase)); - im->private.local.top = _XimCache_mmap->top; - return True; - } - - return False; -} - - -Private void -_XimWriteCachedDefaultTree( - const char *name, - const char *encoding, - const char *cachename, - Xim im) -{ - int fd; - FILE *fp; - struct _XimCacheStruct *m; - int msize = (XOffsetOf(struct _XimCacheStruct, fname) - + strlen(name) + strlen(encoding) + 2 - + XIM_CACHE_TREE_ALIGNMENT-1) & -XIM_CACHE_TREE_ALIGNMENT; - DefTreeBase *b = &im->private.local.base; - - if (! b->tree && ! (b->tree = Xmalloc (sizeof(DefTree))) ) - return; - if (! b->mb && ! (b->mb = Xmalloc (1)) ) - return; - if (! b->wc && ! (b->wc = Xmalloc (sizeof(wchar_t))) ) - return; - if (! b->utf8 && ! (b->utf8 = Xmalloc (1)) ) - return; - - /* First entry is always unused */ - memset (b->tree, 0, sizeof(DefTree)); - b->mb[0] = 0; - b->wc[0] = 0; - b->utf8[0] = 0; - - m = Xmalloc (msize); - memset (m, 0, msize); - m->id = XIM_CACHE_MAGIC; - m->version = XIM_CACHE_VERSION; - m->top = im->private.local.top; - m->treeused = b->treeused; - m->mbused = b->mbused; - m->wcused = b->wcused; - m->utf8used = b->utf8used; - /* Tree first, then wide chars, then the rest due to alignment */ - m->tree = msize; - m->wc = msize + sizeof (DefTree) * m->treeused; - m->mb = m->wc + sizeof (wchar_t) * m->wcused; - m->utf8 = m->mb + m->mbused; - m->size = m->utf8 + m->utf8used; - strcpy (m->fname, name); - strcpy (m->fname+strlen(name)+1, encoding); - - /* This STILL might be racy on NFS */ - if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL, - 0600)) < 0) - return; - if (! (fp = fdopen (fd, "wb")) ) { - close (fd); - return; - } - fwrite (m, msize, 1, fp); - fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp); - fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp); - fwrite (im->private.local.base.mb, 1, m->mbused, fp); - fwrite (im->private.local.base.utf8, 1, m->utf8used, fp); - if (fclose (fp) != 0) - unlink (cachename); - _XimCache_mmap = m; - memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base, - sizeof (_XimCachedDefaultTreeBase)); -/* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */ -} - -#endif - - -Private void -_XimCreateDefaultTree( - Xim im) -{ - FILE *fp = NULL; - char *name, *tmpname = NULL, *intname; - char *cachename = NULL; - /* Should use getpwent() instead of $HOME (cross-platform?) */ - char *home = getenv("HOME"); - char *cachedir = NULL; - char *tmpcachedir = NULL; - int hl = home ? strlen (home) : 0; -#ifdef COMPOSECACHE - const char *encoding = nl_langinfo (CODESET); - uid_t euid = geteuid (); - gid_t egid = getegid (); - int cachefd = -1; - off_t size; -#endif - - name = getenv("XCOMPOSEFILE"); - if (name == (char *) NULL) { - if (home != (char *) NULL) { - tmpname = name = Xmalloc(hl + 10 + 1); - if (name != (char *) NULL) { - int fd; - strcpy(name, home); - strcpy(name + hl, "/.XCompose"); - if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) { - Xfree (name); - name = tmpname = NULL; - } else - close (fd); - } - } - } - - if (name == (char *) NULL) { - tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE); - } - intname = name; - -#ifdef COMPOSECACHE - if (getuid () == euid && getgid () == egid && euid != 0) { - char *c; - /* Usage: XCOMPOSECACHE=[=] - * cachedir: directory of cache files - * filename: internally used name for cache file */ - cachedir = getenv("XCOMPOSECACHE"); - if (cachedir && (c = strchr (cachedir, '='))) { - tmpcachedir = strdup (cachedir); - intname = tmpcachedir + (c-cachedir) + 1; - tmpcachedir[c-cachedir] = '\0'; - cachedir = tmpcachedir; - } - } - - if (! cachedir) { - cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname, - encoding, 0, 1, &cachename, &size); - if (cachefd != -1) { - if (_XimLoadCache (cachefd, intname, encoding, size, im)) { - if (tmpcachedir) - Xfree (tmpcachedir); - if (tmpname) - Xfree (tmpname); - if (cachename) - Xfree (cachename); - close (cachefd); - return; - } - close (cachefd); - } - if (cachename) - Xfree (cachename); - cachename = NULL; - } - - if (getuid () == euid && getgid () == egid && euid != 0 && home) { - - if (! cachedir) { - tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1); - strcpy (cachedir, home); - strcat (cachedir, XIM_HOME_CACHE_DIR); - } - cachefd = _XimCachedFileName (cachedir, name, intname, encoding, - euid, 0, &cachename, &size); - if (cachefd != -1) { - if (_XimLoadCache (cachefd, intname, encoding, size, im)) { - if (tmpcachedir) - Xfree (tmpcachedir); - if (tmpname) - Xfree (tmpname); - if (cachename) - Xfree (cachename); - close (cachefd); - return; - } - close (cachefd); - } - } -#endif - - if (! (fp = _XFopenFile (name, "r"))) { - if (tmpcachedir) - Xfree (tmpcachedir); - if (tmpname) - Xfree (tmpname); - if (cachename) - Xfree (cachename); - return; - } - _XimParseStringFile(fp, im); - fclose(fp); - -#ifdef COMPOSECACHE - if (cachename) { - assert (euid != 0); - _XimWriteCachedDefaultTree (intname, encoding, cachename, im); - } -#endif - - if (tmpcachedir) - Xfree (tmpcachedir); - if (tmpname) - Xfree (tmpname); - if (cachename) - Xfree (cachename); -} - -Private XIMMethodsRec Xim_im_local_methods = { - _XimLocalCloseIM, /* close */ - _XimLocalSetIMValues, /* set_values */ - _XimLocalGetIMValues, /* get_values */ - _XimLocalCreateIC, /* create_ic */ - _XimLcctstombs, /* ctstombs */ - _XimLcctstowcs, /* ctstowcs */ - _XimLcctstoutf8 /* ctstoutf8 */ -}; - -Public Bool -_XimLocalOpenIM( - Xim im) -{ - XLCd lcd = im->core.lcd; - XlcConv conv; - XimDefIMValues im_values; - XimLocalPrivateRec* private = &im->private.local; - - _XimInitialResourceInfo(); - if(_XimSetIMResourceList(&im->core.im_resources, - &im->core.im_num_resources) == False) { - goto Open_Error; - } - if(_XimSetICResourceList(&im->core.ic_resources, - &im->core.ic_num_resources) == False) { - goto Open_Error; - } - - _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); - - _XimGetCurrentIMValues(im, &im_values); - if(_XimSetLocalIMDefaults(im, (XPointer)&im_values, - im->core.im_resources, im->core.im_num_resources) == False) { - goto Open_Error; - } - _XimSetCurrentIMValues(im, &im_values); - - if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte))) - goto Open_Error; - private->ctom_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar))) - goto Open_Error; - private->ctow_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNUtf8String))) - goto Open_Error; - private->ctoutf8_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) - goto Open_Error; - private->cstomb_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) - goto Open_Error; - private->cstowc_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) - goto Open_Error; - private->cstoutf8_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) - goto Open_Error; - private->ucstoc_conv = conv; - - if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) - goto Open_Error; - private->ucstoutf8_conv = conv; - - private->base.treeused = 1; - private->base.mbused = 1; - private->base.wcused = 1; - private->base.utf8used = 1; - - _XimCreateDefaultTree(im); - - im->methods = &Xim_im_local_methods; - private->current_ic = (XIC)NULL; - - return(True); - -Open_Error : - _XimLocalIMFree(im); - return(False); -} +/****************************************************************** + + Copyright 1992, 1993, 1994 by FUJITSU LIMITED + Copyright 1993 by Digital Equipment Corporation + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without fee, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of FUJITSU LIMITED and +Digital Equipment Corporation not be used in advertising or publicity +pertaining to distribution of the software without specific, written +prior permission. FUJITSU LIMITED and Digital Equipment Corporation +makes no representations about the suitability of this software for +any purpose. It is provided "as is" without express or implied +warranty. + +FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION DISCLAIM ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +FUJITSU LIMITED AND DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR +ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + Author: Takashi Fujiwara FUJITSU LIMITED + fujiwara@a80.tech.yk.fujitsu.co.jp + Modifier: Franky Ling Digital Equipment Corporation + frankyling@hgrd01.enet.dec.com + +******************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include +#include "Xlibint.h" +#include "Xlcint.h" +#include "XlcPublic.h" +#include "XlcPubI.h" +#include "Ximint.h" +#include +#include + +#ifdef COMPOSECACHE +# include +# include +# include +# include +#endif + + +#ifdef COMPOSECACHE + +/* include trailing '/' for cache directory, file prefix otherwise */ +#define XIM_GLOBAL_CACHE_DIR "/var/cache/libx11/compose/" +#define XIM_HOME_CACHE_DIR "/.compose-cache/" +#define XIM_CACHE_MAGIC ('X' | 'i'<<8 | 'm'<<16 | 'C'<<24) +#define XIM_CACHE_VERSION 4 +#define XIM_CACHE_TREE_ALIGNMENT 4 + +#define XIM_HASH_PRIME_1 13 +#define XIM_HASH_PRIME_2 1234096939 + +typedef INT32 DTStructIndex; +struct _XimCacheStruct { + INT32 id; + INT32 version; + DTStructIndex tree; + DTStructIndex mb; + DTStructIndex wc; + DTStructIndex utf8; + DTStructIndex size; + DTIndex top; + DTIndex treeused; + DTCharIndex mbused; + DTCharIndex wcused; + DTCharIndex utf8used; + char fname[1]; + /* char encoding[1] */ +}; + +Private struct _XimCacheStruct* _XimCache_mmap = NULL; +Private DefTreeBase _XimCachedDefaultTreeBase; +Private int _XimCachedDefaultTreeRefcount = 0; + +#endif + + +Public Bool +_XimCheckIfLocalProcessing(Xim im) +{ + FILE *fp; + char *name; + + if(strcmp(im->core.im_name, "") == 0) { + name = _XlcFileName(im->core.lcd, COMPOSE_FILE); + if (name != (char *)NULL) { + fp = _XFopenFile (name, "r"); + Xfree(name); + if (fp != (FILE *)NULL) { + fclose(fp); + return(True); + } + } + return(False); + } else if(strcmp(im->core.im_name, "local") == 0 || + strcmp(im->core.im_name, "none" ) == 0 ) { + return(True); + } + return(False); +} + +Private void +XimFreeDefaultTree( + DefTreeBase *b) +{ + if (!b) return; + if (b->tree == NULL) return; +#ifdef COMPOSECACHE + if (b->tree == _XimCachedDefaultTreeBase.tree) { + _XimCachedDefaultTreeRefcount--; + /* No deleting, it's a cache after all. */ + return; + } +#endif + Xfree (b->tree); + if (b->mb) Xfree (b->mb); + if (b->wc) Xfree (b->wc); + if (b->utf8) Xfree (b->utf8); + b->tree = NULL; + b->mb = NULL; + b->wc = NULL; + b->utf8 = NULL; + b->treeused = b->treesize = 0; + b->mbused = b->mbsize = 0; + b->wcused = b->wcsize = 0; + b->utf8used = b->utf8size = 0; +} + +Public void +_XimLocalIMFree( + Xim im) +{ + XimFreeDefaultTree(&im->private.local.base); + im->private.local.top = 0; + + if(im->core.im_resources) { + Xfree(im->core.im_resources); + im->core.im_resources = NULL; + } + if(im->core.ic_resources) { + Xfree(im->core.ic_resources); + im->core.ic_resources = NULL; + } + if(im->core.im_values_list) { + Xfree(im->core.im_values_list); + im->core.im_values_list = NULL; + } + if(im->core.ic_values_list) { + Xfree(im->core.ic_values_list); + im->core.ic_values_list = NULL; + } + if(im->core.styles) { + Xfree(im->core.styles); + im->core.styles = NULL; + } + if(im->core.res_name) { + Xfree(im->core.res_name); + im->core.res_name = NULL; + } + if(im->core.res_class) { + Xfree(im->core.res_class); + im->core.res_class = NULL; + } + if(im->core.im_name) { + Xfree(im->core.im_name); + im->core.im_name = NULL; + } + if (im->private.local.ctom_conv) { + _XlcCloseConverter(im->private.local.ctom_conv); + im->private.local.ctom_conv = NULL; + } + if (im->private.local.ctow_conv) { + _XlcCloseConverter(im->private.local.ctow_conv); + im->private.local.ctow_conv = NULL; + } + if (im->private.local.ctoutf8_conv) { + _XlcCloseConverter(im->private.local.ctoutf8_conv); + im->private.local.ctoutf8_conv = NULL; + } + if (im->private.local.cstomb_conv) { + _XlcCloseConverter(im->private.local.cstomb_conv); + im->private.local.cstomb_conv = NULL; + } + if (im->private.local.cstowc_conv) { + _XlcCloseConverter(im->private.local.cstowc_conv); + im->private.local.cstowc_conv = NULL; + } + if (im->private.local.cstoutf8_conv) { + _XlcCloseConverter(im->private.local.cstoutf8_conv); + im->private.local.cstoutf8_conv = NULL; + } + if (im->private.local.ucstoc_conv) { + _XlcCloseConverter(im->private.local.ucstoc_conv); + im->private.local.ucstoc_conv = NULL; + } + if (im->private.local.ucstoutf8_conv) { + _XlcCloseConverter(im->private.local.ucstoutf8_conv); + im->private.local.ucstoutf8_conv = NULL; + } + return; +} + +Private Status +_XimLocalCloseIM( + XIM xim) +{ + Xim im = (Xim)xim; + XIC ic; + XIC next; + + ic = im->core.ic_chain; + im->core.ic_chain = NULL; + while (ic) { + (*ic->methods->destroy) (ic); + next = ic->core.next; + Xfree ((char *) ic); + ic = next; + } + _XimLocalIMFree(im); + _XimDestroyIMStructureList(im); + return(True); +} + +Public char * +_XimLocalGetIMValues( + XIM xim, + XIMArg *values) +{ + Xim im = (Xim)xim; + XimDefIMValues im_values; + + _XimGetCurrentIMValues(im, &im_values); + return(_XimGetIMValueData(im, (XPointer)&im_values, values, + im->core.im_resources, im->core.im_num_resources)); +} + +Public char * +_XimLocalSetIMValues( + XIM xim, + XIMArg *values) +{ + Xim im = (Xim)xim; + XimDefIMValues im_values; + char *name = (char *)NULL; + + _XimGetCurrentIMValues(im, &im_values); + name = _XimSetIMValueData(im, (XPointer)&im_values, values, + im->core.im_resources, im->core.im_num_resources); + _XimSetCurrentIMValues(im, &im_values); + return(name); +} + + +#ifdef COMPOSECACHE + +Private Bool +_XimReadCachedDefaultTree( + int fd_cache, + const char *name, + const char *encoding, + DTStructIndex size) +{ + struct _XimCacheStruct* m; + int namelen = strlen (name) + 1; + int encodinglen = strlen (encoding) + 1; + + m = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd_cache, 0); + if (m == NULL || m == MAP_FAILED) + return False; + assert (m->id == XIM_CACHE_MAGIC); + assert (m->version == XIM_CACHE_VERSION); + if (size != m->size || + size < XOffsetOf (struct _XimCacheStruct, fname) + namelen + encodinglen) { + fprintf (stderr, "Ignoring broken XimCache %s [%s]\n", name, encoding); + munmap (m, size); + return False; + } + if (strncmp (name, m->fname, namelen) != 0) { + /* m->fname may *not* be terminated - but who cares here */ + fprintf (stderr, "Filename hash clash - expected %s, got %s\n", + name, m->fname); + munmap (m, size); + return False; + } + if (strncmp (encoding, m->fname + namelen, encodinglen) != 0) { + /* m->fname+namelen may *not* be terminated - but who cares here */ + fprintf (stderr, "Enoding hash clash - expected %s, got %s\n", + encoding, m->fname + namelen); + munmap (m, size); + return False; + } + _XimCache_mmap = m; + _XimCachedDefaultTreeBase.tree = (DefTree *) (((char *) m) + m->tree); + _XimCachedDefaultTreeBase.mb = (((char *) m) + m->mb); + _XimCachedDefaultTreeBase.wc = (wchar_t *) (((char *) m) + m->wc); + _XimCachedDefaultTreeBase.utf8 = (((char *) m) + m->utf8); + _XimCachedDefaultTreeBase.treeused = m->treeused; + _XimCachedDefaultTreeBase.mbused = m->mbused; + _XimCachedDefaultTreeBase.wcused = m->wcused; + _XimCachedDefaultTreeBase.utf8used = m->utf8used; + /* treesize etc. is ignored because only used during parsing */ + _XimCachedDefaultTreeRefcount = 0; +/* fprintf (stderr, "read cached tree at %p: %s\n", (void *) m, name); */ + return True; +} + +Private unsigned int strToHash ( + const char *name) +{ + unsigned int hash = 0; + while (*name) + hash = hash * XIM_HASH_PRIME_1 + *(unsigned const char *)name++; + return hash % XIM_HASH_PRIME_2; +} + + +/* Returns read-only fd of cache file, -1 if none. + * Sets *res to cache filename if safe. Sets *size to file size of cache. */ +Private int _XimCachedFileName ( + const char *dir, const char *name, + const char *intname, const char *encoding, + uid_t uid, int isglobal, char **res, off_t *size) +{ + struct stat st_name, st; + int fd; + unsigned int len, hash, hash2; + struct _XimCacheStruct *m; + /* There are some races here with 'dir', but we are either in our own home + * or the global cache dir, and not inside some public writable dir */ +/* fprintf (stderr, "XimCachedFileName for dir %s name %s intname %s encoding %s uid %d\n", dir, name, intname, encoding, uid); */ + if (stat (name, &st_name) == -1 || ! S_ISREG (st_name.st_mode) + || stat (dir, &st) == -1 || ! S_ISDIR (st.st_mode) || st.st_uid != uid + || (st.st_mode & 0022) != 0000) { + *res = NULL; + return -1; + } + len = strlen (dir); + hash = strToHash (intname); + hash2 = strToHash (encoding); + *res = Xmalloc (len + 1 + 27 + 1); /* Max VERSION 9999 */ + + if (len == 0 || dir [len-1] != '/') + sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), + XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2); + else + sprintf (*res, "%s%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), + XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2); + +/* fprintf (stderr, "-> %s\n", *res); */ + if ( (fd = _XOpenFile (*res, O_RDONLY)) == -1) + return -1; + + if (fstat (fd, &st) == -1) { + Xfree (*res); + *res = NULL; + close (fd); + return -1; + } + *size = st.st_size; + + if (! S_ISREG (st.st_mode) || st.st_uid != uid + || (st.st_mode & 0022) != 0000 || st.st_mtime <= st_name.st_mtime + || (st.st_mtime < time (NULL) - 24*60*60 && ! isglobal)) { + + close (fd); + if (unlink (*res) != 0) { + Xfree (*res); + *res = NULL; /* cache is not safe */ + } + return -1; + } + + m = mmap (NULL, sizeof (struct _XimCacheStruct), PROT_READ, MAP_PRIVATE, + fd, 0); + if (m == NULL || m == MAP_FAILED) { + close (fd); + Xfree (*res); + *res = NULL; + return -1; + } + if (*size < sizeof (struct _XimCacheStruct) || m->id != XIM_CACHE_MAGIC) { + munmap (m, sizeof (struct _XimCacheStruct)); + close (fd); + fprintf (stderr, "Ignoring broken XimCache %s\n", *res); + Xfree (*res); + *res = NULL; + return -1; + } + if (m->version != XIM_CACHE_VERSION) { + munmap (m, sizeof (struct _XimCacheStruct)); + close (fd); + if (unlink (*res) != 0) { + Xfree (*res); + *res = NULL; /* cache is not safe */ + } + return -1; + } + munmap (m, sizeof (struct _XimCacheStruct)); + + return fd; +} + + +Private Bool _XimLoadCache ( + int fd, + const char *name, + const char *encoding, + off_t size, + Xim im) +{ + if (_XimCache_mmap || + _XimReadCachedDefaultTree (fd, name, encoding, size)) { + _XimCachedDefaultTreeRefcount++; + memcpy (&im->private.local.base, &_XimCachedDefaultTreeBase, + sizeof (_XimCachedDefaultTreeBase)); + im->private.local.top = _XimCache_mmap->top; + return True; + } + + return False; +} + + +Private void +_XimWriteCachedDefaultTree( + const char *name, + const char *encoding, + const char *cachename, + Xim im) +{ + int fd; + FILE *fp; + struct _XimCacheStruct *m; + int msize = (XOffsetOf(struct _XimCacheStruct, fname) + + strlen(name) + strlen(encoding) + 2 + + XIM_CACHE_TREE_ALIGNMENT-1) & -XIM_CACHE_TREE_ALIGNMENT; + DefTreeBase *b = &im->private.local.base; + + if (! b->tree && ! (b->tree = Xmalloc (sizeof(DefTree))) ) + return; + if (! b->mb && ! (b->mb = Xmalloc (1)) ) + return; + if (! b->wc && ! (b->wc = Xmalloc (sizeof(wchar_t))) ) + return; + if (! b->utf8 && ! (b->utf8 = Xmalloc (1)) ) + return; + + /* First entry is always unused */ + memset (b->tree, 0, sizeof(DefTree)); + b->mb[0] = 0; + b->wc[0] = 0; + b->utf8[0] = 0; + + m = Xmalloc (msize); + memset (m, 0, msize); + m->id = XIM_CACHE_MAGIC; + m->version = XIM_CACHE_VERSION; + m->top = im->private.local.top; + m->treeused = b->treeused; + m->mbused = b->mbused; + m->wcused = b->wcused; + m->utf8used = b->utf8used; + /* Tree first, then wide chars, then the rest due to alignment */ + m->tree = msize; + m->wc = msize + sizeof (DefTree) * m->treeused; + m->mb = m->wc + sizeof (wchar_t) * m->wcused; + m->utf8 = m->mb + m->mbused; + m->size = m->utf8 + m->utf8used; + strcpy (m->fname, name); + strcpy (m->fname+strlen(name)+1, encoding); + + /* This STILL might be racy on NFS */ + if ( (fd = _XOpenFileMode (cachename, O_WRONLY | O_CREAT | O_EXCL, + 0600)) < 0) { + Xfree(m); + return; + } + if (! (fp = fdopen (fd, "wb")) ) { + close (fd); + Xfree(m); + return; + } + fwrite (m, msize, 1, fp); + fwrite (im->private.local.base.tree, sizeof(DefTree), m->treeused, fp); + fwrite (im->private.local.base.wc, sizeof(wchar_t), m->wcused, fp); + fwrite (im->private.local.base.mb, 1, m->mbused, fp); + fwrite (im->private.local.base.utf8, 1, m->utf8used, fp); + if (fclose (fp) != 0) + unlink (cachename); + _XimCache_mmap = m; + memcpy (&_XimCachedDefaultTreeBase, &im->private.local.base, + sizeof (_XimCachedDefaultTreeBase)); +/* fprintf (stderr, "wrote tree %s size %ld to %s\n", name, m->size, cachename); */ +} + +#endif + + +Private void +_XimCreateDefaultTree( + Xim im) +{ + FILE *fp = NULL; + char *name, *tmpname = NULL, *intname; + char *cachename = NULL; + /* Should use getpwent() instead of $HOME (cross-platform?) */ + char *home = getenv("HOME"); + char *cachedir = NULL; + char *tmpcachedir = NULL; + int hl = home ? strlen (home) : 0; +#ifdef COMPOSECACHE + const char *encoding = nl_langinfo (CODESET); + uid_t euid = geteuid (); + gid_t egid = getegid (); + int cachefd = -1; + off_t size; +#endif + + name = getenv("XCOMPOSEFILE"); + if (name == (char *) NULL) { + if (home != (char *) NULL) { + tmpname = name = Xmalloc(hl + 10 + 1); + if (name != (char *) NULL) { + int fd; + strcpy(name, home); + strcpy(name + hl, "/.XCompose"); + if ( (fd = _XOpenFile (name, O_RDONLY)) < 0) { + Xfree (name); + name = tmpname = NULL; + } else + close (fd); + } + } + } + + if (name == (char *) NULL) { + tmpname = name = _XlcFileName(im->core.lcd, COMPOSE_FILE); + } + intname = name; + +#ifdef COMPOSECACHE + if (getuid () == euid && getgid () == egid && euid != 0) { + char *c; + /* Usage: XCOMPOSECACHE=[=] + * cachedir: directory of cache files + * filename: internally used name for cache file */ + cachedir = getenv("XCOMPOSECACHE"); + if (cachedir && (c = strchr (cachedir, '='))) { + tmpcachedir = strdup (cachedir); + intname = tmpcachedir + (c-cachedir) + 1; + tmpcachedir[c-cachedir] = '\0'; + cachedir = tmpcachedir; + } + } + + if (! cachedir) { + cachefd = _XimCachedFileName (XIM_GLOBAL_CACHE_DIR, name, intname, + encoding, 0, 1, &cachename, &size); + if (cachefd != -1) { + if (_XimLoadCache (cachefd, intname, encoding, size, im)) { + if (tmpcachedir) + Xfree (tmpcachedir); + if (tmpname) + Xfree (tmpname); + if (cachename) + Xfree (cachename); + close (cachefd); + return; + } + close (cachefd); + } + if (cachename) + Xfree (cachename); + cachename = NULL; + } + + if (getuid () == euid && getgid () == egid && euid != 0 && home) { + + if (! cachedir) { + tmpcachedir = cachedir = Xmalloc (hl+strlen(XIM_HOME_CACHE_DIR)+1); + strcpy (cachedir, home); + strcat (cachedir, XIM_HOME_CACHE_DIR); + } + cachefd = _XimCachedFileName (cachedir, name, intname, encoding, + euid, 0, &cachename, &size); + if (cachefd != -1) { + if (_XimLoadCache (cachefd, intname, encoding, size, im)) { + if (tmpcachedir) + Xfree (tmpcachedir); + if (tmpname) + Xfree (tmpname); + if (cachename) + Xfree (cachename); + close (cachefd); + return; + } + close (cachefd); + } + } +#endif + + if (! (fp = _XFopenFile (name, "r"))) { + if (tmpcachedir) + Xfree (tmpcachedir); + if (tmpname) + Xfree (tmpname); + if (cachename) + Xfree (cachename); + return; + } + _XimParseStringFile(fp, im); + fclose(fp); + +#ifdef COMPOSECACHE + if (cachename) { + assert (euid != 0); + _XimWriteCachedDefaultTree (intname, encoding, cachename, im); + } +#endif + + if (tmpcachedir) + Xfree (tmpcachedir); + if (tmpname) + Xfree (tmpname); + if (cachename) + Xfree (cachename); +} + +Private XIMMethodsRec Xim_im_local_methods = { + _XimLocalCloseIM, /* close */ + _XimLocalSetIMValues, /* set_values */ + _XimLocalGetIMValues, /* get_values */ + _XimLocalCreateIC, /* create_ic */ + _XimLcctstombs, /* ctstombs */ + _XimLcctstowcs, /* ctstowcs */ + _XimLcctstoutf8 /* ctstoutf8 */ +}; + +Public Bool +_XimLocalOpenIM( + Xim im) +{ + XLCd lcd = im->core.lcd; + XlcConv conv; + XimDefIMValues im_values; + XimLocalPrivateRec* private = &im->private.local; + + _XimInitialResourceInfo(); + if(_XimSetIMResourceList(&im->core.im_resources, + &im->core.im_num_resources) == False) { + goto Open_Error; + } + if(_XimSetICResourceList(&im->core.ic_resources, + &im->core.ic_num_resources) == False) { + goto Open_Error; + } + + _XimSetIMMode(im->core.im_resources, im->core.im_num_resources); + + _XimGetCurrentIMValues(im, &im_values); + if(_XimSetLocalIMDefaults(im, (XPointer)&im_values, + im->core.im_resources, im->core.im_num_resources) == False) { + goto Open_Error; + } + _XimSetCurrentIMValues(im, &im_values); + + if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNMultiByte))) + goto Open_Error; + private->ctom_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNWideChar))) + goto Open_Error; + private->ctow_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCompoundText, lcd, XlcNUtf8String))) + goto Open_Error; + private->ctoutf8_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNMultiByte))) + goto Open_Error; + private->cstomb_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNWideChar))) + goto Open_Error; + private->cstowc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNCharSet, lcd, XlcNUtf8String))) + goto Open_Error; + private->cstoutf8_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNChar))) + goto Open_Error; + private->ucstoc_conv = conv; + + if (!(conv = _XlcOpenConverter(lcd, XlcNUcsChar, lcd, XlcNUtf8String))) + goto Open_Error; + private->ucstoutf8_conv = conv; + + private->base.treeused = 1; + private->base.mbused = 1; + private->base.wcused = 1; + private->base.utf8used = 1; + + _XimCreateDefaultTree(im); + + im->methods = &Xim_im_local_methods; + private->current_ic = (XIC)NULL; + + return(True); + +Open_Error : + _XimLocalIMFree(im); + return(False); +} diff --git a/libX11/modules/im/ximcp/imRmAttr.c b/libX11/modules/im/ximcp/imRmAttr.c index 7503905b2..27dcbc9cd 100644 --- a/libX11/modules/im/ximcp/imRmAttr.c +++ b/libX11/modules/im/ximcp/imRmAttr.c @@ -1433,8 +1433,10 @@ _XimGetAttributeID( bzero((char *)res, res_len); values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len; - if (!(tmp = (XPointer)Xmalloc(values_len))) + if (!(tmp = (XPointer)Xmalloc(values_len))) { + Xfree(res); return False; + } bzero(tmp, values_len); values_list = (XIMValuesList *)tmp; @@ -1480,8 +1482,10 @@ _XimGetAttributeID( bzero((char *)res, res_len); values_len = sizeof(XIMValuesList) + (sizeof(char **) * n) + names_len; - if (!(tmp = (XPointer)Xmalloc(values_len))) + if (!(tmp = (XPointer)Xmalloc(values_len))) { + Xfree(res); return False; + } bzero(tmp, values_len); values_list = (XIMValuesList *)tmp; diff --git a/libX11/modules/om/generic/omGeneric.c b/libX11/modules/om/generic/omGeneric.c index c78c0a9d6..44143ac2e 100644 --- a/libX11/modules/om/generic/omGeneric.c +++ b/libX11/modules/om/generic/omGeneric.c @@ -575,7 +575,7 @@ get_rotate_fontname( } if(field_num < CHARSET_ENCODING_FIELD) - return NULL; + goto free_pattern; /* Pixel Size field : fields[6] */ for(ptr = fields[PIXEL_SIZE_FIELD - 1] ; ptr && *ptr; ptr++) { @@ -584,9 +584,7 @@ get_rotate_fontname( strcpy(pattern, font_name); return(pattern); } - if(pattern) - Xfree(pattern); - return NULL; + goto free_pattern; } } pixel_size = atoi(fields[PIXEL_SIZE_FIELD - 1]); @@ -605,11 +603,11 @@ get_rotate_fontname( /* Max XLFD length is 255 */ if (len > XLFD_MAX_LEN) - return NULL; + goto free_pattern; rotate_font_ptr = (char *)Xmalloc(len + 1); if(!rotate_font_ptr) - return NULL; + goto free_pattern; rotate_font_ptr[0] = '\0'; @@ -619,8 +617,8 @@ get_rotate_fontname( strcat(rotate_font_ptr, fields[field_num]); } - if(pattern) - Xfree(pattern); +free_pattern: + Xfree(pattern); return rotate_font_ptr; } @@ -1932,8 +1930,10 @@ read_EncodingInfo( } else len = strlen(buf); font_data->name = (char *) Xmalloc(len + 1); - if (font_data->name == NULL) + if (font_data->name == NULL) { + Xfree(font_data); return NULL; + } strncpy(font_data->name, buf,len); font_data->name[len] = 0; if (bufptr && _XlcCompareISOLatin1(bufptr, "GL") == 0) @@ -2117,22 +2117,24 @@ init_om( if (required_list == NULL) return False; - bufptr = (char *) Xmalloc(length); - if (bufptr == NULL) { - Xfree(required_list); - return False; - } - om->core.required_charset.charset_list = required_list; om->core.required_charset.charset_count = gen->data_num; count = gen->data_num; data = gen->data; - for ( ; count-- > 0; data++) { - strcpy(bufptr, data->font_data->name); - *required_list++ = bufptr; - bufptr += strlen(bufptr) + 1; + if (count > 0) { + bufptr = (char *) Xmalloc(length); + if (bufptr == NULL) { + Xfree(required_list); + return False; + } + + for ( ; count-- > 0; data++) { + strcpy(bufptr, data->font_data->name); + *required_list++ = bufptr; + bufptr += strlen(bufptr) + 1; + } } /* orientation list */ diff --git a/libX11/src/FSWrap.c b/libX11/src/FSWrap.c index a94709365..94d94fbe9 100644 --- a/libX11/src/FSWrap.c +++ b/libX11/src/FSWrap.c @@ -131,7 +131,7 @@ copy_string_list( char **string_list_ret, **list_src, **list_dst, *dst; int length, count; - if (string_list == NULL) + if (string_list == NULL || list_count == 0) return (char **) NULL; string_list_ret = (char **) Xmalloc(sizeof(char *) * list_count); diff --git a/libX11/src/RdBitF.c b/libX11/src/RdBitF.c index 07967aebe..ab7d800d3 100644 --- a/libX11/src/RdBitF.c +++ b/libX11/src/RdBitF.c @@ -216,6 +216,11 @@ XReadBitmapFileData ( *ptr=value; } } + + /* If we got to this point, we read a full bitmap file. Break so we don't + * start reading another one from the same file and leak the memory + * allocated for the previous one. */ + break; } /* end while */ fclose(fstream); diff --git a/libX11/src/xcms/LRGB.c b/libX11/src/xcms/LRGB.c index 2dca82ee8..5ecb7d120 100644 --- a/libX11/src/xcms/LRGB.c +++ b/libX11/src/xcms/LRGB.c @@ -653,7 +653,7 @@ LINEAR_RGB_InitSCCData( */ if (!(pScreenData = (LINEAR_RGB_SCCData *) Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) { - return(XcmsFailure); + goto Free_property_return; } /* copy matrices */ memcpy((char *)pScreenData, (char *)pScreenDefaultData, @@ -663,7 +663,7 @@ LINEAR_RGB_InitSCCData( if (!(pNewMap = (XcmsIntensityMap *) Xcalloc (1, sizeof(XcmsIntensityMap)))) { Xfree((char *)pScreenData); - return(XcmsFailure); + goto Free_property_return; } pNewMap->visualID = visualID; pNewMap->screenData = (XPointer)pScreenData; @@ -802,7 +802,7 @@ FreeBlueTbl: Xfree((char *)pScreenData->pBlueTbl); FreeGreenTblElements: - Xfree((char *)pScreenData->pBlueTbl->pBase); + Xfree((char *)pScreenData->pGreenTbl->pBase); FreeGreenTbl: Xfree((char *)pScreenData->pGreenTbl); @@ -817,7 +817,7 @@ Free_property_return: Xfree ((char *)property_return); FreeSCCData: - Xfree((char *)pScreenData); + Xfree((char *)pScreenDefaultData); pPerScrnInfo->state = XcmsInitNone; return(XcmsFailure); } diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 5c6ac445c..ddd860813 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1,1937 +1,1952 @@ -dnl Process this file with autoconf to create configure. - -AC_PREREQ([2.59]) - -dnl Versioning - scrape the version from configs/default -m4_define([mesa_version], - [m4_esyscmd([${MAKE-make} -s -f bin/version.mk version | tr -d '\n' | tr -d '\r'])]) -m4_ifval(mesa_version,, - [m4_fatal([Failed to get the Mesa version from `make -f bin/version.mk version`])]) - -dnl Tell the user about autoconf.html in the --help output -m4_divert_once([HELP_END], [ -See docs/autoconf.html for more details on the options for Mesa.]) - -AC_INIT([Mesa],[mesa_version], - [https://bugs.freedesktop.org/enter_bug.cgi?product=Mesa]) -AC_CONFIG_AUX_DIR([bin]) -AC_CANONICAL_HOST - -dnl Versions for external dependencies -LIBDRM_REQUIRED=2.4.24 -LIBDRM_RADEON_REQUIRED=2.4.24 -LIBDRM_INTEL_REQUIRED=2.4.24 -DRI2PROTO_REQUIRED=2.1 -GLPROTO_REQUIRED=1.4.11 -LIBDRM_XORG_REQUIRED=2.4.24 -LIBKMS_XORG_REQUIRED=1.0.0 - -dnl Check for progs -AC_PROG_CPP -AC_PROG_CC -AC_PROG_CXX -AC_CHECK_PROGS([MAKE], [gmake make]) -AC_CHECK_PROGS([PYTHON2], [python2 python]) -AC_PATH_PROG([MKDEP], [makedepend]) -AC_PATH_PROG([SED], [sed]) - -if test "x$MKDEP" = "x"; then - AC_MSG_ERROR([makedepend is required to build Mesa]) -fi - -dnl Our fallback install-sh is a symlink to minstall. Use the existing -dnl configuration in that case. -AC_PROG_INSTALL -test "x$INSTALL" = "x$ac_install_sh" && INSTALL='$(MINSTALL)' - -dnl We need a POSIX shell for parts of the build. Assume we have one -dnl in most cases. -case "$host_os" in -solaris*) - # Solaris /bin/sh is too old/non-POSIX compliant - AC_PATH_PROGS(POSIX_SHELL, [ksh93 ksh sh]) - SHELL="$POSIX_SHELL" - ;; -esac - -dnl clang is mostly GCC-compatible, but its version is much lower, -dnl so we have to check for it. -AC_MSG_CHECKING([if compiling with clang]) - -AC_COMPILE_IFELSE( -[AC_LANG_PROGRAM([], [[ -#ifndef __clang__ - not clang -#endif -]])], -[CLANG=yes], [CLANG=no]) - -AC_MSG_RESULT([$CLANG]) - -dnl If we're using GCC, make sure that it is at least version 3.3.0. Older -dnl versions are explictly not supported. -if test "x$GCC" = xyes -a "x$CLANG" = xno; then - AC_MSG_CHECKING([whether gcc version is sufficient]) - major=0 - minor=0 - - GCC_VERSION=`$CC -dumpversion` - if test $? -eq 0; then - major=`echo $GCC_VERSION | cut -d. -f1` - minor=`echo $GCC_VERSION | cut -d. -f1` - fi - - if test $major -lt 3 -o $major -eq 3 -a $minor -lt 3 ; then - AC_MSG_RESULT([no]) - AC_MSG_ERROR([If using GCC, version 3.3.0 or later is required.]) - else - AC_MSG_RESULT([yes]) - fi -fi - - -MKDEP_OPTIONS=-fdepend -dnl Ask gcc where it's keeping its secret headers -if test "x$GCC" = xyes; then - for dir in include include-fixed; do - GCC_INCLUDES=`$CC -print-file-name=$dir` - if test "x$GCC_INCLUDES" != x && \ - test "$GCC_INCLUDES" != "$dir" && \ - test -d "$GCC_INCLUDES"; then - MKDEP_OPTIONS="$MKDEP_OPTIONS -I$GCC_INCLUDES" - fi - done -fi -AC_SUBST([MKDEP_OPTIONS]) - -dnl Make sure the pkg-config macros are defined -m4_ifndef([PKG_PROG_PKG_CONFIG], - [m4_fatal([Could not locate the pkg-config autoconf macros. - These are usually located in /usr/share/aclocal/pkg.m4. If your macros - are in a different location, try setting the environment variable - ACLOCAL="aclocal -I/other/macro/dir" before running autoreconf.])]) -PKG_PROG_PKG_CONFIG() - -dnl LIB_DIR - library basename -LIB_DIR=`echo $libdir | $SED 's%.*/%%'` -AC_SUBST([LIB_DIR]) - -dnl Cache LDFLAGS so we can add EXTRA_LIB_PATH and restore it later -_SAVE_LDFLAGS="$LDFLAGS" -AC_ARG_VAR([EXTRA_LIB_PATH],[Extra -L paths for the linker]) -AC_SUBST([EXTRA_LIB_PATH]) - -dnl Cache CPPFLAGS so we can add *_INCLUDES and restore it later -_SAVE_CPPFLAGS="$CPPFLAGS" -AC_ARG_VAR([X11_INCLUDES],[Extra -I paths for X11 headers]) -AC_SUBST([X11_INCLUDES]) - -dnl Compiler macros -DEFINES="" -AC_SUBST([DEFINES]) -case "$host_os" in -linux*|*-gnu*|gnu*) - DEFINES="$DEFINES -D_GNU_SOURCE -DPTHREADS" - ;; -solaris*) - DEFINES="$DEFINES -DPTHREADS -DSVR4" - ;; -cygwin*) - DEFINES="$DEFINES -DPTHREADS" - ;; -esac - -dnl Add flags for gcc and g++ -if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99" - if test "x$CLANG" = "xno"; then - CFLAGS="$CFLAGS -ffast-math" - fi - - # Enable -fvisibility=hidden if using a gcc that supports it - save_CFLAGS="$CFLAGS" - AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden]) - VISIBILITY_CFLAGS="-fvisibility=hidden" - CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" - AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), - [VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]); - - # Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed. - CFLAGS=$save_CFLAGS - - # Work around aliasing bugs - developers should comment this out - CFLAGS="$CFLAGS -fno-strict-aliasing" -fi -if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -Wall" - - # Enable -fvisibility=hidden if using a gcc that supports it - save_CXXFLAGS="$CXXFLAGS" - AC_MSG_CHECKING([whether $CXX supports -fvisibility=hidden]) - VISIBILITY_CXXFLAGS="-fvisibility=hidden" - CXXFLAGS="$CXXFLAGS $VISIBILITY_CXXFLAGS" - AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), - [VISIBILITY_CXXFLAGS="" ; AC_MSG_RESULT([no])]); - - # Restore CXXFLAGS; VISIBILITY_CXXFLAGS are added to it where needed. - CXXFLAGS=$save_CXXFLAGS - - # Work around aliasing bugs - developers should comment this out - CXXFLAGS="$CXXFLAGS -fno-strict-aliasing" -fi - -AC_SUBST([VISIBILITY_CFLAGS]) -AC_SUBST([VISIBILITY_CXXFLAGS]) - -dnl These should be unnecessary, but let the user set them if they want -AC_ARG_VAR([OPT_FLAGS], [Additional optimization flags for the compiler. - Default is to use CFLAGS.]) -AC_ARG_VAR([ARCH_FLAGS], [Additional architecture specific flags for the - compiler. Default is to use CFLAGS.]) -AC_SUBST([OPT_FLAGS]) -AC_SUBST([ARCH_FLAGS]) - -dnl -dnl Hacks to enable 32 or 64 bit build -dnl -AC_ARG_ENABLE([32-bit], - [AS_HELP_STRING([--enable-32-bit], - [build 32-bit libraries @<:@default=auto@:>@])], - [enable_32bit="$enableval"], - [enable_32bit=auto] -) -if test "x$enable_32bit" = xyes; then - if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -m32" - ARCH_FLAGS="$ARCH_FLAGS -m32" - fi - if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -m32" - fi -fi -AC_ARG_ENABLE([64-bit], - [AS_HELP_STRING([--enable-64-bit], - [build 64-bit libraries @<:@default=auto@:>@])], - [enable_64bit="$enableval"], - [enable_64bit=auto] -) -if test "x$enable_64bit" = xyes; then - if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -m64" - fi - if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -m64" - fi -fi - -dnl -dnl shared/static libraries, mimic libtool options -dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static], - [build static libraries @<:@default=disabled@:>@])], - [enable_static="$enableval"], - [enable_static=no] -) -case "x$enable_static" in -xyes|xno ) ;; -x ) enable_static=no ;; -* ) - AC_MSG_ERROR([Static library option '$enable_static' is not a valid]) - ;; -esac -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--disable-shared], - [build shared libraries @<:@default=enabled@:>@])], - [enable_shared="$enableval"], - [enable_shared=yes] -) -case "x$enable_shared" in -xyes|xno ) ;; -x ) enable_shared=yes ;; -* ) - AC_MSG_ERROR([Shared library option '$enable_shared' is not a valid]) - ;; -esac - -dnl Can't have static and shared libraries, default to static if user -dnl explicitly requested. If both disabled, set to static since shared -dnl was explicitly requirested. -case "x$enable_static$enable_shared" in -xyesyes ) - AC_MSG_WARN([Can't build static and shared libraries, disabling shared]) - enable_shared=no - ;; -xnono ) - AC_MSG_WARN([Can't disable both static and shared libraries, enabling static]) - enable_static=yes - ;; -esac - -dnl -dnl mklib options -dnl -AC_ARG_VAR([MKLIB_OPTIONS],[Options for the Mesa library script, mklib]) -if test "$enable_static" = yes; then - MKLIB_OPTIONS="$MKLIB_OPTIONS -static" -fi -AC_SUBST([MKLIB_OPTIONS]) - -dnl -dnl other compiler options -dnl -AC_ARG_ENABLE([debug], - [AS_HELP_STRING([--enable-debug], - [use debug compiler flags and macros @<:@default=disabled@:>@])], - [enable_debug="$enableval"], - [enable_debug=no] -) -if test "x$enable_debug" = xyes; then - DEFINES="$DEFINES -DDEBUG" - if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -g" - fi - if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -g" - fi -fi - -dnl -dnl library names -dnl -LIB_PREFIX_GLOB='lib' -LIB_VERSION_SEPARATOR='.' -if test "$enable_static" = yes; then - LIB_EXTENSION='a' -else - case "$host_os" in - darwin* ) - LIB_EXTENSION='dylib' ;; - cygwin* ) - dnl prefix can be 'cyg' or 'lib' - LIB_PREFIX_GLOB='???' - LIB_VERSION_SEPARATOR='-' - LIB_EXTENSION='dll' ;; - aix* ) - LIB_EXTENSION='a' ;; - * ) - LIB_EXTENSION='so' ;; - esac -fi - -GL_LIB_NAME='lib$(GL_LIB).'${LIB_EXTENSION} -GLU_LIB_NAME='lib$(GLU_LIB).'${LIB_EXTENSION} -GLUT_LIB_NAME='lib$(GLUT_LIB).'${LIB_EXTENSION} -GLW_LIB_NAME='lib$(GLW_LIB).'${LIB_EXTENSION} -OSMESA_LIB_NAME='lib$(OSMESA_LIB).'${LIB_EXTENSION} -EGL_LIB_NAME='lib$(EGL_LIB).'${LIB_EXTENSION} -GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION} -GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION} -VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION} -GLAPI_LIB_NAME='lib$(GLAPI_LIB).'${LIB_EXTENSION} -WAYLAND_EGL_LIB_NAME='lib$(WAYLAND_EGL_LIB).'${LIB_EXTENSION} - -GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLUT_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLUT_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLW_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLW_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -OSMESA_LIB_GLOB=${LIB_PREFIX_GLOB}'$(OSMESA_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -GLAPI_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLAPI_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' -WAYLAND_EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(WAYLAND_EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' - -AC_SUBST([GL_LIB_NAME]) -AC_SUBST([GLU_LIB_NAME]) -AC_SUBST([GLUT_LIB_NAME]) -AC_SUBST([GLW_LIB_NAME]) -AC_SUBST([OSMESA_LIB_NAME]) -AC_SUBST([EGL_LIB_NAME]) -AC_SUBST([GLESv1_CM_LIB_NAME]) -AC_SUBST([GLESv2_LIB_NAME]) -AC_SUBST([VG_LIB_NAME]) -AC_SUBST([GLAPI_LIB_NAME]) -AC_SUBST([WAYLAND_EGL_LIB_NAME]) - -AC_SUBST([GL_LIB_GLOB]) -AC_SUBST([GLU_LIB_GLOB]) -AC_SUBST([GLUT_LIB_GLOB]) -AC_SUBST([GLW_LIB_GLOB]) -AC_SUBST([OSMESA_LIB_GLOB]) -AC_SUBST([EGL_LIB_GLOB]) -AC_SUBST([GLESv1_CM_LIB_GLOB]) -AC_SUBST([GLESv2_LIB_GLOB]) -AC_SUBST([VG_LIB_GLOB]) -AC_SUBST([GLAPI_LIB_GLOB]) -AC_SUBST([WAYLAND_EGL_LIB_GLOB]) - -dnl -dnl Arch/platform-specific settings -dnl -AC_ARG_ENABLE([asm], - [AS_HELP_STRING([--disable-asm], - [disable assembly usage @<:@default=enabled on supported plaforms@:>@])], - [enable_asm="$enableval"], - [enable_asm=yes] -) -asm_arch="" -ASM_FLAGS="" -MESA_ASM_SOURCES="" -GLAPI_ASM_SOURCES="" -AC_MSG_CHECKING([whether to enable assembly]) -test "x$enable_asm" = xno && AC_MSG_RESULT([no]) -# disable if cross compiling on x86/x86_64 since we must run gen_matypes -if test "x$enable_asm" = xyes && test "x$cross_compiling" = xyes; then - case "$host_cpu" in - i?86 | x86_64) - enable_asm=no - AC_MSG_RESULT([no, cross compiling]) - ;; - esac -fi -# check for supported arches -if test "x$enable_asm" = xyes; then - case "$host_cpu" in - i?86) - case "$host_os" in - linux* | *freebsd* | dragonfly* | *netbsd*) - test "x$enable_64bit" = xyes && asm_arch=x86_64 || asm_arch=x86 - ;; - esac - ;; - x86_64) - case "$host_os" in - linux* | *freebsd* | dragonfly* | *netbsd*) - test "x$enable_32bit" = xyes && asm_arch=x86 || asm_arch=x86_64 - ;; - esac - ;; - powerpc) - case "$host_os" in - linux*) - asm_arch=ppc - ;; - esac - ;; - sparc*) - case "$host_os" in - linux*) - asm_arch=sparc - ;; - esac - ;; - esac - - case "$asm_arch" in - x86) - ASM_FLAGS="-DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM" - MESA_ASM_SOURCES='$(X86_SOURCES)' - GLAPI_ASM_SOURCES='$(X86_API)' - AC_MSG_RESULT([yes, x86]) - ;; - x86_64) - ASM_FLAGS="-DUSE_X86_64_ASM" - MESA_ASM_SOURCES='$(X86-64_SOURCES)' - GLAPI_ASM_SOURCES='$(X86-64_API)' - AC_MSG_RESULT([yes, x86_64]) - ;; - ppc) - ASM_FLAGS="-DUSE_PPC_ASM -DUSE_VMX_ASM" - MESA_ASM_SOURCES='$(PPC_SOURCES)' - AC_MSG_RESULT([yes, ppc]) - ;; - sparc) - ASM_FLAGS="-DUSE_SPARC_ASM" - MESA_ASM_SOURCES='$(SPARC_SOURCES)' - GLAPI_ASM_SOURCES='$(SPARC_API)' - AC_MSG_RESULT([yes, sparc]) - ;; - *) - AC_MSG_RESULT([no, platform not supported]) - ;; - esac -fi -AC_SUBST([ASM_FLAGS]) -AC_SUBST([MESA_ASM_SOURCES]) -AC_SUBST([GLAPI_ASM_SOURCES]) - -dnl PIC code macro -MESA_PIC_FLAGS - -dnl Check to see if dlopen is in default libraries (like Solaris, which -dnl has it in libc), or if libdl is needed to get it. -AC_CHECK_FUNC([dlopen], [], - [AC_CHECK_LIB([dl], [dlopen], [DLOPEN_LIBS="-ldl"])]) -AC_SUBST([DLOPEN_LIBS]) - -dnl See if posix_memalign is available -AC_CHECK_FUNC([posix_memalign], [DEFINES="$DEFINES -DHAVE_POSIX_MEMALIGN"]) - -dnl SELinux awareness. -AC_ARG_ENABLE([selinux], - [AS_HELP_STRING([--enable-selinux], - [Build SELinux-aware Mesa @<:@default=disabled@:>@])], - [MESA_SELINUX="$enableval"], - [MESA_SELINUX=no]) -if test "x$enable_selinux" = "xyes"; then - AC_CHECK_HEADER([selinux/selinux.h],[], - [AC_MSG_ERROR([SELinux headers not found])]) - AC_CHECK_LIB([selinux],[is_selinux_enabled],[], - [AC_MSG_ERROR([SELinux library not found])]) - SELINUX_LIBS="-lselinux" - DEFINES="$DEFINES -DMESA_SELINUX" -fi - -dnl Determine which APIs to support -AC_ARG_ENABLE([opengl], - [AS_HELP_STRING([--disable-opengl], - [disable support for standard OpenGL API @<:@default=no@:>@])], - [enable_opengl="$enableval"], - [enable_opengl=yes]) -AC_ARG_ENABLE([gles1], - [AS_HELP_STRING([--enable-gles1], - [enable support for OpenGL ES 1.x API @<:@default=no@:>@])], - [enable_gles1="$enableval"], - [enable_gles1=no]) -AC_ARG_ENABLE([gles2], - [AS_HELP_STRING([--enable-gles2], - [enable support for OpenGL ES 2.x API @<:@default=no@:>@])], - [enable_gles2="$enableval"], - [enable_gles2=no]) -AC_ARG_ENABLE([gles-overlay], - [AS_HELP_STRING([--enable-gles-overlay], - [DEPRECATED. Same as --enable-gles1 and --enable-gles2])], - [enable_gles1="$enableval"; enable_gles2="$enableval"], - []) - -AC_ARG_ENABLE([openvg], - [AS_HELP_STRING([--enable-openvg], - [enable support for OpenVG API @<:@default=no@:>@])], - [enable_openvg="$enableval"], - [enable_openvg=no]) - -dnl smooth the transition; should be removed eventually -if test "x$enable_openvg" = xno; then - case "x$with_state_trackers" in - x*vega*) - AC_MSG_WARN([vega state tracker is enabled without --enable-openvg]) - enable_openvg=yes - ;; - esac -fi - -if test "x$enable_opengl" = xno -a \ - "x$enable_gles1" = xno -a \ - "x$enable_gles2" = xno -a \ - "x$enable_openvg" = xno; then - AC_MSG_ERROR([at least one API should be enabled]) -fi - -API_DEFINES="" -if test "x$enable_opengl" = xno; then - API_DEFINES="$API_DEFINES -DFEATURE_GL=0" -else - API_DEFINES="$API_DEFINES -DFEATURE_GL=1" -fi -if test "x$enable_gles1" = xyes; then - API_DEFINES="$API_DEFINES -DFEATURE_ES1=1" -fi -if test "x$enable_gles2" = xyes; then - API_DEFINES="$API_DEFINES -DFEATURE_ES2=1" -fi -AC_SUBST([API_DEFINES]) - -AC_ARG_ENABLE([shared-glapi], - [AS_HELP_STRING([--enable-shared-glapi], - [EXPERIMENTAL. Enable shared glapi for OpenGL @<:@default=no@:>@])], - [enable_shared_glapi="$enableval"], - [enable_shared_glapi=no]) - -SHARED_GLAPI="0" -if test "x$enable_shared_glapi" = xyes; then - SHARED_GLAPI="1" -fi -AC_SUBST([SHARED_GLAPI]) - -dnl -dnl Driver configuration. Options are xlib, dri and osmesa right now. -dnl More later: fbdev, ... -dnl -default_driver="xlib" - -case "$host_os" in -linux*) - case "$host_cpu" in - i*86|x86_64|powerpc*|sparc*) default_driver="dri";; - esac - ;; -*freebsd* | dragonfly* | *netbsd*) - case "$host_cpu" in - i*86|x86_64|powerpc*|sparc*) default_driver="dri";; - esac - ;; -esac - -if test "x$enable_opengl" = xno; then - default_driver="no" -fi - -AC_ARG_WITH([driver], - [AS_HELP_STRING([--with-driver=DRIVER], - [driver for Mesa: xlib,dri,osmesa @<:@default=dri when available, or xlib@:>@])], - [mesa_driver="$withval"], - [mesa_driver="$default_driver"]) -dnl Check for valid option -case "x$mesa_driver" in -xxlib|xdri|xosmesa) - if test "x$enable_opengl" = xno; then - AC_MSG_ERROR([Driver '$mesa_driver' requires OpenGL enabled]) - fi - ;; -xno) - ;; -*) - AC_MSG_ERROR([Driver '$mesa_driver' is not a valid option]) - ;; -esac - -dnl -dnl Driver specific build directories -dnl - -dnl this variable will be prepended to SRC_DIRS and is not exported -CORE_DIRS="" - -SRC_DIRS="" -GLU_DIRS="sgi" -GALLIUM_DIRS="auxiliary drivers state_trackers" -GALLIUM_TARGET_DIRS="" -GALLIUM_WINSYS_DIRS="sw" -GALLIUM_DRIVERS_DIRS="softpipe failover galahad trace rbug noop identity" -GALLIUM_STATE_TRACKERS_DIRS="" - -# build shared-glapi if enabled for OpenGL or if OpenGL ES is enabled -case "x$enable_shared_glapi$enable_gles1$enable_gles2" in -x*yes*) - CORE_DIRS="$CORE_DIRS mapi/shared-glapi" - ;; -esac - -# build glapi if OpenGL is enabled -if test "x$enable_opengl" = xyes; then - CORE_DIRS="$CORE_DIRS mapi/glapi" -fi - -# build es1api if OpenGL ES 1.x is enabled -if test "x$enable_gles1" = xyes; then - CORE_DIRS="$CORE_DIRS mapi/es1api" -fi - -# build es2api if OpenGL ES 2.x is enabled -if test "x$enable_gles2" = xyes; then - CORE_DIRS="$CORE_DIRS mapi/es2api" -fi - -# build vgapi if OpenVG is enabled -if test "x$enable_openvg" = xyes; then - CORE_DIRS="$CORE_DIRS mapi/vgapi" -fi - -# build glsl and mesa if OpenGL or OpenGL ES is enabled -case "x$enable_opengl$enable_gles1$enable_gles2" in -x*yes*) - CORE_DIRS="$CORE_DIRS glsl mesa" - ;; -esac - -case "$mesa_driver" in -xlib) - DRIVER_DIRS="x11" - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib" - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS libgl-xlib" - ;; -dri) - SRC_DIRS="$SRC_DIRS glx" - DRIVER_DIRS="dri" - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib sw/dri" - ;; -osmesa) - DRIVER_DIRS="osmesa" - ;; -no) - DRIVER_DRIS="" - ;; -esac -AC_SUBST([SRC_DIRS]) -AC_SUBST([GLU_DIRS]) -AC_SUBST([DRIVER_DIRS]) -AC_SUBST([GALLIUM_DIRS]) -AC_SUBST([GALLIUM_TARGET_DIRS]) -AC_SUBST([GALLIUM_WINSYS_DIRS]) -AC_SUBST([GALLIUM_DRIVERS_DIRS]) -AC_SUBST([GALLIUM_STATE_TRACKERS_DIRS]) -AC_SUBST([MESA_LLVM]) - -dnl -dnl Find out if X is available. The variable have_x is set if libX11 is -dnl found to mimic AC_PATH_XTRA. -dnl -if test -n "$PKG_CONFIG"; then - AC_MSG_CHECKING([pkg-config files for X11 are available]) - PKG_CHECK_EXISTS([x11],[ - x11_pkgconfig=yes - have_x=yes - ],[ - x11_pkgconfig=no - ]) - AC_MSG_RESULT([$x11_pkgconfig]) -else - x11_pkgconfig=no -fi -dnl Use the autoconf macro if no pkg-config files -if test "$x11_pkgconfig" = yes; then - PKG_CHECK_MODULES([X11], [x11]) -else - AC_PATH_XTRA - test -z "$X11_CFLAGS" && X11_CFLAGS="$X_CFLAGS" - test -z "$X11_LIBS" && X11_LIBS="$X_LIBS -lX11" - AC_SUBST([X11_CFLAGS]) - AC_SUBST([X11_LIBS]) -fi - -dnl Try to tell the user that the --x-* options are only used when -dnl pkg-config is not available. This must be right after AC_PATH_XTRA. -m4_divert_once([HELP_BEGIN], -[These options are only used when the X libraries cannot be found by the -pkg-config utility.]) - -dnl We need X for xlib and dri, so bomb now if it's not found -case "$mesa_driver" in -xlib|dri) - if test "$no_x" = yes; then - AC_MSG_ERROR([X11 development libraries needed for $mesa_driver driver]) - fi - ;; -esac - -dnl XCB - this is only used for GLX right now -AC_ARG_ENABLE([xcb], - [AS_HELP_STRING([--enable-xcb], - [use XCB for GLX @<:@default=disabled@:>@])], - [enable_xcb="$enableval"], - [enable_xcb=no]) -if test "x$enable_xcb" = xyes; then - DEFINES="$DEFINES -DUSE_XCB" -else - enable_xcb=no -fi - -dnl Direct rendering or just indirect rendering -case "$host_os" in -gnu*) - dnl Disable by default on GNU/Hurd - driglx_direct_default="no" - ;; -cygwin*) - dnl Disable by default on cygwin - driglx_direct_default="no" - ;; -*) - driglx_direct_default="yes" - ;; -esac -AC_ARG_ENABLE([driglx-direct], - [AS_HELP_STRING([--disable-driglx-direct], - [enable direct rendering in GLX and EGL for DRI \ - @<:@default=auto@:>@])], - [driglx_direct="$enableval"], - [driglx_direct="$driglx_direct_default"]) - -dnl -dnl libGL configuration per driver -dnl -case "$mesa_driver" in -xlib) - if test "$x11_pkgconfig" = yes; then - PKG_CHECK_MODULES([XLIBGL], [x11 xext]) - GL_PC_REQ_PRIV="x11 xext" - X11_INCLUDES="$X11_INCLUDES $XLIBGL_CFLAGS" - GL_LIB_DEPS="$XLIBGL_LIBS" - else - # should check these... - X11_INCLUDES="$X11_INCLUDES $X_CFLAGS" - GL_LIB_DEPS="$X_LIBS -lX11 -lXext" - GL_PC_LIB_PRIV="$GL_LIB_DEPS" - GL_PC_CFLAGS="$X11_INCLUDES" - fi - GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread" - GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread" - - # if static, move the external libraries to the programs - # and empty the libraries for libGL - if test "$enable_static" = yes; then - APP_LIB_DEPS="$APP_LIB_DEPS $GL_LIB_DEPS" - GL_LIB_DEPS="" - fi - ;; -dri|no) # these checks are still desired when there is no mesa_driver - # DRI must be shared, I think - if test "$enable_static" = yes; then - AC_MSG_ERROR([Can't use static libraries for DRI drivers]) - fi - - PKG_CHECK_MODULES([GLPROTO], [glproto >= $GLPROTO_REQUIRED]) - GL_PC_REQ_PRIV="glproto >= $GLPROTO_REQUIRED" - DRI_PC_REQ_PRIV="" - - if test x"$driglx_direct" = xyes; then - # Check for libdrm - PKG_CHECK_MODULES([LIBDRM], [libdrm >= $LIBDRM_REQUIRED]) - PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED]) - GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" - DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" - fi - - # find the DRI deps for libGL - if test "$x11_pkgconfig" = yes; then - dri_modules="x11 xext xdamage xfixes" - - # add xf86vidmode if available - PKG_CHECK_MODULES([XF86VIDMODE], [xxf86vm], HAVE_XF86VIDMODE=yes, HAVE_XF86VIDMODE=no) - if test "$HAVE_XF86VIDMODE" = yes ; then - dri_modules="$dri_modules xxf86vm" - fi - - # add xcb modules if necessary - if test "$enable_xcb" = yes; then - dri_modules="$dri_modules x11-xcb xcb-glx" - fi - - PKG_CHECK_MODULES([DRIGL], [$dri_modules]) - GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV $dri_modules" - X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS" - GL_LIB_DEPS="$DRIGL_LIBS" - else - # should check these... - X11_INCLUDES="$X11_INCLUDES $X_CFLAGS" - GL_LIB_DEPS="$X_LIBS -lX11 -lXext -lXxf86vm -lXdamage -lXfixes" - GL_PC_LIB_PRIV="$GL_LIB_DEPS" - GL_PC_CFLAGS="$X11_INCLUDES" - - # XCB can only be used from pkg-config - if test "$enable_xcb" = yes; then - PKG_CHECK_MODULES([XCB],[x11-xcb xcb-glx]) - GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV x11-xcb xcb-glx" - X11_INCLUDES="$X11_INCLUDES $XCB_CFLAGS" - GL_LIB_DEPS="$GL_LIB_DEPS $XCB_LIBS" - fi - fi - - # need DRM libs, -lpthread, etc. - GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" - GL_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" - GLESv1_CM_LIB_DEPS="$LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" - GLESv1_CM_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" - GLESv2_LIB_DEPS="$LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" - GLESv2_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" - ;; -osmesa) - # No libGL for osmesa - GL_LIB_DEPS="" - ;; -esac -AC_SUBST([GL_LIB_DEPS]) -AC_SUBST([GL_PC_REQ_PRIV]) -AC_SUBST([GL_PC_LIB_PRIV]) -AC_SUBST([GL_PC_CFLAGS]) -AC_SUBST([DRI_PC_REQ_PRIV]) -AC_SUBST([GLESv1_CM_LIB_DEPS]) -AC_SUBST([GLESv1_CM_PC_LIB_PRIV]) -AC_SUBST([GLESv2_LIB_DEPS]) -AC_SUBST([GLESv2_PC_LIB_PRIV]) - -GLAPI_LIB_DEPS="-lpthread" -AC_SUBST([GLAPI_LIB_DEPS]) - - -dnl Setup default DRI CFLAGS -DRI_CFLAGS='$(CFLAGS)' -DRI_CXXFLAGS='$(CXXFLAGS)' -DRI_LIB_DEPS='$(TOP)/src/mesa/libmesa.a' -MESA_MODULES='$(TOP)/src/mesa/libmesa.a' - -AC_ARG_ENABLE([shared-dricore], - [AS_HELP_STRING([--enable-shared-dricore], - [link DRI modules with shared core DRI routines @<:@default=disabled@:>@])], - [enable_dricore="$enableval"], - [enable_dricore=no]) -if test "$mesa_driver" = dri ; then - if test "$enable_dricore" = yes ; then - if test "$GCC$GXX" != yesyes ; then - AC_MSG_WARN([Shared dricore requires GCC-compatible rpath handling. Disabling shared dricore]) - enable_dricore=no - else - DRICORE_GLSL_LIBS='$(TOP)/$(LIB_DIR)/libglsl.so' - DRICORE_LIBS='$(TOP)/$(LIB_DIR)/libdricore.so' - DRICORE_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -lglsl' - DRI_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -ldricore -lglsl' - DRI_CFLAGS='$(CFLAGS_NOVISIBILITY) -DUSE_DRICORE' - DRI_CXXFLAGS='$(CXXFLAGS_NOVISIBILITY) -DUSE_DRICORE' - MESA_MODULES='$(DRICORE_LIBS) $(DRICORE_GLSL_LIBS)' - fi - fi -fi -AC_SUBST([DRICORE_LIBS]) -AC_SUBST([DRICORE_GLSL_LIBS]) -AC_SUBST([DRICORE_LIB_DEPS]) -AC_SUBST([DRI_CXXFLAGS]) -AC_SUBST([DRI_CFLAGS]) -AC_SUBST([MESA_MODULES]) - -AC_SUBST([HAVE_XF86VIDMODE]) - -PKG_CHECK_MODULES([LIBDRM_RADEON], - [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED], - HAVE_LIBDRM_RADEON=yes, - HAVE_LIBDRM_RADEON=no) - -dnl -dnl More X11 setup -dnl -if test "$mesa_driver" = xlib; then - DEFINES="$DEFINES -DUSE_XSHM" -fi - -dnl -dnl TLS detection -dnl - -AC_ARG_ENABLE([glx-tls], - [AS_HELP_STRING([--enable-glx-tls], - [enable TLS support in GLX @<:@default=disabled@:>@])], - [GLX_USE_TLS="$enableval"], - [GLX_USE_TLS=no]) -AC_SUBST(GLX_TLS, ${GLX_USE_TLS}) - -AS_IF([test "x$GLX_USE_TLS" = xyes], - [DEFINES="${DEFINES} -DGLX_USE_TLS -DPTHREADS"]) - -dnl -dnl More DRI setup -dnl -dnl Directory for DRI drivers -AC_ARG_WITH([dri-driverdir], - [AS_HELP_STRING([--with-dri-driverdir=DIR], - [directory for the DRI drivers @<:@${libdir}/dri@:>@])], - [DRI_DRIVER_INSTALL_DIR="$withval"], - [DRI_DRIVER_INSTALL_DIR='${libdir}/dri']) -AC_SUBST([DRI_DRIVER_INSTALL_DIR]) -dnl Extra search path for DRI drivers -AC_ARG_WITH([dri-searchpath], - [AS_HELP_STRING([--with-dri-searchpath=DIRS...], - [semicolon delimited DRI driver search directories @<:@${libdir}/dri@:>@])], - [DRI_DRIVER_SEARCH_DIR="$withval"], - [DRI_DRIVER_SEARCH_DIR='${DRI_DRIVER_INSTALL_DIR}']) -AC_SUBST([DRI_DRIVER_SEARCH_DIR]) -dnl Which drivers to build - default is chosen by platform -AC_ARG_WITH([dri-drivers], - [AS_HELP_STRING([--with-dri-drivers@<:@=DIRS...@:>@], - [comma delimited DRI drivers list, e.g. - "swrast,i965,radeon" @<:@default=auto@:>@])], - [with_dri_drivers="$withval"], - [with_dri_drivers=yes]) -if test "x$with_dri_drivers" = x; then - with_dri_drivers=no -fi - -dnl If $with_dri_drivers is yes, directories will be added through -dnl platform checks -DRI_DIRS="" -case "$with_dri_drivers" in -no) ;; -yes) - DRI_DIRS="yes" - ;; -*) - # verify the requested driver directories exist - dri_drivers=`IFS=', '; echo $with_dri_drivers` - for driver in $dri_drivers; do - test -d "$srcdir/src/mesa/drivers/dri/$driver" || \ - AC_MSG_ERROR([DRI driver directory '$driver' doesn't exist]) - done - DRI_DIRS="$dri_drivers" - ;; -esac - -dnl Set DRI_DIRS, DEFINES and LIB_DEPS -if test "$mesa_driver" = dri -o "$mesa_driver" = no; then - # Platform specific settings and drivers to build - case "$host_os" in - linux*) - DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" - if test "x$driglx_direct" = xyes; then - DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" - fi - DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING -DHAVE_ALIAS" - - case "$host_cpu" in - x86_64) - # sis is missing because they have not be converted to use - # the new interface. i810 are missing because there is no - # x86-64 system where they could *ever* be used. - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="i915 i965 mach64 mga r128 r200 r300 r600 radeon \ - savage tdfx unichrome swrast" - fi - ;; - powerpc*) - # Build only the drivers for cards that exist on PowerPC. - # At some point MGA will be added, but not yet. - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="mach64 r128 r200 r300 r600 radeon tdfx swrast" - fi - ;; - sparc*) - # Build only the drivers for cards that exist on sparc` - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="mach64 r128 r200 r300 r600 radeon swrast" - fi - ;; - esac - ;; - freebsd* | dragonfly* | *netbsd*) - DEFINES="$DEFINES -DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1" - DEFINES="$DEFINES -DIN_DRI_DRIVER -DHAVE_ALIAS" - DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" - if test "x$driglx_direct" = xyes; then - DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" - fi - - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 r600 radeon tdfx \ - unichrome savage sis swrast" - fi - ;; - gnu*) - DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" - DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING -DHAVE_ALIAS" - ;; - solaris*) - DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" - DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" - if test "x$driglx_direct" = xyes; then - DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" - fi - ;; - cygwin*) - DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" - DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" - if test "x$driglx_direct" = xyes; then - DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" - fi - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="swrast" - fi - ;; - esac - - # default drivers - if test "x$DRI_DIRS" = "xyes"; then - DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 r600 radeon \ - savage sis tdfx unichrome swrast" - fi - - DRI_DIRS=`echo "$DRI_DIRS" | $SED 's/ */ /g'` - - # Check for expat - if test "$mesa_driver" = dri; then - EXPAT_INCLUDES="" - EXPAT_LIB=-lexpat - AC_ARG_WITH([expat], - [AS_HELP_STRING([--with-expat=DIR], - [expat install directory])],[ - EXPAT_INCLUDES="-I$withval/include" - CPPFLAGS="$CPPFLAGS $EXPAT_INCLUDES" - LDFLAGS="$LDFLAGS -L$withval/$LIB_DIR" - EXPAT_LIB="-L$withval/$LIB_DIR -lexpat" - ]) - AC_CHECK_HEADER([expat.h],[],[AC_MSG_ERROR([Expat required for DRI.])]) - AC_CHECK_LIB([expat],[XML_ParserCreate],[], - [AC_MSG_ERROR([Expat required for DRI.])]) - fi - - # put all the necessary libs together, including possibly libdricore - DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS" -fi -AC_SUBST([DRI_DIRS]) -AC_SUBST([EXPAT_INCLUDES]) -AC_SUBST([DRI_LIB_DEPS]) - -case $DRI_DIRS in -*i915*|*i965*) - PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) - ;; -esac - -case $DRI_DIRS in -*radeon*|*r200*|*r300*|*r600*) - if test "x$HAVE_LIBDRM_RADEON" = xyes; then - RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" - RADEON_LDFLAGS=$LIBDRM_RADEON_LIBS - fi - ;; -esac -AC_SUBST([RADEON_CFLAGS]) -AC_SUBST([RADEON_LDFLAGS]) - - -dnl -dnl OSMesa configuration -dnl -if test "$mesa_driver" = xlib; then - default_gl_osmesa=yes -else - default_gl_osmesa=no -fi -AC_ARG_ENABLE([gl-osmesa], - [AS_HELP_STRING([--enable-gl-osmesa], - [enable OSMesa with libGL @<:@default=enabled for xlib driver@:>@])], - [gl_osmesa="$enableval"], - [gl_osmesa="$default_gl_osmesa"]) -if test "x$gl_osmesa" = xyes; then - if test "x$enable_opengl" = xno; then - AC_MSG_ERROR([OpenGL is not available for OSMesa driver]) - fi - if test "$mesa_driver" = osmesa; then - AC_MSG_ERROR([libGL is not available for OSMesa driver]) - else - DRIVER_DIRS="$DRIVER_DIRS osmesa" - fi -fi - -dnl Configure the channel bits for OSMesa (libOSMesa, libOSMesa16, ...) -AC_ARG_WITH([osmesa-bits], - [AS_HELP_STRING([--with-osmesa-bits=BITS], - [OSMesa channel bits and library name: 8, 16, 32 @<:@default=8@:>@])], - [osmesa_bits="$withval"], - [osmesa_bits=8]) -if test "$mesa_driver" != osmesa && test "x$osmesa_bits" != x8; then - AC_MSG_WARN([Ignoring OSMesa channel bits for non-OSMesa driver]) - osmesa_bits=8 -fi -case "x$osmesa_bits" in -x8) - OSMESA_LIB=OSMesa - ;; -x16|x32) - OSMESA_LIB="OSMesa$osmesa_bits" - DEFINES="$DEFINES -DCHAN_BITS=$osmesa_bits -DDEFAULT_SOFTWARE_DEPTH_BITS=31" - ;; -*) - AC_MSG_ERROR([OSMesa bits '$osmesa_bits' is not a valid option]) - ;; -esac -AC_SUBST([OSMESA_LIB]) - -case "$DRIVER_DIRS" in -*osmesa*) - # only link libraries with osmesa if shared - if test "$enable_static" = no; then - OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" - else - OSMESA_LIB_DEPS="" - fi - OSMESA_MESA_DEPS="" - OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" - ;; -esac -AC_SUBST([OSMESA_LIB_DEPS]) -AC_SUBST([OSMESA_MESA_DEPS]) -AC_SUBST([OSMESA_PC_REQ]) -AC_SUBST([OSMESA_PC_LIB_PRIV]) - -dnl -dnl EGL configuration -dnl -AC_ARG_ENABLE([egl], - [AS_HELP_STRING([--disable-egl], - [disable EGL library @<:@default=enabled@:>@])], - [enable_egl="$enableval"], - [enable_egl=yes]) -if test "x$enable_egl" = xno; then - if test "x$mesa_driver" = xno; then - AC_MSG_ERROR([cannot disable EGL when there is no mesa driver]) - fi - if test "x$enable_openvg" = xyes; then - AC_MSG_ERROR([cannot enable OpenVG without EGL]) - fi -fi -if test "x$enable_egl" = xyes; then - SRC_DIRS="$SRC_DIRS egl" - EGL_LIB_DEPS="$DLOPEN_LIBS -lpthread" - EGL_DRIVERS_DIRS="" - if test "$enable_static" != yes; then - # build egl_glx when libGL is built - if test "$mesa_driver" = xlib -o "$mesa_driver" = dri; then - EGL_DRIVERS_DIRS="glx" - fi - - if test "$mesa_driver" = dri; then - # build egl_dri2 when xcb-dri2 is available - PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb-dri2 xcb-xfixes], - [have_xcb_dri2=yes],[have_xcb_dri2=no]) - PKG_CHECK_MODULES([LIBUDEV], [libudev > 150], - [have_libudev=yes],[have_libudev=no]) - - if test "$have_xcb_dri2" = yes; then - EGL_DRIVER_DRI2=dri2 - DEFINES="$DEFINES -DHAVE_XCB_DRI2" - if test "$have_libudev" = yes; then - DEFINES="$DEFINES -DHAVE_LIBUDEV" - fi - # workaround a bug in xcb-dri2 generated by xcb-proto 1.6 - AC_CHECK_LIB(xcb-dri2, xcb_dri2_connect_alignment_pad, [], - [DEFINES="$DEFINES -DXCB_DRI2_CONNECT_DEVICE_NAME_BROKEN"]) - fi - fi - - EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS $EGL_DRIVER_DRI2" - fi -fi -AC_SUBST([EGL_LIB_DEPS]) -AC_SUBST([EGL_DRIVERS_DIRS]) - -dnl -dnl GLU configuration -dnl -AC_ARG_ENABLE([glu], - [AS_HELP_STRING([--disable-glu], - [enable OpenGL Utility library @<:@default=enabled@:>@])], - [enable_glu="$enableval"], - [enable_glu=yes]) - -if test "x$enable_glu" = xyes -a "x$mesa_driver" = xno; then - AC_MSG_NOTICE([Disabling GLU since there is no OpenGL driver]) - enable_glu=no -fi - -if test "x$enable_glu" = xyes; then - SRC_DIRS="$SRC_DIRS glu" - - case "$mesa_driver" in - osmesa) - # Link libGLU to libOSMesa instead of libGL - GLU_LIB_DEPS="" - GLU_PC_REQ="osmesa" - if test "$enable_static" = no; then - GLU_MESA_DEPS='-l$(OSMESA_LIB)' - else - GLU_MESA_DEPS="" - fi - ;; - *) - # If static, empty GLU_LIB_DEPS and add libs for programs to link - GLU_PC_REQ="gl" - GLU_PC_LIB_PRIV="-lm" - if test "$enable_static" = no; then - GLU_LIB_DEPS="-lm" - GLU_MESA_DEPS='-l$(GL_LIB)' - else - GLU_LIB_DEPS="" - GLU_MESA_DEPS="" - APP_LIB_DEPS="$APP_LIB_DEPS -lstdc++" - fi - ;; - esac -fi -if test "$enable_static" = no; then - GLU_LIB_DEPS="$GLU_LIB_DEPS $OS_CPLUSPLUS_LIBS" -fi -GLU_PC_LIB_PRIV="$GLU_PC_LIB_PRIV $OS_CPLUSPLUS_LIBS" -AC_SUBST([GLU_LIB_DEPS]) -AC_SUBST([GLU_MESA_DEPS]) -AC_SUBST([GLU_PC_REQ]) -AC_SUBST([GLU_PC_REQ_PRIV]) -AC_SUBST([GLU_PC_LIB_PRIV]) -AC_SUBST([GLU_PC_CFLAGS]) - -dnl -dnl GLw configuration -dnl -AC_ARG_ENABLE([glw], - [AS_HELP_STRING([--disable-glw], - [enable Xt/Motif widget library @<:@default=enabled@:>@])], - [enable_glw="$enableval"], - [enable_glw=yes]) -dnl Don't build GLw on osmesa -if test "x$enable_glw" = xyes; then - case "$mesa_driver" in - osmesa|no) - AC_MSG_NOTICE([Disabling GLw since there is no OpenGL driver]) - enable_glw=no - ;; - esac -fi -AC_ARG_ENABLE([motif], - [AS_HELP_STRING([--enable-motif], - [use Motif widgets in GLw @<:@default=disabled@:>@])], - [enable_motif="$enableval"], - [enable_motif=no]) - -if test "x$enable_glw" = xyes; then - SRC_DIRS="$SRC_DIRS glw" - if test "$x11_pkgconfig" = yes; then - PKG_CHECK_MODULES([GLW],[x11 xt]) - GLW_PC_REQ_PRIV="x11 xt" - GLW_LIB_DEPS="$GLW_LIBS" - else - # should check these... - GLW_LIB_DEPS="$X_LIBS -lXt -lX11" - GLW_PC_LIB_PRIV="$GLW_LIB_DEPS" - GLW_PC_CFLAGS="$X11_INCLUDES" - fi - - GLW_SOURCES="GLwDrawA.c" - MOTIF_CFLAGS= - if test "x$enable_motif" = xyes; then - GLW_SOURCES="$GLW_SOURCES GLwMDrawA.c" - AC_PATH_PROG([MOTIF_CONFIG], [motif-config], [no]) - if test "x$MOTIF_CONFIG" != xno; then - MOTIF_CFLAGS=`$MOTIF_CONFIG --cflags` - MOTIF_LIBS=`$MOTIF_CONFIG --libs` - else - AC_CHECK_HEADER([Xm/PrimitiveP.h], [], - [AC_MSG_ERROR([Can't locate Motif headers])]) - AC_CHECK_LIB([Xm], [XmGetPixmap], [MOTIF_LIBS="-lXm"], - [AC_MSG_ERROR([Can't locate Motif Xm library])]) - fi - # MOTIF_LIBS is prepended to GLW_LIB_DEPS since Xm needs Xt/X11 - GLW_LIB_DEPS="$MOTIF_LIBS $GLW_LIB_DEPS" - GLW_PC_LIB_PRIV="$MOTIF_LIBS $GLW_PC_LIB_PRIV" - GLW_PC_CFLAGS="$MOTIF_CFLAGS $GLW_PC_CFLAGS" - fi - - # If static, empty GLW_LIB_DEPS and add libs for programs to link - GLW_PC_LIB_PRIV="$GLW_PC_LIB_PRIV" - if test "$enable_static" = no; then - GLW_MESA_DEPS='-l$(GL_LIB)' - GLW_LIB_DEPS="$GLW_LIB_DEPS" - else - APP_LIB_DEPS="$APP_LIB_DEPS $GLW_LIB_DEPS" - GLW_LIB_DEPS="" - GLW_MESA_DEPS="" - fi -fi -AC_SUBST([GLW_LIB_DEPS]) -AC_SUBST([GLW_MESA_DEPS]) -AC_SUBST([GLW_SOURCES]) -AC_SUBST([MOTIF_CFLAGS]) -AC_SUBST([GLW_PC_REQ_PRIV]) -AC_SUBST([GLW_PC_LIB_PRIV]) -AC_SUBST([GLW_PC_CFLAGS]) - -dnl -dnl GLUT configuration -dnl -if test -f "$srcdir/include/GL/glut.h"; then - default_glut=yes -else - default_glut=no -fi -AC_ARG_ENABLE([glut], - [AS_HELP_STRING([--disable-glut], - [enable GLUT library @<:@default=enabled if source available@:>@])], - [enable_glut="$enableval"], - [enable_glut="$default_glut"]) - -dnl Don't build glut on osmesa -if test "x$enable_glut" = xyes; then - case "$mesa_driver" in - osmesa|no) - AC_MSG_NOTICE([Disabling glut since there is no OpenGL driver]) - enable_glut=no - ;; - esac -fi -dnl Can't build glut if GLU not available -if test "x$enable_glu$enable_glut" = xnoyes; then - AC_MSG_WARN([Disabling glut since GLU is disabled]) - enable_glut=no -fi - -if test "x$enable_glut" = xyes; then - SRC_DIRS="$SRC_DIRS glut/glx" - if test "$x11_pkgconfig" = yes; then - PKG_CHECK_MODULES([GLUT],[x11 xmu xi]) - GLUT_PC_REQ_PRIV="x11 xmu xi" - GLUT_LIB_DEPS="$GLUT_LIBS" - else - # should check these... - GLUT_LIB_DEPS="$X_LIBS -lX11 -lXmu -lXi" - GLUT_PC_LIB_PRIV="$GLUT_LIB_DEPS" - GLUT_PC_CFLAGS="$X11_INCLUDES" - fi - if test "x$GCC" = xyes; then - GLUT_CFLAGS="$GLUT_CFLAGS -fexceptions" - fi - GLUT_LIB_DEPS="$GLUT_LIB_DEPS -lm" - GLUT_PC_LIB_PRIV="$GLUT_PC_LIB_PRIV -lm" - - # If static, empty GLUT_LIB_DEPS and add libs for programs to link - if test "$enable_static" = no; then - GLUT_MESA_DEPS='-l$(GLU_LIB) -l$(GL_LIB)' - else - APP_LIB_DEPS="$APP_LIB_DEPS $GLUT_LIB_DEPS" - GLUT_LIB_DEPS="" - GLUT_MESA_DEPS="" - fi -fi -AC_SUBST([GLUT_LIB_DEPS]) -AC_SUBST([GLUT_MESA_DEPS]) -AC_SUBST([GLUT_CFLAGS]) -AC_SUBST([GLUT_PC_REQ_PRIV]) -AC_SUBST([GLUT_PC_LIB_PRIV]) -AC_SUBST([GLUT_PC_CFLAGS]) - -dnl -dnl Program library dependencies -dnl Only libm is added here if necessary as the libraries should -dnl be pulled in by the linker -dnl -if test "x$APP_LIB_DEPS" = x; then - case "$host_os" in - solaris*) - APP_LIB_DEPS="-lX11 -lsocket -lnsl -lm" - ;; - cygwin*) - APP_LIB_DEPS="-lX11" - ;; - *) - APP_LIB_DEPS="-lm" - ;; - esac -fi -AC_SUBST([APP_LIB_DEPS]) -AC_SUBST([PROGRAM_DIRS]) - -dnl -dnl Gallium configuration -dnl -AC_ARG_ENABLE([gallium], - [AS_HELP_STRING([--disable-gallium], - [build gallium @<:@default=enabled@:>@])], - [enable_gallium="$enableval"], - [enable_gallium=yes]) -if test "x$enable_gallium" = xno -a "x$enable_openvg" = xyes; then - AC_MSG_ERROR([cannot enable OpenVG without Gallium]) -fi -if test "x$enable_gallium" = xyes; then - SRC_DIRS="$SRC_DIRS gallium gallium/winsys gallium/targets" - AC_PATH_PROG([LLVM_CONFIG], [llvm-config], [no]) -fi - -AC_SUBST([LLVM_CFLAGS]) -AC_SUBST([LLVM_LIBS]) -AC_SUBST([LLVM_LDFLAGS]) -AC_SUBST([LLVM_VERSION]) - -dnl -dnl Gallium state trackers configuration -dnl - -AC_ARG_ENABLE([gallium-egl], - [AS_HELP_STRING([--enable-gallium-egl], - [enable gallium EGL state tracker @<:@default=auto@:>@])], - [enable_gallium_egl="$enableval"], - [enable_gallium_egl=auto]) -if test "x$enable_gallium_egl" = xauto; then - case "$mesa_driver" in - dri|no) - enable_gallium_egl=$enable_egl - ;; - *) - enable_gallium_egl=$enable_openvg - ;; - esac -fi -case "x$enable_egl$enable_gallium_egl" in -xnoyes) - AC_MSG_ERROR([cannot build Gallium EGL state tracker without EGL]) -esac - -AC_ARG_WITH([state-trackers], - [AS_HELP_STRING([--with-state-trackers@<:@=DIRS...@:>@], - [comma delimited state_trackers list, e.g. - "egl,glx" @<:@default=auto@:>@])], - [with_state_trackers="$withval"], - [with_state_trackers=yes]) - -case "$with_state_trackers" in -no) - GALLIUM_STATE_TRACKERS_DIRS="" - ;; -yes) - # look at what else is built - case "$mesa_driver" in - xlib) - GALLIUM_STATE_TRACKERS_DIRS=glx - ;; - dri) - GALLIUM_STATE_TRACKERS_DIRS="dri" - HAVE_ST_DRI="yes" - # Have only tested st/xorg on 1.6.0 servers - PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0 libdrm >= $LIBDRM_XORG_REQUIRED libkms >= $LIBKMS_XORG_REQUIRED], - HAVE_ST_XORG="yes"; GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS xorg", - HAVE_ST_XORG="no") - ;; - esac - - if test "x$enable_egl" = xyes; then - if test "$enable_openvg" = yes; then - GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS vega" - st_egl="yes" - fi - - if test "$enable_gallium_egl" = yes; then - GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl" - HAVE_ST_EGL="yes" - fi - fi - ;; -*) - # verify the requested state tracker exist - state_trackers="" - _state_trackers=`IFS=', '; echo $with_state_trackers` - for tracker in $_state_trackers; do - case "$tracker" in - dri) - if test "x$mesa_driver" != xdri; then - AC_MSG_ERROR([cannot build dri state tracker without mesa driver set to dri]) - fi - HAVE_ST_DRI="yes" - ;; - egl) - if test "x$enable_egl" != xyes; then - AC_MSG_ERROR([cannot build egl state tracker without EGL library]) - fi - HAVE_ST_EGL="yes" - ;; - xorg) - PKG_CHECK_MODULES([XORG], [xorg-server >= 1.6.0]) - PKG_CHECK_MODULES([LIBDRM_XORG], [libdrm >= $LIBDRM_XORG_REQUIRED]) - PKG_CHECK_MODULES([LIBKMS_XORG], [libkms >= $LIBKMS_XORG_REQUIRED]) - HAVE_ST_XORG="yes" - ;; - vega) - if test "x$enable_openvg" != xyes; then - AC_MSG_ERROR([cannot build vega state tracker without --enable-openvg]) - fi - have_st_vega="yes" - ;; - esac - - if test -n "$tracker"; then - test -d "$srcdir/src/gallium/state_trackers/$tracker" || \ - AC_MSG_ERROR([state tracker '$tracker' doesn't exist]) - if test -n "$state_trackers"; then - state_trackers="$state_trackers $tracker" - else - state_trackers="$tracker" - fi - fi - done - GALLIUM_STATE_TRACKERS_DIRS="$state_trackers" - - # append --enable-openvg/--enable-gallium-egl to --with-state-trackers - if test "x$have_st_vega" != xyes -a "x$enable_openvg" = xyes; then - AC_MSG_ERROR([--with-state-trackers specified but vega is missing]) - fi - if test "x$HAVE_ST_EGL" != xyes -a "x$enable_gallium_egl" = xyes; then - AC_MSG_ERROR([--with-state-trackers specified but egl is missing]) - fi - ;; -esac - - -EGL_CLIENT_APIS="" -VG_LIB_DEPS="" - -case "x$enable_opengl$enable_gles1$enable_gles2" in -x*yes*) - EGL_CLIENT_APIS="$EGL_CLIENT_APIS "'$(GL_LIB)' - ;; -esac -if test "x$enable_openvg" = xyes; then - EGL_CLIENT_APIS="$EGL_CLIENT_APIS "'$(VG_LIB)' - VG_LIB_DEPS="$VG_LIB_DEPS -lpthread" -fi - -AC_SUBST([VG_LIB_DEPS]) -AC_SUBST([EGL_CLIENT_APIS]) - -if test "x$HAVE_ST_EGL" = xyes; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl" -fi - -if test "x$HAVE_ST_XORG" = xyes; then - PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], - HAVE_XEXTPROTO_71="yes"; DEFINES="$DEFINES -DHAVE_XEXTPROTO_71", - HAVE_XEXTPROTO_71="no") -fi - -AC_ARG_WITH([egl-platforms], - [AS_HELP_STRING([--with-egl-platforms@<:@=DIRS...@:>@], - [comma delimited native platforms libEGL supports, e.g. - "x11,drm" @<:@default=auto@:>@])], - [with_egl_platforms="$withval"], - [with_egl_platforms=yes]) -AC_ARG_WITH([egl-displays], - [AS_HELP_STRING([--with-egl-displays@<:@=DIRS...@:>@], - [DEPRECATED. Use --with-egl-platforms instead])], - [with_egl_platforms="$withval"]) - -EGL_PLATFORMS="" -WAYLAND_EGL_LIB_DEPS="" - -case "$with_egl_platforms" in -yes) - if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then - EGL_PLATFORMS="x11" - if test "$mesa_driver" = dri; then - EGL_PLATFORMS="$EGL_PLATFORMS drm" - fi - fi - ;; -*) - if test "x$enable_egl" != xyes; then - AC_MSG_ERROR([cannot build egl state tracker without EGL library]) - fi - # verify the requested driver directories exist - egl_platforms=`IFS=', '; echo $with_egl_platforms` - for plat in $egl_platforms; do - test -d "$srcdir/src/gallium/state_trackers/egl/$plat" || \ - AC_MSG_ERROR([EGL platform '$plat' doesn't exist]) - if test "$plat" = "fbdev"; then - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev" - fi - if test "$plat" = "wayland"; then - PKG_CHECK_MODULES([WAYLAND], [wayland-client wayland-server],, \ - [AC_MSG_ERROR([cannot find libwayland-client])]) - WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS" - fi - done - EGL_PLATFORMS="$egl_platforms" - ;; -esac -AC_SUBST([EGL_PLATFORMS]) - -AC_SUBST([WAYLAND_EGL_LIB_DEPS]) -WAYLAND_EGL_PC_REQ_PRIV="wayland-client libdrm" -WAYLAND_EGL_PC_LIB_PRIV= -WAYLAND_EGL_PC_CFLAGS= - -AC_SUBST([WAYLAND_EGL_PC_REQ_PRIV]) -AC_SUBST([WAYLAND_EGL_PC_LIB_PRIV]) -AC_SUBST([WAYLAND_EGL_PC_CFLAGS]) - - -AC_ARG_WITH([egl-driver-dir], - [AS_HELP_STRING([--with-egl-driver-dir=DIR], - [directory for EGL drivers [[default=${libdir}/egl]]])], - [EGL_DRIVER_INSTALL_DIR="$withval"], - [EGL_DRIVER_INSTALL_DIR='${libdir}/egl']) -AC_SUBST([EGL_DRIVER_INSTALL_DIR]) - -AC_ARG_WITH([xorg-driver-dir], - [AS_HELP_STRING([--with-xorg-driver-dir=DIR], - [Default xorg driver directory[[default=${libdir}/xorg/modules/drivers]]])], - [XORG_DRIVER_INSTALL_DIR="$withval"], - [XORG_DRIVER_INSTALL_DIR="${libdir}/xorg/modules/drivers"]) -AC_SUBST([XORG_DRIVER_INSTALL_DIR]) - -AC_ARG_WITH([max-width], - [AS_HELP_STRING([--with-max-width=N], - [Maximum framebuffer width (4096)])], - [DEFINES="${DEFINES} -DMAX_WIDTH=${withval}"; - AS_IF([test "${withval}" -gt "4096"], - [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] -) -AC_ARG_WITH([max-height], - [AS_HELP_STRING([--with-max-height=N], - [Maximum framebuffer height (4096)])], - [DEFINES="${DEFINES} -DMAX_HEIGHT=${withval}"; - AS_IF([test "${withval}" -gt "4096"], - [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] -) - -dnl -dnl Gallium LLVM -dnl -AC_ARG_ENABLE([gallium-llvm], - [AS_HELP_STRING([--enable-gallium-llvm], - [build gallium LLVM support @<:@default=disabled@:>@])], - [enable_gallium_llvm="$enableval"], - [enable_gallium_llvm=auto]) -if test "x$enable_gallium_llvm" = xyes; then - if test "x$LLVM_CONFIG" != xno; then - LLVM_VERSION=`$LLVM_CONFIG --version` - LLVM_CFLAGS=`$LLVM_CONFIG --cppflags` - LLVM_LIBS="`$LLVM_CONFIG --libs` -lstdc++" - - LLVM_LDFLAGS=`$LLVM_CONFIG --ldflags` - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe" - DEFINES="$DEFINES -DGALLIUM_LLVMPIPE -D__STDC_CONSTANT_MACROS" - MESA_LLVM=1 - else - MESA_LLVM=0 - fi -else - MESA_LLVM=0 -fi - -dnl -dnl Gallium helper functions -dnl -gallium_check_st() { - if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_XORG" = xyes; then - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS $1" - fi - if test "x$HAVE_ST_DRI" = xyes && test "x$2" != x; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $2" - fi - if test "x$HAVE_ST_XORG" = xyes && test "x$3" != x; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $3" - fi -} - - -dnl -dnl Gallium SVGA configuration -dnl -AC_ARG_ENABLE([gallium-svga], - [AS_HELP_STRING([--enable-gallium-svga], - [build gallium SVGA @<:@default=disabled@:>@])], - [enable_gallium_svga="$enableval"], - [enable_gallium_svga=auto]) -if test "x$enable_gallium_svga" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" - gallium_check_st "svga/drm" "dri-vmwgfx" "xorg-vmwgfx" -elif test "x$enable_gallium_svga" = xauto; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" -fi - -dnl -dnl Gallium i915 configuration -dnl -AC_ARG_ENABLE([gallium-i915], - [AS_HELP_STRING([--enable-gallium-i915], - [build gallium i915 @<:@default=disabled@:>@])], - [enable_gallium_i915="$enableval"], - [enable_gallium_i915=auto]) -if test "x$enable_gallium_i915" = xyes; then - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw" - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" - gallium_check_st "i915/drm" "dri-i915" "xorg-i915" -elif test "x$enable_gallium_i915" = xauto; then - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw" - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" -fi - -dnl -dnl Gallium i965 configuration -dnl -AC_ARG_ENABLE([gallium-i965], - [AS_HELP_STRING([--enable-gallium-i965], - [build gallium i965 @<:@default=disabled@:>@])], - [enable_gallium_i965="$enableval"], - [enable_gallium_i965=auto]) -if test "x$enable_gallium_i965" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965" - gallium_check_st "i965/drm" "dri-i965" "xorg-i965" -elif test "x$enable_gallium_i965" = xauto; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965" -fi - -dnl -dnl Gallium Radeon r300g configuration -dnl -AC_ARG_ENABLE([gallium-radeon], - [AS_HELP_STRING([--enable-gallium-radeon], - [build gallium radeon @<:@default=disabled@:>@])], - [enable_gallium_radeon="$enableval"], - [enable_gallium_radeon=auto]) -if test "x$enable_gallium_radeon" = xauto; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "dri-r300" -fi -if test "x$enable_gallium_radeon" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon" -fi - -dnl -dnl Gallium Radeon r600g configuration -dnl -AC_ARG_ENABLE([gallium-r600], - [AS_HELP_STRING([--enable-gallium-r600], - [build gallium radeon @<:@default=disabled@:>@])], - [enable_gallium_r600="$enableval"], - [enable_gallium_r600=auto]) -if test "x$enable_gallium_r600" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" - gallium_check_st "r600/drm" "dri-r600" -fi - -dnl -dnl Gallium Nouveau configuration -dnl -AC_ARG_ENABLE([gallium-nouveau], - [AS_HELP_STRING([--enable-gallium-nouveau], - [build gallium nouveau @<:@default=disabled@:>@])], - [enable_gallium_nouveau="$enableval"], - [enable_gallium_nouveau=no]) -if test "x$enable_gallium_nouveau" = xyes; then - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50 nvc0" - gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" -fi - -dnl -dnl Gallium swrast configuration -dnl -AC_ARG_ENABLE([gallium-swrast], - [AS_HELP_STRING([--enable-gallium-swrast], - [build gallium swrast @<:@default=auto@:>@])], - [enable_gallium_swrast="$enableval"], - [enable_gallium_swrast=auto]) -if test "x$enable_gallium_swrast" = xyes || test "x$enable_gallium_swrast" = xauto; then - if test "x$HAVE_ST_DRI" = xyes; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri-swrast" - fi -fi - -dnl prepend CORE_DIRS to SRC_DIRS -SRC_DIRS="$CORE_DIRS $SRC_DIRS" - -dnl Restore LDFLAGS and CPPFLAGS -LDFLAGS="$_SAVE_LDFLAGS" -CPPFLAGS="$_SAVE_CPPFLAGS" - -dnl Substitute the config -AC_CONFIG_FILES([configs/autoconf]) - -dnl Replace the configs/current symlink -AC_CONFIG_COMMANDS([configs],[ -if test -f configs/current || test -L configs/current; then - rm -f configs/current -fi -ln -s autoconf configs/current -]) - -AC_OUTPUT - -dnl -dnl Output some configuration info for the user -dnl -echo "" -echo " prefix: $prefix" -echo " exec_prefix: $exec_prefix" -echo " libdir: $libdir" -echo " includedir: $includedir" - -dnl API info -echo "" -echo " OpenGL: $enable_opengl (ES1: $enable_gles1 ES2: $enable_gles2)" -echo " OpenVG: $enable_openvg" - -dnl Driver info -echo "" -echo " Driver: $mesa_driver" -if test "$mesa_driver" != no; then - if echo "$DRIVER_DIRS" | grep 'osmesa' >/dev/null 2>&1; then - echo " OSMesa: lib$OSMESA_LIB" - else - echo " OSMesa: no" - fi - if test "$mesa_driver" = dri; then - # cleanup the drivers var - dri_dirs=`echo $DRI_DIRS | $SED 's/^ *//;s/ */ /;s/ *$//'` - if test "x$DRI_DIRS" = x; then - echo " DRI drivers: no" - else - echo " DRI drivers: $dri_dirs" - fi - echo " DRI driver dir: $DRI_DRIVER_INSTALL_DIR" - echo " Use XCB: $enable_xcb" - echo " Shared dricore: $enable_dricore" - fi -fi -echo "" -echo " GLU: $enable_glu" -echo " GLw: $enable_glw (Motif: $enable_motif)" -echo " glut: $enable_glut" - -dnl EGL -echo "" -echo " EGL: $enable_egl" -if test "$enable_egl" = yes; then - echo " EGL platforms: $EGL_PLATFORMS" - - egl_drivers="" - for d in $EGL_DRIVERS_DIRS; do - egl_drivers="$egl_drivers builtin:egl_$d" - done - - if test "$enable_gallium" = yes -a "$HAVE_ST_EGL" = yes; then - echo " EGL drivers: ${egl_drivers} egl_gallium" - echo " EGL Gallium STs:$EGL_CLIENT_APIS" - else - echo " EGL drivers: $egl_drivers" - fi -fi - -echo "" -if test "x$MESA_LLVM" = x1; then - echo " llvm: yes" - echo " llvm-config: $LLVM_CONFIG" - echo " llvm-version: $LLVM_VERSION" -else - echo " llvm: no" -fi - -echo "" -if echo "$SRC_DIRS" | grep 'gallium' >/dev/null 2>&1; then - echo " Gallium: yes" - echo " Gallium dirs: $GALLIUM_DIRS" - echo " Target dirs: $GALLIUM_TARGET_DIRS" - echo " Winsys dirs: $GALLIUM_WINSYS_DIRS" - echo " Driver dirs: $GALLIUM_DRIVERS_DIRS" - echo " Trackers dirs: $GALLIUM_STATE_TRACKERS_DIRS" -else - echo " Gallium: no" -fi - -dnl Libraries -echo "" -echo " Shared libs: $enable_shared" -echo " Static libs: $enable_static" - -dnl Compiler options -# cleanup the CFLAGS/CXXFLAGS/DEFINES vars -cflags=`echo $CFLAGS $OPT_FLAGS $PIC_FLAGS $ARCH_FLAGS | \ - $SED 's/^ *//;s/ */ /;s/ *$//'` -cxxflags=`echo $CXXFLAGS $OPT_FLAGS $PIC_FLAGS $ARCH_FLAGS | \ - $SED 's/^ *//;s/ */ /;s/ *$//'` -defines=`echo $DEFINES $ASM_FLAGS | $SED 's/^ *//;s/ */ /;s/ *$//'` -echo "" -echo " CFLAGS: $cflags" -echo " CXXFLAGS: $cxxflags" -echo " Macros: $defines" -echo "" -echo " PYTHON2: $PYTHON2" - -echo "" -echo " Run '${MAKE-make}' to build Mesa" -echo "" +dnl Process this file with autoconf to create configure. + +AC_PREREQ([2.59]) + +dnl Versioning - scrape the version from configs/default +m4_define([mesa_version], + [m4_esyscmd([${MAKE-make} -s -f bin/version.mk version | tr -d '\n' | tr -d '\r'])]) +m4_ifval(mesa_version,, + [m4_fatal([Failed to get the Mesa version from `make -f bin/version.mk version`])]) + +dnl Tell the user about autoconf.html in the --help output +m4_divert_once([HELP_END], [ +See docs/autoconf.html for more details on the options for Mesa.]) + +AC_INIT([Mesa],[mesa_version], + [https://bugs.freedesktop.org/enter_bug.cgi?product=Mesa]) +AC_CONFIG_AUX_DIR([bin]) +AC_CANONICAL_HOST + +dnl Versions for external dependencies +LIBDRM_REQUIRED=2.4.24 +LIBDRM_RADEON_REQUIRED=2.4.24 +LIBDRM_INTEL_REQUIRED=2.4.24 +DRI2PROTO_REQUIRED=2.1 +GLPROTO_REQUIRED=1.4.11 +LIBDRM_XORG_REQUIRED=2.4.24 +LIBKMS_XORG_REQUIRED=1.0.0 + +dnl Check for progs +AC_PROG_CPP +AC_PROG_CC +AC_PROG_CXX +AC_CHECK_PROGS([MAKE], [gmake make]) +AC_CHECK_PROGS([PYTHON2], [python2 python]) +AC_PATH_PROG([MKDEP], [makedepend]) +AC_PATH_PROG([SED], [sed]) + +if test "x$MKDEP" = "x"; then + AC_MSG_ERROR([makedepend is required to build Mesa]) +fi + +dnl Our fallback install-sh is a symlink to minstall. Use the existing +dnl configuration in that case. +AC_PROG_INSTALL +test "x$INSTALL" = "x$ac_install_sh" && INSTALL='$(MINSTALL)' + +dnl We need a POSIX shell for parts of the build. Assume we have one +dnl in most cases. +case "$host_os" in +solaris*) + # Solaris /bin/sh is too old/non-POSIX compliant + AC_PATH_PROGS(POSIX_SHELL, [ksh93 ksh sh]) + SHELL="$POSIX_SHELL" + ;; +esac + +dnl clang is mostly GCC-compatible, but its version is much lower, +dnl so we have to check for it. +AC_MSG_CHECKING([if compiling with clang]) + +AC_COMPILE_IFELSE( +[AC_LANG_PROGRAM([], [[ +#ifndef __clang__ + not clang +#endif +]])], +[CLANG=yes], [CLANG=no]) + +AC_MSG_RESULT([$CLANG]) + +dnl If we're using GCC, make sure that it is at least version 3.3.0. Older +dnl versions are explictly not supported. +if test "x$GCC" = xyes -a "x$CLANG" = xno; then + AC_MSG_CHECKING([whether gcc version is sufficient]) + major=0 + minor=0 + + GCC_VERSION=`$CC -dumpversion` + if test $? -eq 0; then + major=`echo $GCC_VERSION | cut -d. -f1` + minor=`echo $GCC_VERSION | cut -d. -f1` + fi + + if test $major -lt 3 -o $major -eq 3 -a $minor -lt 3 ; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([If using GCC, version 3.3.0 or later is required.]) + else + AC_MSG_RESULT([yes]) + fi +fi + + +MKDEP_OPTIONS=-fdepend +dnl Ask gcc where it's keeping its secret headers +if test "x$GCC" = xyes; then + for dir in include include-fixed; do + GCC_INCLUDES=`$CC -print-file-name=$dir` + if test "x$GCC_INCLUDES" != x && \ + test "$GCC_INCLUDES" != "$dir" && \ + test -d "$GCC_INCLUDES"; then + MKDEP_OPTIONS="$MKDEP_OPTIONS -I$GCC_INCLUDES" + fi + done +fi +AC_SUBST([MKDEP_OPTIONS]) + +dnl Make sure the pkg-config macros are defined +m4_ifndef([PKG_PROG_PKG_CONFIG], + [m4_fatal([Could not locate the pkg-config autoconf macros. + These are usually located in /usr/share/aclocal/pkg.m4. If your macros + are in a different location, try setting the environment variable + ACLOCAL="aclocal -I/other/macro/dir" before running autoreconf.])]) +PKG_PROG_PKG_CONFIG() + +dnl LIB_DIR - library basename +LIB_DIR=`echo $libdir | $SED 's%.*/%%'` +AC_SUBST([LIB_DIR]) + +dnl Cache LDFLAGS so we can add EXTRA_LIB_PATH and restore it later +_SAVE_LDFLAGS="$LDFLAGS" +AC_ARG_VAR([EXTRA_LIB_PATH],[Extra -L paths for the linker]) +AC_SUBST([EXTRA_LIB_PATH]) + +dnl Cache CPPFLAGS so we can add *_INCLUDES and restore it later +_SAVE_CPPFLAGS="$CPPFLAGS" +AC_ARG_VAR([X11_INCLUDES],[Extra -I paths for X11 headers]) +AC_SUBST([X11_INCLUDES]) + +dnl Compiler macros +DEFINES="" +AC_SUBST([DEFINES]) +case "$host_os" in +linux*|*-gnu*|gnu*) + DEFINES="$DEFINES -D_GNU_SOURCE -DPTHREADS" + ;; +solaris*) + DEFINES="$DEFINES -DPTHREADS -DSVR4" + ;; +cygwin*) + DEFINES="$DEFINES -DPTHREADS" + ;; +esac + +dnl Add flags for gcc and g++ +if test "x$GCC" = xyes; then + CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99" + if test "x$CLANG" = "xno"; then + CFLAGS="$CFLAGS -ffast-math" + fi + + # Enable -fvisibility=hidden if using a gcc that supports it + save_CFLAGS="$CFLAGS" + AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden]) + VISIBILITY_CFLAGS="-fvisibility=hidden" + CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), + [VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]); + + # Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed. + CFLAGS=$save_CFLAGS + + # Work around aliasing bugs - developers should comment this out + CFLAGS="$CFLAGS -fno-strict-aliasing" +fi +if test "x$GXX" = xyes; then + CXXFLAGS="$CXXFLAGS -Wall" + + # Enable -fvisibility=hidden if using a gcc that supports it + save_CXXFLAGS="$CXXFLAGS" + AC_MSG_CHECKING([whether $CXX supports -fvisibility=hidden]) + VISIBILITY_CXXFLAGS="-fvisibility=hidden" + CXXFLAGS="$CXXFLAGS $VISIBILITY_CXXFLAGS" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]), + [VISIBILITY_CXXFLAGS="" ; AC_MSG_RESULT([no])]); + + # Restore CXXFLAGS; VISIBILITY_CXXFLAGS are added to it where needed. + CXXFLAGS=$save_CXXFLAGS + + # Work around aliasing bugs - developers should comment this out + CXXFLAGS="$CXXFLAGS -fno-strict-aliasing" +fi + +AC_SUBST([VISIBILITY_CFLAGS]) +AC_SUBST([VISIBILITY_CXXFLAGS]) + +dnl These should be unnecessary, but let the user set them if they want +AC_ARG_VAR([OPT_FLAGS], [Additional optimization flags for the compiler. + Default is to use CFLAGS.]) +AC_ARG_VAR([ARCH_FLAGS], [Additional architecture specific flags for the + compiler. Default is to use CFLAGS.]) +AC_SUBST([OPT_FLAGS]) +AC_SUBST([ARCH_FLAGS]) + +dnl +dnl Hacks to enable 32 or 64 bit build +dnl +AC_ARG_ENABLE([32-bit], + [AS_HELP_STRING([--enable-32-bit], + [build 32-bit libraries @<:@default=auto@:>@])], + [enable_32bit="$enableval"], + [enable_32bit=auto] +) +if test "x$enable_32bit" = xyes; then + if test "x$GCC" = xyes; then + CFLAGS="$CFLAGS -m32" + ARCH_FLAGS="$ARCH_FLAGS -m32" + fi + if test "x$GXX" = xyes; then + CXXFLAGS="$CXXFLAGS -m32" + fi +fi +AC_ARG_ENABLE([64-bit], + [AS_HELP_STRING([--enable-64-bit], + [build 64-bit libraries @<:@default=auto@:>@])], + [enable_64bit="$enableval"], + [enable_64bit=auto] +) +if test "x$enable_64bit" = xyes; then + if test "x$GCC" = xyes; then + CFLAGS="$CFLAGS -m64" + fi + if test "x$GXX" = xyes; then + CXXFLAGS="$CXXFLAGS -m64" + fi +fi + +dnl +dnl shared/static libraries, mimic libtool options +dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static], + [build static libraries @<:@default=disabled@:>@])], + [enable_static="$enableval"], + [enable_static=no] +) +case "x$enable_static" in +xyes|xno ) ;; +x ) enable_static=no ;; +* ) + AC_MSG_ERROR([Static library option '$enable_static' is not a valid]) + ;; +esac +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--disable-shared], + [build shared libraries @<:@default=enabled@:>@])], + [enable_shared="$enableval"], + [enable_shared=yes] +) +case "x$enable_shared" in +xyes|xno ) ;; +x ) enable_shared=yes ;; +* ) + AC_MSG_ERROR([Shared library option '$enable_shared' is not a valid]) + ;; +esac + +dnl Can't have static and shared libraries, default to static if user +dnl explicitly requested. If both disabled, set to static since shared +dnl was explicitly requirested. +case "x$enable_static$enable_shared" in +xyesyes ) + AC_MSG_WARN([Can't build static and shared libraries, disabling shared]) + enable_shared=no + ;; +xnono ) + AC_MSG_WARN([Can't disable both static and shared libraries, enabling static]) + enable_static=yes + ;; +esac + +dnl +dnl mklib options +dnl +AC_ARG_VAR([MKLIB_OPTIONS],[Options for the Mesa library script, mklib]) +if test "$enable_static" = yes; then + MKLIB_OPTIONS="$MKLIB_OPTIONS -static" +fi +AC_SUBST([MKLIB_OPTIONS]) + +dnl +dnl other compiler options +dnl +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], + [use debug compiler flags and macros @<:@default=disabled@:>@])], + [enable_debug="$enableval"], + [enable_debug=no] +) +if test "x$enable_debug" = xyes; then + DEFINES="$DEFINES -DDEBUG" + if test "x$GCC" = xyes; then + CFLAGS="$CFLAGS -g" + fi + if test "x$GXX" = xyes; then + CXXFLAGS="$CXXFLAGS -g" + fi +fi + +dnl +dnl library names +dnl +LIB_PREFIX_GLOB='lib' +LIB_VERSION_SEPARATOR='.' +if test "$enable_static" = yes; then + LIB_EXTENSION='a' +else + case "$host_os" in + darwin* ) + LIB_EXTENSION='dylib' ;; + cygwin* ) + dnl prefix can be 'cyg' or 'lib' + LIB_PREFIX_GLOB='???' + LIB_VERSION_SEPARATOR='-' + LIB_EXTENSION='dll' ;; + aix* ) + LIB_EXTENSION='a' ;; + * ) + LIB_EXTENSION='so' ;; + esac +fi + +dnl +dnl potentially-infringing-but-nobody-knows-for-sure stuff +dnl +AC_ARG_ENABLE([texture-float], + [AS_HELP_STRING([--enable-texture-float], + [enable floating-point textures and renderbuffers @<:@default=disabled@:>@])], + [enable_texture_float="$enableval"], + [enable_texture_float=no] +) +if test "x$enable_texture_float" = xyes; then + AC_MSG_WARN([Floating-point textures enabled.]) + AC_MSG_WARN([Please consult docs/patents.txt with your lawyer before building Mesa.]) + DEFINES="$DEFINES -DTEXTURE_FLOAT_ENABLED" +fi + +GL_LIB_NAME='lib$(GL_LIB).'${LIB_EXTENSION} +GLU_LIB_NAME='lib$(GLU_LIB).'${LIB_EXTENSION} +GLUT_LIB_NAME='lib$(GLUT_LIB).'${LIB_EXTENSION} +GLW_LIB_NAME='lib$(GLW_LIB).'${LIB_EXTENSION} +OSMESA_LIB_NAME='lib$(OSMESA_LIB).'${LIB_EXTENSION} +EGL_LIB_NAME='lib$(EGL_LIB).'${LIB_EXTENSION} +GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION} +GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION} +VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION} +GLAPI_LIB_NAME='lib$(GLAPI_LIB).'${LIB_EXTENSION} +WAYLAND_EGL_LIB_NAME='lib$(WAYLAND_EGL_LIB).'${LIB_EXTENSION} + +GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLUT_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLUT_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLW_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLW_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +OSMESA_LIB_GLOB=${LIB_PREFIX_GLOB}'$(OSMESA_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +GLAPI_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLAPI_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' +WAYLAND_EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(WAYLAND_EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*' + +AC_SUBST([GL_LIB_NAME]) +AC_SUBST([GLU_LIB_NAME]) +AC_SUBST([GLUT_LIB_NAME]) +AC_SUBST([GLW_LIB_NAME]) +AC_SUBST([OSMESA_LIB_NAME]) +AC_SUBST([EGL_LIB_NAME]) +AC_SUBST([GLESv1_CM_LIB_NAME]) +AC_SUBST([GLESv2_LIB_NAME]) +AC_SUBST([VG_LIB_NAME]) +AC_SUBST([GLAPI_LIB_NAME]) +AC_SUBST([WAYLAND_EGL_LIB_NAME]) + +AC_SUBST([GL_LIB_GLOB]) +AC_SUBST([GLU_LIB_GLOB]) +AC_SUBST([GLUT_LIB_GLOB]) +AC_SUBST([GLW_LIB_GLOB]) +AC_SUBST([OSMESA_LIB_GLOB]) +AC_SUBST([EGL_LIB_GLOB]) +AC_SUBST([GLESv1_CM_LIB_GLOB]) +AC_SUBST([GLESv2_LIB_GLOB]) +AC_SUBST([VG_LIB_GLOB]) +AC_SUBST([GLAPI_LIB_GLOB]) +AC_SUBST([WAYLAND_EGL_LIB_GLOB]) + +dnl +dnl Arch/platform-specific settings +dnl +AC_ARG_ENABLE([asm], + [AS_HELP_STRING([--disable-asm], + [disable assembly usage @<:@default=enabled on supported plaforms@:>@])], + [enable_asm="$enableval"], + [enable_asm=yes] +) +asm_arch="" +ASM_FLAGS="" +MESA_ASM_SOURCES="" +GLAPI_ASM_SOURCES="" +AC_MSG_CHECKING([whether to enable assembly]) +test "x$enable_asm" = xno && AC_MSG_RESULT([no]) +# disable if cross compiling on x86/x86_64 since we must run gen_matypes +if test "x$enable_asm" = xyes && test "x$cross_compiling" = xyes; then + case "$host_cpu" in + i?86 | x86_64) + enable_asm=no + AC_MSG_RESULT([no, cross compiling]) + ;; + esac +fi +# check for supported arches +if test "x$enable_asm" = xyes; then + case "$host_cpu" in + i?86) + case "$host_os" in + linux* | *freebsd* | dragonfly* | *netbsd*) + test "x$enable_64bit" = xyes && asm_arch=x86_64 || asm_arch=x86 + ;; + esac + ;; + x86_64) + case "$host_os" in + linux* | *freebsd* | dragonfly* | *netbsd*) + test "x$enable_32bit" = xyes && asm_arch=x86 || asm_arch=x86_64 + ;; + esac + ;; + powerpc) + case "$host_os" in + linux*) + asm_arch=ppc + ;; + esac + ;; + sparc*) + case "$host_os" in + linux*) + asm_arch=sparc + ;; + esac + ;; + esac + + case "$asm_arch" in + x86) + ASM_FLAGS="-DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM" + MESA_ASM_SOURCES='$(X86_SOURCES)' + GLAPI_ASM_SOURCES='$(X86_API)' + AC_MSG_RESULT([yes, x86]) + ;; + x86_64) + ASM_FLAGS="-DUSE_X86_64_ASM" + MESA_ASM_SOURCES='$(X86-64_SOURCES)' + GLAPI_ASM_SOURCES='$(X86-64_API)' + AC_MSG_RESULT([yes, x86_64]) + ;; + ppc) + ASM_FLAGS="-DUSE_PPC_ASM -DUSE_VMX_ASM" + MESA_ASM_SOURCES='$(PPC_SOURCES)' + AC_MSG_RESULT([yes, ppc]) + ;; + sparc) + ASM_FLAGS="-DUSE_SPARC_ASM" + MESA_ASM_SOURCES='$(SPARC_SOURCES)' + GLAPI_ASM_SOURCES='$(SPARC_API)' + AC_MSG_RESULT([yes, sparc]) + ;; + *) + AC_MSG_RESULT([no, platform not supported]) + ;; + esac +fi +AC_SUBST([ASM_FLAGS]) +AC_SUBST([MESA_ASM_SOURCES]) +AC_SUBST([GLAPI_ASM_SOURCES]) + +dnl PIC code macro +MESA_PIC_FLAGS + +dnl Check to see if dlopen is in default libraries (like Solaris, which +dnl has it in libc), or if libdl is needed to get it. +AC_CHECK_FUNC([dlopen], [], + [AC_CHECK_LIB([dl], [dlopen], [DLOPEN_LIBS="-ldl"])]) +AC_SUBST([DLOPEN_LIBS]) + +dnl See if posix_memalign is available +AC_CHECK_FUNC([posix_memalign], [DEFINES="$DEFINES -DHAVE_POSIX_MEMALIGN"]) + +dnl SELinux awareness. +AC_ARG_ENABLE([selinux], + [AS_HELP_STRING([--enable-selinux], + [Build SELinux-aware Mesa @<:@default=disabled@:>@])], + [MESA_SELINUX="$enableval"], + [MESA_SELINUX=no]) +if test "x$enable_selinux" = "xyes"; then + AC_CHECK_HEADER([selinux/selinux.h],[], + [AC_MSG_ERROR([SELinux headers not found])]) + AC_CHECK_LIB([selinux],[is_selinux_enabled],[], + [AC_MSG_ERROR([SELinux library not found])]) + SELINUX_LIBS="-lselinux" + DEFINES="$DEFINES -DMESA_SELINUX" +fi + +dnl Determine which APIs to support +AC_ARG_ENABLE([opengl], + [AS_HELP_STRING([--disable-opengl], + [disable support for standard OpenGL API @<:@default=no@:>@])], + [enable_opengl="$enableval"], + [enable_opengl=yes]) +AC_ARG_ENABLE([gles1], + [AS_HELP_STRING([--enable-gles1], + [enable support for OpenGL ES 1.x API @<:@default=no@:>@])], + [enable_gles1="$enableval"], + [enable_gles1=no]) +AC_ARG_ENABLE([gles2], + [AS_HELP_STRING([--enable-gles2], + [enable support for OpenGL ES 2.x API @<:@default=no@:>@])], + [enable_gles2="$enableval"], + [enable_gles2=no]) +AC_ARG_ENABLE([gles-overlay], + [AS_HELP_STRING([--enable-gles-overlay], + [DEPRECATED. Same as --enable-gles1 and --enable-gles2])], + [enable_gles1="$enableval"; enable_gles2="$enableval"], + []) + +AC_ARG_ENABLE([openvg], + [AS_HELP_STRING([--enable-openvg], + [enable support for OpenVG API @<:@default=no@:>@])], + [enable_openvg="$enableval"], + [enable_openvg=no]) + +dnl smooth the transition; should be removed eventually +if test "x$enable_openvg" = xno; then + case "x$with_state_trackers" in + x*vega*) + AC_MSG_WARN([vega state tracker is enabled without --enable-openvg]) + enable_openvg=yes + ;; + esac +fi + +if test "x$enable_opengl" = xno -a \ + "x$enable_gles1" = xno -a \ + "x$enable_gles2" = xno -a \ + "x$enable_openvg" = xno; then + AC_MSG_ERROR([at least one API should be enabled]) +fi + +API_DEFINES="" +if test "x$enable_opengl" = xno; then + API_DEFINES="$API_DEFINES -DFEATURE_GL=0" +else + API_DEFINES="$API_DEFINES -DFEATURE_GL=1" +fi +if test "x$enable_gles1" = xyes; then + API_DEFINES="$API_DEFINES -DFEATURE_ES1=1" +fi +if test "x$enable_gles2" = xyes; then + API_DEFINES="$API_DEFINES -DFEATURE_ES2=1" +fi +AC_SUBST([API_DEFINES]) + +AC_ARG_ENABLE([shared-glapi], + [AS_HELP_STRING([--enable-shared-glapi], + [EXPERIMENTAL. Enable shared glapi for OpenGL @<:@default=no@:>@])], + [enable_shared_glapi="$enableval"], + [enable_shared_glapi=no]) + +SHARED_GLAPI="0" +if test "x$enable_shared_glapi" = xyes; then + SHARED_GLAPI="1" +fi +AC_SUBST([SHARED_GLAPI]) + +dnl +dnl Driver configuration. Options are xlib, dri and osmesa right now. +dnl More later: fbdev, ... +dnl +default_driver="xlib" + +case "$host_os" in +linux*) + case "$host_cpu" in + i*86|x86_64|powerpc*|sparc*) default_driver="dri";; + esac + ;; +*freebsd* | dragonfly* | *netbsd*) + case "$host_cpu" in + i*86|x86_64|powerpc*|sparc*) default_driver="dri";; + esac + ;; +esac + +if test "x$enable_opengl" = xno; then + default_driver="no" +fi + +AC_ARG_WITH([driver], + [AS_HELP_STRING([--with-driver=DRIVER], + [driver for Mesa: xlib,dri,osmesa @<:@default=dri when available, or xlib@:>@])], + [mesa_driver="$withval"], + [mesa_driver="$default_driver"]) +dnl Check for valid option +case "x$mesa_driver" in +xxlib|xdri|xosmesa) + if test "x$enable_opengl" = xno; then + AC_MSG_ERROR([Driver '$mesa_driver' requires OpenGL enabled]) + fi + ;; +xno) + ;; +*) + AC_MSG_ERROR([Driver '$mesa_driver' is not a valid option]) + ;; +esac + +dnl +dnl Driver specific build directories +dnl + +dnl this variable will be prepended to SRC_DIRS and is not exported +CORE_DIRS="" + +SRC_DIRS="" +GLU_DIRS="sgi" +GALLIUM_DIRS="auxiliary drivers state_trackers" +GALLIUM_TARGET_DIRS="" +GALLIUM_WINSYS_DIRS="sw" +GALLIUM_DRIVERS_DIRS="softpipe failover galahad trace rbug noop identity" +GALLIUM_STATE_TRACKERS_DIRS="" + +# build shared-glapi if enabled for OpenGL or if OpenGL ES is enabled +case "x$enable_shared_glapi$enable_gles1$enable_gles2" in +x*yes*) + CORE_DIRS="$CORE_DIRS mapi/shared-glapi" + ;; +esac + +# build glapi if OpenGL is enabled +if test "x$enable_opengl" = xyes; then + CORE_DIRS="$CORE_DIRS mapi/glapi" +fi + +# build es1api if OpenGL ES 1.x is enabled +if test "x$enable_gles1" = xyes; then + CORE_DIRS="$CORE_DIRS mapi/es1api" +fi + +# build es2api if OpenGL ES 2.x is enabled +if test "x$enable_gles2" = xyes; then + CORE_DIRS="$CORE_DIRS mapi/es2api" +fi + +# build vgapi if OpenVG is enabled +if test "x$enable_openvg" = xyes; then + CORE_DIRS="$CORE_DIRS mapi/vgapi" +fi + +# build glsl and mesa if OpenGL or OpenGL ES is enabled +case "x$enable_opengl$enable_gles1$enable_gles2" in +x*yes*) + CORE_DIRS="$CORE_DIRS glsl mesa" + ;; +esac + +case "$mesa_driver" in +xlib) + DRIVER_DIRS="x11" + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib" + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS libgl-xlib" + ;; +dri) + SRC_DIRS="$SRC_DIRS glx" + DRIVER_DIRS="dri" + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib sw/dri" + ;; +osmesa) + DRIVER_DIRS="osmesa" + ;; +no) + DRIVER_DRIS="" + ;; +esac +AC_SUBST([SRC_DIRS]) +AC_SUBST([GLU_DIRS]) +AC_SUBST([DRIVER_DIRS]) +AC_SUBST([GALLIUM_DIRS]) +AC_SUBST([GALLIUM_TARGET_DIRS]) +AC_SUBST([GALLIUM_WINSYS_DIRS]) +AC_SUBST([GALLIUM_DRIVERS_DIRS]) +AC_SUBST([GALLIUM_STATE_TRACKERS_DIRS]) +AC_SUBST([MESA_LLVM]) + +dnl +dnl Find out if X is available. The variable have_x is set if libX11 is +dnl found to mimic AC_PATH_XTRA. +dnl +if test -n "$PKG_CONFIG"; then + AC_MSG_CHECKING([pkg-config files for X11 are available]) + PKG_CHECK_EXISTS([x11],[ + x11_pkgconfig=yes + have_x=yes + ],[ + x11_pkgconfig=no + ]) + AC_MSG_RESULT([$x11_pkgconfig]) +else + x11_pkgconfig=no +fi +dnl Use the autoconf macro if no pkg-config files +if test "$x11_pkgconfig" = yes; then + PKG_CHECK_MODULES([X11], [x11]) +else + AC_PATH_XTRA + test -z "$X11_CFLAGS" && X11_CFLAGS="$X_CFLAGS" + test -z "$X11_LIBS" && X11_LIBS="$X_LIBS -lX11" + AC_SUBST([X11_CFLAGS]) + AC_SUBST([X11_LIBS]) +fi + +dnl Try to tell the user that the --x-* options are only used when +dnl pkg-config is not available. This must be right after AC_PATH_XTRA. +m4_divert_once([HELP_BEGIN], +[These options are only used when the X libraries cannot be found by the +pkg-config utility.]) + +dnl We need X for xlib and dri, so bomb now if it's not found +case "$mesa_driver" in +xlib|dri) + if test "$no_x" = yes; then + AC_MSG_ERROR([X11 development libraries needed for $mesa_driver driver]) + fi + ;; +esac + +dnl XCB - this is only used for GLX right now +AC_ARG_ENABLE([xcb], + [AS_HELP_STRING([--enable-xcb], + [use XCB for GLX @<:@default=disabled@:>@])], + [enable_xcb="$enableval"], + [enable_xcb=no]) +if test "x$enable_xcb" = xyes; then + DEFINES="$DEFINES -DUSE_XCB" +else + enable_xcb=no +fi + +dnl Direct rendering or just indirect rendering +case "$host_os" in +gnu*) + dnl Disable by default on GNU/Hurd + driglx_direct_default="no" + ;; +cygwin*) + dnl Disable by default on cygwin + driglx_direct_default="no" + ;; +*) + driglx_direct_default="yes" + ;; +esac +AC_ARG_ENABLE([driglx-direct], + [AS_HELP_STRING([--disable-driglx-direct], + [enable direct rendering in GLX and EGL for DRI \ + @<:@default=auto@:>@])], + [driglx_direct="$enableval"], + [driglx_direct="$driglx_direct_default"]) + +dnl +dnl libGL configuration per driver +dnl +case "$mesa_driver" in +xlib) + if test "$x11_pkgconfig" = yes; then + PKG_CHECK_MODULES([XLIBGL], [x11 xext]) + GL_PC_REQ_PRIV="x11 xext" + X11_INCLUDES="$X11_INCLUDES $XLIBGL_CFLAGS" + GL_LIB_DEPS="$XLIBGL_LIBS" + else + # should check these... + X11_INCLUDES="$X11_INCLUDES $X_CFLAGS" + GL_LIB_DEPS="$X_LIBS -lX11 -lXext" + GL_PC_LIB_PRIV="$GL_LIB_DEPS" + GL_PC_CFLAGS="$X11_INCLUDES" + fi + GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread" + GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread" + + # if static, move the external libraries to the programs + # and empty the libraries for libGL + if test "$enable_static" = yes; then + APP_LIB_DEPS="$APP_LIB_DEPS $GL_LIB_DEPS" + GL_LIB_DEPS="" + fi + ;; +dri|no) # these checks are still desired when there is no mesa_driver + # DRI must be shared, I think + if test "$enable_static" = yes; then + AC_MSG_ERROR([Can't use static libraries for DRI drivers]) + fi + + PKG_CHECK_MODULES([GLPROTO], [glproto >= $GLPROTO_REQUIRED]) + GL_PC_REQ_PRIV="glproto >= $GLPROTO_REQUIRED" + DRI_PC_REQ_PRIV="" + + if test x"$driglx_direct" = xyes; then + # Check for libdrm + PKG_CHECK_MODULES([LIBDRM], [libdrm >= $LIBDRM_REQUIRED]) + PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED]) + GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" + DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" + fi + + # find the DRI deps for libGL + if test "$x11_pkgconfig" = yes; then + dri_modules="x11 xext xdamage xfixes" + + # add xf86vidmode if available + PKG_CHECK_MODULES([XF86VIDMODE], [xxf86vm], HAVE_XF86VIDMODE=yes, HAVE_XF86VIDMODE=no) + if test "$HAVE_XF86VIDMODE" = yes ; then + dri_modules="$dri_modules xxf86vm" + fi + + # add xcb modules if necessary + if test "$enable_xcb" = yes; then + dri_modules="$dri_modules x11-xcb xcb-glx" + fi + + PKG_CHECK_MODULES([DRIGL], [$dri_modules]) + GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV $dri_modules" + X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS" + GL_LIB_DEPS="$DRIGL_LIBS" + else + # should check these... + X11_INCLUDES="$X11_INCLUDES $X_CFLAGS" + GL_LIB_DEPS="$X_LIBS -lX11 -lXext -lXxf86vm -lXdamage -lXfixes" + GL_PC_LIB_PRIV="$GL_LIB_DEPS" + GL_PC_CFLAGS="$X11_INCLUDES" + + # XCB can only be used from pkg-config + if test "$enable_xcb" = yes; then + PKG_CHECK_MODULES([XCB],[x11-xcb xcb-glx]) + GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV x11-xcb xcb-glx" + X11_INCLUDES="$X11_INCLUDES $XCB_CFLAGS" + GL_LIB_DEPS="$GL_LIB_DEPS $XCB_LIBS" + fi + fi + + # need DRM libs, -lpthread, etc. + GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" + GL_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" + GLESv1_CM_LIB_DEPS="$LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" + GLESv1_CM_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" + GLESv2_LIB_DEPS="$LIBDRM_LIBS -lm -lpthread $DLOPEN_LIBS" + GLESv2_PC_LIB_PRIV="-lm -lpthread $DLOPEN_LIBS" + ;; +osmesa) + # No libGL for osmesa + GL_LIB_DEPS="" + ;; +esac +AC_SUBST([GL_LIB_DEPS]) +AC_SUBST([GL_PC_REQ_PRIV]) +AC_SUBST([GL_PC_LIB_PRIV]) +AC_SUBST([GL_PC_CFLAGS]) +AC_SUBST([DRI_PC_REQ_PRIV]) +AC_SUBST([GLESv1_CM_LIB_DEPS]) +AC_SUBST([GLESv1_CM_PC_LIB_PRIV]) +AC_SUBST([GLESv2_LIB_DEPS]) +AC_SUBST([GLESv2_PC_LIB_PRIV]) + +GLAPI_LIB_DEPS="-lpthread" +AC_SUBST([GLAPI_LIB_DEPS]) + + +dnl Setup default DRI CFLAGS +DRI_CFLAGS='$(CFLAGS)' +DRI_CXXFLAGS='$(CXXFLAGS)' +DRI_LIB_DEPS='$(TOP)/src/mesa/libmesa.a' +MESA_MODULES='$(TOP)/src/mesa/libmesa.a' + +AC_ARG_ENABLE([shared-dricore], + [AS_HELP_STRING([--enable-shared-dricore], + [link DRI modules with shared core DRI routines @<:@default=disabled@:>@])], + [enable_dricore="$enableval"], + [enable_dricore=no]) +if test "$mesa_driver" = dri ; then + if test "$enable_dricore" = yes ; then + if test "$GCC$GXX" != yesyes ; then + AC_MSG_WARN([Shared dricore requires GCC-compatible rpath handling. Disabling shared dricore]) + enable_dricore=no + else + DRICORE_GLSL_LIBS='$(TOP)/$(LIB_DIR)/libglsl.so' + DRICORE_LIBS='$(TOP)/$(LIB_DIR)/libdricore.so' + DRICORE_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -lglsl' + DRI_LIB_DEPS='-L$(TOP)/$(LIB_DIR) -Wl,-R$(DRI_DRIVER_INSTALL_DIR) -ldricore -lglsl' + DRI_CFLAGS='$(CFLAGS_NOVISIBILITY) -DUSE_DRICORE' + DRI_CXXFLAGS='$(CXXFLAGS_NOVISIBILITY) -DUSE_DRICORE' + MESA_MODULES='$(DRICORE_LIBS) $(DRICORE_GLSL_LIBS)' + fi + fi +fi +AC_SUBST([DRICORE_LIBS]) +AC_SUBST([DRICORE_GLSL_LIBS]) +AC_SUBST([DRICORE_LIB_DEPS]) +AC_SUBST([DRI_CXXFLAGS]) +AC_SUBST([DRI_CFLAGS]) +AC_SUBST([MESA_MODULES]) + +AC_SUBST([HAVE_XF86VIDMODE]) + +PKG_CHECK_MODULES([LIBDRM_RADEON], + [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED], + HAVE_LIBDRM_RADEON=yes, + HAVE_LIBDRM_RADEON=no) + +dnl +dnl More X11 setup +dnl +if test "$mesa_driver" = xlib; then + DEFINES="$DEFINES -DUSE_XSHM" +fi + +dnl +dnl TLS detection +dnl + +AC_ARG_ENABLE([glx-tls], + [AS_HELP_STRING([--enable-glx-tls], + [enable TLS support in GLX @<:@default=disabled@:>@])], + [GLX_USE_TLS="$enableval"], + [GLX_USE_TLS=no]) +AC_SUBST(GLX_TLS, ${GLX_USE_TLS}) + +AS_IF([test "x$GLX_USE_TLS" = xyes], + [DEFINES="${DEFINES} -DGLX_USE_TLS -DPTHREADS"]) + +dnl +dnl More DRI setup +dnl +dnl Directory for DRI drivers +AC_ARG_WITH([dri-driverdir], + [AS_HELP_STRING([--with-dri-driverdir=DIR], + [directory for the DRI drivers @<:@${libdir}/dri@:>@])], + [DRI_DRIVER_INSTALL_DIR="$withval"], + [DRI_DRIVER_INSTALL_DIR='${libdir}/dri']) +AC_SUBST([DRI_DRIVER_INSTALL_DIR]) +dnl Extra search path for DRI drivers +AC_ARG_WITH([dri-searchpath], + [AS_HELP_STRING([--with-dri-searchpath=DIRS...], + [semicolon delimited DRI driver search directories @<:@${libdir}/dri@:>@])], + [DRI_DRIVER_SEARCH_DIR="$withval"], + [DRI_DRIVER_SEARCH_DIR='${DRI_DRIVER_INSTALL_DIR}']) +AC_SUBST([DRI_DRIVER_SEARCH_DIR]) +dnl Which drivers to build - default is chosen by platform +AC_ARG_WITH([dri-drivers], + [AS_HELP_STRING([--with-dri-drivers@<:@=DIRS...@:>@], + [comma delimited DRI drivers list, e.g. + "swrast,i965,radeon" @<:@default=auto@:>@])], + [with_dri_drivers="$withval"], + [with_dri_drivers=yes]) +if test "x$with_dri_drivers" = x; then + with_dri_drivers=no +fi + +dnl If $with_dri_drivers is yes, directories will be added through +dnl platform checks +DRI_DIRS="" +case "$with_dri_drivers" in +no) ;; +yes) + DRI_DIRS="yes" + ;; +*) + # verify the requested driver directories exist + dri_drivers=`IFS=', '; echo $with_dri_drivers` + for driver in $dri_drivers; do + test -d "$srcdir/src/mesa/drivers/dri/$driver" || \ + AC_MSG_ERROR([DRI driver directory '$driver' doesn't exist]) + done + DRI_DIRS="$dri_drivers" + ;; +esac + +dnl Set DRI_DIRS, DEFINES and LIB_DEPS +if test "$mesa_driver" = dri -o "$mesa_driver" = no; then + # Platform specific settings and drivers to build + case "$host_os" in + linux*) + DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" + if test "x$driglx_direct" = xyes; then + DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" + fi + DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING -DHAVE_ALIAS" + + case "$host_cpu" in + x86_64) + # sis is missing because they have not be converted to use + # the new interface. i810 are missing because there is no + # x86-64 system where they could *ever* be used. + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="i915 i965 mach64 mga r128 r200 r300 r600 radeon \ + savage tdfx unichrome swrast" + fi + ;; + powerpc*) + # Build only the drivers for cards that exist on PowerPC. + # At some point MGA will be added, but not yet. + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="mach64 r128 r200 r300 r600 radeon tdfx swrast" + fi + ;; + sparc*) + # Build only the drivers for cards that exist on sparc` + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="mach64 r128 r200 r300 r600 radeon swrast" + fi + ;; + esac + ;; + freebsd* | dragonfly* | *netbsd*) + DEFINES="$DEFINES -DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1" + DEFINES="$DEFINES -DIN_DRI_DRIVER -DHAVE_ALIAS" + DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" + if test "x$driglx_direct" = xyes; then + DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" + fi + + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 r600 radeon tdfx \ + unichrome savage sis swrast" + fi + ;; + gnu*) + DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" + DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING -DHAVE_ALIAS" + ;; + solaris*) + DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" + DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" + if test "x$driglx_direct" = xyes; then + DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" + fi + ;; + cygwin*) + DEFINES="$DEFINES -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER" + DEFINES="$DEFINES -DGLX_INDIRECT_RENDERING" + if test "x$driglx_direct" = xyes; then + DEFINES="$DEFINES -DGLX_DIRECT_RENDERING" + fi + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="swrast" + fi + ;; + esac + + # default drivers + if test "x$DRI_DIRS" = "xyes"; then + DRI_DIRS="i810 i915 i965 mach64 mga r128 r200 r300 r600 radeon \ + savage sis tdfx unichrome swrast" + fi + + DRI_DIRS=`echo "$DRI_DIRS" | $SED 's/ */ /g'` + + # Check for expat + if test "$mesa_driver" = dri; then + EXPAT_INCLUDES="" + EXPAT_LIB=-lexpat + AC_ARG_WITH([expat], + [AS_HELP_STRING([--with-expat=DIR], + [expat install directory])],[ + EXPAT_INCLUDES="-I$withval/include" + CPPFLAGS="$CPPFLAGS $EXPAT_INCLUDES" + LDFLAGS="$LDFLAGS -L$withval/$LIB_DIR" + EXPAT_LIB="-L$withval/$LIB_DIR -lexpat" + ]) + AC_CHECK_HEADER([expat.h],[],[AC_MSG_ERROR([Expat required for DRI.])]) + AC_CHECK_LIB([expat],[XML_ParserCreate],[], + [AC_MSG_ERROR([Expat required for DRI.])]) + fi + + # put all the necessary libs together, including possibly libdricore + DRI_LIB_DEPS="$DRI_LIB_DEPS $SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS" +fi +AC_SUBST([DRI_DIRS]) +AC_SUBST([EXPAT_INCLUDES]) +AC_SUBST([DRI_LIB_DEPS]) + +case $DRI_DIRS in +*i915*|*i965*) + PKG_CHECK_MODULES([INTEL], [libdrm_intel >= $LIBDRM_INTEL_REQUIRED]) + ;; +esac + +case $DRI_DIRS in +*radeon*|*r200*|*r300*|*r600*) + if test "x$HAVE_LIBDRM_RADEON" = xyes; then + RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" + RADEON_LDFLAGS=$LIBDRM_RADEON_LIBS + fi + ;; +esac +AC_SUBST([RADEON_CFLAGS]) +AC_SUBST([RADEON_LDFLAGS]) + + +dnl +dnl OSMesa configuration +dnl +if test "$mesa_driver" = xlib; then + default_gl_osmesa=yes +else + default_gl_osmesa=no +fi +AC_ARG_ENABLE([gl-osmesa], + [AS_HELP_STRING([--enable-gl-osmesa], + [enable OSMesa with libGL @<:@default=enabled for xlib driver@:>@])], + [gl_osmesa="$enableval"], + [gl_osmesa="$default_gl_osmesa"]) +if test "x$gl_osmesa" = xyes; then + if test "x$enable_opengl" = xno; then + AC_MSG_ERROR([OpenGL is not available for OSMesa driver]) + fi + if test "$mesa_driver" = osmesa; then + AC_MSG_ERROR([libGL is not available for OSMesa driver]) + else + DRIVER_DIRS="$DRIVER_DIRS osmesa" + fi +fi + +dnl Configure the channel bits for OSMesa (libOSMesa, libOSMesa16, ...) +AC_ARG_WITH([osmesa-bits], + [AS_HELP_STRING([--with-osmesa-bits=BITS], + [OSMesa channel bits and library name: 8, 16, 32 @<:@default=8@:>@])], + [osmesa_bits="$withval"], + [osmesa_bits=8]) +if test "$mesa_driver" != osmesa && test "x$osmesa_bits" != x8; then + AC_MSG_WARN([Ignoring OSMesa channel bits for non-OSMesa driver]) + osmesa_bits=8 +fi +case "x$osmesa_bits" in +x8) + OSMESA_LIB=OSMesa + ;; +x16|x32) + OSMESA_LIB="OSMesa$osmesa_bits" + DEFINES="$DEFINES -DCHAN_BITS=$osmesa_bits -DDEFAULT_SOFTWARE_DEPTH_BITS=31" + ;; +*) + AC_MSG_ERROR([OSMesa bits '$osmesa_bits' is not a valid option]) + ;; +esac +AC_SUBST([OSMESA_LIB]) + +case "$DRIVER_DIRS" in +*osmesa*) + # only link libraries with osmesa if shared + if test "$enable_static" = no; then + OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" + else + OSMESA_LIB_DEPS="" + fi + OSMESA_MESA_DEPS="" + OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS" + ;; +esac +AC_SUBST([OSMESA_LIB_DEPS]) +AC_SUBST([OSMESA_MESA_DEPS]) +AC_SUBST([OSMESA_PC_REQ]) +AC_SUBST([OSMESA_PC_LIB_PRIV]) + +dnl +dnl EGL configuration +dnl +AC_ARG_ENABLE([egl], + [AS_HELP_STRING([--disable-egl], + [disable EGL library @<:@default=enabled@:>@])], + [enable_egl="$enableval"], + [enable_egl=yes]) +if test "x$enable_egl" = xno; then + if test "x$mesa_driver" = xno; then + AC_MSG_ERROR([cannot disable EGL when there is no mesa driver]) + fi + if test "x$enable_openvg" = xyes; then + AC_MSG_ERROR([cannot enable OpenVG without EGL]) + fi +fi +if test "x$enable_egl" = xyes; then + SRC_DIRS="$SRC_DIRS egl" + EGL_LIB_DEPS="$DLOPEN_LIBS -lpthread" + EGL_DRIVERS_DIRS="" + if test "$enable_static" != yes; then + # build egl_glx when libGL is built + if test "$mesa_driver" = xlib -o "$mesa_driver" = dri; then + EGL_DRIVERS_DIRS="glx" + fi + + if test "$mesa_driver" = dri; then + # build egl_dri2 when xcb-dri2 is available + PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb-dri2 xcb-xfixes], + [have_xcb_dri2=yes],[have_xcb_dri2=no]) + PKG_CHECK_MODULES([LIBUDEV], [libudev > 150], + [have_libudev=yes],[have_libudev=no]) + + if test "$have_xcb_dri2" = yes; then + EGL_DRIVER_DRI2=dri2 + DEFINES="$DEFINES -DHAVE_XCB_DRI2" + if test "$have_libudev" = yes; then + DEFINES="$DEFINES -DHAVE_LIBUDEV" + fi + # workaround a bug in xcb-dri2 generated by xcb-proto 1.6 + AC_CHECK_LIB(xcb-dri2, xcb_dri2_connect_alignment_pad, [], + [DEFINES="$DEFINES -DXCB_DRI2_CONNECT_DEVICE_NAME_BROKEN"]) + fi + fi + + EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS $EGL_DRIVER_DRI2" + fi +fi +AC_SUBST([EGL_LIB_DEPS]) +AC_SUBST([EGL_DRIVERS_DIRS]) + +dnl +dnl GLU configuration +dnl +AC_ARG_ENABLE([glu], + [AS_HELP_STRING([--disable-glu], + [enable OpenGL Utility library @<:@default=enabled@:>@])], + [enable_glu="$enableval"], + [enable_glu=yes]) + +if test "x$enable_glu" = xyes -a "x$mesa_driver" = xno; then + AC_MSG_NOTICE([Disabling GLU since there is no OpenGL driver]) + enable_glu=no +fi + +if test "x$enable_glu" = xyes; then + SRC_DIRS="$SRC_DIRS glu" + + case "$mesa_driver" in + osmesa) + # Link libGLU to libOSMesa instead of libGL + GLU_LIB_DEPS="" + GLU_PC_REQ="osmesa" + if test "$enable_static" = no; then + GLU_MESA_DEPS='-l$(OSMESA_LIB)' + else + GLU_MESA_DEPS="" + fi + ;; + *) + # If static, empty GLU_LIB_DEPS and add libs for programs to link + GLU_PC_REQ="gl" + GLU_PC_LIB_PRIV="-lm" + if test "$enable_static" = no; then + GLU_LIB_DEPS="-lm" + GLU_MESA_DEPS='-l$(GL_LIB)' + else + GLU_LIB_DEPS="" + GLU_MESA_DEPS="" + APP_LIB_DEPS="$APP_LIB_DEPS -lstdc++" + fi + ;; + esac +fi +if test "$enable_static" = no; then + GLU_LIB_DEPS="$GLU_LIB_DEPS $OS_CPLUSPLUS_LIBS" +fi +GLU_PC_LIB_PRIV="$GLU_PC_LIB_PRIV $OS_CPLUSPLUS_LIBS" +AC_SUBST([GLU_LIB_DEPS]) +AC_SUBST([GLU_MESA_DEPS]) +AC_SUBST([GLU_PC_REQ]) +AC_SUBST([GLU_PC_REQ_PRIV]) +AC_SUBST([GLU_PC_LIB_PRIV]) +AC_SUBST([GLU_PC_CFLAGS]) + +dnl +dnl GLw configuration +dnl +AC_ARG_ENABLE([glw], + [AS_HELP_STRING([--disable-glw], + [enable Xt/Motif widget library @<:@default=enabled@:>@])], + [enable_glw="$enableval"], + [enable_glw=yes]) +dnl Don't build GLw on osmesa +if test "x$enable_glw" = xyes; then + case "$mesa_driver" in + osmesa|no) + AC_MSG_NOTICE([Disabling GLw since there is no OpenGL driver]) + enable_glw=no + ;; + esac +fi +AC_ARG_ENABLE([motif], + [AS_HELP_STRING([--enable-motif], + [use Motif widgets in GLw @<:@default=disabled@:>@])], + [enable_motif="$enableval"], + [enable_motif=no]) + +if test "x$enable_glw" = xyes; then + SRC_DIRS="$SRC_DIRS glw" + if test "$x11_pkgconfig" = yes; then + PKG_CHECK_MODULES([GLW],[x11 xt]) + GLW_PC_REQ_PRIV="x11 xt" + GLW_LIB_DEPS="$GLW_LIBS" + else + # should check these... + GLW_LIB_DEPS="$X_LIBS -lXt -lX11" + GLW_PC_LIB_PRIV="$GLW_LIB_DEPS" + GLW_PC_CFLAGS="$X11_INCLUDES" + fi + + GLW_SOURCES="GLwDrawA.c" + MOTIF_CFLAGS= + if test "x$enable_motif" = xyes; then + GLW_SOURCES="$GLW_SOURCES GLwMDrawA.c" + AC_PATH_PROG([MOTIF_CONFIG], [motif-config], [no]) + if test "x$MOTIF_CONFIG" != xno; then + MOTIF_CFLAGS=`$MOTIF_CONFIG --cflags` + MOTIF_LIBS=`$MOTIF_CONFIG --libs` + else + AC_CHECK_HEADER([Xm/PrimitiveP.h], [], + [AC_MSG_ERROR([Can't locate Motif headers])]) + AC_CHECK_LIB([Xm], [XmGetPixmap], [MOTIF_LIBS="-lXm"], + [AC_MSG_ERROR([Can't locate Motif Xm library])]) + fi + # MOTIF_LIBS is prepended to GLW_LIB_DEPS since Xm needs Xt/X11 + GLW_LIB_DEPS="$MOTIF_LIBS $GLW_LIB_DEPS" + GLW_PC_LIB_PRIV="$MOTIF_LIBS $GLW_PC_LIB_PRIV" + GLW_PC_CFLAGS="$MOTIF_CFLAGS $GLW_PC_CFLAGS" + fi + + # If static, empty GLW_LIB_DEPS and add libs for programs to link + GLW_PC_LIB_PRIV="$GLW_PC_LIB_PRIV" + if test "$enable_static" = no; then + GLW_MESA_DEPS='-l$(GL_LIB)' + GLW_LIB_DEPS="$GLW_LIB_DEPS" + else + APP_LIB_DEPS="$APP_LIB_DEPS $GLW_LIB_DEPS" + GLW_LIB_DEPS="" + GLW_MESA_DEPS="" + fi +fi +AC_SUBST([GLW_LIB_DEPS]) +AC_SUBST([GLW_MESA_DEPS]) +AC_SUBST([GLW_SOURCES]) +AC_SUBST([MOTIF_CFLAGS]) +AC_SUBST([GLW_PC_REQ_PRIV]) +AC_SUBST([GLW_PC_LIB_PRIV]) +AC_SUBST([GLW_PC_CFLAGS]) + +dnl +dnl GLUT configuration +dnl +if test -f "$srcdir/include/GL/glut.h"; then + default_glut=yes +else + default_glut=no +fi +AC_ARG_ENABLE([glut], + [AS_HELP_STRING([--disable-glut], + [enable GLUT library @<:@default=enabled if source available@:>@])], + [enable_glut="$enableval"], + [enable_glut="$default_glut"]) + +dnl Don't build glut on osmesa +if test "x$enable_glut" = xyes; then + case "$mesa_driver" in + osmesa|no) + AC_MSG_NOTICE([Disabling glut since there is no OpenGL driver]) + enable_glut=no + ;; + esac +fi +dnl Can't build glut if GLU not available +if test "x$enable_glu$enable_glut" = xnoyes; then + AC_MSG_WARN([Disabling glut since GLU is disabled]) + enable_glut=no +fi + +if test "x$enable_glut" = xyes; then + SRC_DIRS="$SRC_DIRS glut/glx" + if test "$x11_pkgconfig" = yes; then + PKG_CHECK_MODULES([GLUT],[x11 xmu xi]) + GLUT_PC_REQ_PRIV="x11 xmu xi" + GLUT_LIB_DEPS="$GLUT_LIBS" + else + # should check these... + GLUT_LIB_DEPS="$X_LIBS -lX11 -lXmu -lXi" + GLUT_PC_LIB_PRIV="$GLUT_LIB_DEPS" + GLUT_PC_CFLAGS="$X11_INCLUDES" + fi + if test "x$GCC" = xyes; then + GLUT_CFLAGS="$GLUT_CFLAGS -fexceptions" + fi + GLUT_LIB_DEPS="$GLUT_LIB_DEPS -lm" + GLUT_PC_LIB_PRIV="$GLUT_PC_LIB_PRIV -lm" + + # If static, empty GLUT_LIB_DEPS and add libs for programs to link + if test "$enable_static" = no; then + GLUT_MESA_DEPS='-l$(GLU_LIB) -l$(GL_LIB)' + else + APP_LIB_DEPS="$APP_LIB_DEPS $GLUT_LIB_DEPS" + GLUT_LIB_DEPS="" + GLUT_MESA_DEPS="" + fi +fi +AC_SUBST([GLUT_LIB_DEPS]) +AC_SUBST([GLUT_MESA_DEPS]) +AC_SUBST([GLUT_CFLAGS]) +AC_SUBST([GLUT_PC_REQ_PRIV]) +AC_SUBST([GLUT_PC_LIB_PRIV]) +AC_SUBST([GLUT_PC_CFLAGS]) + +dnl +dnl Program library dependencies +dnl Only libm is added here if necessary as the libraries should +dnl be pulled in by the linker +dnl +if test "x$APP_LIB_DEPS" = x; then + case "$host_os" in + solaris*) + APP_LIB_DEPS="-lX11 -lsocket -lnsl -lm" + ;; + cygwin*) + APP_LIB_DEPS="-lX11" + ;; + *) + APP_LIB_DEPS="-lm" + ;; + esac +fi +AC_SUBST([APP_LIB_DEPS]) +AC_SUBST([PROGRAM_DIRS]) + +dnl +dnl Gallium configuration +dnl +AC_ARG_ENABLE([gallium], + [AS_HELP_STRING([--disable-gallium], + [build gallium @<:@default=enabled@:>@])], + [enable_gallium="$enableval"], + [enable_gallium=yes]) +if test "x$enable_gallium" = xno -a "x$enable_openvg" = xyes; then + AC_MSG_ERROR([cannot enable OpenVG without Gallium]) +fi +if test "x$enable_gallium" = xyes; then + SRC_DIRS="$SRC_DIRS gallium gallium/winsys gallium/targets" + AC_PATH_PROG([LLVM_CONFIG], [llvm-config], [no]) +fi + +AC_SUBST([LLVM_CFLAGS]) +AC_SUBST([LLVM_LIBS]) +AC_SUBST([LLVM_LDFLAGS]) +AC_SUBST([LLVM_VERSION]) + +dnl +dnl Gallium state trackers configuration +dnl + +AC_ARG_ENABLE([gallium-egl], + [AS_HELP_STRING([--enable-gallium-egl], + [enable gallium EGL state tracker @<:@default=auto@:>@])], + [enable_gallium_egl="$enableval"], + [enable_gallium_egl=auto]) +if test "x$enable_gallium_egl" = xauto; then + case "$mesa_driver" in + dri|no) + enable_gallium_egl=$enable_egl + ;; + *) + enable_gallium_egl=$enable_openvg + ;; + esac +fi +case "x$enable_egl$enable_gallium_egl" in +xnoyes) + AC_MSG_ERROR([cannot build Gallium EGL state tracker without EGL]) +esac + +AC_ARG_WITH([state-trackers], + [AS_HELP_STRING([--with-state-trackers@<:@=DIRS...@:>@], + [comma delimited state_trackers list, e.g. + "egl,glx" @<:@default=auto@:>@])], + [with_state_trackers="$withval"], + [with_state_trackers=yes]) + +case "$with_state_trackers" in +no) + GALLIUM_STATE_TRACKERS_DIRS="" + ;; +yes) + # look at what else is built + case "$mesa_driver" in + xlib) + GALLIUM_STATE_TRACKERS_DIRS=glx + ;; + dri) + GALLIUM_STATE_TRACKERS_DIRS="dri" + HAVE_ST_DRI="yes" + # Have only tested st/xorg on 1.6.0 servers + PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0 libdrm >= $LIBDRM_XORG_REQUIRED libkms >= $LIBKMS_XORG_REQUIRED], + HAVE_ST_XORG="yes"; GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS xorg", + HAVE_ST_XORG="no") + ;; + esac + + if test "x$enable_egl" = xyes; then + if test "$enable_openvg" = yes; then + GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS vega" + st_egl="yes" + fi + + if test "$enable_gallium_egl" = yes; then + GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl" + HAVE_ST_EGL="yes" + fi + fi + ;; +*) + # verify the requested state tracker exist + state_trackers="" + _state_trackers=`IFS=', '; echo $with_state_trackers` + for tracker in $_state_trackers; do + case "$tracker" in + dri) + if test "x$mesa_driver" != xdri; then + AC_MSG_ERROR([cannot build dri state tracker without mesa driver set to dri]) + fi + HAVE_ST_DRI="yes" + ;; + egl) + if test "x$enable_egl" != xyes; then + AC_MSG_ERROR([cannot build egl state tracker without EGL library]) + fi + HAVE_ST_EGL="yes" + ;; + xorg) + PKG_CHECK_MODULES([XORG], [xorg-server >= 1.6.0]) + PKG_CHECK_MODULES([LIBDRM_XORG], [libdrm >= $LIBDRM_XORG_REQUIRED]) + PKG_CHECK_MODULES([LIBKMS_XORG], [libkms >= $LIBKMS_XORG_REQUIRED]) + HAVE_ST_XORG="yes" + ;; + vega) + if test "x$enable_openvg" != xyes; then + AC_MSG_ERROR([cannot build vega state tracker without --enable-openvg]) + fi + have_st_vega="yes" + ;; + esac + + if test -n "$tracker"; then + test -d "$srcdir/src/gallium/state_trackers/$tracker" || \ + AC_MSG_ERROR([state tracker '$tracker' doesn't exist]) + if test -n "$state_trackers"; then + state_trackers="$state_trackers $tracker" + else + state_trackers="$tracker" + fi + fi + done + GALLIUM_STATE_TRACKERS_DIRS="$state_trackers" + + # append --enable-openvg/--enable-gallium-egl to --with-state-trackers + if test "x$have_st_vega" != xyes -a "x$enable_openvg" = xyes; then + AC_MSG_ERROR([--with-state-trackers specified but vega is missing]) + fi + if test "x$HAVE_ST_EGL" != xyes -a "x$enable_gallium_egl" = xyes; then + AC_MSG_ERROR([--with-state-trackers specified but egl is missing]) + fi + ;; +esac + + +EGL_CLIENT_APIS="" +VG_LIB_DEPS="" + +case "x$enable_opengl$enable_gles1$enable_gles2" in +x*yes*) + EGL_CLIENT_APIS="$EGL_CLIENT_APIS "'$(GL_LIB)' + ;; +esac +if test "x$enable_openvg" = xyes; then + EGL_CLIENT_APIS="$EGL_CLIENT_APIS "'$(VG_LIB)' + VG_LIB_DEPS="$VG_LIB_DEPS -lpthread" +fi + +AC_SUBST([VG_LIB_DEPS]) +AC_SUBST([EGL_CLIENT_APIS]) + +if test "x$HAVE_ST_EGL" = xyes; then + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl" +fi + +if test "x$HAVE_ST_XORG" = xyes; then + PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], + HAVE_XEXTPROTO_71="yes"; DEFINES="$DEFINES -DHAVE_XEXTPROTO_71", + HAVE_XEXTPROTO_71="no") +fi + +AC_ARG_WITH([egl-platforms], + [AS_HELP_STRING([--with-egl-platforms@<:@=DIRS...@:>@], + [comma delimited native platforms libEGL supports, e.g. + "x11,drm" @<:@default=auto@:>@])], + [with_egl_platforms="$withval"], + [with_egl_platforms=yes]) +AC_ARG_WITH([egl-displays], + [AS_HELP_STRING([--with-egl-displays@<:@=DIRS...@:>@], + [DEPRECATED. Use --with-egl-platforms instead])], + [with_egl_platforms="$withval"]) + +EGL_PLATFORMS="" +WAYLAND_EGL_LIB_DEPS="" + +case "$with_egl_platforms" in +yes) + if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then + EGL_PLATFORMS="x11" + if test "$mesa_driver" = dri; then + EGL_PLATFORMS="$EGL_PLATFORMS drm" + fi + fi + ;; +*) + if test "x$enable_egl" != xyes; then + AC_MSG_ERROR([cannot build egl state tracker without EGL library]) + fi + # verify the requested driver directories exist + egl_platforms=`IFS=', '; echo $with_egl_platforms` + for plat in $egl_platforms; do + test -d "$srcdir/src/gallium/state_trackers/egl/$plat" || \ + AC_MSG_ERROR([EGL platform '$plat' doesn't exist]) + if test "$plat" = "fbdev"; then + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev" + fi + if test "$plat" = "wayland"; then + PKG_CHECK_MODULES([WAYLAND], [wayland-client wayland-server],, \ + [AC_MSG_ERROR([cannot find libwayland-client])]) + WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS" + fi + done + EGL_PLATFORMS="$egl_platforms" + ;; +esac +AC_SUBST([EGL_PLATFORMS]) + +AC_SUBST([WAYLAND_EGL_LIB_DEPS]) +WAYLAND_EGL_PC_REQ_PRIV="wayland-client libdrm" +WAYLAND_EGL_PC_LIB_PRIV= +WAYLAND_EGL_PC_CFLAGS= + +AC_SUBST([WAYLAND_EGL_PC_REQ_PRIV]) +AC_SUBST([WAYLAND_EGL_PC_LIB_PRIV]) +AC_SUBST([WAYLAND_EGL_PC_CFLAGS]) + + +AC_ARG_WITH([egl-driver-dir], + [AS_HELP_STRING([--with-egl-driver-dir=DIR], + [directory for EGL drivers [[default=${libdir}/egl]]])], + [EGL_DRIVER_INSTALL_DIR="$withval"], + [EGL_DRIVER_INSTALL_DIR='${libdir}/egl']) +AC_SUBST([EGL_DRIVER_INSTALL_DIR]) + +AC_ARG_WITH([xorg-driver-dir], + [AS_HELP_STRING([--with-xorg-driver-dir=DIR], + [Default xorg driver directory[[default=${libdir}/xorg/modules/drivers]]])], + [XORG_DRIVER_INSTALL_DIR="$withval"], + [XORG_DRIVER_INSTALL_DIR="${libdir}/xorg/modules/drivers"]) +AC_SUBST([XORG_DRIVER_INSTALL_DIR]) + +AC_ARG_WITH([max-width], + [AS_HELP_STRING([--with-max-width=N], + [Maximum framebuffer width (4096)])], + [DEFINES="${DEFINES} -DMAX_WIDTH=${withval}"; + AS_IF([test "${withval}" -gt "4096"], + [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] +) +AC_ARG_WITH([max-height], + [AS_HELP_STRING([--with-max-height=N], + [Maximum framebuffer height (4096)])], + [DEFINES="${DEFINES} -DMAX_HEIGHT=${withval}"; + AS_IF([test "${withval}" -gt "4096"], + [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] +) + +dnl +dnl Gallium LLVM +dnl +AC_ARG_ENABLE([gallium-llvm], + [AS_HELP_STRING([--enable-gallium-llvm], + [build gallium LLVM support @<:@default=disabled@:>@])], + [enable_gallium_llvm="$enableval"], + [enable_gallium_llvm=auto]) +if test "x$enable_gallium_llvm" = xyes; then + if test "x$LLVM_CONFIG" != xno; then + LLVM_VERSION=`$LLVM_CONFIG --version` + LLVM_CFLAGS=`$LLVM_CONFIG --cppflags` + LLVM_LIBS="`$LLVM_CONFIG --libs` -lstdc++" + + LLVM_LDFLAGS=`$LLVM_CONFIG --ldflags` + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe" + DEFINES="$DEFINES -DGALLIUM_LLVMPIPE -D__STDC_CONSTANT_MACROS" + MESA_LLVM=1 + else + MESA_LLVM=0 + fi +else + MESA_LLVM=0 +fi + +dnl +dnl Gallium helper functions +dnl +gallium_check_st() { + if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_XORG" = xyes; then + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS $1" + fi + if test "x$HAVE_ST_DRI" = xyes && test "x$2" != x; then + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $2" + fi + if test "x$HAVE_ST_XORG" = xyes && test "x$3" != x; then + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $3" + fi +} + + +dnl +dnl Gallium SVGA configuration +dnl +AC_ARG_ENABLE([gallium-svga], + [AS_HELP_STRING([--enable-gallium-svga], + [build gallium SVGA @<:@default=disabled@:>@])], + [enable_gallium_svga="$enableval"], + [enable_gallium_svga=auto]) +if test "x$enable_gallium_svga" = xyes; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" + gallium_check_st "svga/drm" "dri-vmwgfx" "xorg-vmwgfx" +elif test "x$enable_gallium_svga" = xauto; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" +fi + +dnl +dnl Gallium i915 configuration +dnl +AC_ARG_ENABLE([gallium-i915], + [AS_HELP_STRING([--enable-gallium-i915], + [build gallium i915 @<:@default=disabled@:>@])], + [enable_gallium_i915="$enableval"], + [enable_gallium_i915=auto]) +if test "x$enable_gallium_i915" = xyes; then + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" + gallium_check_st "i915/drm" "dri-i915" "xorg-i915" +elif test "x$enable_gallium_i915" = xauto; then + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" +fi + +dnl +dnl Gallium i965 configuration +dnl +AC_ARG_ENABLE([gallium-i965], + [AS_HELP_STRING([--enable-gallium-i965], + [build gallium i965 @<:@default=disabled@:>@])], + [enable_gallium_i965="$enableval"], + [enable_gallium_i965=auto]) +if test "x$enable_gallium_i965" = xyes; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965" + gallium_check_st "i965/drm" "dri-i965" "xorg-i965" +elif test "x$enable_gallium_i965" = xauto; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965" +fi + +dnl +dnl Gallium Radeon r300g configuration +dnl +AC_ARG_ENABLE([gallium-radeon], + [AS_HELP_STRING([--enable-gallium-radeon], + [build gallium radeon @<:@default=disabled@:>@])], + [enable_gallium_radeon="$enableval"], + [enable_gallium_radeon=auto]) +if test "x$enable_gallium_radeon" = xauto; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" + gallium_check_st "radeon/drm" "dri-r300" +fi +if test "x$enable_gallium_radeon" = xyes; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" + gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon" +fi + +dnl +dnl Gallium Radeon r600g configuration +dnl +AC_ARG_ENABLE([gallium-r600], + [AS_HELP_STRING([--enable-gallium-r600], + [build gallium radeon @<:@default=disabled@:>@])], + [enable_gallium_r600="$enableval"], + [enable_gallium_r600=auto]) +if test "x$enable_gallium_r600" = xyes; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" + gallium_check_st "r600/drm" "dri-r600" +fi + +dnl +dnl Gallium Nouveau configuration +dnl +AC_ARG_ENABLE([gallium-nouveau], + [AS_HELP_STRING([--enable-gallium-nouveau], + [build gallium nouveau @<:@default=disabled@:>@])], + [enable_gallium_nouveau="$enableval"], + [enable_gallium_nouveau=no]) +if test "x$enable_gallium_nouveau" = xyes; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50 nvc0" + gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" +fi + +dnl +dnl Gallium swrast configuration +dnl +AC_ARG_ENABLE([gallium-swrast], + [AS_HELP_STRING([--enable-gallium-swrast], + [build gallium swrast @<:@default=auto@:>@])], + [enable_gallium_swrast="$enableval"], + [enable_gallium_swrast=auto]) +if test "x$enable_gallium_swrast" = xyes || test "x$enable_gallium_swrast" = xauto; then + if test "x$HAVE_ST_DRI" = xyes; then + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri-swrast" + fi +fi + +dnl prepend CORE_DIRS to SRC_DIRS +SRC_DIRS="$CORE_DIRS $SRC_DIRS" + +dnl Restore LDFLAGS and CPPFLAGS +LDFLAGS="$_SAVE_LDFLAGS" +CPPFLAGS="$_SAVE_CPPFLAGS" + +dnl Substitute the config +AC_CONFIG_FILES([configs/autoconf]) + +dnl Replace the configs/current symlink +AC_CONFIG_COMMANDS([configs],[ +if test -f configs/current || test -L configs/current; then + rm -f configs/current +fi +ln -s autoconf configs/current +]) + +AC_OUTPUT + +dnl +dnl Output some configuration info for the user +dnl +echo "" +echo " prefix: $prefix" +echo " exec_prefix: $exec_prefix" +echo " libdir: $libdir" +echo " includedir: $includedir" + +dnl API info +echo "" +echo " OpenGL: $enable_opengl (ES1: $enable_gles1 ES2: $enable_gles2)" +echo " OpenVG: $enable_openvg" + +dnl Driver info +echo "" +echo " Driver: $mesa_driver" +if test "$mesa_driver" != no; then + if echo "$DRIVER_DIRS" | grep 'osmesa' >/dev/null 2>&1; then + echo " OSMesa: lib$OSMESA_LIB" + else + echo " OSMesa: no" + fi + if test "$mesa_driver" = dri; then + # cleanup the drivers var + dri_dirs=`echo $DRI_DIRS | $SED 's/^ *//;s/ */ /;s/ *$//'` + if test "x$DRI_DIRS" = x; then + echo " DRI drivers: no" + else + echo " DRI drivers: $dri_dirs" + fi + echo " DRI driver dir: $DRI_DRIVER_INSTALL_DIR" + echo " Use XCB: $enable_xcb" + echo " Shared dricore: $enable_dricore" + fi +fi +echo "" +echo " GLU: $enable_glu" +echo " GLw: $enable_glw (Motif: $enable_motif)" +echo " glut: $enable_glut" + +dnl EGL +echo "" +echo " EGL: $enable_egl" +if test "$enable_egl" = yes; then + echo " EGL platforms: $EGL_PLATFORMS" + + egl_drivers="" + for d in $EGL_DRIVERS_DIRS; do + egl_drivers="$egl_drivers builtin:egl_$d" + done + + if test "$enable_gallium" = yes -a "$HAVE_ST_EGL" = yes; then + echo " EGL drivers: ${egl_drivers} egl_gallium" + echo " EGL Gallium STs:$EGL_CLIENT_APIS" + else + echo " EGL drivers: $egl_drivers" + fi +fi + +echo "" +if test "x$MESA_LLVM" = x1; then + echo " llvm: yes" + echo " llvm-config: $LLVM_CONFIG" + echo " llvm-version: $LLVM_VERSION" +else + echo " llvm: no" +fi + +echo "" +if echo "$SRC_DIRS" | grep 'gallium' >/dev/null 2>&1; then + echo " Gallium: yes" + echo " Gallium dirs: $GALLIUM_DIRS" + echo " Target dirs: $GALLIUM_TARGET_DIRS" + echo " Winsys dirs: $GALLIUM_WINSYS_DIRS" + echo " Driver dirs: $GALLIUM_DRIVERS_DIRS" + echo " Trackers dirs: $GALLIUM_STATE_TRACKERS_DIRS" +else + echo " Gallium: no" +fi + +dnl Libraries +echo "" +echo " Shared libs: $enable_shared" +echo " Static libs: $enable_static" + +dnl Compiler options +# cleanup the CFLAGS/CXXFLAGS/DEFINES vars +cflags=`echo $CFLAGS $OPT_FLAGS $PIC_FLAGS $ARCH_FLAGS | \ + $SED 's/^ *//;s/ */ /;s/ *$//'` +cxxflags=`echo $CXXFLAGS $OPT_FLAGS $PIC_FLAGS $ARCH_FLAGS | \ + $SED 's/^ *//;s/ */ /;s/ *$//'` +defines=`echo $DEFINES $ASM_FLAGS | $SED 's/^ *//;s/ */ /;s/ *$//'` +echo "" +echo " CFLAGS: $cflags" +echo " CXXFLAGS: $cxxflags" +echo " Macros: $defines" +echo "" +echo " PYTHON2: $PYTHON2" + +echo "" +echo " Run '${MAKE-make}' to build Mesa" +echo "" diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 339a0cbdf..e373a9453 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -12,11 +12,11 @@ Feature Status GL 3.0: -GLSL changes (GL_EXT_gpu_shader4, etc) not started +GLSL 1.30 (GL_EXT_gpu_shader4, etc.) not started Conditional rendering (GL_NV_conditional_render) DONE (swrast & softpipe) Map buffer subranges (GL_ARB_map_buffer_range) DONE Clamping controls (GL_ARB_color_buffer_float) DONE -Float textures, renderbuffers (GL_ARB_texture_float) BRANCH ~mareko/mesa floating2 +Float textures, renderbuffers (GL_ARB_texture_float) DONE (gallium r300) GL_EXT_packed_float not started GL_EXT_texture_shared_exponent not started Float depth buffers (GL_ARB_depth_buffer_float) not started @@ -45,7 +45,7 @@ Depth format cube textures 0% done GL 3.1: -GLSL 1.30 and 1.40 not started +GLSL 1.40 not started Instanced drawing (GL_ARB_draw_instanced) DONE (gallium, swrast) Buffer copying (GL_ARB_copy_buffer) DONE Primitive restart (GL_NV_primitive_restart) DONE (gallium) diff --git a/mesalib/docs/relnotes-7.11.html b/mesalib/docs/relnotes-7.11.html index c8d380e3b..131fecd18 100644 --- a/mesalib/docs/relnotes-7.11.html +++ b/mesalib/docs/relnotes-7.11.html @@ -36,12 +36,22 @@ tbd

New features

    +
  • GL_ARB_color_buffer_float (gallium drivers) +
  • GL_ARB_draw_buffers_blend (gallium)
  • GL_ARB_draw_instanced extension (gallium drivers, swrast)
  • GL_ARB_instanced_arrays extension (gallium drivers) -
  • GL_ARB_texture_compression_rgtc (gallium r600, swrast) -
  • GL_ARB_draw_buffers_blend (gallium) -
  • GL_EXT_texture_sRGB_decode (gallium drivers, swrast, i965) +
  • GL_ARB_occlusion_query2 (gallium drivers, swrast)
  • GL_ARB_sampler_objects (gallium drivers) +
  • GL_ARB_texture_compression_rgtc (gallium drivers, swrast) +
  • GL_ARB_texture_float (gallium) +
  • GL_EXT_texture_compression_latc (gallium drivers, swrast) +
  • GL_EXT_texture_compression_rgtc (gallium drivers, swrast) +
  • GL_EXT_texture_sRGB_decode (gallium drivers, swrast, i965) +
  • GL_EXT_texture_snorm (gallium drivers) +
  • GL_ATI_draw_buffers (all drivers) +
  • GL_ATI_texture_compression_3dc (gallium drivers, swrast) +
  • GL_ATI_texture_float (gallium) +
  • GL_NV_texture_barrier (gallium drivers)
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 1f6e67fa0..fdc946780 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -95,16 +95,16 @@ _token_list_append_list (token_list_t *list, token_list_t *tail); static int _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b); -static active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker); +static void +_parser_active_list_push (glcpp_parser_t *parser, + const char *identifier, + token_node_t *marker); -static active_list_t * -_active_list_pop (active_list_t *list); +static void +_parser_active_list_pop (glcpp_parser_t *parser); -int -_active_list_contains (active_list_t *list, const char *identifier); +static int +_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier); static void _glcpp_parser_expand_if (glcpp_parser_t *parser, int type, token_list_t *list); @@ -1468,7 +1468,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, /* Finally, don't expand this macro if we're already actively * expanding it, (to avoid infinite recursion). */ - if (_active_list_contains (parser->active, identifier)) { + if (_parser_active_list_contains (parser, identifier)) { /* We change the token type here from IDENTIFIER to * OTHER to prevent any future expansion of this * unexpanded token. */ @@ -1498,51 +1498,53 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser, return _glcpp_parser_expand_function (parser, node, last); } -/* Push a new identifier onto the active list, returning the new list. +/* Push a new identifier onto the parser's active list. * * Here, 'marker' is the token node that appears in the list after the * expansion of 'identifier'. That is, when the list iterator begins - * examinging 'marker', then it is time to pop this node from the + * examining 'marker', then it is time to pop this node from the * active stack. */ -active_list_t * -_active_list_push (active_list_t *list, - const char *identifier, - token_node_t *marker) +static void +_parser_active_list_push (glcpp_parser_t *parser, + const char *identifier, + token_node_t *marker) { active_list_t *node; - node = ralloc (list, active_list_t); + node = ralloc (parser->active, active_list_t); node->identifier = ralloc_strdup (node, identifier); node->marker = marker; - node->next = list; + node->next = parser->active; - return node; + parser->active = node; } -active_list_t * -_active_list_pop (active_list_t *list) +static void +_parser_active_list_pop (glcpp_parser_t *parser) { - active_list_t *node = list; + active_list_t *node = parser->active; - if (node == NULL) - return NULL; + if (node == NULL) { + parser->active = NULL; + return; + } - node = list->next; - ralloc_free (list); + node = parser->active->next; + ralloc_free (parser->active); - return node; + parser->active = node; } -int -_active_list_contains (active_list_t *list, const char *identifier) +static int +_parser_active_list_contains (glcpp_parser_t *parser, const char *identifier) { active_list_t *node; - if (list == NULL) + if (parser->active == NULL) return 0; - for (node = list; node; node = node->next) + for (node = parser->active; node; node = node->next) if (strcmp (node->identifier, identifier) == 0) return 1; @@ -1573,10 +1575,8 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, while (node) { while (parser->active && parser->active->marker == node) - parser->active = _active_list_pop (parser->active); + _parser_active_list_pop (parser); - /* Find the expansion for node, which will replace all - * nodes from node to last, inclusive. */ expansion = _glcpp_parser_expand_node (parser, node, &last); if (expansion) { token_node_t *n; @@ -1585,12 +1585,12 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, while (parser->active && parser->active->marker == n) { - parser->active = _active_list_pop (parser->active); + _parser_active_list_pop (parser); } - parser->active = _active_list_push (parser->active, - node->token->value.str, - last->next); + _parser_active_list_push (parser, + node->token->value.str, + last->next); /* Splice expansion into list, supporting a * simple deletion if the expansion is @@ -1618,7 +1618,7 @@ _glcpp_parser_expand_token_list (glcpp_parser_t *parser, } while (parser->active) - parser->active = _active_list_pop (parser->active); + _parser_active_list_pop (parser); list->non_space_tail = list->tail; } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index c45265900..8a0ab9615 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -124,6 +124,7 @@ static const struct extension extension_table[] = { { "GL_ARB_texture_env_combine", o(ARB_texture_env_combine), GL, 2001 }, { "GL_ARB_texture_env_crossbar", o(ARB_texture_env_crossbar), GL, 2001 }, { "GL_ARB_texture_env_dot3", o(ARB_texture_env_dot3), GL, 2001 }, + { "GL_ARB_texture_float", o(ARB_texture_float), GL, 2004 }, { "GL_ARB_texture_mirrored_repeat", o(ARB_texture_mirrored_repeat), GL, 2001 }, { "GL_ARB_texture_multisample", o(ARB_texture_multisample), GL, 2009 }, { "GL_ARB_texture_non_power_of_two", o(ARB_texture_non_power_of_two), GL, 2003 }, @@ -268,6 +269,7 @@ static const struct extension extension_table[] = { { "GL_ATI_separate_stencil", o(ATI_separate_stencil), GL, 2006 }, { "GL_ATI_texture_compression_3dc", o(ATI_texture_compression_3dc), GL, 2004 }, { "GL_ATI_texture_env_combine3", o(ATI_texture_env_combine3), GL, 2002 }, + { "GL_ATI_texture_float", o(ARB_texture_float), GL, 2002 }, { "GL_ATI_texture_mirror_once", o(ATI_texture_mirror_once), GL, 2006 }, { "GL_IBM_multimode_draw_arrays", o(IBM_multimode_draw_arrays), GL, 1998 }, { "GL_IBM_rasterpos_clip", o(IBM_rasterpos_clip), GL, 1996 }, @@ -278,7 +280,6 @@ static const struct extension extension_table[] = { { "GL_MESA_texture_array", o(MESA_texture_array), GL, 2007 }, { "GL_MESA_texture_signed_rgba", o(EXT_texture_snorm), GL, 2009 }, { "GL_MESA_window_pos", o(ARB_window_pos), GL, 2000 }, - { "GL_MESAX_texture_float", o(ARB_texture_float), GL, 2009 }, { "GL_MESA_ycbcr_texture", o(MESA_ycbcr_texture), GL, 2002 }, { "GL_NV_blend_square", o(NV_blend_square), GL, 1999 }, { "GL_NV_conditional_render", o(NV_conditional_render), GL, 2008 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 76493f1a8..1edb310ea 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1,2496 +1,2526 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -/* - * GL_EXT/ARB_framebuffer_object extensions - * - * Authors: - * Brian Paul - */ - - -#include "buffers.h" -#include "context.h" -#include "enums.h" -#include "fbobject.h" -#include "formats.h" -#include "framebuffer.h" -#include "hash.h" -#include "macros.h" -#include "mfeatures.h" -#include "mtypes.h" -#include "renderbuffer.h" -#include "state.h" -#include "teximage.h" -#include "texobj.h" - - -/** Set this to 1 to help debug FBO incompleteness problems */ -#define DEBUG_FBO 0 - -/** Set this to 1 to debug/log glBlitFramebuffer() calls */ -#define DEBUG_BLIT 0 - - -/** - * Notes: - * - * None of the GL_EXT_framebuffer_object functions are compiled into - * display lists. - */ - - - -/* - * When glGenRender/FramebuffersEXT() is called we insert pointers to - * these placeholder objects into the hash table. - * Later, when the object ID is first bound, we replace the placeholder - * with the real frame/renderbuffer. - */ -static struct gl_framebuffer DummyFramebuffer; -static struct gl_renderbuffer DummyRenderbuffer; - -/* We bind this framebuffer when applications pass a NULL - * drawable/surface in make current. */ -static struct gl_framebuffer IncompleteFramebuffer; - - -#define IS_CUBE_FACE(TARGET) \ - ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \ - (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) - - -static void -delete_dummy_renderbuffer(struct gl_renderbuffer *rb) -{ - /* no op */ -} - -static void -delete_dummy_framebuffer(struct gl_framebuffer *fb) -{ - /* no op */ -} - - -void -_mesa_init_fbobjects(struct gl_context *ctx) -{ - _glthread_INIT_MUTEX(DummyFramebuffer.Mutex); - _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex); - _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex); - DummyFramebuffer.Delete = delete_dummy_framebuffer; - DummyRenderbuffer.Delete = delete_dummy_renderbuffer; - IncompleteFramebuffer.Delete = delete_dummy_framebuffer; -} - -struct gl_framebuffer * -_mesa_get_incomplete_framebuffer(void) -{ - return &IncompleteFramebuffer; -} - -/** - * Helper routine for getting a gl_renderbuffer. - */ -struct gl_renderbuffer * -_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id) -{ - struct gl_renderbuffer *rb; - - if (id == 0) - return NULL; - - rb = (struct gl_renderbuffer *) - _mesa_HashLookup(ctx->Shared->RenderBuffers, id); - return rb; -} - - -/** - * Helper routine for getting a gl_framebuffer. - */ -struct gl_framebuffer * -_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id) -{ - struct gl_framebuffer *fb; - - if (id == 0) - return NULL; - - fb = (struct gl_framebuffer *) - _mesa_HashLookup(ctx->Shared->FrameBuffers, id); - return fb; -} - - -/** - * Mark the given framebuffer as invalid. This will force the - * test for framebuffer completeness to be done before the framebuffer - * is used. - */ -static void -invalidate_framebuffer(struct gl_framebuffer *fb) -{ - fb->_Status = 0; /* "indeterminate" */ -} - - -/** - * Return the gl_framebuffer object which corresponds to the given - * framebuffer target, such as GL_DRAW_FRAMEBUFFER. - * Check support for GL_EXT_framebuffer_blit to determine if certain - * targets are legal. - * \return gl_framebuffer pointer or NULL if target is illegal - */ -static struct gl_framebuffer * -get_framebuffer_target(struct gl_context *ctx, GLenum target) -{ - switch (target) { - case GL_DRAW_FRAMEBUFFER: - return ctx->Extensions.EXT_framebuffer_blit ? ctx->DrawBuffer : NULL; - case GL_READ_FRAMEBUFFER: - return ctx->Extensions.EXT_framebuffer_blit ? ctx->ReadBuffer : NULL; - case GL_FRAMEBUFFER_EXT: - return ctx->DrawBuffer; - default: - return NULL; - } -} - - -/** - * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding - * gl_renderbuffer_attachment object. - * This function is only used for user-created FB objects, not the - * default / window-system FB object. - * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to - * the depth buffer attachment point. - */ -struct gl_renderbuffer_attachment * -_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, - GLenum attachment) -{ - GLuint i; - - assert(fb->Name > 0); - - switch (attachment) { - case GL_COLOR_ATTACHMENT0_EXT: - case GL_COLOR_ATTACHMENT1_EXT: - case GL_COLOR_ATTACHMENT2_EXT: - case GL_COLOR_ATTACHMENT3_EXT: - case GL_COLOR_ATTACHMENT4_EXT: - case GL_COLOR_ATTACHMENT5_EXT: - case GL_COLOR_ATTACHMENT6_EXT: - case GL_COLOR_ATTACHMENT7_EXT: - case GL_COLOR_ATTACHMENT8_EXT: - case GL_COLOR_ATTACHMENT9_EXT: - case GL_COLOR_ATTACHMENT10_EXT: - case GL_COLOR_ATTACHMENT11_EXT: - case GL_COLOR_ATTACHMENT12_EXT: - case GL_COLOR_ATTACHMENT13_EXT: - case GL_COLOR_ATTACHMENT14_EXT: - case GL_COLOR_ATTACHMENT15_EXT: - i = attachment - GL_COLOR_ATTACHMENT0_EXT; - if (i >= ctx->Const.MaxColorAttachments) { - return NULL; - } - return &fb->Attachment[BUFFER_COLOR0 + i]; - case GL_DEPTH_STENCIL_ATTACHMENT: - /* fall-through */ - case GL_DEPTH_BUFFER: - /* fall-through / new in GL 3.0 */ - case GL_DEPTH_ATTACHMENT_EXT: - return &fb->Attachment[BUFFER_DEPTH]; - case GL_STENCIL_BUFFER: - /* fall-through / new in GL 3.0 */ - case GL_STENCIL_ATTACHMENT_EXT: - return &fb->Attachment[BUFFER_STENCIL]; - default: - return NULL; - } -} - - -/** - * As above, but only used for getting attachments of the default / - * window-system framebuffer (not user-created framebuffer objects). - */ -static struct gl_renderbuffer_attachment * -_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, - GLenum attachment) -{ - assert(fb->Name == 0); - - switch (attachment) { - case GL_FRONT_LEFT: - return &fb->Attachment[BUFFER_FRONT_LEFT]; - case GL_FRONT_RIGHT: - return &fb->Attachment[BUFFER_FRONT_RIGHT]; - case GL_BACK_LEFT: - return &fb->Attachment[BUFFER_BACK_LEFT]; - case GL_BACK_RIGHT: - return &fb->Attachment[BUFFER_BACK_RIGHT]; - case GL_AUX0: - if (fb->Visual.numAuxBuffers == 1) { - return &fb->Attachment[BUFFER_AUX0]; - } - return NULL; - case GL_DEPTH_BUFFER: - /* fall-through / new in GL 3.0 */ - case GL_DEPTH_ATTACHMENT_EXT: - return &fb->Attachment[BUFFER_DEPTH]; - case GL_STENCIL_BUFFER: - /* fall-through / new in GL 3.0 */ - case GL_STENCIL_ATTACHMENT_EXT: - return &fb->Attachment[BUFFER_STENCIL]; - default: - return NULL; - } -} - - - -/** - * Remove any texture or renderbuffer attached to the given attachment - * point. Update reference counts, etc. - */ -void -_mesa_remove_attachment(struct gl_context *ctx, - struct gl_renderbuffer_attachment *att) -{ - if (att->Type == GL_TEXTURE) { - ASSERT(att->Texture); - if (ctx->Driver.FinishRenderTexture) { - /* tell driver that we're done rendering to this texture. */ - ctx->Driver.FinishRenderTexture(ctx, att); - } - _mesa_reference_texobj(&att->Texture, NULL); /* unbind */ - ASSERT(!att->Texture); - } - if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { - ASSERT(!att->Texture); - _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */ - ASSERT(!att->Renderbuffer); - } - att->Type = GL_NONE; - att->Complete = GL_TRUE; -} - - -/** - * Bind a texture object to an attachment point. - * The previous binding, if any, will be removed first. - */ -void -_mesa_set_texture_attachment(struct gl_context *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att, - struct gl_texture_object *texObj, - GLenum texTarget, GLuint level, GLuint zoffset) -{ - if (att->Texture == texObj) { - /* re-attaching same texture */ - ASSERT(att->Type == GL_TEXTURE); - if (ctx->Driver.FinishRenderTexture) - ctx->Driver.FinishRenderTexture(ctx, att); - } - else { - /* new attachment */ - if (ctx->Driver.FinishRenderTexture && att->Texture) - ctx->Driver.FinishRenderTexture(ctx, att); - _mesa_remove_attachment(ctx, att); - att->Type = GL_TEXTURE; - assert(!att->Texture); - _mesa_reference_texobj(&att->Texture, texObj); - } - - /* always update these fields */ - att->TextureLevel = level; - att->CubeMapFace = _mesa_tex_target_to_face(texTarget); - att->Zoffset = zoffset; - att->Complete = GL_FALSE; - - if (_mesa_get_attachment_teximage(att)) { - ctx->Driver.RenderTexture(ctx, fb, att); - } - - invalidate_framebuffer(fb); -} - - -/** - * Bind a renderbuffer to an attachment point. - * The previous binding, if any, will be removed first. - */ -void -_mesa_set_renderbuffer_attachment(struct gl_context *ctx, - struct gl_renderbuffer_attachment *att, - struct gl_renderbuffer *rb) -{ - /* XXX check if re-doing same attachment, exit early */ - _mesa_remove_attachment(ctx, att); - att->Type = GL_RENDERBUFFER_EXT; - att->Texture = NULL; /* just to be safe */ - att->Complete = GL_FALSE; - _mesa_reference_renderbuffer(&att->Renderbuffer, rb); -} - - -/** - * Fallback for ctx->Driver.FramebufferRenderbuffer() - * Attach a renderbuffer object to a framebuffer object. - */ -void -_mesa_framebuffer_renderbuffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb) -{ - struct gl_renderbuffer_attachment *att; - - _glthread_LOCK_MUTEX(fb->Mutex); - - att = _mesa_get_attachment(ctx, fb, attachment); - ASSERT(att); - if (rb) { - _mesa_set_renderbuffer_attachment(ctx, att, rb); - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - /* do stencil attachment here (depth already done above) */ - att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT); - assert(att); - _mesa_set_renderbuffer_attachment(ctx, att, rb); - } - rb->AttachedAnytime = GL_TRUE; - } - else { - _mesa_remove_attachment(ctx, att); - } - - invalidate_framebuffer(fb); - - _glthread_UNLOCK_MUTEX(fb->Mutex); -} - - -/** - * Fallback for ctx->Driver.ValidateFramebuffer() - * Check if the renderbuffer's formats are supported by the software - * renderer. - * Drivers should probably override this. - */ -void -_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - gl_buffer_index buf; - for (buf = 0; buf < BUFFER_COUNT; buf++) { - const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer; - if (rb) { - switch (rb->_BaseFormat) { - case GL_ALPHA: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: - case GL_RED: - case GL_RG: - fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; - return; - default: - /* render buffer format is supported by software rendering */ - ; - } - } - } -} - - -/** - * For debug only. - */ -static void -att_incomplete(const char *msg) -{ -#if DEBUG_FBO - _mesa_debug(NULL, "attachment incomplete: %s\n", msg); -#else - (void) msg; -#endif -} - - -/** - * For debug only. - */ -static void -fbo_incomplete(const char *msg, int index) -{ -#if DEBUG_FBO - _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); -#else - (void) msg; - (void) index; -#endif -} - - -/** - * Is the given base format a legal format for a color renderbuffer? - */ -GLboolean -_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat) -{ - switch (baseFormat) { - case GL_RGB: - case GL_RGBA: - return GL_TRUE; - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - case GL_ALPHA: - return ctx->Extensions.ARB_framebuffer_object; - case GL_RED: - case GL_RG: - return ctx->Extensions.ARB_texture_rg; - default: - return GL_FALSE; - } -} - - -/** - * Is the given base format a legal format for a depth/stencil renderbuffer? - */ -static GLboolean -is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat) -{ - switch (baseFormat) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if an attachment point is complete and update its Complete field. - * \param format if GL_COLOR, this is a color attachment point, - * if GL_DEPTH, this is a depth component attachment point, - * if GL_STENCIL, this is a stencil component attachment point. - */ -static void -test_attachment_completeness(const struct gl_context *ctx, GLenum format, - struct gl_renderbuffer_attachment *att) -{ - assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL); - - /* assume complete */ - att->Complete = GL_TRUE; - - /* Look for reasons why the attachment might be incomplete */ - if (att->Type == GL_TEXTURE) { - const struct gl_texture_object *texObj = att->Texture; - struct gl_texture_image *texImage; - GLenum baseFormat; - - if (!texObj) { - att_incomplete("no texobj"); - att->Complete = GL_FALSE; - return; - } - - texImage = texObj->Image[att->CubeMapFace][att->TextureLevel]; - if (!texImage) { - att_incomplete("no teximage"); - att->Complete = GL_FALSE; - return; - } - if (texImage->Width < 1 || texImage->Height < 1) { - att_incomplete("teximage width/height=0"); - printf("texobj = %u\n", texObj->Name); - printf("level = %d\n", att->TextureLevel); - att->Complete = GL_FALSE; - return; - } - if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) { - att_incomplete("bad z offset"); - att->Complete = GL_FALSE; - return; - } - - baseFormat = _mesa_get_format_base_format(texImage->TexFormat); - - if (format == GL_COLOR) { - if (!_mesa_is_legal_color_format(ctx, baseFormat)) { - att_incomplete("bad format"); - att->Complete = GL_FALSE; - return; - } - if (_mesa_is_format_compressed(texImage->TexFormat)) { - att_incomplete("compressed internalformat"); - att->Complete = GL_FALSE; - return; - } - } - else if (format == GL_DEPTH) { - if (baseFormat == GL_DEPTH_COMPONENT) { - /* OK */ - } - else if (ctx->Extensions.EXT_packed_depth_stencil && - ctx->Extensions.ARB_depth_texture && - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* OK */ - } - else { - att->Complete = GL_FALSE; - att_incomplete("bad depth format"); - return; - } - } - else { - ASSERT(format == GL_STENCIL); - if (ctx->Extensions.EXT_packed_depth_stencil && - ctx->Extensions.ARB_depth_texture && - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* OK */ - } - else { - /* no such thing as stencil-only textures */ - att_incomplete("illegal stencil texture"); - att->Complete = GL_FALSE; - return; - } - } - } - else if (att->Type == GL_RENDERBUFFER_EXT) { - const GLenum baseFormat = - _mesa_get_format_base_format(att->Renderbuffer->Format); - - ASSERT(att->Renderbuffer); - if (!att->Renderbuffer->InternalFormat || - att->Renderbuffer->Width < 1 || - att->Renderbuffer->Height < 1) { - att_incomplete("0x0 renderbuffer"); - att->Complete = GL_FALSE; - return; - } - if (format == GL_COLOR) { - if (!_mesa_is_legal_color_format(ctx, baseFormat)) { - att_incomplete("bad renderbuffer color format"); - att->Complete = GL_FALSE; - return; - } - } - else if (format == GL_DEPTH) { - if (baseFormat == GL_DEPTH_COMPONENT) { - /* OK */ - } - else if (ctx->Extensions.EXT_packed_depth_stencil && - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* OK */ - } - else { - att_incomplete("bad renderbuffer depth format"); - att->Complete = GL_FALSE; - return; - } - } - else { - assert(format == GL_STENCIL); - if (baseFormat == GL_STENCIL_INDEX) { - /* OK */ - } - else if (ctx->Extensions.EXT_packed_depth_stencil && - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* OK */ - } - else { - att->Complete = GL_FALSE; - att_incomplete("bad renderbuffer stencil format"); - return; - } - } - } - else { - ASSERT(att->Type == GL_NONE); - /* complete */ - return; - } -} - - -/** - * Test if the given framebuffer object is complete and update its - * Status field with the results. - * Calls the ctx->Driver.ValidateFramebuffer() function to allow the - * driver to make hardware-specific validation/completeness checks. - * Also update the framebuffer's Width and Height fields if the - * framebuffer is complete. - */ -void -_mesa_test_framebuffer_completeness(struct gl_context *ctx, - struct gl_framebuffer *fb) -{ - GLuint numImages; - GLenum intFormat = GL_NONE; /* color buffers' internal format */ - GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0; - GLint numSamples = -1; - GLint i; - GLuint j; - - assert(fb->Name != 0); - - numImages = 0; - fb->Width = 0; - fb->Height = 0; - - /* Start at -2 to more easily loop over all attachment points. - * -2: depth buffer - * -1: stencil buffer - * >=0: color buffer - */ - for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { - struct gl_renderbuffer_attachment *att; - GLenum f; - gl_format attFormat; - - /* - * XXX for ARB_fbo, only check color buffers that are named by - * GL_READ_BUFFER and GL_DRAW_BUFFERi. - */ - - /* check for attachment completeness - */ - if (i == -2) { - att = &fb->Attachment[BUFFER_DEPTH]; - test_attachment_completeness(ctx, GL_DEPTH, att); - if (!att->Complete) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; - fbo_incomplete("depth attachment incomplete", -1); - return; - } - } - else if (i == -1) { - att = &fb->Attachment[BUFFER_STENCIL]; - test_attachment_completeness(ctx, GL_STENCIL, att); - if (!att->Complete) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; - fbo_incomplete("stencil attachment incomplete", -1); - return; - } - } - else { - att = &fb->Attachment[BUFFER_COLOR0 + i]; - test_attachment_completeness(ctx, GL_COLOR, att); - if (!att->Complete) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; - fbo_incomplete("color attachment incomplete", i); - return; - } - } - - /* get width, height, format of the renderbuffer/texture - */ - if (att->Type == GL_TEXTURE) { - const struct gl_texture_image *texImg = - _mesa_get_attachment_teximage(att); - minWidth = MIN2(minWidth, texImg->Width); - maxWidth = MAX2(maxWidth, texImg->Width); - minHeight = MIN2(minHeight, texImg->Height); - maxHeight = MAX2(maxHeight, texImg->Height); - f = texImg->_BaseFormat; - attFormat = texImg->TexFormat; - numImages++; - if (!_mesa_is_legal_color_format(ctx, f) && - !is_legal_depth_format(ctx, f)) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; - fbo_incomplete("texture attachment incomplete", -1); - return; - } - } - else if (att->Type == GL_RENDERBUFFER_EXT) { - minWidth = MIN2(minWidth, att->Renderbuffer->Width); - maxWidth = MAX2(minWidth, att->Renderbuffer->Width); - minHeight = MIN2(minHeight, att->Renderbuffer->Height); - maxHeight = MAX2(minHeight, att->Renderbuffer->Height); - f = att->Renderbuffer->InternalFormat; - attFormat = att->Renderbuffer->Format; - numImages++; - } - else { - assert(att->Type == GL_NONE); - continue; - } - - if (att->Renderbuffer && numSamples < 0) { - /* first buffer */ - numSamples = att->Renderbuffer->NumSamples; - } - - /* check if integer color */ - fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); - - /* Error-check width, height, format, samples - */ - if (numImages == 1) { - /* save format, num samples */ - if (i >= 0) { - intFormat = f; - } - } - else { - if (!ctx->Extensions.ARB_framebuffer_object) { - /* check that width, height, format are same */ - if (minWidth != maxWidth || minHeight != maxHeight) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; - fbo_incomplete("width or height mismatch", -1); - return; - } - /* check that all color buffer have same format */ - if (intFormat != GL_NONE && f != intFormat) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; - fbo_incomplete("format mismatch", -1); - return; - } - } - if (att->Renderbuffer && - att->Renderbuffer->NumSamples != numSamples) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; - fbo_incomplete("inconsistant number of samples", i); - return; - } - - } - } - -#if FEATURE_GL - if (ctx->API == API_OPENGL) { - /* Check that all DrawBuffers are present */ - for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { - if (fb->ColorDrawBuffer[j] != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; - fbo_incomplete("missing drawbuffer", j); - return; - } - } - } - - /* Check that the ReadBuffer is present */ - if (fb->ColorReadBuffer != GL_NONE) { - const struct gl_renderbuffer_attachment *att - = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); - assert(att); - if (att->Type == GL_NONE) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; - fbo_incomplete("missing readbuffer", -1); - return; - } - } - } -#else - (void) j; -#endif - - if (numImages == 0) { - fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; - fbo_incomplete("no attachments", -1); - return; - } - - /* Provisionally set status = COMPLETE ... */ - fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; - - /* ... but the driver may say the FB is incomplete. - * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED - * if anything. - */ - if (ctx->Driver.ValidateFramebuffer) { - ctx->Driver.ValidateFramebuffer(ctx, fb); - if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - fbo_incomplete("driver marked FBO as incomplete", -1); - } - } - - if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) { - /* - * Note that if ARB_framebuffer_object is supported and the attached - * renderbuffers/textures are different sizes, the framebuffer - * width/height will be set to the smallest width/height. - */ - fb->Width = minWidth; - fb->Height = minHeight; - - /* finally, update the visual info for the framebuffer */ - _mesa_update_framebuffer_visual(ctx, fb); - } -} - - -GLboolean GLAPIENTRY -_mesa_IsRenderbufferEXT(GLuint renderbuffer) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (renderbuffer) { - struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (rb != NULL && rb != &DummyRenderbuffer) - return GL_TRUE; - } - return GL_FALSE; -} - - -void GLAPIENTRY -_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) -{ - struct gl_renderbuffer *newRb; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); - return; - } - - /* No need to flush here since the render buffer binding has no - * effect on rendering state. - */ - - if (renderbuffer) { - newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (newRb == &DummyRenderbuffer) { - /* ID was reserved, but no real renderbuffer object made yet */ - newRb = NULL; - } - else if (!newRb && ctx->Extensions.ARB_framebuffer_object) { - /* All RB IDs must be Gen'd */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); - return; - } - - if (!newRb) { - /* create new renderbuffer object */ - newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); - if (!newRb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); - return; - } - ASSERT(newRb->AllocStorage); - _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); - newRb->RefCount = 1; /* referenced by hash table */ - } - } - else { - newRb = NULL; - } - - ASSERT(newRb != &DummyRenderbuffer); - - _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); -} - - -/** - * If the given renderbuffer is anywhere attached to the framebuffer, detach - * the renderbuffer. - * This is used when a renderbuffer object is deleted. - * The spec calls for unbinding. - */ -static void -detach_renderbuffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer *rb) -{ - GLuint i; - for (i = 0; i < BUFFER_COUNT; i++) { - if (fb->Attachment[i].Renderbuffer == rb) { - _mesa_remove_attachment(ctx, &fb->Attachment[i]); - } - } - invalidate_framebuffer(fb); -} - - -void GLAPIENTRY -_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) -{ - GLint i; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - for (i = 0; i < n; i++) { - if (renderbuffers[i] > 0) { - struct gl_renderbuffer *rb; - rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); - if (rb) { - /* check if deleting currently bound renderbuffer object */ - if (rb == ctx->CurrentRenderbuffer) { - /* bind default */ - ASSERT(rb->RefCount >= 2); - _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - } - - if (ctx->DrawBuffer->Name) { - detach_renderbuffer(ctx, ctx->DrawBuffer, rb); - } - if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) { - detach_renderbuffer(ctx, ctx->ReadBuffer, rb); - } - - /* Remove from hash table immediately, to free the ID. - * But the object will not be freed until it's no longer - * referenced anywhere else. - */ - _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); - - if (rb != &DummyRenderbuffer) { - /* no longer referenced by hash table */ - _mesa_reference_renderbuffer(&rb, NULL); - } - } - } - } -} - - -void GLAPIENTRY -_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) -{ - GET_CURRENT_CONTEXT(ctx); - GLuint first; - GLint i; - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); - return; - } - - if (!renderbuffers) - return; - - first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); - - for (i = 0; i < n; i++) { - GLuint name = first + i; - renderbuffers[i] = name; - /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); - } -} - - -/** - * Given an internal format token for a render buffer, return the - * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, - * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, - * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). - * - * This is similar to _mesa_base_tex_format() but the set of valid - * internal formats is different. - * - * Note that even if a format is determined to be legal here, validation - * of the FBO may fail if the format is not supported by the driver/GPU. - * - * \param internalFormat as passed to glRenderbufferStorage() - * \return the base internal format, or 0 if internalFormat is illegal - */ -GLenum -_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) -{ - /* - * Notes: some formats such as alpha, luminance, etc. were added - * with GL_ARB_framebuffer_object. - */ - switch (internalFormat) { - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; - case GL_RGB: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - case GL_SRGB8_EXT: - return GL_RGB; - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - case GL_SRGB8_ALPHA8_EXT: - return GL_RGBA; - case GL_STENCIL_INDEX: - case GL_STENCIL_INDEX1_EXT: - case GL_STENCIL_INDEX4_EXT: - case GL_STENCIL_INDEX8_EXT: - case GL_STENCIL_INDEX16_EXT: - return GL_STENCIL_INDEX; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - return GL_DEPTH_COMPONENT; - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - if (ctx->Extensions.EXT_packed_depth_stencil) - return GL_DEPTH_STENCIL_EXT; - else - return 0; - case GL_RED: - case GL_R8: - case GL_R16: - return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; - case GL_RG: - case GL_RG8: - case GL_RG16: - return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; - /* signed normalized texture formats */ - case GL_RED_SNORM: - case GL_R8_SNORM: - case GL_R16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; - case GL_RG_SNORM: - case GL_RG8_SNORM: - case GL_RG16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; - case GL_RGB_SNORM: - case GL_RGB8_SNORM: - case GL_RGB16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; - case GL_RGBA_SNORM: - case GL_RGBA8_SNORM: - case GL_RGBA16_SNORM: - return ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; - case GL_ALPHA_SNORM: - case GL_ALPHA8_SNORM: - case GL_ALPHA16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - return ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; - /* XXX add floating point and integer formats eventually */ - default: - return 0; - } -} - - -/** - * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk(). - */ -static void -invalidate_rb(GLuint key, void *data, void *userData) -{ - struct gl_framebuffer *fb = (struct gl_framebuffer *) data; - struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; - - /* If this is a user-created FBO */ - if (fb->Name) { - GLuint i; - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = fb->Attachment + i; - if (att->Type == GL_RENDERBUFFER && - att->Renderbuffer == rb) { - /* Mark fb status as indeterminate to force re-validation */ - fb->_Status = 0; - return; - } - } - } -} - - -/** sentinal value, see below */ -#define NO_SAMPLES 1000 - - -/** - * Helper function used by _mesa_RenderbufferStorageEXT() and - * _mesa_RenderbufferStorageMultisample(). - * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT(). - */ -static void -renderbuffer_storage(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei samples) -{ - const char *func = samples == NO_SAMPLES ? - "glRenderbufferStorage" : "RenderbufferStorageMultisample"; - struct gl_renderbuffer *rb; - GLenum baseFormat; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); - return; - } - - baseFormat = _mesa_base_fbo_format(ctx, internalFormat); - if (baseFormat == 0) { - _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); - return; - } - - if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); - return; - } - - if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); - return; - } - - if (samples == NO_SAMPLES) { - /* NumSamples == 0 indicates non-multisampling */ - samples = 0; - } - else if (samples > (GLsizei) ctx->Const.MaxSamples) { - /* note: driver may choose to use more samples than what's requested */ - _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); - return; - } - - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); - return; - } - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - if (rb->InternalFormat == internalFormat && - rb->Width == (GLuint) width && - rb->Height == (GLuint) height) { - /* no change in allocation needed */ - return; - } - - /* These MUST get set by the AllocStorage func */ - rb->Format = MESA_FORMAT_NONE; - rb->NumSamples = samples; - - /* Now allocate the storage */ - ASSERT(rb->AllocStorage); - if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { - /* No error - check/set fields now */ - assert(rb->Format != MESA_FORMAT_NONE); - assert(rb->Width == (GLuint) width); - assert(rb->Height == (GLuint) height); - rb->InternalFormat = internalFormat; - rb->_BaseFormat = baseFormat; - assert(rb->_BaseFormat != 0); - } - else { - /* Probably ran out of memory - clear the fields */ - rb->Width = 0; - rb->Height = 0; - rb->Format = MESA_FORMAT_NONE; - rb->InternalFormat = GL_NONE; - rb->_BaseFormat = GL_NONE; - rb->NumSamples = 0; - } - - /* Invalidate the framebuffers the renderbuffer is attached in. */ - if (rb->AttachedAnytime) { - _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb); - } -} - - -#if FEATURE_OES_EGL_image -void GLAPIENTRY -_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) -{ - struct gl_renderbuffer *rb; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (!ctx->Extensions.OES_EGL_image) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glEGLImageTargetRenderbufferStorageOES(unsupported)"); - return; - } - - if (target != GL_RENDERBUFFER) { - _mesa_error(ctx, GL_INVALID_ENUM, - "EGLImageTargetRenderbufferStorageOES"); - return; - } - - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "EGLImageTargetRenderbufferStorageOES"); - return; - } - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); -} -#endif - - -/** - * Helper function for _mesa_GetRenderbufferParameterivEXT() and - * _mesa_GetFramebufferAttachmentParameterivEXT() - * We have to be careful to respect the base format. For example, if a - * renderbuffer/texture was created with internalFormat=GL_RGB but the - * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE - * we need to return zero. - */ -static GLint -get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) -{ - switch (pname) { - case GL_RENDERBUFFER_RED_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - if (baseFormat == GL_RGB || baseFormat == GL_RGBA || - baseFormat == GL_RG || baseFormat == GL_RED) - return _mesa_get_format_bits(format, pname); - else - return 0; - case GL_RENDERBUFFER_GREEN_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - if (baseFormat == GL_RGB || baseFormat == GL_RGBA || baseFormat == GL_RG) - return _mesa_get_format_bits(format, pname); - else - return 0; - case GL_RENDERBUFFER_BLUE_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - if (baseFormat == GL_RGB || baseFormat == GL_RGBA) - return _mesa_get_format_bits(format, pname); - else - return 0; - case GL_RENDERBUFFER_ALPHA_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA || - baseFormat == GL_LUMINANCE_ALPHA) - return _mesa_get_format_bits(format, pname); - else - return 0; - case GL_RENDERBUFFER_DEPTH_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) - return _mesa_get_format_bits(format, pname); - else - return 0; - case GL_RENDERBUFFER_STENCIL_SIZE_EXT: - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL) - return _mesa_get_format_bits(format, pname); - else - return 0; - default: - return 0; - } -} - - - -void GLAPIENTRY -_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height) -{ - /* GL_ARB_fbo says calling this function is equivalent to calling - * glRenderbufferStorageMultisample() with samples=0. We pass in - * a token value here just for error reporting purposes. - */ - renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); -} - - -void GLAPIENTRY -_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, - GLenum internalFormat, - GLsizei width, GLsizei height) -{ - renderbuffer_storage(target, internalFormat, width, height, samples); -} - - -/** - * OpenGL ES version of glRenderBufferStorage. - */ -void GLAPIENTRY -_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, - GLsizei width, GLsizei height) -{ - switch (internalFormat) { - case GL_RGB565: - /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */ - /* choose a closest format */ - internalFormat = GL_RGB5; - break; - default: - break; - } - - renderbuffer_storage(target, internalFormat, width, height, 0); -} - - -void GLAPIENTRY -_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) -{ - struct gl_renderbuffer *rb; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (target != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetRenderbufferParameterivEXT(target)"); - return; - } - - rb = ctx->CurrentRenderbuffer; - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetRenderbufferParameterivEXT"); - return; - } - - /* No need to flush here since we're just quering state which is - * not effected by rendering. - */ - - switch (pname) { - case GL_RENDERBUFFER_WIDTH_EXT: - *params = rb->Width; - return; - case GL_RENDERBUFFER_HEIGHT_EXT: - *params = rb->Height; - return; - case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: - *params = rb->InternalFormat; - return; - case GL_RENDERBUFFER_RED_SIZE_EXT: - case GL_RENDERBUFFER_GREEN_SIZE_EXT: - case GL_RENDERBUFFER_BLUE_SIZE_EXT: - case GL_RENDERBUFFER_ALPHA_SIZE_EXT: - case GL_RENDERBUFFER_DEPTH_SIZE_EXT: - case GL_RENDERBUFFER_STENCIL_SIZE_EXT: - *params = get_component_bits(pname, rb->_BaseFormat, rb->Format); - break; - case GL_RENDERBUFFER_SAMPLES: - if (ctx->Extensions.ARB_framebuffer_object) { - *params = rb->NumSamples; - break; - } - /* fallthrough */ - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetRenderbufferParameterivEXT(target)"); - return; - } -} - - -GLboolean GLAPIENTRY -_mesa_IsFramebufferEXT(GLuint framebuffer) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (framebuffer) { - struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer); - if (rb != NULL && rb != &DummyFramebuffer) - return GL_TRUE; - } - return GL_FALSE; -} - - -/** - * Check if any of the attachments of the given framebuffer are textures - * (render to texture). Call ctx->Driver.RenderTexture() for such - * attachments. - */ -static void -check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - GLuint i; - ASSERT(ctx->Driver.RenderTexture); - - if (fb->Name == 0) - return; /* can't render to texture with winsys framebuffers */ - - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = fb->Attachment + i; - if (att->Texture && _mesa_get_attachment_teximage(att)) { - ctx->Driver.RenderTexture(ctx, fb, att); - } - } -} - - -/** - * Examine all the framebuffer's attachments to see if any are textures. - * If so, call ctx->Driver.FinishRenderTexture() for each texture to - * notify the device driver that the texture image may have changed. - */ -static void -check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - if (fb->Name == 0) - return; /* can't render to texture with winsys framebuffers */ - - if (ctx->Driver.FinishRenderTexture) { - GLuint i; - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = fb->Attachment + i; - if (att->Texture && att->Renderbuffer) { - ctx->Driver.FinishRenderTexture(ctx, att); - } - } - } -} - - -void GLAPIENTRY -_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) -{ - struct gl_framebuffer *newDrawFb, *newReadFb; - struct gl_framebuffer *oldDrawFb, *oldReadFb; - GLboolean bindReadBuf, bindDrawBuf; - GET_CURRENT_CONTEXT(ctx); - -#ifdef DEBUG - if (ctx->Extensions.ARB_framebuffer_object) { - ASSERT(ctx->Extensions.EXT_framebuffer_object); - ASSERT(ctx->Extensions.EXT_framebuffer_blit); - } -#endif - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (!ctx->Extensions.EXT_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBindFramebufferEXT(unsupported)"); - return; - } - - switch (target) { -#if FEATURE_EXT_framebuffer_blit - case GL_DRAW_FRAMEBUFFER_EXT: - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); - return; - } - bindDrawBuf = GL_TRUE; - bindReadBuf = GL_FALSE; - break; - case GL_READ_FRAMEBUFFER_EXT: - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); - return; - } - bindDrawBuf = GL_FALSE; - bindReadBuf = GL_TRUE; - break; -#endif - case GL_FRAMEBUFFER_EXT: - bindDrawBuf = GL_TRUE; - bindReadBuf = GL_TRUE; - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); - return; - } - - if (framebuffer) { - /* Binding a user-created framebuffer object */ - newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer); - if (newDrawFb == &DummyFramebuffer) { - /* ID was reserved, but no real framebuffer object made yet */ - newDrawFb = NULL; - } - else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) { - /* All FBO IDs must be Gen'd */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); - return; - } - - if (!newDrawFb) { - /* create new framebuffer object */ - newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); - if (!newDrawFb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); - return; - } - _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); - } - newReadFb = newDrawFb; - } - else { - /* Binding the window system framebuffer (which was originally set - * with MakeCurrent). - */ - newDrawFb = ctx->WinSysDrawBuffer; - newReadFb = ctx->WinSysReadBuffer; - } - - ASSERT(newDrawFb); - ASSERT(newDrawFb != &DummyFramebuffer); - - /* save pointers to current/old framebuffers */ - oldDrawFb = ctx->DrawBuffer; - oldReadFb = ctx->ReadBuffer; - - /* check if really changing bindings */ - if (oldDrawFb == newDrawFb) - bindDrawBuf = GL_FALSE; - if (oldReadFb == newReadFb) - bindReadBuf = GL_FALSE; - - /* - * OK, now bind the new Draw/Read framebuffers, if they're changing. - * - * We also check if we're beginning and/or ending render-to-texture. - * When a framebuffer with texture attachments is unbound, call - * ctx->Driver.FinishRenderTexture(). - * When a framebuffer with texture attachments is bound, call - * ctx->Driver.RenderTexture(). - * - * Note that if the ReadBuffer has texture attachments we don't consider - * that a render-to-texture case. - */ - if (bindReadBuf) { - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - /* check if old readbuffer was render-to-texture */ - check_end_texture_render(ctx, oldReadFb); - - _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb); - } - - if (bindDrawBuf) { - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - /* check if old read/draw buffers were render-to-texture */ - if (!bindReadBuf) - check_end_texture_render(ctx, oldReadFb); - - if (oldDrawFb != oldReadFb) - check_end_texture_render(ctx, oldDrawFb); - - /* check if newly bound framebuffer has any texture attachments */ - check_begin_texture_render(ctx, newDrawFb); - - _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb); - } - - if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) { - ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb); - } -} - - -void GLAPIENTRY -_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) -{ - GLint i; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - for (i = 0; i < n; i++) { - if (framebuffers[i] > 0) { - struct gl_framebuffer *fb; - fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); - if (fb) { - ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); - - /* check if deleting currently bound framebuffer object */ - if (ctx->Extensions.EXT_framebuffer_blit) { - /* separate draw/read binding points */ - if (fb == ctx->DrawBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); - } - if (fb == ctx->ReadBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); - } - } - else { - /* only one binding point for read/draw buffers */ - if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { - /* bind default */ - ASSERT(fb->RefCount >= 2); - _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } - } - - /* remove from hash table immediately, to free the ID */ - _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); - - if (fb != &DummyFramebuffer) { - /* But the object will not be freed until it's no longer - * bound in any context. - */ - _mesa_reference_framebuffer(&fb, NULL); - } - } - } - } -} - - -void GLAPIENTRY -_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) -{ - GET_CURRENT_CONTEXT(ctx); - GLuint first; - GLint i; - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); - return; - } - - if (!framebuffers) - return; - - first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); - - for (i = 0; i < n; i++) { - GLuint name = first + i; - framebuffers[i] = name; - /* insert dummy placeholder into hash table */ - _glthread_LOCK_MUTEX(ctx->Shared->Mutex); - _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); - _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); - } -} - - - -GLenum GLAPIENTRY -_mesa_CheckFramebufferStatusEXT(GLenum target) -{ - struct gl_framebuffer *buffer; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); - - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { - _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); - return 0; - } - - if (buffer->Name == 0) { - /* The window system / default framebuffer is always complete */ - return GL_FRAMEBUFFER_COMPLETE_EXT; - } - - /* No need to flush here */ - - if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) { - _mesa_test_framebuffer_completeness(ctx, buffer); - } - - return buffer->_Status; -} - - - -/** - * Common code called by glFramebufferTexture1D/2D/3DEXT(). - */ -static void -framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, - GLenum attachment, GLenum textarget, GLuint texture, - GLint level, GLint zoffset) -{ - struct gl_renderbuffer_attachment *att; - struct gl_texture_object *texObj = NULL; - struct gl_framebuffer *fb; - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%sEXT(target=0x%x)", caller, target); - return; - } - - /* check framebuffer binding */ - if (fb->Name == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%sEXT", caller); - return; - } - - - /* The textarget, level, and zoffset parameters are only validated if - * texture is non-zero. - */ - if (texture) { - GLboolean err = GL_TRUE; - - texObj = _mesa_lookup_texture(ctx, texture); - if (texObj != NULL) { - if (textarget == 0) { - /* XXX what's the purpose of this? */ - err = (texObj->Target != GL_TEXTURE_3D) && - (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && - (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); - } - else { - err = (texObj->Target == GL_TEXTURE_CUBE_MAP) - ? !IS_CUBE_FACE(textarget) - : (texObj->Target != textarget); - } - } - else { - /* can't render to a non-existant texture */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%sEXT(non existant texture)", - caller); - return; - } - - if (err) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture%sEXT(texture target mismatch)", - caller); - return; - } - - if (texObj->Target == GL_TEXTURE_3D) { - const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); - if (zoffset < 0 || zoffset >= maxSize) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%sEXT(zoffset)", caller); - return; - } - } - else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || - (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { - if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%sEXT(layer)", caller); - return; - } - } - - if ((level < 0) || - (level >= _mesa_max_texture_levels(ctx, texObj->Target))) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferTexture%sEXT(level)", caller); - return; - } - } - - att = _mesa_get_attachment(ctx, fb, attachment); - if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture%sEXT(attachment)", caller); - return; - } - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - _glthread_LOCK_MUTEX(fb->Mutex); - if (texObj) { - _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, - level, zoffset); - /* Set the render-to-texture flag. We'll check this flag in - * glTexImage() and friends to determine if we need to revalidate - * any FBOs that might be rendering into this texture. - * This flag never gets cleared since it's non-trivial to determine - * when all FBOs might be done rendering to this texture. That's OK - * though since it's uncommon to render to a texture then repeatedly - * call glTexImage() to change images in the texture. - */ - texObj->_RenderToTexture = GL_TRUE; - } - else { - _mesa_remove_attachment(ctx, att); - } - - invalidate_framebuffer(fb); - - _glthread_UNLOCK_MUTEX(fb->Mutex); -} - - - -void GLAPIENTRY -_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) -{ - GET_CURRENT_CONTEXT(ctx); - - if ((texture != 0) && (textarget != GL_TEXTURE_1D)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture1DEXT(textarget)"); - return; - } - - framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, - level, 0); -} - - -void GLAPIENTRY -_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) -{ - GET_CURRENT_CONTEXT(ctx); - - if ((texture != 0) && - (textarget != GL_TEXTURE_2D) && - (textarget != GL_TEXTURE_RECTANGLE_ARB) && - (!IS_CUBE_FACE(textarget))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTexture2DEXT(textarget=0x%x)", textarget); - return; - } - - framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, - level, 0); -} - - -void GLAPIENTRY -_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, - GLint level, GLint zoffset) -{ - GET_CURRENT_CONTEXT(ctx); - - if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferTexture3DEXT(textarget)"); - return; - } - - framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, - level, zoffset); -} - - -void GLAPIENTRY -_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLint layer) -{ - GET_CURRENT_CONTEXT(ctx); - - framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, - level, layer); -} - - -void GLAPIENTRY -_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, - GLenum renderbufferTarget, - GLuint renderbuffer) -{ - struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *fb; - struct gl_renderbuffer *rb; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - fb = get_framebuffer_target(ctx, target); - if (!fb) { - _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); - return; - } - - if (renderbufferTarget != GL_RENDERBUFFER_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbufferEXT(renderbufferTarget)"); - return; - } - - if (fb->Name == 0) { - /* Can't attach new renderbuffers to a window system framebuffer */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); - return; - } - - att = _mesa_get_attachment(ctx, fb, attachment); - if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glFramebufferRenderbufferEXT(invalid attachment %s)", - _mesa_lookup_enum_by_nr(attachment)); - return; - } - - if (renderbuffer) { - rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); - if (!rb) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbufferEXT(non-existant" - " renderbuffer %u)", renderbuffer); - return; - } - else if (rb == &DummyRenderbuffer) { - /* This is what NVIDIA does */ - _mesa_error(ctx, GL_INVALID_VALUE, - "glFramebufferRenderbufferEXT(renderbuffer %u)", - renderbuffer); - return; - } - } - else { - /* remove renderbuffer attachment */ - rb = NULL; - } - - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && - rb && rb->Format != MESA_FORMAT_NONE) { - /* make sure the renderbuffer is a depth/stencil format */ - const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); - if (baseFormat != GL_DEPTH_STENCIL) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferRenderbufferEXT(renderbuffer" - " is not DEPTH_STENCIL format)"); - return; - } - } - - - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - assert(ctx->Driver.FramebufferRenderbuffer); - ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); - - /* Some subsequent GL commands may depend on the framebuffer's visual - * after the binding is updated. Update visual info now. - */ - _mesa_update_framebuffer_visual(ctx, fb); -} - - -void GLAPIENTRY -_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, - GLenum pname, GLint *params) -{ - const struct gl_renderbuffer_attachment *att; - struct gl_framebuffer *buffer; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - - buffer = get_framebuffer_target(ctx, target); - if (!buffer) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(target)"); - return; - } - - if (buffer->Name == 0) { - /* the default / window-system FBO */ - att = _mesa_get_fb0_attachment(ctx, buffer, attachment); - } - else { - /* user-created framebuffer FBO */ - att = _mesa_get_attachment(ctx, buffer, attachment); - } - - if (att == NULL) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(attachment)"); - return; - } - - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - /* the depth and stencil attachments must point to the same buffer */ - const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; - depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); - stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); - if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL" - " attachments differ)"); - return; - } - } - - /* No need to flush here */ - - switch (pname) { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: - *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type; - return; - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: - if (att->Type == GL_RENDERBUFFER_EXT) { - *params = att->Renderbuffer->Name; - } - else if (att->Type == GL_TEXTURE) { - *params = att->Texture->Name; - } - else { - assert(att->Type == GL_NONE); - *params = 0; - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: - if (att->Type == GL_TEXTURE) { - *params = att->TextureLevel; - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: - if (att->Type == GL_TEXTURE) { - if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) { - *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; - } - else { - *params = 0; - } - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: - if (att->Type == GL_TEXTURE) { - if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { - *params = att->Zoffset; - } - else { - *params = 0; - } - } - else { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } - else { - if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) { - *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); - } - else { - /* According to ARB_framebuffer_sRGB, we should return LINEAR - * if the sRGB conversion is unsupported. */ - *params = GL_LINEAR; - } - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - return; - } - else { - gl_format format = att->Renderbuffer->Format; - if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) { - /* special cases */ - *params = GL_INDEX; - } - else { - *params = _mesa_get_format_datatype(format); - } - } - return; - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - if (!ctx->Extensions.ARB_framebuffer_object) { - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - } - else if (att->Texture) { - const struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, - att->TextureLevel); - if (texImage) { - *params = get_component_bits(pname, texImage->_BaseFormat, - texImage->TexFormat); - } - else { - *params = 0; - } - } - else if (att->Renderbuffer) { - *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, - att->Renderbuffer->Format); - } - else { - *params = 0; - } - return; - default: - _mesa_error(ctx, GL_INVALID_ENUM, - "glGetFramebufferAttachmentParameterivEXT(pname)"); - return; - } -} - - -void GLAPIENTRY -_mesa_GenerateMipmapEXT(GLenum target) -{ - struct gl_texture_object *texObj; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - switch (target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_CUBE_MAP: - /* OK, legal value */ - break; - default: - /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */ - _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)"); - return; - } - - texObj = _mesa_get_current_tex_object(ctx, target); - - if (texObj->BaseLevel >= texObj->MaxLevel) { - /* nothing to do */ - return; - } - - if (texObj->Target == GL_TEXTURE_CUBE_MAP && - !_mesa_cube_complete(texObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glGenerateMipmap(incomplete cube map)"); - return; - } - - _mesa_lock_texture(ctx, texObj); - if (target == GL_TEXTURE_CUBE_MAP) { - GLuint face; - for (face = 0; face < 6; face++) - ctx->Driver.GenerateMipmap(ctx, - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, - texObj); - } - else { - ctx->Driver.GenerateMipmap(ctx, target, texObj); - } - _mesa_unlock_texture(ctx, texObj); -} - - -#if FEATURE_EXT_framebuffer_blit - -static const struct gl_renderbuffer_attachment * -find_attachment(const struct gl_framebuffer *fb, - const struct gl_renderbuffer *rb) -{ - GLuint i; - for (i = 0; i < Elements(fb->Attachment); i++) { - if (fb->Attachment[i].Renderbuffer == rb) - return &fb->Attachment[i]; - } - return NULL; -} - - - -/** - * Blit rectangular region, optionally from one framebuffer to another. - * - * Note, if the src buffer is multisampled and the dest is not, this is - * when the samples must be resolved to a single color. - */ -void GLAPIENTRY -_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT | - GL_STENCIL_BUFFER_BIT); - const struct gl_framebuffer *readFb, *drawFb; - const struct gl_renderbuffer *colorReadRb, *colorDrawRb; - GET_CURRENT_CONTEXT(ctx); - - ASSERT_OUTSIDE_BEGIN_END(ctx); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, - "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, _mesa_lookup_enum_by_nr(filter)); - - if (ctx->NewState) { - _mesa_update_state(ctx); - } - - readFb = ctx->ReadBuffer; - drawFb = ctx->DrawBuffer; - - if (!readFb || !drawFb) { - /* This will normally never happen but someday we may want to - * support MakeCurrent() with no drawables. - */ - return; - } - - /* check for complete framebuffers */ - if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || - readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glBlitFramebufferEXT(incomplete draw/read buffers)"); - return; - } - - if (filter != GL_NEAREST && filter != GL_LINEAR) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); - return; - } - - if (mask & ~legalMaskBits) { - _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); - return; - } - - /* depth/stencil must be blitted with nearest filtering */ - if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) - && filter != GL_NEAREST) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); - return; - } - - /* get color read/draw renderbuffers */ - if (mask & GL_COLOR_BUFFER_BIT) { - colorReadRb = readFb->_ColorReadBuffer; - colorDrawRb = drawFb->_ColorDrawBuffers[0]; - } - else { - colorReadRb = colorDrawRb = NULL; - } - - if (mask & GL_STENCIL_BUFFER_BIT) { - struct gl_renderbuffer *readRb = readFb->_StencilBuffer; - struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer; - if (!readRb || - !drawRb || - _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(stencil buffer size mismatch)"); - return; - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) { - struct gl_renderbuffer *readRb = readFb->_DepthBuffer; - struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer; - if (!readRb || - !drawRb || - _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != - _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(depth buffer size mismatch)"); - return; - } - } - - if (readFb->Visual.samples > 0 && - drawFb->Visual.samples > 0 && - readFb->Visual.samples != drawFb->Visual.samples) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(mismatched samples"); - return; - } - - /* extra checks for multisample copies... */ - if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { - /* src and dest region sizes must be the same */ - if (srcX1 - srcX0 != dstX1 - dstX0 || - srcY1 - srcY0 != dstY1 - dstY0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); - return; - } - - /* color formats must match */ - if (colorReadRb && - colorDrawRb && - colorReadRb->Format != colorDrawRb->Format) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); - return; - } - } - - if (!ctx->Extensions.EXT_framebuffer_blit) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); - return; - } - - /* Debug code */ - if (DEBUG_BLIT) { - printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," - " 0x%x, 0x%x)\n", - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (colorReadRb) { - const struct gl_renderbuffer_attachment *att; - - att = find_attachment(readFb, colorReadRb); - printf(" Src FBO %u RB %u (%dx%d) ", - readFb->Name, colorReadRb->Name, - colorReadRb->Width, colorReadRb->Height); - if (att && att->Texture) { - printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); - } - printf("\n"); - - att = find_attachment(drawFb, colorDrawRb); - printf(" Dst FBO %u RB %u (%dx%d) ", - drawFb->Name, colorDrawRb->Name, - colorDrawRb->Width, colorDrawRb->Height); - if (att && att->Texture) { - printf("Tex %u tgt 0x%x level %u face %u", - att->Texture->Name, - att->Texture->Target, - att->TextureLevel, - att->CubeMapFace); - } - printf("\n"); - } - } - - ASSERT(ctx->Driver.BlitFramebuffer); - ctx->Driver.BlitFramebuffer(ctx, - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, - mask, filter); -} -#endif /* FEATURE_EXT_framebuffer_blit */ - -#if FEATURE_ARB_geometry_shader4 -void GLAPIENTRY -_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, - GLuint texture, GLint level) -{ - GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTextureARB " - "not implemented!"); -} - -void GLAPIENTRY -_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, - GLuint texture, GLint level, GLenum face) -{ - GET_CURRENT_CONTEXT(ctx); - _mesa_error(ctx, GL_INVALID_OPERATION, - "glFramebufferTextureFaceARB " - "not implemented!"); -} -#endif /* FEATURE_ARB_geometry_shader4 */ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * GL_EXT/ARB_framebuffer_object extensions + * + * Authors: + * Brian Paul + */ + + +#include "buffers.h" +#include "context.h" +#include "enums.h" +#include "fbobject.h" +#include "formats.h" +#include "framebuffer.h" +#include "hash.h" +#include "macros.h" +#include "mfeatures.h" +#include "mtypes.h" +#include "renderbuffer.h" +#include "state.h" +#include "teximage.h" +#include "texobj.h" + + +/** Set this to 1 to help debug FBO incompleteness problems */ +#define DEBUG_FBO 0 + +/** Set this to 1 to debug/log glBlitFramebuffer() calls */ +#define DEBUG_BLIT 0 + + +/** + * Notes: + * + * None of the GL_EXT_framebuffer_object functions are compiled into + * display lists. + */ + + + +/* + * When glGenRender/FramebuffersEXT() is called we insert pointers to + * these placeholder objects into the hash table. + * Later, when the object ID is first bound, we replace the placeholder + * with the real frame/renderbuffer. + */ +static struct gl_framebuffer DummyFramebuffer; +static struct gl_renderbuffer DummyRenderbuffer; + +/* We bind this framebuffer when applications pass a NULL + * drawable/surface in make current. */ +static struct gl_framebuffer IncompleteFramebuffer; + + +#define IS_CUBE_FACE(TARGET) \ + ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \ + (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) + + +static void +delete_dummy_renderbuffer(struct gl_renderbuffer *rb) +{ + /* no op */ +} + +static void +delete_dummy_framebuffer(struct gl_framebuffer *fb) +{ + /* no op */ +} + + +void +_mesa_init_fbobjects(struct gl_context *ctx) +{ + _glthread_INIT_MUTEX(DummyFramebuffer.Mutex); + _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex); + _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex); + DummyFramebuffer.Delete = delete_dummy_framebuffer; + DummyRenderbuffer.Delete = delete_dummy_renderbuffer; + IncompleteFramebuffer.Delete = delete_dummy_framebuffer; +} + +struct gl_framebuffer * +_mesa_get_incomplete_framebuffer(void) +{ + return &IncompleteFramebuffer; +} + +/** + * Helper routine for getting a gl_renderbuffer. + */ +struct gl_renderbuffer * +_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id) +{ + struct gl_renderbuffer *rb; + + if (id == 0) + return NULL; + + rb = (struct gl_renderbuffer *) + _mesa_HashLookup(ctx->Shared->RenderBuffers, id); + return rb; +} + + +/** + * Helper routine for getting a gl_framebuffer. + */ +struct gl_framebuffer * +_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id) +{ + struct gl_framebuffer *fb; + + if (id == 0) + return NULL; + + fb = (struct gl_framebuffer *) + _mesa_HashLookup(ctx->Shared->FrameBuffers, id); + return fb; +} + + +/** + * Mark the given framebuffer as invalid. This will force the + * test for framebuffer completeness to be done before the framebuffer + * is used. + */ +static void +invalidate_framebuffer(struct gl_framebuffer *fb) +{ + fb->_Status = 0; /* "indeterminate" */ +} + + +/** + * Return the gl_framebuffer object which corresponds to the given + * framebuffer target, such as GL_DRAW_FRAMEBUFFER. + * Check support for GL_EXT_framebuffer_blit to determine if certain + * targets are legal. + * \return gl_framebuffer pointer or NULL if target is illegal + */ +static struct gl_framebuffer * +get_framebuffer_target(struct gl_context *ctx, GLenum target) +{ + switch (target) { + case GL_DRAW_FRAMEBUFFER: + return ctx->Extensions.EXT_framebuffer_blit ? ctx->DrawBuffer : NULL; + case GL_READ_FRAMEBUFFER: + return ctx->Extensions.EXT_framebuffer_blit ? ctx->ReadBuffer : NULL; + case GL_FRAMEBUFFER_EXT: + return ctx->DrawBuffer; + default: + return NULL; + } +} + + +/** + * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding + * gl_renderbuffer_attachment object. + * This function is only used for user-created FB objects, not the + * default / window-system FB object. + * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to + * the depth buffer attachment point. + */ +struct gl_renderbuffer_attachment * +_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment) +{ + GLuint i; + + assert(fb->Name > 0); + + switch (attachment) { + case GL_COLOR_ATTACHMENT0_EXT: + case GL_COLOR_ATTACHMENT1_EXT: + case GL_COLOR_ATTACHMENT2_EXT: + case GL_COLOR_ATTACHMENT3_EXT: + case GL_COLOR_ATTACHMENT4_EXT: + case GL_COLOR_ATTACHMENT5_EXT: + case GL_COLOR_ATTACHMENT6_EXT: + case GL_COLOR_ATTACHMENT7_EXT: + case GL_COLOR_ATTACHMENT8_EXT: + case GL_COLOR_ATTACHMENT9_EXT: + case GL_COLOR_ATTACHMENT10_EXT: + case GL_COLOR_ATTACHMENT11_EXT: + case GL_COLOR_ATTACHMENT12_EXT: + case GL_COLOR_ATTACHMENT13_EXT: + case GL_COLOR_ATTACHMENT14_EXT: + case GL_COLOR_ATTACHMENT15_EXT: + i = attachment - GL_COLOR_ATTACHMENT0_EXT; + if (i >= ctx->Const.MaxColorAttachments) { + return NULL; + } + return &fb->Attachment[BUFFER_COLOR0 + i]; + case GL_DEPTH_STENCIL_ATTACHMENT: + /* fall-through */ + case GL_DEPTH_BUFFER: + /* fall-through / new in GL 3.0 */ + case GL_DEPTH_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL_BUFFER: + /* fall-through / new in GL 3.0 */ + case GL_STENCIL_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_STENCIL]; + default: + return NULL; + } +} + + +/** + * As above, but only used for getting attachments of the default / + * window-system framebuffer (not user-created framebuffer objects). + */ +static struct gl_renderbuffer_attachment * +_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb, + GLenum attachment) +{ + assert(fb->Name == 0); + + switch (attachment) { + case GL_FRONT_LEFT: + return &fb->Attachment[BUFFER_FRONT_LEFT]; + case GL_FRONT_RIGHT: + return &fb->Attachment[BUFFER_FRONT_RIGHT]; + case GL_BACK_LEFT: + return &fb->Attachment[BUFFER_BACK_LEFT]; + case GL_BACK_RIGHT: + return &fb->Attachment[BUFFER_BACK_RIGHT]; + case GL_AUX0: + if (fb->Visual.numAuxBuffers == 1) { + return &fb->Attachment[BUFFER_AUX0]; + } + return NULL; + case GL_DEPTH_BUFFER: + /* fall-through / new in GL 3.0 */ + case GL_DEPTH_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL_BUFFER: + /* fall-through / new in GL 3.0 */ + case GL_STENCIL_ATTACHMENT_EXT: + return &fb->Attachment[BUFFER_STENCIL]; + default: + return NULL; + } +} + + + +/** + * Remove any texture or renderbuffer attached to the given attachment + * point. Update reference counts, etc. + */ +void +_mesa_remove_attachment(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att) +{ + if (att->Type == GL_TEXTURE) { + ASSERT(att->Texture); + if (ctx->Driver.FinishRenderTexture) { + /* tell driver that we're done rendering to this texture. */ + ctx->Driver.FinishRenderTexture(ctx, att); + } + _mesa_reference_texobj(&att->Texture, NULL); /* unbind */ + ASSERT(!att->Texture); + } + if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) { + ASSERT(!att->Texture); + _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */ + ASSERT(!att->Renderbuffer); + } + att->Type = GL_NONE; + att->Complete = GL_TRUE; +} + + +/** + * Bind a texture object to an attachment point. + * The previous binding, if any, will be removed first. + */ +void +_mesa_set_texture_attachment(struct gl_context *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att, + struct gl_texture_object *texObj, + GLenum texTarget, GLuint level, GLuint zoffset) +{ + if (att->Texture == texObj) { + /* re-attaching same texture */ + ASSERT(att->Type == GL_TEXTURE); + if (ctx->Driver.FinishRenderTexture) + ctx->Driver.FinishRenderTexture(ctx, att); + } + else { + /* new attachment */ + if (ctx->Driver.FinishRenderTexture && att->Texture) + ctx->Driver.FinishRenderTexture(ctx, att); + _mesa_remove_attachment(ctx, att); + att->Type = GL_TEXTURE; + assert(!att->Texture); + _mesa_reference_texobj(&att->Texture, texObj); + } + + /* always update these fields */ + att->TextureLevel = level; + att->CubeMapFace = _mesa_tex_target_to_face(texTarget); + att->Zoffset = zoffset; + att->Complete = GL_FALSE; + + if (_mesa_get_attachment_teximage(att)) { + ctx->Driver.RenderTexture(ctx, fb, att); + } + + invalidate_framebuffer(fb); +} + + +/** + * Bind a renderbuffer to an attachment point. + * The previous binding, if any, will be removed first. + */ +void +_mesa_set_renderbuffer_attachment(struct gl_context *ctx, + struct gl_renderbuffer_attachment *att, + struct gl_renderbuffer *rb) +{ + /* XXX check if re-doing same attachment, exit early */ + _mesa_remove_attachment(ctx, att); + att->Type = GL_RENDERBUFFER_EXT; + att->Texture = NULL; /* just to be safe */ + att->Complete = GL_FALSE; + _mesa_reference_renderbuffer(&att->Renderbuffer, rb); +} + + +/** + * Fallback for ctx->Driver.FramebufferRenderbuffer() + * Attach a renderbuffer object to a framebuffer object. + */ +void +_mesa_framebuffer_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLenum attachment, struct gl_renderbuffer *rb) +{ + struct gl_renderbuffer_attachment *att; + + _glthread_LOCK_MUTEX(fb->Mutex); + + att = _mesa_get_attachment(ctx, fb, attachment); + ASSERT(att); + if (rb) { + _mesa_set_renderbuffer_attachment(ctx, att, rb); + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { + /* do stencil attachment here (depth already done above) */ + att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT); + assert(att); + _mesa_set_renderbuffer_attachment(ctx, att, rb); + } + rb->AttachedAnytime = GL_TRUE; + } + else { + _mesa_remove_attachment(ctx, att); + } + + invalidate_framebuffer(fb); + + _glthread_UNLOCK_MUTEX(fb->Mutex); +} + + +/** + * Fallback for ctx->Driver.ValidateFramebuffer() + * Check if the renderbuffer's formats are supported by the software + * renderer. + * Drivers should probably override this. + */ +void +_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + gl_buffer_index buf; + for (buf = 0; buf < BUFFER_COUNT; buf++) { + const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer; + if (rb) { + switch (rb->_BaseFormat) { + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE: + case GL_INTENSITY: + case GL_RED: + case GL_RG: + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + return; + default: + /* render buffer format is supported by software rendering */ + ; + } + } + } +} + + +/** + * For debug only. + */ +static void +att_incomplete(const char *msg) +{ +#if DEBUG_FBO + _mesa_debug(NULL, "attachment incomplete: %s\n", msg); +#else + (void) msg; +#endif +} + + +/** + * For debug only. + */ +static void +fbo_incomplete(const char *msg, int index) +{ +#if DEBUG_FBO + _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index); +#else + (void) msg; + (void) index; +#endif +} + + +/** + * Is the given base format a legal format for a color renderbuffer? + */ +GLboolean +_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat) +{ + switch (baseFormat) { + case GL_RGB: + case GL_RGBA: + return GL_TRUE; + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_ALPHA: + return ctx->Extensions.ARB_framebuffer_object; + case GL_RED: + case GL_RG: + return ctx->Extensions.ARB_texture_rg; + default: + return GL_FALSE; + } +} + + +/** + * Is the given base format a legal format for a depth/stencil renderbuffer? + */ +static GLboolean +is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat) +{ + switch (baseFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if an attachment point is complete and update its Complete field. + * \param format if GL_COLOR, this is a color attachment point, + * if GL_DEPTH, this is a depth component attachment point, + * if GL_STENCIL, this is a stencil component attachment point. + */ +static void +test_attachment_completeness(const struct gl_context *ctx, GLenum format, + struct gl_renderbuffer_attachment *att) +{ + assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL); + + /* assume complete */ + att->Complete = GL_TRUE; + + /* Look for reasons why the attachment might be incomplete */ + if (att->Type == GL_TEXTURE) { + const struct gl_texture_object *texObj = att->Texture; + struct gl_texture_image *texImage; + GLenum baseFormat; + + if (!texObj) { + att_incomplete("no texobj"); + att->Complete = GL_FALSE; + return; + } + + texImage = texObj->Image[att->CubeMapFace][att->TextureLevel]; + if (!texImage) { + att_incomplete("no teximage"); + att->Complete = GL_FALSE; + return; + } + if (texImage->Width < 1 || texImage->Height < 1) { + att_incomplete("teximage width/height=0"); + printf("texobj = %u\n", texObj->Name); + printf("level = %d\n", att->TextureLevel); + att->Complete = GL_FALSE; + return; + } + if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) { + att_incomplete("bad z offset"); + att->Complete = GL_FALSE; + return; + } + + baseFormat = _mesa_get_format_base_format(texImage->TexFormat); + + if (format == GL_COLOR) { + if (!_mesa_is_legal_color_format(ctx, baseFormat)) { + att_incomplete("bad format"); + att->Complete = GL_FALSE; + return; + } + if (_mesa_is_format_compressed(texImage->TexFormat)) { + att_incomplete("compressed internalformat"); + att->Complete = GL_FALSE; + return; + } + } + else if (format == GL_DEPTH) { + if (baseFormat == GL_DEPTH_COMPONENT) { + /* OK */ + } + else if (ctx->Extensions.EXT_packed_depth_stencil && + ctx->Extensions.ARB_depth_texture && + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* OK */ + } + else { + att->Complete = GL_FALSE; + att_incomplete("bad depth format"); + return; + } + } + else { + ASSERT(format == GL_STENCIL); + if (ctx->Extensions.EXT_packed_depth_stencil && + ctx->Extensions.ARB_depth_texture && + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* OK */ + } + else { + /* no such thing as stencil-only textures */ + att_incomplete("illegal stencil texture"); + att->Complete = GL_FALSE; + return; + } + } + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + const GLenum baseFormat = + _mesa_get_format_base_format(att->Renderbuffer->Format); + + ASSERT(att->Renderbuffer); + if (!att->Renderbuffer->InternalFormat || + att->Renderbuffer->Width < 1 || + att->Renderbuffer->Height < 1) { + att_incomplete("0x0 renderbuffer"); + att->Complete = GL_FALSE; + return; + } + if (format == GL_COLOR) { + if (!_mesa_is_legal_color_format(ctx, baseFormat)) { + att_incomplete("bad renderbuffer color format"); + att->Complete = GL_FALSE; + return; + } + } + else if (format == GL_DEPTH) { + if (baseFormat == GL_DEPTH_COMPONENT) { + /* OK */ + } + else if (ctx->Extensions.EXT_packed_depth_stencil && + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* OK */ + } + else { + att_incomplete("bad renderbuffer depth format"); + att->Complete = GL_FALSE; + return; + } + } + else { + assert(format == GL_STENCIL); + if (baseFormat == GL_STENCIL_INDEX) { + /* OK */ + } + else if (ctx->Extensions.EXT_packed_depth_stencil && + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* OK */ + } + else { + att->Complete = GL_FALSE; + att_incomplete("bad renderbuffer stencil format"); + return; + } + } + } + else { + ASSERT(att->Type == GL_NONE); + /* complete */ + return; + } +} + + +/** + * Test if the given framebuffer object is complete and update its + * Status field with the results. + * Calls the ctx->Driver.ValidateFramebuffer() function to allow the + * driver to make hardware-specific validation/completeness checks. + * Also update the framebuffer's Width and Height fields if the + * framebuffer is complete. + */ +void +_mesa_test_framebuffer_completeness(struct gl_context *ctx, + struct gl_framebuffer *fb) +{ + GLuint numImages; + GLenum intFormat = GL_NONE; /* color buffers' internal format */ + GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0; + GLint numSamples = -1; + GLint i; + GLuint j; + + assert(fb->Name != 0); + + numImages = 0; + fb->Width = 0; + fb->Height = 0; + + /* Start at -2 to more easily loop over all attachment points. + * -2: depth buffer + * -1: stencil buffer + * >=0: color buffer + */ + for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { + struct gl_renderbuffer_attachment *att; + GLenum f; + gl_format attFormat; + + /* + * XXX for ARB_fbo, only check color buffers that are named by + * GL_READ_BUFFER and GL_DRAW_BUFFERi. + */ + + /* check for attachment completeness + */ + if (i == -2) { + att = &fb->Attachment[BUFFER_DEPTH]; + test_attachment_completeness(ctx, GL_DEPTH, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fbo_incomplete("depth attachment incomplete", -1); + return; + } + } + else if (i == -1) { + att = &fb->Attachment[BUFFER_STENCIL]; + test_attachment_completeness(ctx, GL_STENCIL, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fbo_incomplete("stencil attachment incomplete", -1); + return; + } + } + else { + att = &fb->Attachment[BUFFER_COLOR0 + i]; + test_attachment_completeness(ctx, GL_COLOR, att); + if (!att->Complete) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT; + fbo_incomplete("color attachment incomplete", i); + return; + } + } + + /* get width, height, format of the renderbuffer/texture + */ + if (att->Type == GL_TEXTURE) { + const struct gl_texture_image *texImg = + _mesa_get_attachment_teximage(att); + minWidth = MIN2(minWidth, texImg->Width); + maxWidth = MAX2(maxWidth, texImg->Width); + minHeight = MIN2(minHeight, texImg->Height); + maxHeight = MAX2(maxHeight, texImg->Height); + f = texImg->_BaseFormat; + attFormat = texImg->TexFormat; + numImages++; + if (!_mesa_is_legal_color_format(ctx, f) && + !is_legal_depth_format(ctx, f)) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; + fbo_incomplete("texture attachment incomplete", -1); + return; + } + } + else if (att->Type == GL_RENDERBUFFER_EXT) { + minWidth = MIN2(minWidth, att->Renderbuffer->Width); + maxWidth = MAX2(minWidth, att->Renderbuffer->Width); + minHeight = MIN2(minHeight, att->Renderbuffer->Height); + maxHeight = MAX2(minHeight, att->Renderbuffer->Height); + f = att->Renderbuffer->InternalFormat; + attFormat = att->Renderbuffer->Format; + numImages++; + } + else { + assert(att->Type == GL_NONE); + continue; + } + + if (att->Renderbuffer && numSamples < 0) { + /* first buffer */ + numSamples = att->Renderbuffer->NumSamples; + } + + /* check if integer color */ + fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); + + /* Error-check width, height, format, samples + */ + if (numImages == 1) { + /* save format, num samples */ + if (i >= 0) { + intFormat = f; + } + } + else { + if (!ctx->Extensions.ARB_framebuffer_object) { + /* check that width, height, format are same */ + if (minWidth != maxWidth || minHeight != maxHeight) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT; + fbo_incomplete("width or height mismatch", -1); + return; + } + /* check that all color buffer have same format */ + if (intFormat != GL_NONE && f != intFormat) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT; + fbo_incomplete("format mismatch", -1); + return; + } + } + if (att->Renderbuffer && + att->Renderbuffer->NumSamples != numSamples) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; + fbo_incomplete("inconsistant number of samples", i); + return; + } + + } + } + +#if FEATURE_GL + if (ctx->API == API_OPENGL) { + /* Check that all DrawBuffers are present */ + for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) { + if (fb->ColorDrawBuffer[j] != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT; + fbo_incomplete("missing drawbuffer", j); + return; + } + } + } + + /* Check that the ReadBuffer is present */ + if (fb->ColorReadBuffer != GL_NONE) { + const struct gl_renderbuffer_attachment *att + = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer); + assert(att); + if (att->Type == GL_NONE) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT; + fbo_incomplete("missing readbuffer", -1); + return; + } + } + } +#else + (void) j; +#endif + + if (numImages == 0) { + fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT; + fbo_incomplete("no attachments", -1); + return; + } + + /* Provisionally set status = COMPLETE ... */ + fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + + /* ... but the driver may say the FB is incomplete. + * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED + * if anything. + */ + if (ctx->Driver.ValidateFramebuffer) { + ctx->Driver.ValidateFramebuffer(ctx, fb); + if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + fbo_incomplete("driver marked FBO as incomplete", -1); + } + } + + if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) { + /* + * Note that if ARB_framebuffer_object is supported and the attached + * renderbuffers/textures are different sizes, the framebuffer + * width/height will be set to the smallest width/height. + */ + fb->Width = minWidth; + fb->Height = minHeight; + + /* finally, update the visual info for the framebuffer */ + _mesa_update_framebuffer_visual(ctx, fb); + } +} + + +GLboolean GLAPIENTRY +_mesa_IsRenderbufferEXT(GLuint renderbuffer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (renderbuffer) { + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (rb != NULL && rb != &DummyRenderbuffer) + return GL_TRUE; + } + return GL_FALSE; +} + + +void GLAPIENTRY +_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) +{ + struct gl_renderbuffer *newRb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)"); + return; + } + + /* No need to flush here since the render buffer binding has no + * effect on rendering state. + */ + + if (renderbuffer) { + newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (newRb == &DummyRenderbuffer) { + /* ID was reserved, but no real renderbuffer object made yet */ + newRb = NULL; + } + else if (!newRb && ctx->Extensions.ARB_framebuffer_object) { + /* All RB IDs must be Gen'd */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); + return; + } + + if (!newRb) { + /* create new renderbuffer object */ + newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer); + if (!newRb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT"); + return; + } + ASSERT(newRb->AllocStorage); + _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb); + newRb->RefCount = 1; /* referenced by hash table */ + } + } + else { + newRb = NULL; + } + + ASSERT(newRb != &DummyRenderbuffer); + + _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); +} + + +/** + * If the given renderbuffer is anywhere attached to the framebuffer, detach + * the renderbuffer. + * This is used when a renderbuffer object is deleted. + * The spec calls for unbinding. + */ +static void +detach_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer *rb) +{ + GLuint i; + for (i = 0; i < BUFFER_COUNT; i++) { + if (fb->Attachment[i].Renderbuffer == rb) { + _mesa_remove_attachment(ctx, &fb->Attachment[i]); + } + } + invalidate_framebuffer(fb); +} + + +void GLAPIENTRY +_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + for (i = 0; i < n; i++) { + if (renderbuffers[i] > 0) { + struct gl_renderbuffer *rb; + rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]); + if (rb) { + /* check if deleting currently bound renderbuffer object */ + if (rb == ctx->CurrentRenderbuffer) { + /* bind default */ + ASSERT(rb->RefCount >= 2); + _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + + if (ctx->DrawBuffer->Name) { + detach_renderbuffer(ctx, ctx->DrawBuffer, rb); + } + if (ctx->ReadBuffer->Name && ctx->ReadBuffer != ctx->DrawBuffer) { + detach_renderbuffer(ctx, ctx->ReadBuffer, rb); + } + + /* Remove from hash table immediately, to free the ID. + * But the object will not be freed until it's no longer + * referenced anywhere else. + */ + _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]); + + if (rb != &DummyRenderbuffer) { + /* no longer referenced by hash table */ + _mesa_reference_renderbuffer(&rb, NULL); + } + } + } + } +} + + +void GLAPIENTRY +_mesa_GenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)"); + return; + } + + if (!renderbuffers) + return; + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n); + + for (i = 0; i < n; i++) { + GLuint name = first + i; + renderbuffers[i] = name; + /* insert dummy placeholder into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } +} + + +/** + * Given an internal format token for a render buffer, return the + * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX, + * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE, + * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc). + * + * This is similar to _mesa_base_tex_format() but the set of valid + * internal formats is different. + * + * Note that even if a format is determined to be legal here, validation + * of the FBO may fail if the format is not supported by the driver/GPU. + * + * \param internalFormat as passed to glRenderbufferStorage() + * \return the base internal format, or 0 if internalFormat is illegal + */ +GLenum +_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) +{ + /* + * Notes: some formats such as alpha, luminance, etc. were added + * with GL_ARB_framebuffer_object. + */ + switch (internalFormat) { + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + case GL_RGB: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case GL_SRGB8_EXT: + return GL_RGB; + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + case GL_SRGB8_ALPHA8_EXT: + return GL_RGBA; + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + case GL_STENCIL_INDEX16_EXT: + return GL_STENCIL_INDEX; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + return GL_DEPTH_COMPONENT; + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + if (ctx->Extensions.EXT_packed_depth_stencil) + return GL_DEPTH_STENCIL_EXT; + else + return 0; + case GL_RED: + case GL_R8: + case GL_R16: + return ctx->Extensions.ARB_texture_rg ? GL_RED : 0; + case GL_RG: + case GL_RG8: + case GL_RG16: + return ctx->Extensions.ARB_texture_rg ? GL_RG : 0; + /* signed normalized texture formats */ + case GL_RED_SNORM: + case GL_R8_SNORM: + case GL_R16_SNORM: + return ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; + case GL_RG_SNORM: + case GL_RG8_SNORM: + case GL_RG16_SNORM: + return ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; + case GL_RGB_SNORM: + case GL_RGB8_SNORM: + case GL_RGB16_SNORM: + return ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + case GL_RGBA16_SNORM: + return ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; + case GL_ALPHA_SNORM: + case GL_ALPHA8_SNORM: + case GL_ALPHA16_SNORM: + return ctx->Extensions.EXT_texture_snorm && + ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE8_SNORM: + case GL_LUMINANCE16_SNORM: + return ctx->Extensions.EXT_texture_snorm && + ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; + case GL_LUMINANCE_ALPHA_SNORM: + case GL_LUMINANCE8_ALPHA8_SNORM: + case GL_LUMINANCE16_ALPHA16_SNORM: + return ctx->Extensions.EXT_texture_snorm && + ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_INTENSITY_SNORM: + case GL_INTENSITY8_SNORM: + case GL_INTENSITY16_SNORM: + return ctx->Extensions.EXT_texture_snorm && + ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + case GL_R16F: + case GL_R32F: + return ctx->Extensions.ARB_texture_rg && + ctx->Extensions.ARB_texture_float ? GL_RED : 0; + case GL_RG16F: + case GL_RG32F: + return ctx->Extensions.ARB_texture_rg && + ctx->Extensions.ARB_texture_float ? GL_RG : 0; + case GL_RGB16F: + case GL_RGB32F: + return ctx->Extensions.ARB_texture_float ? GL_RGB : 0; + case GL_RGBA16F: + case GL_RGBA32F: + return ctx->Extensions.ARB_texture_float ? GL_RGBA : 0; + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + return ctx->Extensions.ARB_texture_float && + ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + return ctx->Extensions.ARB_texture_float && + ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + return ctx->Extensions.ARB_texture_float && + ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + return ctx->Extensions.ARB_texture_float && + ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + /* XXX add integer formats eventually */ + default: + return 0; + } +} + + +/** + * Invalidate a renderbuffer attachment. Called from _mesa_HashWalk(). + */ +static void +invalidate_rb(GLuint key, void *data, void *userData) +{ + struct gl_framebuffer *fb = (struct gl_framebuffer *) data; + struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData; + + /* If this is a user-created FBO */ + if (fb->Name) { + GLuint i; + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = fb->Attachment + i; + if (att->Type == GL_RENDERBUFFER && + att->Renderbuffer == rb) { + /* Mark fb status as indeterminate to force re-validation */ + fb->_Status = 0; + return; + } + } + } +} + + +/** sentinal value, see below */ +#define NO_SAMPLES 1000 + + +/** + * Helper function used by _mesa_RenderbufferStorageEXT() and + * _mesa_RenderbufferStorageMultisample(). + * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorageEXT(). + */ +static void +renderbuffer_storage(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height, GLsizei samples) +{ + const char *func = samples == NO_SAMPLES ? + "glRenderbufferStorage" : "RenderbufferStorageMultisample"; + struct gl_renderbuffer *rb; + GLenum baseFormat; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); + return; + } + + baseFormat = _mesa_base_fbo_format(ctx, internalFormat); + if (baseFormat == 0) { + _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat)", func); + return; + } + + if (width < 1 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func); + return; + } + + if (height < 1 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func); + return; + } + + if (samples == NO_SAMPLES) { + /* NumSamples == 0 indicates non-multisampling */ + samples = 0; + } + else if (samples > (GLsizei) ctx->Const.MaxSamples) { + /* note: driver may choose to use more samples than what's requested */ + _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); + return; + } + + rb = ctx->CurrentRenderbuffer; + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (rb->InternalFormat == internalFormat && + rb->Width == (GLuint) width && + rb->Height == (GLuint) height) { + /* no change in allocation needed */ + return; + } + + /* These MUST get set by the AllocStorage func */ + rb->Format = MESA_FORMAT_NONE; + rb->NumSamples = samples; + + /* Now allocate the storage */ + ASSERT(rb->AllocStorage); + if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) { + /* No error - check/set fields now */ + assert(rb->Format != MESA_FORMAT_NONE); + assert(rb->Width == (GLuint) width); + assert(rb->Height == (GLuint) height); + rb->InternalFormat = internalFormat; + rb->_BaseFormat = baseFormat; + assert(rb->_BaseFormat != 0); + } + else { + /* Probably ran out of memory - clear the fields */ + rb->Width = 0; + rb->Height = 0; + rb->Format = MESA_FORMAT_NONE; + rb->InternalFormat = GL_NONE; + rb->_BaseFormat = GL_NONE; + rb->NumSamples = 0; + } + + /* Invalidate the framebuffers the renderbuffer is attached in. */ + if (rb->AttachedAnytime) { + _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb); + } +} + + +#if FEATURE_OES_EGL_image +void GLAPIENTRY +_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.OES_EGL_image) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glEGLImageTargetRenderbufferStorageOES(unsupported)"); + return; + } + + if (target != GL_RENDERBUFFER) { + _mesa_error(ctx, GL_INVALID_ENUM, + "EGLImageTargetRenderbufferStorageOES"); + return; + } + + rb = ctx->CurrentRenderbuffer; + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "EGLImageTargetRenderbufferStorageOES"); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image); +} +#endif + + +/** + * Helper function for _mesa_GetRenderbufferParameterivEXT() and + * _mesa_GetFramebufferAttachmentParameterivEXT() + * We have to be careful to respect the base format. For example, if a + * renderbuffer/texture was created with internalFormat=GL_RGB but the + * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE + * we need to return zero. + */ +static GLint +get_component_bits(GLenum pname, GLenum baseFormat, gl_format format) +{ + switch (pname) { + case GL_RENDERBUFFER_RED_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + if (baseFormat == GL_RGB || baseFormat == GL_RGBA || + baseFormat == GL_RG || baseFormat == GL_RED) + return _mesa_get_format_bits(format, pname); + else + return 0; + case GL_RENDERBUFFER_GREEN_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + if (baseFormat == GL_RGB || baseFormat == GL_RGBA || baseFormat == GL_RG) + return _mesa_get_format_bits(format, pname); + else + return 0; + case GL_RENDERBUFFER_BLUE_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + if (baseFormat == GL_RGB || baseFormat == GL_RGBA) + return _mesa_get_format_bits(format, pname); + else + return 0; + case GL_RENDERBUFFER_ALPHA_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + if (baseFormat == GL_RGBA || baseFormat == GL_ALPHA || + baseFormat == GL_LUMINANCE_ALPHA) + return _mesa_get_format_bits(format, pname); + else + return 0; + case GL_RENDERBUFFER_DEPTH_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) + return _mesa_get_format_bits(format, pname); + else + return 0; + case GL_RENDERBUFFER_STENCIL_SIZE_EXT: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + if (baseFormat == GL_STENCIL_INDEX || baseFormat == GL_DEPTH_STENCIL) + return _mesa_get_format_bits(format, pname); + else + return 0; + default: + return 0; + } +} + + + +void GLAPIENTRY +_mesa_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height) +{ + /* GL_ARB_fbo says calling this function is equivalent to calling + * glRenderbufferStorageMultisample() with samples=0. We pass in + * a token value here just for error reporting purposes. + */ + renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES); +} + + +void GLAPIENTRY +_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples, + GLenum internalFormat, + GLsizei width, GLsizei height) +{ + renderbuffer_storage(target, internalFormat, width, height, samples); +} + + +/** + * OpenGL ES version of glRenderBufferStorage. + */ +void GLAPIENTRY +_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat, + GLsizei width, GLsizei height) +{ + switch (internalFormat) { + case GL_RGB565: + /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */ + /* choose a closest format */ + internalFormat = GL_RGB5; + break; + default: + break; + } + + renderbuffer_storage(target, internalFormat, width, height, 0); +} + + +void GLAPIENTRY +_mesa_GetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) +{ + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (target != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetRenderbufferParameterivEXT(target)"); + return; + } + + rb = ctx->CurrentRenderbuffer; + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetRenderbufferParameterivEXT"); + return; + } + + /* No need to flush here since we're just quering state which is + * not effected by rendering. + */ + + switch (pname) { + case GL_RENDERBUFFER_WIDTH_EXT: + *params = rb->Width; + return; + case GL_RENDERBUFFER_HEIGHT_EXT: + *params = rb->Height; + return; + case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT: + *params = rb->InternalFormat; + return; + case GL_RENDERBUFFER_RED_SIZE_EXT: + case GL_RENDERBUFFER_GREEN_SIZE_EXT: + case GL_RENDERBUFFER_BLUE_SIZE_EXT: + case GL_RENDERBUFFER_ALPHA_SIZE_EXT: + case GL_RENDERBUFFER_DEPTH_SIZE_EXT: + case GL_RENDERBUFFER_STENCIL_SIZE_EXT: + *params = get_component_bits(pname, rb->_BaseFormat, rb->Format); + break; + case GL_RENDERBUFFER_SAMPLES: + if (ctx->Extensions.ARB_framebuffer_object) { + *params = rb->NumSamples; + break; + } + /* fallthrough */ + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetRenderbufferParameterivEXT(target)"); + return; + } +} + + +GLboolean GLAPIENTRY +_mesa_IsFramebufferEXT(GLuint framebuffer) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + if (framebuffer) { + struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer); + if (rb != NULL && rb != &DummyFramebuffer) + return GL_TRUE; + } + return GL_FALSE; +} + + +/** + * Check if any of the attachments of the given framebuffer are textures + * (render to texture). Call ctx->Driver.RenderTexture() for such + * attachments. + */ +static void +check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + GLuint i; + ASSERT(ctx->Driver.RenderTexture); + + if (fb->Name == 0) + return; /* can't render to texture with winsys framebuffers */ + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = fb->Attachment + i; + if (att->Texture && _mesa_get_attachment_teximage(att)) { + ctx->Driver.RenderTexture(ctx, fb, att); + } + } +} + + +/** + * Examine all the framebuffer's attachments to see if any are textures. + * If so, call ctx->Driver.FinishRenderTexture() for each texture to + * notify the device driver that the texture image may have changed. + */ +static void +check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + if (fb->Name == 0) + return; /* can't render to texture with winsys framebuffers */ + + if (ctx->Driver.FinishRenderTexture) { + GLuint i; + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = fb->Attachment + i; + if (att->Texture && att->Renderbuffer) { + ctx->Driver.FinishRenderTexture(ctx, att); + } + } + } +} + + +void GLAPIENTRY +_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) +{ + struct gl_framebuffer *newDrawFb, *newReadFb; + struct gl_framebuffer *oldDrawFb, *oldReadFb; + GLboolean bindReadBuf, bindDrawBuf; + GET_CURRENT_CONTEXT(ctx); + +#ifdef DEBUG + if (ctx->Extensions.ARB_framebuffer_object) { + ASSERT(ctx->Extensions.EXT_framebuffer_object); + ASSERT(ctx->Extensions.EXT_framebuffer_blit); + } +#endif + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.EXT_framebuffer_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindFramebufferEXT(unsupported)"); + return; + } + + switch (target) { +#if FEATURE_EXT_framebuffer_blit + case GL_DRAW_FRAMEBUFFER_EXT: + if (!ctx->Extensions.EXT_framebuffer_blit) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); + return; + } + bindDrawBuf = GL_TRUE; + bindReadBuf = GL_FALSE; + break; + case GL_READ_FRAMEBUFFER_EXT: + if (!ctx->Extensions.EXT_framebuffer_blit) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); + return; + } + bindDrawBuf = GL_FALSE; + bindReadBuf = GL_TRUE; + break; +#endif + case GL_FRAMEBUFFER_EXT: + bindDrawBuf = GL_TRUE; + bindReadBuf = GL_TRUE; + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)"); + return; + } + + if (framebuffer) { + /* Binding a user-created framebuffer object */ + newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer); + if (newDrawFb == &DummyFramebuffer) { + /* ID was reserved, but no real framebuffer object made yet */ + newDrawFb = NULL; + } + else if (!newDrawFb && ctx->Extensions.ARB_framebuffer_object) { + /* All FBO IDs must be Gen'd */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); + return; + } + + if (!newDrawFb) { + /* create new framebuffer object */ + newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer); + if (!newDrawFb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT"); + return; + } + _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb); + } + newReadFb = newDrawFb; + } + else { + /* Binding the window system framebuffer (which was originally set + * with MakeCurrent). + */ + newDrawFb = ctx->WinSysDrawBuffer; + newReadFb = ctx->WinSysReadBuffer; + } + + ASSERT(newDrawFb); + ASSERT(newDrawFb != &DummyFramebuffer); + + /* save pointers to current/old framebuffers */ + oldDrawFb = ctx->DrawBuffer; + oldReadFb = ctx->ReadBuffer; + + /* check if really changing bindings */ + if (oldDrawFb == newDrawFb) + bindDrawBuf = GL_FALSE; + if (oldReadFb == newReadFb) + bindReadBuf = GL_FALSE; + + /* + * OK, now bind the new Draw/Read framebuffers, if they're changing. + * + * We also check if we're beginning and/or ending render-to-texture. + * When a framebuffer with texture attachments is unbound, call + * ctx->Driver.FinishRenderTexture(). + * When a framebuffer with texture attachments is bound, call + * ctx->Driver.RenderTexture(). + * + * Note that if the ReadBuffer has texture attachments we don't consider + * that a render-to-texture case. + */ + if (bindReadBuf) { + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + /* check if old readbuffer was render-to-texture */ + check_end_texture_render(ctx, oldReadFb); + + _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb); + } + + if (bindDrawBuf) { + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + /* check if old read/draw buffers were render-to-texture */ + if (!bindReadBuf) + check_end_texture_render(ctx, oldReadFb); + + if (oldDrawFb != oldReadFb) + check_end_texture_render(ctx, oldDrawFb); + + /* check if newly bound framebuffer has any texture attachments */ + check_begin_texture_render(ctx, newDrawFb); + + _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb); + } + + if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) { + ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb); + } +} + + +void GLAPIENTRY +_mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) +{ + GLint i; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + for (i = 0; i < n; i++) { + if (framebuffers[i] > 0) { + struct gl_framebuffer *fb; + fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]); + if (fb) { + ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]); + + /* check if deleting currently bound framebuffer object */ + if (ctx->Extensions.EXT_framebuffer_blit) { + /* separate draw/read binding points */ + if (fb == ctx->DrawBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + } + if (fb == ctx->ReadBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + } + } + else { + /* only one binding point for read/draw buffers */ + if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) { + /* bind default */ + ASSERT(fb->RefCount >= 2); + _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + } + + /* remove from hash table immediately, to free the ID */ + _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]); + + if (fb != &DummyFramebuffer) { + /* But the object will not be freed until it's no longer + * bound in any context. + */ + _mesa_reference_framebuffer(&fb, NULL); + } + } + } + } +} + + +void GLAPIENTRY +_mesa_GenFramebuffersEXT(GLsizei n, GLuint *framebuffers) +{ + GET_CURRENT_CONTEXT(ctx); + GLuint first; + GLint i; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)"); + return; + } + + if (!framebuffers) + return; + + first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n); + + for (i = 0; i < n; i++) { + GLuint name = first + i; + framebuffers[i] = name; + /* insert dummy placeholder into hash table */ + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } +} + + + +GLenum GLAPIENTRY +_mesa_CheckFramebufferStatusEXT(GLenum target) +{ + struct gl_framebuffer *buffer; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); + + buffer = get_framebuffer_target(ctx, target); + if (!buffer) { + _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)"); + return 0; + } + + if (buffer->Name == 0) { + /* The window system / default framebuffer is always complete */ + return GL_FRAMEBUFFER_COMPLETE_EXT; + } + + /* No need to flush here */ + + if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) { + _mesa_test_framebuffer_completeness(ctx, buffer); + } + + return buffer->_Status; +} + + + +/** + * Common code called by glFramebufferTexture1D/2D/3DEXT(). + */ +static void +framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target, + GLenum attachment, GLenum textarget, GLuint texture, + GLint level, GLint zoffset) +{ + struct gl_renderbuffer_attachment *att; + struct gl_texture_object *texObj = NULL; + struct gl_framebuffer *fb; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture%sEXT(target=0x%x)", caller, target); + return; + } + + /* check framebuffer binding */ + if (fb->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%sEXT", caller); + return; + } + + + /* The textarget, level, and zoffset parameters are only validated if + * texture is non-zero. + */ + if (texture) { + GLboolean err = GL_TRUE; + + texObj = _mesa_lookup_texture(ctx, texture); + if (texObj != NULL) { + if (textarget == 0) { + /* XXX what's the purpose of this? */ + err = (texObj->Target != GL_TEXTURE_3D) && + (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) && + (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT); + } + else { + err = (texObj->Target == GL_TEXTURE_CUBE_MAP) + ? !IS_CUBE_FACE(textarget) + : (texObj->Target != textarget); + } + } + else { + /* can't render to a non-existant texture */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%sEXT(non existant texture)", + caller); + return; + } + + if (err) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture%sEXT(texture target mismatch)", + caller); + return; + } + + if (texObj->Target == GL_TEXTURE_3D) { + const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); + if (zoffset < 0 || zoffset >= maxSize) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%sEXT(zoffset)", caller); + return; + } + } + else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) || + (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT)) { + if (zoffset < 0 || zoffset >= ctx->Const.MaxArrayTextureLayers) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%sEXT(layer)", caller); + return; + } + } + + if ((level < 0) || + (level >= _mesa_max_texture_levels(ctx, texObj->Target))) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferTexture%sEXT(level)", caller); + return; + } + } + + att = _mesa_get_attachment(ctx, fb, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture%sEXT(attachment)", caller); + return; + } + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + _glthread_LOCK_MUTEX(fb->Mutex); + if (texObj) { + _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget, + level, zoffset); + /* Set the render-to-texture flag. We'll check this flag in + * glTexImage() and friends to determine if we need to revalidate + * any FBOs that might be rendering into this texture. + * This flag never gets cleared since it's non-trivial to determine + * when all FBOs might be done rendering to this texture. That's OK + * though since it's uncommon to render to a texture then repeatedly + * call glTexImage() to change images in the texture. + */ + texObj->_RenderToTexture = GL_TRUE; + } + else { + _mesa_remove_attachment(ctx, att); + } + + invalidate_framebuffer(fb); + + _glthread_UNLOCK_MUTEX(fb->Mutex); +} + + + +void GLAPIENTRY +_mesa_FramebufferTexture1DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + GET_CURRENT_CONTEXT(ctx); + + if ((texture != 0) && (textarget != GL_TEXTURE_1D)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture1DEXT(textarget)"); + return; + } + + framebuffer_texture(ctx, "1D", target, attachment, textarget, texture, + level, 0); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture2DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + GET_CURRENT_CONTEXT(ctx); + + if ((texture != 0) && + (textarget != GL_TEXTURE_2D) && + (textarget != GL_TEXTURE_RECTANGLE_ARB) && + (!IS_CUBE_FACE(textarget))) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTexture2DEXT(textarget=0x%x)", textarget); + return; + } + + framebuffer_texture(ctx, "2D", target, attachment, textarget, texture, + level, 0); +} + + +void GLAPIENTRY +_mesa_FramebufferTexture3DEXT(GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level, GLint zoffset) +{ + GET_CURRENT_CONTEXT(ctx); + + if ((texture != 0) && (textarget != GL_TEXTURE_3D)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferTexture3DEXT(textarget)"); + return; + } + + framebuffer_texture(ctx, "3D", target, attachment, textarget, texture, + level, zoffset); +} + + +void GLAPIENTRY +_mesa_FramebufferTextureLayerEXT(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) +{ + GET_CURRENT_CONTEXT(ctx); + + framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, + level, layer); +} + + +void GLAPIENTRY +_mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, + GLenum renderbufferTarget, + GLuint renderbuffer) +{ + struct gl_renderbuffer_attachment *att; + struct gl_framebuffer *fb; + struct gl_renderbuffer *rb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + fb = get_framebuffer_target(ctx, target); + if (!fb) { + _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)"); + return; + } + + if (renderbufferTarget != GL_RENDERBUFFER_EXT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(renderbufferTarget)"); + return; + } + + if (fb->Name == 0) { + /* Can't attach new renderbuffers to a window system framebuffer */ + _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT"); + return; + } + + att = _mesa_get_attachment(ctx, fb, attachment); + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glFramebufferRenderbufferEXT(invalid attachment %s)", + _mesa_lookup_enum_by_nr(attachment)); + return; + } + + if (renderbuffer) { + rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); + if (!rb) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbufferEXT(non-existant" + " renderbuffer %u)", renderbuffer); + return; + } + else if (rb == &DummyRenderbuffer) { + /* This is what NVIDIA does */ + _mesa_error(ctx, GL_INVALID_VALUE, + "glFramebufferRenderbufferEXT(renderbuffer %u)", + renderbuffer); + return; + } + } + else { + /* remove renderbuffer attachment */ + rb = NULL; + } + + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT && + rb && rb->Format != MESA_FORMAT_NONE) { + /* make sure the renderbuffer is a depth/stencil format */ + const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); + if (baseFormat != GL_DEPTH_STENCIL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferRenderbufferEXT(renderbuffer" + " is not DEPTH_STENCIL format)"); + return; + } + } + + + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + assert(ctx->Driver.FramebufferRenderbuffer); + ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); + + /* Some subsequent GL commands may depend on the framebuffer's visual + * after the binding is updated. Update visual info now. + */ + _mesa_update_framebuffer_visual(ctx, fb); +} + + +void GLAPIENTRY +_mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, + GLenum pname, GLint *params) +{ + const struct gl_renderbuffer_attachment *att; + struct gl_framebuffer *buffer; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + buffer = get_framebuffer_target(ctx, target); + if (!buffer) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(target)"); + return; + } + + if (buffer->Name == 0) { + /* the default / window-system FBO */ + att = _mesa_get_fb0_attachment(ctx, buffer, attachment); + } + else { + /* user-created framebuffer FBO */ + att = _mesa_get_attachment(ctx, buffer, attachment); + } + + if (att == NULL) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(attachment)"); + return; + } + + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { + /* the depth and stencil attachments must point to the same buffer */ + const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt; + depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT); + stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT); + if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL" + " attachments differ)"); + return; + } + } + + /* No need to flush here */ + + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: + *params = buffer->Name == 0 ? GL_FRAMEBUFFER_DEFAULT : att->Type; + return; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT: + if (att->Type == GL_RENDERBUFFER_EXT) { + *params = att->Renderbuffer->Name; + } + else if (att->Type == GL_TEXTURE) { + *params = att->Texture->Name; + } + else { + assert(att->Type == GL_NONE); + *params = 0; + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT: + if (att->Type == GL_TEXTURE) { + *params = att->TextureLevel; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT: + if (att->Type == GL_TEXTURE) { + if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) { + *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace; + } + else { + *params = 0; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT: + if (att->Type == GL_TEXTURE) { + if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) { + *params = att->Zoffset; + } + else { + *params = 0; + } + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (!ctx->Extensions.ARB_framebuffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + else { + if (ctx->Extensions.EXT_framebuffer_sRGB && ctx->Const.sRGBCapable) { + *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format); + } + else { + /* According to ARB_framebuffer_sRGB, we should return LINEAR + * if the sRGB conversion is unsupported. */ + *params = GL_LINEAR; + } + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (!ctx->Extensions.ARB_framebuffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + return; + } + else { + gl_format format = att->Renderbuffer->Format; + if (format == MESA_FORMAT_CI8 || format == MESA_FORMAT_S8) { + /* special cases */ + *params = GL_INDEX; + } + else { + *params = _mesa_get_format_datatype(format); + } + } + return; + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + if (!ctx->Extensions.ARB_framebuffer_object) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + } + else if (att->Texture) { + const struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target, + att->TextureLevel); + if (texImage) { + *params = get_component_bits(pname, texImage->_BaseFormat, + texImage->TexFormat); + } + else { + *params = 0; + } + } + else if (att->Renderbuffer) { + *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat, + att->Renderbuffer->Format); + } + else { + *params = 0; + } + return; + default: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetFramebufferAttachmentParameterivEXT(pname)"); + return; + } +} + + +void GLAPIENTRY +_mesa_GenerateMipmapEXT(GLenum target) +{ + struct gl_texture_object *texObj; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + switch (target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + /* OK, legal value */ + break; + default: + /* XXX need to implement GL_TEXTURE_1D_ARRAY and GL_TEXTURE_2D_ARRAY */ + _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target)"); + return; + } + + texObj = _mesa_get_current_tex_object(ctx, target); + + if (texObj->BaseLevel >= texObj->MaxLevel) { + /* nothing to do */ + return; + } + + if (texObj->Target == GL_TEXTURE_CUBE_MAP && + !_mesa_cube_complete(texObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGenerateMipmap(incomplete cube map)"); + return; + } + + _mesa_lock_texture(ctx, texObj); + if (target == GL_TEXTURE_CUBE_MAP) { + GLuint face; + for (face = 0; face < 6; face++) + ctx->Driver.GenerateMipmap(ctx, + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face, + texObj); + } + else { + ctx->Driver.GenerateMipmap(ctx, target, texObj); + } + _mesa_unlock_texture(ctx, texObj); +} + + +#if FEATURE_EXT_framebuffer_blit + +static const struct gl_renderbuffer_attachment * +find_attachment(const struct gl_framebuffer *fb, + const struct gl_renderbuffer *rb) +{ + GLuint i; + for (i = 0; i < Elements(fb->Attachment); i++) { + if (fb->Attachment[i].Renderbuffer == rb) + return &fb->Attachment[i]; + } + return NULL; +} + + + +/** + * Blit rectangular region, optionally from one framebuffer to another. + * + * Note, if the src buffer is multisampled and the dest is not, this is + * when the samples must be resolved to a single color. + */ +void GLAPIENTRY +_mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + const struct gl_framebuffer *readFb, *drawFb; + const struct gl_renderbuffer *colorReadRb, *colorDrawRb; + GET_CURRENT_CONTEXT(ctx); + + ASSERT_OUTSIDE_BEGIN_END(ctx); + FLUSH_VERTICES(ctx, _NEW_BUFFERS); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d, 0x%x, %s)\n", + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, _mesa_lookup_enum_by_nr(filter)); + + if (ctx->NewState) { + _mesa_update_state(ctx); + } + + readFb = ctx->ReadBuffer; + drawFb = ctx->DrawBuffer; + + if (!readFb || !drawFb) { + /* This will normally never happen but someday we may want to + * support MakeCurrent() with no drawables. + */ + return; + } + + /* check for complete framebuffers */ + if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT || + readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glBlitFramebufferEXT(incomplete draw/read buffers)"); + return; + } + + if (filter != GL_NEAREST && filter != GL_LINEAR) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(filter)"); + return; + } + + if (mask & ~legalMaskBits) { + _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)"); + return; + } + + /* depth/stencil must be blitted with nearest filtering */ + if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) + && filter != GL_NEAREST) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)"); + return; + } + + /* get color read/draw renderbuffers */ + if (mask & GL_COLOR_BUFFER_BIT) { + colorReadRb = readFb->_ColorReadBuffer; + colorDrawRb = drawFb->_ColorDrawBuffers[0]; + } + else { + colorReadRb = colorDrawRb = NULL; + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + struct gl_renderbuffer *readRb = readFb->_StencilBuffer; + struct gl_renderbuffer *drawRb = drawFb->_StencilBuffer; + if (!readRb || + !drawRb || + _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) != + _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(stencil buffer size mismatch)"); + return; + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) { + struct gl_renderbuffer *readRb = readFb->_DepthBuffer; + struct gl_renderbuffer *drawRb = drawFb->_DepthBuffer; + if (!readRb || + !drawRb || + _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) != + _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(depth buffer size mismatch)"); + return; + } + } + + if (readFb->Visual.samples > 0 && + drawFb->Visual.samples > 0 && + readFb->Visual.samples != drawFb->Visual.samples) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(mismatched samples"); + return; + } + + /* extra checks for multisample copies... */ + if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) { + /* src and dest region sizes must be the same */ + if (srcX1 - srcX0 != dstX1 - dstX0 || + srcY1 - srcY0 != dstY1 - dstY0) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(bad src/dst multisample region sizes)"); + return; + } + + /* color formats must match */ + if (colorReadRb && + colorDrawRb && + colorReadRb->Format != colorDrawRb->Format) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBlitFramebufferEXT(bad src/dst multisample pixel formats)"); + return; + } + } + + if (!ctx->Extensions.EXT_framebuffer_blit) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT"); + return; + } + + /* Debug code */ + if (DEBUG_BLIT) { + printf("glBlitFramebuffer(%d, %d, %d, %d, %d, %d, %d, %d," + " 0x%x, 0x%x)\n", + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); + if (colorReadRb) { + const struct gl_renderbuffer_attachment *att; + + att = find_attachment(readFb, colorReadRb); + printf(" Src FBO %u RB %u (%dx%d) ", + readFb->Name, colorReadRb->Name, + colorReadRb->Width, colorReadRb->Height); + if (att && att->Texture) { + printf("Tex %u tgt 0x%x level %u face %u", + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); + } + printf("\n"); + + att = find_attachment(drawFb, colorDrawRb); + printf(" Dst FBO %u RB %u (%dx%d) ", + drawFb->Name, colorDrawRb->Name, + colorDrawRb->Width, colorDrawRb->Height); + if (att && att->Texture) { + printf("Tex %u tgt 0x%x level %u face %u", + att->Texture->Name, + att->Texture->Target, + att->TextureLevel, + att->CubeMapFace); + } + printf("\n"); + } + } + + ASSERT(ctx->Driver.BlitFramebuffer); + ctx->Driver.BlitFramebuffer(ctx, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, + mask, filter); +} +#endif /* FEATURE_EXT_framebuffer_blit */ + +#if FEATURE_ARB_geometry_shader4 +void GLAPIENTRY +_mesa_FramebufferTextureARB(GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTextureARB " + "not implemented!"); +} + +void GLAPIENTRY +_mesa_FramebufferTextureFaceARB(GLenum target, GLenum attachment, + GLuint texture, GLint level, GLenum face) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_error(ctx, GL_INVALID_OPERATION, + "glFramebufferTextureFaceARB " + "not implemented!"); +} +#endif /* FEATURE_ARB_geometry_shader4 */ diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index e62170b71..4c31ccb76 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -677,7 +677,7 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = { MESA_FORMAT_LUMINANCE_FLOAT32, "MESA_FORMAT_LUMINANCE_FLOAT32", - GL_ALPHA, + GL_LUMINANCE, GL_FLOAT, 0, 0, 0, 0, 32, 0, 0, 0, 0, @@ -686,7 +686,7 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = { MESA_FORMAT_LUMINANCE_FLOAT16, "MESA_FORMAT_LUMINANCE_FLOAT16", - GL_ALPHA, + GL_LUMINANCE, GL_FLOAT, 0, 0, 0, 0, 16, 0, 0, 0, 0, @@ -728,6 +728,42 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 16, 0, 0, 0, 1, 1, 2 }, + { + MESA_FORMAT_R_FLOAT32, + "MESA_FORMAT_R_FLOAT32", + GL_RED, + GL_FLOAT, + 32, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 4 + }, + { + MESA_FORMAT_R_FLOAT16, + "MESA_FORMAT_R_FLOAT16", + GL_RED, + GL_FLOAT, + 16, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 2 + }, + { + MESA_FORMAT_RG_FLOAT32, + "MESA_FORMAT_RG_FLOAT32", + GL_RG, + GL_FLOAT, + 32, 32, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 8 + }, + { + MESA_FORMAT_RG_FLOAT16, + "MESA_FORMAT_RG_FLOAT16", + GL_RG, + GL_FLOAT, + 16, 16, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 4 + }, /* unnormalized signed int formats */ { @@ -1714,22 +1750,26 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 3; return; case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: + case MESA_FORMAT_RG_FLOAT32: *datatype = GL_FLOAT; *comps = 2; return; case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: + case MESA_FORMAT_RG_FLOAT16: *datatype = GL_HALF_FLOAT_ARB; *comps = 2; return; case MESA_FORMAT_ALPHA_FLOAT32: case MESA_FORMAT_LUMINANCE_FLOAT32: case MESA_FORMAT_INTENSITY_FLOAT32: + case MESA_FORMAT_R_FLOAT32: *datatype = GL_FLOAT; *comps = 1; return; case MESA_FORMAT_ALPHA_FLOAT16: case MESA_FORMAT_LUMINANCE_FLOAT16: case MESA_FORMAT_INTENSITY_FLOAT16: + case MESA_FORMAT_R_FLOAT16: *datatype = GL_HALF_FLOAT_ARB; *comps = 1; return; diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index e0c2acbb9..15ac62cfe 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -142,6 +142,10 @@ typedef enum MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, MESA_FORMAT_INTENSITY_FLOAT32, MESA_FORMAT_INTENSITY_FLOAT16, + MESA_FORMAT_R_FLOAT32, + MESA_FORMAT_R_FLOAT16, + MESA_FORMAT_RG_FLOAT32, + MESA_FORMAT_RG_FLOAT16, /*@}*/ /** diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index b741c51ab..66c9bd910 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -1,1085 +1,1097 @@ -/* - * Mesa 3-D graphics library - * Version: 7.2 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -/** - * Functions for allocating/managing framebuffers and renderbuffers. - * Also, routines for reading/writing renderbuffer data as ubytes, - * ushorts, uints, etc. - */ - - -#include "glheader.h" -#include "imports.h" -#include "buffers.h" -#include "context.h" -#include "depthstencil.h" -#include "enums.h" -#include "formats.h" -#include "macros.h" -#include "mtypes.h" -#include "fbobject.h" -#include "framebuffer.h" -#include "renderbuffer.h" -#include "texobj.h" - - - -/** - * Compute/set the _DepthMax field for the given framebuffer. - * This value depends on the Z buffer resolution. - */ -static void -compute_depth_max(struct gl_framebuffer *fb) -{ - if (fb->Visual.depthBits == 0) { - /* Special case. Even if we don't have a depth buffer we need - * good values for DepthMax for Z vertex transformation purposes - * and for per-fragment fog computation. - */ - fb->_DepthMax = (1 << 16) - 1; - } - else if (fb->Visual.depthBits < 32) { - fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; - } - else { - /* Special case since shift values greater than or equal to the - * number of bits in the left hand expression's type are undefined. - */ - fb->_DepthMax = 0xffffffff; - } - fb->_DepthMaxF = (GLfloat) fb->_DepthMax; - - /* Minimum resolvable depth value, for polygon offset */ - fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF; -} - -/** - * Create and initialize a gl_framebuffer object. - * This is intended for creating _window_system_ framebuffers, not generic - * framebuffer objects ala GL_EXT_framebuffer_object. - * - * \sa _mesa_new_framebuffer - */ -struct gl_framebuffer * -_mesa_create_framebuffer(const struct gl_config *visual) -{ - struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); - assert(visual); - if (fb) { - _mesa_initialize_window_framebuffer(fb, visual); - } - return fb; -} - - -/** - * Allocate a new gl_framebuffer object. - * This is the default function for ctx->Driver.NewFramebuffer(). - * This is for allocating user-created framebuffers, not window-system - * framebuffers! - * \sa _mesa_create_framebuffer - */ -struct gl_framebuffer * -_mesa_new_framebuffer(struct gl_context *ctx, GLuint name) -{ - struct gl_framebuffer *fb; - (void) ctx; - assert(name != 0); - fb = CALLOC_STRUCT(gl_framebuffer); - if (fb) { - _mesa_initialize_user_framebuffer(fb, name); - } - return fb; -} - - -/** - * Initialize a gl_framebuffer object. Typically used to initialize - * window system-created framebuffers, not user-created framebuffers. - * \sa _mesa_initialize_user_framebuffer - */ -void -_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, - const struct gl_config *visual) -{ - assert(fb); - assert(visual); - - memset(fb, 0, sizeof(struct gl_framebuffer)); - - _glthread_INIT_MUTEX(fb->Mutex); - - fb->RefCount = 1; - - /* save the visual */ - fb->Visual = *visual; - - /* Init read/draw renderbuffer state */ - if (visual->doubleBufferMode) { - fb->_NumColorDrawBuffers = 1; - fb->ColorDrawBuffer[0] = GL_BACK; - fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; - fb->ColorReadBuffer = GL_BACK; - fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; - } - else { - fb->_NumColorDrawBuffers = 1; - fb->ColorDrawBuffer[0] = GL_FRONT; - fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; - fb->ColorReadBuffer = GL_FRONT; - fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; - } - - fb->Delete = _mesa_destroy_framebuffer; - fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; - - compute_depth_max(fb); -} - - -/** - * Initialize a user-created gl_framebuffer object. - * \sa _mesa_initialize_window_framebuffer - */ -void -_mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name) -{ - assert(fb); - assert(name); - - memset(fb, 0, sizeof(struct gl_framebuffer)); - - fb->Name = name; - fb->RefCount = 1; - fb->_NumColorDrawBuffers = 1; - fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; - fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0; - fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; - fb->_ColorReadBufferIndex = BUFFER_COLOR0; - fb->Delete = _mesa_destroy_framebuffer; - _glthread_INIT_MUTEX(fb->Mutex); -} - - -/** - * Deallocate buffer and everything attached to it. - * Typically called via the gl_framebuffer->Delete() method. - */ -void -_mesa_destroy_framebuffer(struct gl_framebuffer *fb) -{ - if (fb) { - _mesa_free_framebuffer_data(fb); - free(fb); - } -} - - -/** - * Free all the data hanging off the given gl_framebuffer, but don't free - * the gl_framebuffer object itself. - */ -void -_mesa_free_framebuffer_data(struct gl_framebuffer *fb) -{ - GLuint i; - - assert(fb); - assert(fb->RefCount == 0); - - _glthread_DESTROY_MUTEX(fb->Mutex); - - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; - if (att->Renderbuffer) { - _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); - } - if (att->Texture) { - _mesa_reference_texobj(&att->Texture, NULL); - } - ASSERT(!att->Renderbuffer); - ASSERT(!att->Texture); - att->Type = GL_NONE; - } - - /* unbind _Depth/_StencilBuffer to decr ref counts */ - _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL); - _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL); -} - - -/** - * Set *ptr to point to fb, with refcounting and locking. - */ -void -_mesa_reference_framebuffer(struct gl_framebuffer **ptr, - struct gl_framebuffer *fb) -{ - assert(ptr); - if (*ptr == fb) { - /* no change */ - return; - } - - if (*ptr) { - /* unreference old renderbuffer */ - GLboolean deleteFlag = GL_FALSE; - struct gl_framebuffer *oldFb = *ptr; - - _glthread_LOCK_MUTEX(oldFb->Mutex); - ASSERT(oldFb->RefCount > 0); - oldFb->RefCount--; - deleteFlag = (oldFb->RefCount == 0); - _glthread_UNLOCK_MUTEX(oldFb->Mutex); - - if (deleteFlag) - oldFb->Delete(oldFb); - - *ptr = NULL; - } - assert(!*ptr); - - if (fb) { - _glthread_LOCK_MUTEX(fb->Mutex); - fb->RefCount++; - _glthread_UNLOCK_MUTEX(fb->Mutex); - *ptr = fb; - } -} - - -/** - * Resize the given framebuffer's renderbuffers to the new width and height. - * This should only be used for window-system framebuffers, not - * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). - * This will typically be called via ctx->Driver.ResizeBuffers() or directly - * from a device driver. - * - * \note it's possible for ctx to be null since a window can be resized - * without a currently bound rendering context. - */ -void -_mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, - GLuint width, GLuint height) -{ - GLuint i; - - /* XXX I think we could check if the size is not changing - * and return early. - */ - - /* For window system framebuffers, Name is zero */ - assert(fb->Name == 0); - - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; - if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { - struct gl_renderbuffer *rb = att->Renderbuffer; - /* only resize if size is changing */ - if (rb->Width != width || rb->Height != height) { - if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { - ASSERT(rb->Width == width); - ASSERT(rb->Height == height); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); - /* no return */ - } - } - } - } - - if (fb->_DepthBuffer) { - struct gl_renderbuffer *rb = fb->_DepthBuffer; - if (rb->Width != width || rb->Height != height) { - if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); - } - } - } - - if (fb->_StencilBuffer) { - struct gl_renderbuffer *rb = fb->_StencilBuffer; - if (rb->Width != width || rb->Height != height) { - if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); - } - } - } - - fb->Width = width; - fb->Height = height; - - if (ctx) { - /* update scissor / window bounds */ - _mesa_update_draw_buffer_bounds(ctx); - /* Signal new buffer state so that swrast will update its clipping - * info (the CLIP_BIT flag). - */ - ctx->NewState |= _NEW_BUFFERS; - } -} - - - -/** - * XXX THIS IS OBSOLETE - drivers should take care of detecting window - * size changes and act accordingly, likely calling _mesa_resize_framebuffer(). - * - * GL_MESA_resize_buffers extension. - * - * When this function is called, we'll ask the window system how large - * the current window is. If it's a new size, we'll call the driver's - * ResizeBuffers function. The driver will then resize its color buffers - * as needed, and maybe call the swrast's routine for reallocating - * swrast-managed depth/stencil/accum/etc buffers. - * \note This function should only be called through the GL API, not - * from device drivers (as was done in the past). - */ -void -_mesa_resizebuffers( struct gl_context *ctx ) -{ - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glResizeBuffersMESA\n"); - - if (!ctx->Driver.GetBufferSize) { - return; - } - - if (ctx->WinSysDrawBuffer) { - GLuint newWidth, newHeight; - struct gl_framebuffer *buffer = ctx->WinSysDrawBuffer; - - assert(buffer->Name == 0); - - /* ask device driver for size of output buffer */ - ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); - - /* see if size of device driver's color buffer (window) has changed */ - if (buffer->Width != newWidth || buffer->Height != newHeight) { - if (ctx->Driver.ResizeBuffers) - ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); - } - } - - if (ctx->WinSysReadBuffer - && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { - GLuint newWidth, newHeight; - struct gl_framebuffer *buffer = ctx->WinSysReadBuffer; - - assert(buffer->Name == 0); - - /* ask device driver for size of read buffer */ - ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); - - /* see if size of device driver's color buffer (window) has changed */ - if (buffer->Width != newWidth || buffer->Height != newHeight) { - if (ctx->Driver.ResizeBuffers) - ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); - } - } - - ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ -} - - -/* - * XXX THIS IS OBSOLETE - */ -void GLAPIENTRY -_mesa_ResizeBuffersMESA( void ) -{ - GET_CURRENT_CONTEXT(ctx); - - if (ctx->Extensions.MESA_resize_buffers) - _mesa_resizebuffers( ctx ); -} - - - -/** - * Examine all the framebuffer's renderbuffers to update the Width/Height - * fields of the framebuffer. If we have renderbuffers with different - * sizes, set the framebuffer's width and height to the min size. - * Note: this is only intended for user-created framebuffers, not - * window-system framebuffes. - */ -static void -update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - GLuint minWidth = ~0, minHeight = ~0; - GLuint i; - - /* user-created framebuffers only */ - assert(fb->Name); - - for (i = 0; i < BUFFER_COUNT; i++) { - struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; - const struct gl_renderbuffer *rb = att->Renderbuffer; - if (rb) { - minWidth = MIN2(minWidth, rb->Width); - minHeight = MIN2(minHeight, rb->Height); - } - } - - if (minWidth != ~0) { - fb->Width = minWidth; - fb->Height = minHeight; - } - else { - fb->Width = 0; - fb->Height = 0; - } -} - - -/** - * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. - * These values are computed from the buffer's width and height and - * the scissor box, if it's enabled. - * \param ctx the GL context. - */ -void -_mesa_update_draw_buffer_bounds(struct gl_context *ctx) -{ - struct gl_framebuffer *buffer = ctx->DrawBuffer; - - if (!buffer) - return; - - if (buffer->Name) { - /* user-created framebuffer size depends on the renderbuffers */ - update_framebuffer_size(ctx, buffer); - } - - buffer->_Xmin = 0; - buffer->_Ymin = 0; - buffer->_Xmax = buffer->Width; - buffer->_Ymax = buffer->Height; - - if (ctx->Scissor.Enabled) { - if (ctx->Scissor.X > buffer->_Xmin) { - buffer->_Xmin = ctx->Scissor.X; - } - if (ctx->Scissor.Y > buffer->_Ymin) { - buffer->_Ymin = ctx->Scissor.Y; - } - if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) { - buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width; - } - if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) { - buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height; - } - /* finally, check for empty region */ - if (buffer->_Xmin > buffer->_Xmax) { - buffer->_Xmin = buffer->_Xmax; - } - if (buffer->_Ymin > buffer->_Ymax) { - buffer->_Ymin = buffer->_Ymax; - } - } - - ASSERT(buffer->_Xmin <= buffer->_Xmax); - ASSERT(buffer->_Ymin <= buffer->_Ymax); -} - - -/** - * The glGet queries of the framebuffer red/green/blue size, stencil size, - * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can - * change depending on the renderbuffer bindings. This function updates - * the given framebuffer's Visual from the current renderbuffer bindings. - * - * This may apply to user-created framebuffers or window system framebuffers. - * - * Also note: ctx->DrawBuffer->Visual.depthBits might not equal - * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. - * The former one is used to convert floating point depth values into - * integer Z values. - */ -void -_mesa_update_framebuffer_visual(struct gl_context *ctx, - struct gl_framebuffer *fb) -{ - GLuint i; - - memset(&fb->Visual, 0, sizeof(fb->Visual)); - fb->Visual.rgbMode = GL_TRUE; /* assume this */ - -#if 0 /* this _might_ be needed */ - if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - /* leave visual fields zero'd */ - return; - } -#endif - - /* find first RGB renderbuffer */ - for (i = 0; i < BUFFER_COUNT; i++) { - if (fb->Attachment[i].Renderbuffer) { - const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; - const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); - const gl_format fmt = rb->Format; - - if (_mesa_is_legal_color_format(ctx, baseFormat)) { - fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS); - fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); - fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); - fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); - fb->Visual.rgbBits = fb->Visual.redBits - + fb->Visual.greenBits + fb->Visual.blueBits; - fb->Visual.floatMode = GL_FALSE; - fb->Visual.samples = rb->NumSamples; - if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) - fb->Visual.sRGBCapable = ctx->Const.sRGBCapable; - break; - } - } - } - - if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { - const struct gl_renderbuffer *rb = - fb->Attachment[BUFFER_DEPTH].Renderbuffer; - const gl_format fmt = rb->Format; - fb->Visual.haveDepthBuffer = GL_TRUE; - fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS); - } - - if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { - const struct gl_renderbuffer *rb = - fb->Attachment[BUFFER_STENCIL].Renderbuffer; - const gl_format fmt = rb->Format; - fb->Visual.haveStencilBuffer = GL_TRUE; - fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS); - } - - if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { - const struct gl_renderbuffer *rb = - fb->Attachment[BUFFER_ACCUM].Renderbuffer; - const gl_format fmt = rb->Format; - fb->Visual.haveAccumBuffer = GL_TRUE; - fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS); - fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); - fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); - fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); - } - - compute_depth_max(fb); -} - - -/** - * Update the framebuffer's _DepthBuffer field using the renderbuffer - * found at the given attachment index. - * - * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, - * create and install a depth wrapper/adaptor. - * - * \param fb the framebuffer whose _DepthBuffer field to update - * \param attIndex indicates the renderbuffer to possibly wrap - */ -void -_mesa_update_depth_buffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - GLuint attIndex) -{ - struct gl_renderbuffer *depthRb; - - /* only one possiblity for now */ - ASSERT(attIndex == BUFFER_DEPTH); - - depthRb = fb->Attachment[attIndex].Renderbuffer; - - if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) { - /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ - if (!fb->_DepthBuffer - || fb->_DepthBuffer->Wrapped != depthRb - || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) { - /* need to update wrapper */ - struct gl_renderbuffer *wrapper - = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); - _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); - ASSERT(fb->_DepthBuffer->Wrapped == depthRb); - } - } - else { - /* depthRb may be null */ - _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb); - } -} - - -/** - * Update the framebuffer's _StencilBuffer field using the renderbuffer - * found at the given attachment index. - * - * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, - * create and install a stencil wrapper/adaptor. - * - * \param fb the framebuffer whose _StencilBuffer field to update - * \param attIndex indicates the renderbuffer to possibly wrap - */ -void -_mesa_update_stencil_buffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - GLuint attIndex) -{ - struct gl_renderbuffer *stencilRb; - - ASSERT(attIndex == BUFFER_DEPTH || - attIndex == BUFFER_STENCIL); - - stencilRb = fb->Attachment[attIndex].Renderbuffer; - - if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) { - /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ - if (!fb->_StencilBuffer - || fb->_StencilBuffer->Wrapped != stencilRb - || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) { - /* need to update wrapper */ - struct gl_renderbuffer *wrapper - = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); - _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); - ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); - } - } - else { - /* stencilRb may be null */ - _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); - } -} - - -/* - * Example DrawBuffers scenarios: - * - * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to - * "gl_FragColor" or program writes to the "result.color" register: - * - * fragment color output renderbuffer - * --------------------- --------------- - * color[0] Front, Back - * - * - * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to - * gl_FragData[i] or program writes to result.color[i] registers: - * - * fragment color output renderbuffer - * --------------------- --------------- - * color[0] Front - * color[1] Aux0 - * color[3] Aux1 - * - * - * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to - * gl_FragColor, or fixed function: - * - * fragment color output renderbuffer - * --------------------- --------------- - * color[0] Front, Aux0, Aux1 - * - * - * In either case, the list of renderbuffers is stored in the - * framebuffer->_ColorDrawBuffers[] array and - * framebuffer->_NumColorDrawBuffers indicates the number of buffers. - * The renderer (like swrast) has to look at the current fragment shader - * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine - * how to map color outputs to renderbuffers. - * - * Note that these two calls are equivalent (for fixed function fragment - * shading anyway): - * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) - * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); - */ - - - - -/** - * Update the (derived) list of color drawing renderbuffer pointers. - * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers - * writing colors. - */ -static void -update_color_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - GLuint output; - - /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */ - fb->_ColorDrawBuffers[0] = NULL; - - for (output = 0; output < fb->_NumColorDrawBuffers; output++) { - GLint buf = fb->_ColorDrawBufferIndexes[output]; - if (buf >= 0) { - fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer; - } - else { - fb->_ColorDrawBuffers[output] = NULL; - } - } -} - - -/** - * Update the (derived) color read renderbuffer pointer. - * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. - */ -static void -update_color_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - (void) ctx; - if (fb->_ColorReadBufferIndex == -1 || - fb->DeletePending || - fb->Width == 0 || - fb->Height == 0) { - fb->_ColorReadBuffer = NULL; /* legal! */ - } - else { - ASSERT(fb->_ColorReadBufferIndex >= 0); - ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); - fb->_ColorReadBuffer - = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; - } -} - - -/** - * Update a gl_framebuffer's derived state. - * - * Specifically, update these framebuffer fields: - * _ColorDrawBuffers - * _NumColorDrawBuffers - * _ColorReadBuffer - * _DepthBuffer - * _StencilBuffer - * - * If the framebuffer is user-created, make sure it's complete. - * - * The following functions (at least) can effect framebuffer state: - * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, - * glRenderbufferStorageEXT. - */ -static void -update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) -{ - if (fb->Name == 0) { - /* This is a window-system framebuffer */ - /* Need to update the FB's GL_DRAW_BUFFER state to match the - * context state (GL_READ_BUFFER too). - */ - if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { - _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, - ctx->Color.DrawBuffer, NULL); - } - } - else { - /* This is a user-created framebuffer. - * Completeness only matters for user-created framebuffers. - */ - if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) { - _mesa_test_framebuffer_completeness(ctx, fb); - } - } - - /* Strictly speaking, we don't need to update the draw-state - * if this FB is bound as ctx->ReadBuffer (and conversely, the - * read-state if this FB is bound as ctx->DrawBuffer), but no - * harm. - */ - update_color_draw_buffers(ctx, fb); - update_color_read_buffer(ctx, fb); - _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); - _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); - - compute_depth_max(fb); -} - - -/** - * Update state related to the current draw/read framebuffers. - */ -void -_mesa_update_framebuffer(struct gl_context *ctx) -{ - struct gl_framebuffer *drawFb; - struct gl_framebuffer *readFb; - - assert(ctx); - drawFb = ctx->DrawBuffer; - readFb = ctx->ReadBuffer; - - update_framebuffer(ctx, drawFb); - if (readFb != drawFb) - update_framebuffer(ctx, readFb); -} - - -/** - * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, - * glCopyTex[Sub]Image, etc) exists. - * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, - * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. - * \return GL_TRUE if buffer exists, GL_FALSE otherwise - */ -GLboolean -_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) -{ - const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; - - /* If we don't know the framebuffer status, update it now */ - if (ctx->ReadBuffer->_Status == 0) { - _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); - } - - if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - return GL_FALSE; - } - - switch (format) { - case GL_COLOR: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - case GL_RG: - case GL_RGB: - case GL_BGR: - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - case GL_COLOR_INDEX: - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - case GL_RGB_INTEGER_EXT: - case GL_RGBA_INTEGER_EXT: - case GL_BGR_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { - return GL_FALSE; - } - ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 || - _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_ALPHA_BITS) > 0 || - _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 || - _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 || - _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0); - break; - case GL_DEPTH: - case GL_DEPTH_COMPONENT: - if (!att[BUFFER_DEPTH].Renderbuffer) { - return GL_FALSE; - } - /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ - break; - case GL_STENCIL: - case GL_STENCIL_INDEX: - if (!att[BUFFER_STENCIL].Renderbuffer) { - return GL_FALSE; - } - /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ - break; - case GL_DEPTH_STENCIL_EXT: - if (!att[BUFFER_DEPTH].Renderbuffer || - !att[BUFFER_STENCIL].Renderbuffer) { - return GL_FALSE; - } - /* - ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); - ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); - */ - break; - default: - _mesa_problem(ctx, - "Unexpected format 0x%x in _mesa_source_buffer_exists", - format); - return GL_FALSE; - } - - /* OK */ - return GL_TRUE; -} - - -/** - * As above, but for drawing operations. - * XXX could do some code merging w/ above function. - */ -GLboolean -_mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) -{ - const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; - - /* If we don't know the framebuffer status, update it now */ - if (ctx->DrawBuffer->_Status == 0) { - _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); - } - - if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - return GL_FALSE; - } - - switch (format) { - case GL_COLOR: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_INTENSITY: - case GL_RGB: - case GL_BGR: - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - case GL_COLOR_INDEX: - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - case GL_RGB_INTEGER_EXT: - case GL_RGBA_INTEGER_EXT: - case GL_BGR_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */ - /* Could assert that colorbuffer has RedBits > 0 */ - break; - case GL_DEPTH: - case GL_DEPTH_COMPONENT: - if (!att[BUFFER_DEPTH].Renderbuffer) { - return GL_FALSE; - } - /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ - break; - case GL_STENCIL: - case GL_STENCIL_INDEX: - if (!att[BUFFER_STENCIL].Renderbuffer) { - return GL_FALSE; - } - /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ - break; - case GL_DEPTH_STENCIL_EXT: - if (!att[BUFFER_DEPTH].Renderbuffer || - !att[BUFFER_STENCIL].Renderbuffer) { - return GL_FALSE; - } - /* - ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); - ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); - */ - break; - default: - _mesa_problem(ctx, - "Unexpected format 0x%x in _mesa_dest_buffer_exists", - format); - return GL_FALSE; - } - - /* OK */ - return GL_TRUE; -} - - -/** - * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES query. - */ -GLenum -_mesa_get_color_read_format(struct gl_context *ctx) -{ - switch (ctx->ReadBuffer->_ColorReadBuffer->Format) { - case MESA_FORMAT_ARGB8888: - return GL_BGRA; - case MESA_FORMAT_RGB565: - return GL_BGR; - default: - return GL_RGBA; - } -} - - -/** - * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES query. - */ -GLenum -_mesa_get_color_read_type(struct gl_context *ctx) -{ - switch (ctx->ReadBuffer->_ColorReadBuffer->Format) { - case MESA_FORMAT_ARGB8888: - return GL_UNSIGNED_BYTE; - case MESA_FORMAT_RGB565: - return GL_UNSIGNED_SHORT_5_6_5_REV; - default: - return GL_UNSIGNED_BYTE; - } -} - - -/** - * Print framebuffer info to stderr, for debugging. - */ -void -_mesa_print_framebuffer(const struct gl_framebuffer *fb) -{ - GLuint i; - - fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb); - fprintf(stderr, " Size: %u x %u Status: %s\n", fb->Width, fb->Height, - _mesa_lookup_enum_by_nr(fb->_Status)); - fprintf(stderr, " Attachments:\n"); - - for (i = 0; i < BUFFER_COUNT; i++) { - const struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; - if (att->Type == GL_TEXTURE) { - const struct gl_texture_image *texImage = - _mesa_get_attachment_teximage_const(att); - fprintf(stderr, - " %2d: Texture %u, level %u, face %u, slice %u, complete %d\n", - i, att->Texture->Name, att->TextureLevel, att->CubeMapFace, - att->Zoffset, att->Complete); - fprintf(stderr, " Size: %u x %u x %u Format %s\n", - texImage->Width, texImage->Height, texImage->Depth, - _mesa_get_format_name(texImage->TexFormat)); - } - else if (att->Type == GL_RENDERBUFFER) { - fprintf(stderr, " %2d: Renderbuffer %u, complete %d\n", - i, att->Renderbuffer->Name, att->Complete); - fprintf(stderr, " Size: %u x %u Format %s\n", - att->Renderbuffer->Width, att->Renderbuffer->Height, - _mesa_get_format_name(att->Renderbuffer->Format)); - } - else { - fprintf(stderr, " %2d: none\n", i); - } - } -} +/* + * Mesa 3-D graphics library + * Version: 7.2 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * Functions for allocating/managing framebuffers and renderbuffers. + * Also, routines for reading/writing renderbuffer data as ubytes, + * ushorts, uints, etc. + */ + + +#include "glheader.h" +#include "imports.h" +#include "buffers.h" +#include "context.h" +#include "depthstencil.h" +#include "enums.h" +#include "formats.h" +#include "macros.h" +#include "mtypes.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "texobj.h" + + + +/** + * Compute/set the _DepthMax field for the given framebuffer. + * This value depends on the Z buffer resolution. + */ +static void +compute_depth_max(struct gl_framebuffer *fb) +{ + if (fb->Visual.depthBits == 0) { + /* Special case. Even if we don't have a depth buffer we need + * good values for DepthMax for Z vertex transformation purposes + * and for per-fragment fog computation. + */ + fb->_DepthMax = (1 << 16) - 1; + } + else if (fb->Visual.depthBits < 32) { + fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; + } + else { + /* Special case since shift values greater than or equal to the + * number of bits in the left hand expression's type are undefined. + */ + fb->_DepthMax = 0xffffffff; + } + fb->_DepthMaxF = (GLfloat) fb->_DepthMax; + + /* Minimum resolvable depth value, for polygon offset */ + fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF; +} + +/** + * Create and initialize a gl_framebuffer object. + * This is intended for creating _window_system_ framebuffers, not generic + * framebuffer objects ala GL_EXT_framebuffer_object. + * + * \sa _mesa_new_framebuffer + */ +struct gl_framebuffer * +_mesa_create_framebuffer(const struct gl_config *visual) +{ + struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); + assert(visual); + if (fb) { + _mesa_initialize_window_framebuffer(fb, visual); + } + return fb; +} + + +/** + * Allocate a new gl_framebuffer object. + * This is the default function for ctx->Driver.NewFramebuffer(). + * This is for allocating user-created framebuffers, not window-system + * framebuffers! + * \sa _mesa_create_framebuffer + */ +struct gl_framebuffer * +_mesa_new_framebuffer(struct gl_context *ctx, GLuint name) +{ + struct gl_framebuffer *fb; + (void) ctx; + assert(name != 0); + fb = CALLOC_STRUCT(gl_framebuffer); + if (fb) { + _mesa_initialize_user_framebuffer(fb, name); + } + return fb; +} + + +/** + * Initialize a gl_framebuffer object. Typically used to initialize + * window system-created framebuffers, not user-created framebuffers. + * \sa _mesa_initialize_user_framebuffer + */ +void +_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, + const struct gl_config *visual) +{ + assert(fb); + assert(visual); + + memset(fb, 0, sizeof(struct gl_framebuffer)); + + _glthread_INIT_MUTEX(fb->Mutex); + + fb->RefCount = 1; + + /* save the visual */ + fb->Visual = *visual; + + /* Init read/draw renderbuffer state */ + if (visual->doubleBufferMode) { + fb->_NumColorDrawBuffers = 1; + fb->ColorDrawBuffer[0] = GL_BACK; + fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; + fb->ColorReadBuffer = GL_BACK; + fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; + } + else { + fb->_NumColorDrawBuffers = 1; + fb->ColorDrawBuffer[0] = GL_FRONT; + fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; + fb->ColorReadBuffer = GL_FRONT; + fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; + } + + fb->Delete = _mesa_destroy_framebuffer; + fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + + compute_depth_max(fb); +} + + +/** + * Initialize a user-created gl_framebuffer object. + * \sa _mesa_initialize_window_framebuffer + */ +void +_mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name) +{ + assert(fb); + assert(name); + + memset(fb, 0, sizeof(struct gl_framebuffer)); + + fb->Name = name; + fb->RefCount = 1; + fb->_NumColorDrawBuffers = 1; + fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; + fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0; + fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; + fb->_ColorReadBufferIndex = BUFFER_COLOR0; + fb->Delete = _mesa_destroy_framebuffer; + _glthread_INIT_MUTEX(fb->Mutex); +} + + +/** + * Deallocate buffer and everything attached to it. + * Typically called via the gl_framebuffer->Delete() method. + */ +void +_mesa_destroy_framebuffer(struct gl_framebuffer *fb) +{ + if (fb) { + _mesa_free_framebuffer_data(fb); + free(fb); + } +} + + +/** + * Free all the data hanging off the given gl_framebuffer, but don't free + * the gl_framebuffer object itself. + */ +void +_mesa_free_framebuffer_data(struct gl_framebuffer *fb) +{ + GLuint i; + + assert(fb); + assert(fb->RefCount == 0); + + _glthread_DESTROY_MUTEX(fb->Mutex); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Renderbuffer) { + _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); + } + if (att->Texture) { + _mesa_reference_texobj(&att->Texture, NULL); + } + ASSERT(!att->Renderbuffer); + ASSERT(!att->Texture); + att->Type = GL_NONE; + } + + /* unbind _Depth/_StencilBuffer to decr ref counts */ + _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL); + _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL); +} + + +/** + * Set *ptr to point to fb, with refcounting and locking. + */ +void +_mesa_reference_framebuffer(struct gl_framebuffer **ptr, + struct gl_framebuffer *fb) +{ + assert(ptr); + if (*ptr == fb) { + /* no change */ + return; + } + + if (*ptr) { + /* unreference old renderbuffer */ + GLboolean deleteFlag = GL_FALSE; + struct gl_framebuffer *oldFb = *ptr; + + _glthread_LOCK_MUTEX(oldFb->Mutex); + ASSERT(oldFb->RefCount > 0); + oldFb->RefCount--; + deleteFlag = (oldFb->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldFb->Mutex); + + if (deleteFlag) + oldFb->Delete(oldFb); + + *ptr = NULL; + } + assert(!*ptr); + + if (fb) { + _glthread_LOCK_MUTEX(fb->Mutex); + fb->RefCount++; + _glthread_UNLOCK_MUTEX(fb->Mutex); + *ptr = fb; + } +} + + +/** + * Resize the given framebuffer's renderbuffers to the new width and height. + * This should only be used for window-system framebuffers, not + * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). + * This will typically be called via ctx->Driver.ResizeBuffers() or directly + * from a device driver. + * + * \note it's possible for ctx to be null since a window can be resized + * without a currently bound rendering context. + */ +void +_mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, + GLuint width, GLuint height) +{ + GLuint i; + + /* XXX I think we could check if the size is not changing + * and return early. + */ + + /* For window system framebuffers, Name is zero */ + assert(fb->Name == 0); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { + struct gl_renderbuffer *rb = att->Renderbuffer; + /* only resize if size is changing */ + if (rb->Width != width || rb->Height != height) { + if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + ASSERT(rb->Width == width); + ASSERT(rb->Height == height); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + /* no return */ + } + } + } + } + + if (fb->_DepthBuffer) { + struct gl_renderbuffer *rb = fb->_DepthBuffer; + if (rb->Width != width || rb->Height != height) { + if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + } + } + } + + if (fb->_StencilBuffer) { + struct gl_renderbuffer *rb = fb->_StencilBuffer; + if (rb->Width != width || rb->Height != height) { + if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); + } + } + } + + fb->Width = width; + fb->Height = height; + + if (ctx) { + /* update scissor / window bounds */ + _mesa_update_draw_buffer_bounds(ctx); + /* Signal new buffer state so that swrast will update its clipping + * info (the CLIP_BIT flag). + */ + ctx->NewState |= _NEW_BUFFERS; + } +} + + + +/** + * XXX THIS IS OBSOLETE - drivers should take care of detecting window + * size changes and act accordingly, likely calling _mesa_resize_framebuffer(). + * + * GL_MESA_resize_buffers extension. + * + * When this function is called, we'll ask the window system how large + * the current window is. If it's a new size, we'll call the driver's + * ResizeBuffers function. The driver will then resize its color buffers + * as needed, and maybe call the swrast's routine for reallocating + * swrast-managed depth/stencil/accum/etc buffers. + * \note This function should only be called through the GL API, not + * from device drivers (as was done in the past). + */ +void +_mesa_resizebuffers( struct gl_context *ctx ) +{ + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glResizeBuffersMESA\n"); + + if (!ctx->Driver.GetBufferSize) { + return; + } + + if (ctx->WinSysDrawBuffer) { + GLuint newWidth, newHeight; + struct gl_framebuffer *buffer = ctx->WinSysDrawBuffer; + + assert(buffer->Name == 0); + + /* ask device driver for size of output buffer */ + ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); + + /* see if size of device driver's color buffer (window) has changed */ + if (buffer->Width != newWidth || buffer->Height != newHeight) { + if (ctx->Driver.ResizeBuffers) + ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); + } + } + + if (ctx->WinSysReadBuffer + && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { + GLuint newWidth, newHeight; + struct gl_framebuffer *buffer = ctx->WinSysReadBuffer; + + assert(buffer->Name == 0); + + /* ask device driver for size of read buffer */ + ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); + + /* see if size of device driver's color buffer (window) has changed */ + if (buffer->Width != newWidth || buffer->Height != newHeight) { + if (ctx->Driver.ResizeBuffers) + ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); + } + } + + ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ +} + + +/* + * XXX THIS IS OBSOLETE + */ +void GLAPIENTRY +_mesa_ResizeBuffersMESA( void ) +{ + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Extensions.MESA_resize_buffers) + _mesa_resizebuffers( ctx ); +} + + + +/** + * Examine all the framebuffer's renderbuffers to update the Width/Height + * fields of the framebuffer. If we have renderbuffers with different + * sizes, set the framebuffer's width and height to the min size. + * Note: this is only intended for user-created framebuffers, not + * window-system framebuffes. + */ +static void +update_framebuffer_size(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + GLuint minWidth = ~0, minHeight = ~0; + GLuint i; + + /* user-created framebuffers only */ + assert(fb->Name); + + for (i = 0; i < BUFFER_COUNT; i++) { + struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + const struct gl_renderbuffer *rb = att->Renderbuffer; + if (rb) { + minWidth = MIN2(minWidth, rb->Width); + minHeight = MIN2(minHeight, rb->Height); + } + } + + if (minWidth != ~0) { + fb->Width = minWidth; + fb->Height = minHeight; + } + else { + fb->Width = 0; + fb->Height = 0; + } +} + + +/** + * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. + * These values are computed from the buffer's width and height and + * the scissor box, if it's enabled. + * \param ctx the GL context. + */ +void +_mesa_update_draw_buffer_bounds(struct gl_context *ctx) +{ + struct gl_framebuffer *buffer = ctx->DrawBuffer; + + if (!buffer) + return; + + if (buffer->Name) { + /* user-created framebuffer size depends on the renderbuffers */ + update_framebuffer_size(ctx, buffer); + } + + buffer->_Xmin = 0; + buffer->_Ymin = 0; + buffer->_Xmax = buffer->Width; + buffer->_Ymax = buffer->Height; + + if (ctx->Scissor.Enabled) { + if (ctx->Scissor.X > buffer->_Xmin) { + buffer->_Xmin = ctx->Scissor.X; + } + if (ctx->Scissor.Y > buffer->_Ymin) { + buffer->_Ymin = ctx->Scissor.Y; + } + if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) { + buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width; + } + if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) { + buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height; + } + /* finally, check for empty region */ + if (buffer->_Xmin > buffer->_Xmax) { + buffer->_Xmin = buffer->_Xmax; + } + if (buffer->_Ymin > buffer->_Ymax) { + buffer->_Ymin = buffer->_Ymax; + } + } + + ASSERT(buffer->_Xmin <= buffer->_Xmax); + ASSERT(buffer->_Ymin <= buffer->_Ymax); +} + + +/** + * The glGet queries of the framebuffer red/green/blue size, stencil size, + * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can + * change depending on the renderbuffer bindings. This function updates + * the given framebuffer's Visual from the current renderbuffer bindings. + * + * This may apply to user-created framebuffers or window system framebuffers. + * + * Also note: ctx->DrawBuffer->Visual.depthBits might not equal + * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. + * The former one is used to convert floating point depth values into + * integer Z values. + */ +void +_mesa_update_framebuffer_visual(struct gl_context *ctx, + struct gl_framebuffer *fb) +{ + GLuint i; + + memset(&fb->Visual, 0, sizeof(fb->Visual)); + fb->Visual.rgbMode = GL_TRUE; /* assume this */ + +#if 0 /* this _might_ be needed */ + if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + /* leave visual fields zero'd */ + return; + } +#endif + + /* find first RGB renderbuffer */ + for (i = 0; i < BUFFER_COUNT; i++) { + if (fb->Attachment[i].Renderbuffer) { + const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; + const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); + const gl_format fmt = rb->Format; + + if (_mesa_is_legal_color_format(ctx, baseFormat)) { + fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS); + fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); + fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); + fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); + fb->Visual.rgbBits = fb->Visual.redBits + + fb->Visual.greenBits + fb->Visual.blueBits; + fb->Visual.samples = rb->NumSamples; + if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) + fb->Visual.sRGBCapable = ctx->Const.sRGBCapable; + break; + } + } + } + + fb->Visual.floatMode = GL_FALSE; + for (i = 0; i < BUFFER_COUNT; i++) { + if (fb->Attachment[i].Renderbuffer) { + const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; + const gl_format fmt = rb->Format; + + if (_mesa_get_format_datatype(fmt) == GL_FLOAT) { + fb->Visual.floatMode = GL_TRUE; + break; + } + } + } + + if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { + const struct gl_renderbuffer *rb = + fb->Attachment[BUFFER_DEPTH].Renderbuffer; + const gl_format fmt = rb->Format; + fb->Visual.haveDepthBuffer = GL_TRUE; + fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS); + } + + if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { + const struct gl_renderbuffer *rb = + fb->Attachment[BUFFER_STENCIL].Renderbuffer; + const gl_format fmt = rb->Format; + fb->Visual.haveStencilBuffer = GL_TRUE; + fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS); + } + + if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { + const struct gl_renderbuffer *rb = + fb->Attachment[BUFFER_ACCUM].Renderbuffer; + const gl_format fmt = rb->Format; + fb->Visual.haveAccumBuffer = GL_TRUE; + fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS); + fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); + fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); + fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); + } + + compute_depth_max(fb); +} + + +/** + * Update the framebuffer's _DepthBuffer field using the renderbuffer + * found at the given attachment index. + * + * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, + * create and install a depth wrapper/adaptor. + * + * \param fb the framebuffer whose _DepthBuffer field to update + * \param attIndex indicates the renderbuffer to possibly wrap + */ +void +_mesa_update_depth_buffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLuint attIndex) +{ + struct gl_renderbuffer *depthRb; + + /* only one possiblity for now */ + ASSERT(attIndex == BUFFER_DEPTH); + + depthRb = fb->Attachment[attIndex].Renderbuffer; + + if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) { + /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ + if (!fb->_DepthBuffer + || fb->_DepthBuffer->Wrapped != depthRb + || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) { + /* need to update wrapper */ + struct gl_renderbuffer *wrapper + = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); + _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); + ASSERT(fb->_DepthBuffer->Wrapped == depthRb); + } + } + else { + /* depthRb may be null */ + _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb); + } +} + + +/** + * Update the framebuffer's _StencilBuffer field using the renderbuffer + * found at the given attachment index. + * + * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer, + * create and install a stencil wrapper/adaptor. + * + * \param fb the framebuffer whose _StencilBuffer field to update + * \param attIndex indicates the renderbuffer to possibly wrap + */ +void +_mesa_update_stencil_buffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + GLuint attIndex) +{ + struct gl_renderbuffer *stencilRb; + + ASSERT(attIndex == BUFFER_DEPTH || + attIndex == BUFFER_STENCIL); + + stencilRb = fb->Attachment[attIndex].Renderbuffer; + + if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) { + /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ + if (!fb->_StencilBuffer + || fb->_StencilBuffer->Wrapped != stencilRb + || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) { + /* need to update wrapper */ + struct gl_renderbuffer *wrapper + = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); + _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); + ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); + } + } + else { + /* stencilRb may be null */ + _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); + } +} + + +/* + * Example DrawBuffers scenarios: + * + * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to + * "gl_FragColor" or program writes to the "result.color" register: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front, Back + * + * + * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to + * gl_FragData[i] or program writes to result.color[i] registers: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front + * color[1] Aux0 + * color[3] Aux1 + * + * + * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to + * gl_FragColor, or fixed function: + * + * fragment color output renderbuffer + * --------------------- --------------- + * color[0] Front, Aux0, Aux1 + * + * + * In either case, the list of renderbuffers is stored in the + * framebuffer->_ColorDrawBuffers[] array and + * framebuffer->_NumColorDrawBuffers indicates the number of buffers. + * The renderer (like swrast) has to look at the current fragment shader + * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine + * how to map color outputs to renderbuffers. + * + * Note that these two calls are equivalent (for fixed function fragment + * shading anyway): + * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) + * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); + */ + + + + +/** + * Update the (derived) list of color drawing renderbuffer pointers. + * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers + * writing colors. + */ +static void +update_color_draw_buffers(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + GLuint output; + + /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */ + fb->_ColorDrawBuffers[0] = NULL; + + for (output = 0; output < fb->_NumColorDrawBuffers; output++) { + GLint buf = fb->_ColorDrawBufferIndexes[output]; + if (buf >= 0) { + fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer; + } + else { + fb->_ColorDrawBuffers[output] = NULL; + } + } +} + + +/** + * Update the (derived) color read renderbuffer pointer. + * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. + */ +static void +update_color_read_buffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + (void) ctx; + if (fb->_ColorReadBufferIndex == -1 || + fb->DeletePending || + fb->Width == 0 || + fb->Height == 0) { + fb->_ColorReadBuffer = NULL; /* legal! */ + } + else { + ASSERT(fb->_ColorReadBufferIndex >= 0); + ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); + fb->_ColorReadBuffer + = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; + } +} + + +/** + * Update a gl_framebuffer's derived state. + * + * Specifically, update these framebuffer fields: + * _ColorDrawBuffers + * _NumColorDrawBuffers + * _ColorReadBuffer + * _DepthBuffer + * _StencilBuffer + * + * If the framebuffer is user-created, make sure it's complete. + * + * The following functions (at least) can effect framebuffer state: + * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, + * glRenderbufferStorageEXT. + */ +static void +update_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) +{ + if (fb->Name == 0) { + /* This is a window-system framebuffer */ + /* Need to update the FB's GL_DRAW_BUFFER state to match the + * context state (GL_READ_BUFFER too). + */ + if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { + _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, + ctx->Color.DrawBuffer, NULL); + } + } + else { + /* This is a user-created framebuffer. + * Completeness only matters for user-created framebuffers. + */ + if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) { + _mesa_test_framebuffer_completeness(ctx, fb); + } + } + + /* Strictly speaking, we don't need to update the draw-state + * if this FB is bound as ctx->ReadBuffer (and conversely, the + * read-state if this FB is bound as ctx->DrawBuffer), but no + * harm. + */ + update_color_draw_buffers(ctx, fb); + update_color_read_buffer(ctx, fb); + _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); + _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); + + compute_depth_max(fb); +} + + +/** + * Update state related to the current draw/read framebuffers. + */ +void +_mesa_update_framebuffer(struct gl_context *ctx) +{ + struct gl_framebuffer *drawFb; + struct gl_framebuffer *readFb; + + assert(ctx); + drawFb = ctx->DrawBuffer; + readFb = ctx->ReadBuffer; + + update_framebuffer(ctx, drawFb); + if (readFb != drawFb) + update_framebuffer(ctx, readFb); +} + + +/** + * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, + * glCopyTex[Sub]Image, etc) exists. + * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, + * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. + * \return GL_TRUE if buffer exists, GL_FALSE otherwise + */ +GLboolean +_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) +{ + const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment; + + /* If we don't know the framebuffer status, update it now */ + if (ctx->ReadBuffer->_Status == 0) { + _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); + } + + if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + return GL_FALSE; + } + + switch (format) { + case GL_COLOR: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_RG: + case GL_RGB: + case GL_BGR: + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + case GL_COLOR_INDEX: + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { + return GL_FALSE; + } + ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 || + _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_ALPHA_BITS) > 0 || + _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 || + _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 || + _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0); + break; + case GL_DEPTH: + case GL_DEPTH_COMPONENT: + if (!att[BUFFER_DEPTH].Renderbuffer) { + return GL_FALSE; + } + /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ + break; + case GL_STENCIL: + case GL_STENCIL_INDEX: + if (!att[BUFFER_STENCIL].Renderbuffer) { + return GL_FALSE; + } + /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ + break; + case GL_DEPTH_STENCIL_EXT: + if (!att[BUFFER_DEPTH].Renderbuffer || + !att[BUFFER_STENCIL].Renderbuffer) { + return GL_FALSE; + } + /* + ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); + ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); + */ + break; + default: + _mesa_problem(ctx, + "Unexpected format 0x%x in _mesa_source_buffer_exists", + format); + return GL_FALSE; + } + + /* OK */ + return GL_TRUE; +} + + +/** + * As above, but for drawing operations. + * XXX could do some code merging w/ above function. + */ +GLboolean +_mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) +{ + const struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment; + + /* If we don't know the framebuffer status, update it now */ + if (ctx->DrawBuffer->_Status == 0) { + _mesa_test_framebuffer_completeness(ctx, ctx->DrawBuffer); + } + + if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + return GL_FALSE; + } + + switch (format) { + case GL_COLOR: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_RGB: + case GL_BGR: + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + case GL_COLOR_INDEX: + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + /* Nothing special since GL_DRAW_BUFFER could be GL_NONE. */ + /* Could assert that colorbuffer has RedBits > 0 */ + break; + case GL_DEPTH: + case GL_DEPTH_COMPONENT: + if (!att[BUFFER_DEPTH].Renderbuffer) { + return GL_FALSE; + } + /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/ + break; + case GL_STENCIL: + case GL_STENCIL_INDEX: + if (!att[BUFFER_STENCIL].Renderbuffer) { + return GL_FALSE; + } + /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/ + break; + case GL_DEPTH_STENCIL_EXT: + if (!att[BUFFER_DEPTH].Renderbuffer || + !att[BUFFER_STENCIL].Renderbuffer) { + return GL_FALSE; + } + /* + ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); + ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); + */ + break; + default: + _mesa_problem(ctx, + "Unexpected format 0x%x in _mesa_dest_buffer_exists", + format); + return GL_FALSE; + } + + /* OK */ + return GL_TRUE; +} + + +/** + * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES query. + */ +GLenum +_mesa_get_color_read_format(struct gl_context *ctx) +{ + switch (ctx->ReadBuffer->_ColorReadBuffer->Format) { + case MESA_FORMAT_ARGB8888: + return GL_BGRA; + case MESA_FORMAT_RGB565: + return GL_BGR; + default: + return GL_RGBA; + } +} + + +/** + * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES query. + */ +GLenum +_mesa_get_color_read_type(struct gl_context *ctx) +{ + switch (ctx->ReadBuffer->_ColorReadBuffer->Format) { + case MESA_FORMAT_ARGB8888: + return GL_UNSIGNED_BYTE; + case MESA_FORMAT_RGB565: + return GL_UNSIGNED_SHORT_5_6_5_REV; + default: + return GL_UNSIGNED_BYTE; + } +} + + +/** + * Print framebuffer info to stderr, for debugging. + */ +void +_mesa_print_framebuffer(const struct gl_framebuffer *fb) +{ + GLuint i; + + fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb); + fprintf(stderr, " Size: %u x %u Status: %s\n", fb->Width, fb->Height, + _mesa_lookup_enum_by_nr(fb->_Status)); + fprintf(stderr, " Attachments:\n"); + + for (i = 0; i < BUFFER_COUNT; i++) { + const struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; + if (att->Type == GL_TEXTURE) { + const struct gl_texture_image *texImage = + _mesa_get_attachment_teximage_const(att); + fprintf(stderr, + " %2d: Texture %u, level %u, face %u, slice %u, complete %d\n", + i, att->Texture->Name, att->TextureLevel, att->CubeMapFace, + att->Zoffset, att->Complete); + fprintf(stderr, " Size: %u x %u x %u Format %s\n", + texImage->Width, texImage->Height, texImage->Depth, + _mesa_get_format_name(texImage->TexFormat)); + } + else if (att->Type == GL_RENDERBUFFER) { + fprintf(stderr, " %2d: Renderbuffer %u, complete %d\n", + i, att->Renderbuffer->Name, att->Complete); + fprintf(stderr, " Size: %u x %u Format %s\n", + att->Renderbuffer->Width, att->Renderbuffer->Height, + _mesa_get_format_name(att->Renderbuffer->Format)); + } + else { + fprintf(stderr, " %2d: none\n", i); + } + } +} diff --git a/mesalib/src/mesa/main/texfetch.c b/mesalib/src/mesa/main/texfetch.c index caabc19bb..d091789ff 100644 --- a/mesalib/src/mesa/main/texfetch.c +++ b/mesalib/src/mesa/main/texfetch.c @@ -631,6 +631,34 @@ texfetch_funcs[MESA_FORMAT_COUNT] = fetch_texel_3d_f_intensity_f16, store_texel_intensity_f16 }, + { + MESA_FORMAT_R_FLOAT32, + fetch_texel_1d_f_r_f32, + fetch_texel_2d_f_r_f32, + fetch_texel_3d_f_r_f32, + store_texel_r_f32 + }, + { + MESA_FORMAT_R_FLOAT16, + fetch_texel_1d_f_r_f16, + fetch_texel_2d_f_r_f16, + fetch_texel_3d_f_r_f16, + store_texel_r_f16 + }, + { + MESA_FORMAT_RG_FLOAT32, + fetch_texel_1d_f_rg_f32, + fetch_texel_2d_f_rg_f32, + fetch_texel_3d_f_rg_f32, + store_texel_rg_f32 + }, + { + MESA_FORMAT_RG_FLOAT16, + fetch_texel_1d_f_rg_f16, + fetch_texel_2d_f_rg_f16, + fetch_texel_3d_f_rg_f16, + store_texel_rg_f16 + }, /* non-normalized, signed int */ { diff --git a/mesalib/src/mesa/main/texfetch_tmp.h b/mesalib/src/mesa/main/texfetch_tmp.h index f1f6a01a4..0b9d5da07 100644 --- a/mesalib/src/mesa/main/texfetch_tmp.h +++ b/mesalib/src/mesa/main/texfetch_tmp.h @@ -438,6 +438,110 @@ static void store_texel_intensity_f16(struct gl_texture_image *texImage, #endif +/* MESA_FORMAT_R_FLOAT32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = src[0]; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_R_FLOAT16 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_RG_FLOAT32 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; +} +#endif + + +/* MESA_FORMAT_RG_FLOAT16 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[GCOMP]); +} +#endif /* diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index da907455b..97b905fd3 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -628,6 +628,22 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.ARB_texture_rg && ctx->Extensions.ARB_texture_float) { + switch (internalFormat) { + case GL_R16F: + return MESA_FORMAT_R_FLOAT16; + case GL_R32F: + return MESA_FORMAT_R_FLOAT32; + case GL_RG16F: + return MESA_FORMAT_RG_FLOAT16; + case GL_RG32F: + return MESA_FORMAT_RG_FLOAT32; + + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.EXT_texture_format_BGRA8888) { switch (internalFormat) { case GL_BGRA: diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 87cb327d2..9a690529a 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -3535,13 +3535,17 @@ _mesa_texstore_rgba_float32(TEXSTORE_PARAMS) dstFormat == MESA_FORMAT_ALPHA_FLOAT32 || dstFormat == MESA_FORMAT_LUMINANCE_FLOAT32 || dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32 || - dstFormat == MESA_FORMAT_INTENSITY_FLOAT32); + dstFormat == MESA_FORMAT_INTENSITY_FLOAT32 || + dstFormat == MESA_FORMAT_R_FLOAT32 || + dstFormat == MESA_FORMAT_RG_FLOAT32); ASSERT(baseInternalFormat == GL_RGBA || baseInternalFormat == GL_RGB || baseInternalFormat == GL_ALPHA || baseInternalFormat == GL_LUMINANCE || baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); + baseInternalFormat == GL_INTENSITY || + baseInternalFormat == GL_RED || + baseInternalFormat == GL_RG); ASSERT(texelBytes == components * sizeof(GLfloat)); if (!ctx->_ImageTransferState && @@ -3605,13 +3609,17 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS) dstFormat == MESA_FORMAT_ALPHA_FLOAT16 || dstFormat == MESA_FORMAT_LUMINANCE_FLOAT16 || dstFormat == MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16 || - dstFormat == MESA_FORMAT_INTENSITY_FLOAT16); + dstFormat == MESA_FORMAT_INTENSITY_FLOAT16 || + dstFormat == MESA_FORMAT_R_FLOAT16 || + dstFormat == MESA_FORMAT_RG_FLOAT16); ASSERT(baseInternalFormat == GL_RGBA || baseInternalFormat == GL_RGB || baseInternalFormat == GL_ALPHA || baseInternalFormat == GL_LUMINANCE || baseInternalFormat == GL_LUMINANCE_ALPHA || - baseInternalFormat == GL_INTENSITY); + baseInternalFormat == GL_INTENSITY || + baseInternalFormat == GL_RED || + baseInternalFormat == GL_RG); ASSERT(texelBytes == components * sizeof(GLhalfARB)); if (!ctx->_ImageTransferState && @@ -4252,6 +4260,10 @@ texstore_funcs[MESA_FORMAT_COUNT] = { MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, _mesa_texstore_rgba_float16 }, { MESA_FORMAT_INTENSITY_FLOAT32, _mesa_texstore_rgba_float32 }, { MESA_FORMAT_INTENSITY_FLOAT16, _mesa_texstore_rgba_float16 }, + { MESA_FORMAT_R_FLOAT32, _mesa_texstore_rgba_float32 }, + { MESA_FORMAT_R_FLOAT16, _mesa_texstore_rgba_float16 }, + { MESA_FORMAT_RG_FLOAT32, _mesa_texstore_rgba_float32 }, + { MESA_FORMAT_RG_FLOAT16, _mesa_texstore_rgba_float16 }, { MESA_FORMAT_RGBA_INT8, _mesa_texstore_rgba_int8 }, { MESA_FORMAT_RGBA_INT16, _mesa_texstore_rgba_int16 }, diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 03f58bf0f..fdb7770e4 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -201,7 +201,8 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, enum combination { A8R8G8B8_UNORM_TO_RGBA_UBYTE, A8R8G8B8_UNORM_TO_RGB_UBYTE, - A8R8G8B8_UNORM_TO_BGRA_UINT + A8R8G8B8_UNORM_TO_BGRA_UINT, + A8R8G8B8_UNORM_TO_RGBA_UINT } combo; if (ctx->_ImageTransferState) @@ -219,6 +220,10 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) { combo = A8R8G8B8_UNORM_TO_BGRA_UINT; } + else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM && + format == GL_RGBA && type == GL_UNSIGNED_INT_8_8_8_8) { + combo = A8R8G8B8_UNORM_TO_RGBA_UINT; + } else { return GL_FALSE; } @@ -305,6 +310,20 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, y += dy; } break; + case A8R8G8B8_UNORM_TO_RGBA_UINT: + for (row = 0; row < height; row++) { + const GLubyte *src = map + y * trans->stride; + for (col = 0; col < width; col++) { + GLuint pixel = ((GLuint *) src)[col]; + dst[col*4+0] = (pixel >> 24) & 0xff; + dst[col*4+1] = (pixel >> 0) & 0xff; + dst[col*4+2] = (pixel >> 8) & 0xff; + dst[col*4+3] = (pixel >> 16) & 0xff; + } + dst += dstStride; + y += dy; + } + break; default: ; /* nothing */ } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 914c06b70..43c24ae95 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -600,7 +600,12 @@ st_TexImage(struct gl_context * ctx, * memory or malloc space for it. */ if (stImage->pt) { - /* Store the image in the gallium texture memory buffer */ + if (!pixels) { + /* We've allocated texture resource, but have no pixel data - all done. */ + goto done; + } + + /* Store the image in the gallium transfer object */ if (format == GL_DEPTH_COMPONENT && util_format_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 9bc9d7a10..bdc08949d 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -382,6 +382,18 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE; } + /* float support - assume nothing exclusively supports 64-bit floats */ + if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_RENDER_TARGET) && + screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_RENDER_TARGET)) { + ctx->Extensions.ARB_texture_float = GL_TRUE; + } + /* sRGB support */ if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB, PIPE_TEXTURE_2D, 0, diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 957a06c08..8e50dbda6 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -214,6 +214,39 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) case MESA_FORMAT_SARGB8: return PIPE_FORMAT_B8G8R8A8_SRGB; #endif + case MESA_FORMAT_RGBA_FLOAT32: + return PIPE_FORMAT_R32G32B32A32_FLOAT; + case MESA_FORMAT_RGBA_FLOAT16: + return PIPE_FORMAT_R16G16B16A16_FLOAT; + case MESA_FORMAT_RGB_FLOAT32: + return PIPE_FORMAT_R32G32B32_FLOAT; + case MESA_FORMAT_RGB_FLOAT16: + return PIPE_FORMAT_R16G16B16_FLOAT; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: + return PIPE_FORMAT_L32A32_FLOAT; + case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: + return PIPE_FORMAT_L16A16_FLOAT; + case MESA_FORMAT_LUMINANCE_FLOAT32: + return PIPE_FORMAT_L32_FLOAT; + case MESA_FORMAT_LUMINANCE_FLOAT16: + return PIPE_FORMAT_L16_FLOAT; + case MESA_FORMAT_ALPHA_FLOAT32: + return PIPE_FORMAT_A32_FLOAT; + case MESA_FORMAT_ALPHA_FLOAT16: + return PIPE_FORMAT_A16_FLOAT; + case MESA_FORMAT_INTENSITY_FLOAT32: + return PIPE_FORMAT_I32_FLOAT; + case MESA_FORMAT_INTENSITY_FLOAT16: + return PIPE_FORMAT_I16_FLOAT; + case MESA_FORMAT_R_FLOAT32: + return PIPE_FORMAT_R32_FLOAT; + case MESA_FORMAT_R_FLOAT16: + return PIPE_FORMAT_R16_FLOAT; + case MESA_FORMAT_RG_FLOAT32: + return PIPE_FORMAT_R32G32_FLOAT; + case MESA_FORMAT_RG_FLOAT16: + return PIPE_FORMAT_R16G16_FLOAT; + case MESA_FORMAT_R8: return PIPE_FORMAT_R8_UNORM; case MESA_FORMAT_R16: @@ -403,6 +436,38 @@ st_pipe_format_to_mesa_format(enum pipe_format format) case PIPE_FORMAT_B8G8R8A8_SRGB: return MESA_FORMAT_SARGB8; #endif + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return MESA_FORMAT_RGBA_FLOAT32; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + return MESA_FORMAT_RGBA_FLOAT16; + case PIPE_FORMAT_R32G32B32_FLOAT: + return MESA_FORMAT_RGB_FLOAT32; + case PIPE_FORMAT_R16G16B16_FLOAT: + return MESA_FORMAT_RGB_FLOAT16; + case PIPE_FORMAT_L32A32_FLOAT: + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; + case PIPE_FORMAT_L16A16_FLOAT: + return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; + case PIPE_FORMAT_L32_FLOAT: + return MESA_FORMAT_LUMINANCE_FLOAT32; + case PIPE_FORMAT_L16_FLOAT: + return MESA_FORMAT_LUMINANCE_FLOAT16; + case PIPE_FORMAT_A32_FLOAT: + return MESA_FORMAT_ALPHA_FLOAT32; + case PIPE_FORMAT_A16_FLOAT: + return MESA_FORMAT_ALPHA_FLOAT16; + case PIPE_FORMAT_I32_FLOAT: + return MESA_FORMAT_INTENSITY_FLOAT32; + case PIPE_FORMAT_I16_FLOAT: + return MESA_FORMAT_INTENSITY_FLOAT16; + case PIPE_FORMAT_R32_FLOAT: + return MESA_FORMAT_R_FLOAT32; + case PIPE_FORMAT_R16_FLOAT: + return MESA_FORMAT_R_FLOAT16; + case PIPE_FORMAT_R32G32_FLOAT: + return MESA_FORMAT_RG_FLOAT32; + case PIPE_FORMAT_R16G16_FLOAT: + return MESA_FORMAT_RG_FLOAT16; case PIPE_FORMAT_R8_UNORM: return MESA_FORMAT_R8; @@ -887,6 +952,178 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return PIPE_FORMAT_L8_SRGB; return default_srgba_format( screen, target, sample_count, bindings); + /* prefer formats in order of data size, choosing 16-bit ones if equal sized */ + case GL_RGBA16F_ARB: + case GL_RGB16F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_LUMINANCE_ALPHA16F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_ALPHA16F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_A16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_A32_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_INTENSITY16F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_I16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_I32_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_LUMINANCE16F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_L16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_L32_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_R16F: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R16_FLOAT, + PIPE_FORMAT_R16G16_FLOAT, + PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_RG16F: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R16G16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT, + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + + /* try a 32-bit format if available, otherwise fallback to a 16-bit one */ + case GL_RGBA32F_ARB: + case GL_RGB32F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_LUMINANCE_ALPHA32F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_ALPHA32F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_A32_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_A16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_INTENSITY32F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_I32_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_I16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_LUMINANCE32F_ARB: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_L32_FLOAT, + PIPE_FORMAT_L32A32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_L16_FLOAT, + PIPE_FORMAT_L16A16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_R32F: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_R16_FLOAT, + PIPE_FORMAT_R16G16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_RG32F: + { + static const enum pipe_format formats[] = { + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_R16G16_FLOAT, + PIPE_FORMAT_R16G16B16A16_FLOAT + }; + return find_supported_format(screen, formats, Elements(formats), + target, sample_count, bindings); + } + case GL_RED: case GL_R8: if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, target, diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index 10be59953..5c42a51df 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -358,7 +358,7 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, static void update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, - DRI2BufferPtr *buffers, int *out_count, int *width, int *height) + DRI2BufferPtr *buffers, int out_count, int *width, int *height) { DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); int i; @@ -374,7 +374,7 @@ update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, } pPriv->buffers = buffers; - pPriv->bufferCount = *out_count; + pPriv->bufferCount = out_count; pPriv->width = pDraw->width; pPriv->height = pDraw->height; *width = pPriv->width; @@ -409,6 +409,8 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, && (pPriv->serialNumber == DRI2DrawableSerial(pDraw)); buffers = calloc((count + 1), sizeof(buffers[0])); + if (!buffers) + goto err_out; for (i = 0; i < count; i++) { const unsigned attachment = *(attachments++); @@ -475,7 +477,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, *out_count = i; - update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); + update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height); /* If the client is getting a fake front-buffer, pre-fill it with the * contents of the real front-buffer. This ensures correct operation of @@ -501,15 +503,17 @@ err_out: *out_count = 0; - for (i = 0; i < count; i++) { + if (buffers) { + for (i = 0; i < count; i++) { if (buffers[i] != NULL) - (*ds->DestroyBuffer)(pDraw, buffers[i]); - } + (*ds->DestroyBuffer)(pDraw, buffers[i]); + } - free(buffers); - buffers = NULL; + free(buffers); + buffers = NULL; + } - update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); + update_dri2_drawable_buffers(pPriv, pDraw, buffers, *out_count, width, height); return buffers; } diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in index 60eafdd9d..19f8fade7 100644 --- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in @@ -12,6 +12,30 @@ + + + ca + <_shortDescription>fr + <_description>French (Canada) + fr + + + + + kut + <_shortDescription>kut + <_description>Kutenai + + + + + shs + <_shortDescription>shs + <_description>Secwepemctsin + + + + ir diff --git a/xorg-server/xkeyboard-config/rules/base.xml.in b/xorg-server/xkeyboard-config/rules/base.xml.in index 3f26331cb..5979d36ac 100644 --- a/xorg-server/xkeyboard-config/rules/base.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.xml.in @@ -2177,20 +2177,6 @@ - - - shs - <_shortDescription>shs - <_description>Secwepemctsin - - - - - kut - <_shortDescription>kut - <_description>Kutenai - - eng diff --git a/xorg-server/xkeyboard-config/symbols/ca b/xorg-server/xkeyboard-config/symbols/ca index cfb7b25e5..ab9cef19d 100644 --- a/xorg-server/xkeyboard-config/symbols/ca +++ b/xorg-server/xkeyboard-config/symbols/ca @@ -451,31 +451,6 @@ xkb_symbols "multix" { include "level5(rctrl_switch)" }; -// Secwepemctsin keyboard for X11 -// written by Neskie Manuel - -partial alphanumeric_keys -xkb_symbols "shs" { - - include "us" - - name[Group1]= "Secwepemctsin"; - - //Using Dead key to get COMBINING COMMA ABOVE for ejectives on - //q, l, t, s, m, g, k, p, w, y, r - //XCompose key is used for the other accute and grave. - - key { [ comma, less, U0313 ] }; - key { [ a, A, aacute, Aacute ] }; - key { [ e, E, eacute, Eacute ] }; - key { [ u, U, uacute, Uacute ] }; - key { [ i, I, iacute, Iacute ] }; - key { [ o, O, oacute, Oacute ] }; - - include "level3(ralt_switch)" - include "compose(rctrl)" -}; - // OLPC Section xkb_symbols "olpc" { @@ -491,6 +466,14 @@ xkb_symbols "olpc" { key { [ guillemotleft, guillemotright, degree, VoidSymbol ] }; }; +partial alphanumeric_keys +xkb_symbols "eng" { + name[Group1] = "English (Canada)"; + include "us(basic)" +}; + +// EXTRAS: + partial alphanumeric_keys xkb_symbols "kut" { @@ -520,8 +503,28 @@ xkb_symbols "kut" { key { [ semicolon, colon,U02BE,U02BE ] }; }; -partial alphanumeric_keys -xkb_symbols "eng" { - name[Group1] = "English (Canada)"; - include "us(basic)" +// Secwepemctsin keyboard for X11 +// written by Neskie Manuel + +partial alphanumeric_keys +xkb_symbols "shs" { + + include "us" + + name[Group1]= "Secwepemctsin"; + + //Using Dead key to get COMBINING COMMA ABOVE for ejectives on + //q, l, t, s, m, g, k, p, w, y, r + //XCompose key is used for the other accute and grave. + + key { [ comma, less, U0313 ] }; + key { [ a, A, aacute, Aacute ] }; + key { [ e, E, eacute, Eacute ] }; + key { [ u, U, uacute, Uacute ] }; + key { [ i, I, iacute, Iacute ] }; + key { [ o, O, oacute, Oacute ] }; + + include "level3(ralt_switch)" + include "compose(rctrl)" }; + diff --git a/xorg-server/xkeyboard-config/symbols/lv b/xorg-server/xkeyboard-config/symbols/lv index 1e7fc1fcc..97e4220fc 100644 --- a/xorg-server/xkeyboard-config/symbols/lv +++ b/xorg-server/xkeyboard-config/symbols/lv @@ -42,7 +42,7 @@ //============================================================================ // Latvian QWERTY layout -// http://en.wikipedia.org/wiki/QWERTY +// http://en.wikipedia.org/wiki/QWERTY // partial default alphanumeric_keys modifier_keys xkb_symbols "basic" { @@ -262,7 +262,7 @@ xkb_symbols "modern" { name[Group1]= "Latvian (modern)"; - key {[ grave, asciitilde, acute, asciitilde ]}; + key {[ grave, asciitilde, acute, copyright ]}; key {[ 1, exclam, onesuperior, exclamdown ]}; key {[ 2, at, twosuperior, oneeighth ]}; key {[ 3, numbersign, threesuperior, sterling ]}; @@ -273,8 +273,8 @@ xkb_symbols "modern" { key {[ 8, asterisk, bracketleft, trademark ]}; key {[ 9, parenleft, bracketright, plusminus ]}; key {[ 0, parenright, braceright, degree ]}; - key {[ minus, underscore, backslash, endash ]}; - key {[ equal, plus, bar, emdash ]}; + key {[ minus, underscore, backslash, questiondown ]}; + key {[ equal, plus, endash, emdash ]}; key {[ emacron, Emacron, emacron, Emacron ]}; key {[ o, O, omacron, Omacron ]}; @@ -285,8 +285,8 @@ xkb_symbols "modern" { key {[ d, D, d, D ]}; key {[ imacron, Imacron, imacron, Imacron ]}; key {[ l, L, lcedilla, Lcedilla ]}; - key {[ g, G, gcedilla, Gcedilla ]}; - key {[ bracketleft, braceleft, guillemotleft, leftdoublequotemark ]}; + key {[ g, G, gcedilla, Gcedilla ]}; + Key {[ bracketleft, braceleft, guillemotleft, leftdoublequotemark ]}; key {[ bracketright, braceright, guillemotright, rightdoublequotemark ]}; key {[ e, E, e, E ]}; @@ -299,8 +299,8 @@ xkb_symbols "modern" { key {[ i, I, i, I ]}; key {[ t, T, t, T ]}; key {[ r, R, rcedilla, Rcedilla ]}; - key {[ m, M, m, M ]}; - key {[ slash, question, backslash, bar ]}; + key {[ m, M, bar, M ]}; + key {[ slash, question, backslash, U263A ]}; key {[ q, Q, q, Q ]}; key {[ x, X, q, Q ]}; @@ -310,7 +310,7 @@ xkb_symbols "modern" { key {[ w, W, w, W ]}; key {[ f, F, f, F ]}; key {[ y, Y, y, Y ]}; - key {[ h, H, h, H ]}; + key {[ h, H, h, H ]}; key {[ comma, semicolon, less, multiply ]}; key {[ period, colon, greater, division ]}; key {[ space, space, apostrophe ]}; -- cgit v1.2.3