mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 19:08:03 +03:00
init
This commit is contained in:
12511 files changed
+6156641
No files matched your search
@@ -0,0 +1,71 @@
|
||||
AppleSGLX Release Notes
|
||||
|
||||
o OpenGL Support
|
||||
|
||||
AppleSGLX supports the same version of OpenGL as Leopard (OpenGL 2.1).
|
||||
Many extensions from the OpenGL framework are now builtin.
|
||||
|
||||
This adds support for GLSL, and a variety of other features.
|
||||
|
||||
o Thread Support
|
||||
|
||||
Thread support has been improved since the libGL in XQuartz 2.3.2.1.
|
||||
|
||||
o GLX 1.4 Support
|
||||
|
||||
The GLX 1.3 and 1.4 functions should all work with a few exceptions
|
||||
as outlined in this document.
|
||||
|
||||
o glXMakeContextCurrent (a GLX 1.3 feature)
|
||||
|
||||
glXMakeContextCurrent should work with the readable drawable. The
|
||||
OpenGL functions: glReadPixels, glCopyPixels, and glCopyColorTable,
|
||||
should use the readable drawable if it's different than the rendering
|
||||
drawable.
|
||||
|
||||
o glXGetProcAddress (a GLX 1.4 feature and ARB extension)
|
||||
|
||||
glXGetProcAddress should work and allow getting the address of any
|
||||
extension functions you may need from the X11 libGL, or OpenGL framework
|
||||
libGL. Previous versions of the X11 libGL didn't allow getting the newer
|
||||
OpenGL framework addresses.
|
||||
|
||||
o GLXPixmaps
|
||||
|
||||
New support for GLXPixmaps works well with mixed X11 and OpenGL drawing
|
||||
operations. You can create them using glXCreateGLXPixmap or
|
||||
glXCreatePixmap.
|
||||
|
||||
o GLXPbuffers
|
||||
|
||||
Support for GLXPbuffers has been added. These are drawables that are
|
||||
not possible to render to with X11, which is allowed by the spec.
|
||||
A GLXPbuffer will never generate a clobber event, however
|
||||
glXSelectEvent and glXGetSelectedEvent should operate normally.
|
||||
|
||||
Clobber events are not generated due to low-level architectural
|
||||
differences. The contents of your pbuffers will not be clobbered.
|
||||
|
||||
o Shared Contexts
|
||||
|
||||
Due to basic low-level architectural differences the usage of shared
|
||||
contexts requires a similar visual or GLXFBConfig be used in the
|
||||
creation of a shared context. It's best if you specify the same
|
||||
visual. This is due to a CGL design difference, and not something
|
||||
that is easily worked around. UPDATE: some changes made seem to
|
||||
help resolve this issue in many cases, so you may be able to use a
|
||||
shared context without this restriction.
|
||||
|
||||
|
||||
o Indirect
|
||||
|
||||
The X server supports indirect fairly well, so OpenGL applications
|
||||
can be run remotely and displayed by XQuartz. This means you can run
|
||||
applications from a remote host on an XQuartz X server.
|
||||
|
||||
AppleSGLX does not support indirect rendering. Any indirect context
|
||||
created will appear to glXIsDirect as an indirect context, but it
|
||||
does not actually support indirect rendering to a remote X server.
|
||||
|
||||
AppleSGLX supports GLXPixmaps and GLXPbuffers with direct and indirect
|
||||
contexts, though they are all direct contexts by definition (see above).
|
||||
@@ -0,0 +1,26 @@
|
||||
Test shared contexts!
|
||||
|
||||
Go over every glxcmd in glxcmds.c and make sure we have them working.
|
||||
Verify the XError behavior of GLXPixmap support functions.
|
||||
|
||||
Test GLXPixmap support with various pixmap depths.
|
||||
|
||||
Test GLXPixmap support with invalid pixmaps (to stress the protocol code).
|
||||
|
||||
-- Feb 10, 2009
|
||||
|
||||
Test glXCopyContext.
|
||||
|
||||
-- Dec 12 2008
|
||||
|
||||
TEST glXCopyContext needs some work and additional code in apple_glx.c.
|
||||
|
||||
----
|
||||
|
||||
Make sure we report the proper list of GLX extensions available. Apple direct may not support some
|
||||
that Mesa does, and vice-versa.
|
||||
|
||||
Modify create_destroy_context and create a new test called create_destroy_context_thread_race.
|
||||
Where 2 threads are doing the same sort of path of create and destroy. The locking should protect
|
||||
us there, but we need to verify nothing goes wrong.
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (c) 2008 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "apple_cgl.h"
|
||||
#include "apple_glx.h"
|
||||
#include "util/os_misc.h"
|
||||
|
||||
#ifndef OPENGL_FRAMEWORK_PATH
|
||||
#define OPENGL_FRAMEWORK_PATH "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL"
|
||||
#endif
|
||||
|
||||
static void *dl_handle = NULL;
|
||||
|
||||
struct apple_cgl_api apple_cgl;
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
static void *
|
||||
sym(void *h, const char *name)
|
||||
{
|
||||
void *s;
|
||||
|
||||
s = dlsym(h, name);
|
||||
|
||||
if (NULL == s) {
|
||||
fprintf(stderr, "error: %s\n", dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
apple_cgl_init(void)
|
||||
{
|
||||
void *h;
|
||||
const char *opengl_framework_path;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
|
||||
opengl_framework_path = os_get_option("OPENGL_FRAMEWORK_PATH");
|
||||
if (!opengl_framework_path) {
|
||||
opengl_framework_path = OPENGL_FRAMEWORK_PATH;
|
||||
}
|
||||
|
||||
(void) dlerror(); /*drain dlerror */
|
||||
h = dlopen(opengl_framework_path, RTLD_NOW);
|
||||
|
||||
if (NULL == h) {
|
||||
fprintf(stderr, "error: unable to dlopen %s : %s\n",
|
||||
opengl_framework_path, dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
dl_handle = h;
|
||||
|
||||
apple_cgl.get_version = sym(h, "CGLGetVersion");
|
||||
|
||||
apple_cgl.get_version(&apple_cgl.version_major, &apple_cgl.version_minor);
|
||||
|
||||
apple_glx_diagnostic("CGL major %d minor %d\n", apple_cgl.version_major, apple_cgl.version_minor);
|
||||
|
||||
if (1 != apple_cgl.version_major) {
|
||||
fprintf(stderr, "WARNING: the CGL major version has changed!\n"
|
||||
"libGL may be incompatible!\n");
|
||||
}
|
||||
|
||||
apple_cgl.choose_pixel_format = sym(h, "CGLChoosePixelFormat");
|
||||
apple_cgl.destroy_pixel_format = sym(h, "CGLDestroyPixelFormat");
|
||||
|
||||
apple_cgl.clear_drawable = sym(h, "CGLClearDrawable");
|
||||
apple_cgl.flush_drawable = sym(h, "CGLFlushDrawable");
|
||||
|
||||
apple_cgl.create_context = sym(h, "CGLCreateContext");
|
||||
apple_cgl.destroy_context = sym(h, "CGLDestroyContext");
|
||||
|
||||
apple_cgl.set_current_context = sym(h, "CGLSetCurrentContext");
|
||||
apple_cgl.get_current_context = sym(h, "CGLGetCurrentContext");
|
||||
apple_cgl.error_string = sym(h, "CGLErrorString");
|
||||
|
||||
apple_cgl.set_off_screen = sym(h, "CGLSetOffScreen");
|
||||
|
||||
apple_cgl.copy_context = sym(h, "CGLCopyContext");
|
||||
|
||||
apple_cgl.create_pbuffer = sym(h, "CGLCreatePBuffer");
|
||||
apple_cgl.destroy_pbuffer = sym(h, "CGLDestroyPBuffer");
|
||||
apple_cgl.set_pbuffer = sym(h, "CGLSetPBuffer");
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void *
|
||||
apple_cgl_get_dl_handle(void)
|
||||
{
|
||||
return dl_handle;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_CGL_H
|
||||
#define APPLE_CGL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
/* For GLint and GLsizei on Tiger */
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
struct apple_cgl_api
|
||||
{
|
||||
GLint version_major, version_minor;
|
||||
void (*get_version) (GLint * version_major, GLint * version_minor);
|
||||
|
||||
CGLError(*choose_pixel_format) (const CGLPixelFormatAttribute * attribs,
|
||||
CGLPixelFormatObj * pix, GLint * npix);
|
||||
CGLError(*destroy_pixel_format) (CGLPixelFormatObj pix);
|
||||
|
||||
CGLError(*clear_drawable) (CGLContextObj ctx);
|
||||
CGLError(*flush_drawable) (CGLContextObj ctx);
|
||||
|
||||
CGLError(*create_context) (CGLPixelFormatObj pix, CGLContextObj share,
|
||||
CGLContextObj * ctx);
|
||||
CGLError(*destroy_context) (CGLContextObj pix);
|
||||
|
||||
CGLError(*set_current_context) (CGLContextObj ctx);
|
||||
CGLContextObj(*get_current_context) (void);
|
||||
const char *(*error_string) (CGLError error);
|
||||
|
||||
CGLError(*set_off_screen) (CGLContextObj ctx,
|
||||
GLsizei width, GLsizei height, GLint rowbytes,
|
||||
void *baseaddr);
|
||||
|
||||
CGLError(*copy_context) (CGLContextObj src, CGLContextObj dst,
|
||||
GLbitfield mask);
|
||||
|
||||
CGLError(*create_pbuffer) (GLsizei width,
|
||||
GLsizei height,
|
||||
GLenum target,
|
||||
GLenum internalFormat,
|
||||
GLint max_level, CGLPBufferObj * pbuffer);
|
||||
|
||||
CGLError(*destroy_pbuffer) (CGLPBufferObj pbuffer);
|
||||
|
||||
CGLError(*set_pbuffer) (CGLContextObj ctx,
|
||||
CGLPBufferObj pbuffer,
|
||||
GLenum face, GLint level, GLint screen);
|
||||
};
|
||||
|
||||
extern struct apple_cgl_api apple_cgl;
|
||||
|
||||
extern void apple_cgl_init(void);
|
||||
|
||||
extern void *apple_cgl_get_dl_handle(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* GLX implementation that uses Apple's OpenGL.framework
|
||||
*
|
||||
* Copyright (c) 2007-2011 Apple Inc.
|
||||
* Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
|
||||
* Copyright (c) 2002 Greg Parker. All Rights Reserved.
|
||||
*
|
||||
* Portions of this file are copied from Mesa's xf86glx.c,
|
||||
* which contains the following copyright:
|
||||
*
|
||||
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* 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
|
||||
* THE ABOVE LISTED COPYRIGHT HOLDER(S) 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "glapi.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
#include "apple_glx.h"
|
||||
#include "apple_xgl_api.h"
|
||||
#include "apple_cgl.h"
|
||||
|
||||
struct _glapi_table * __ogl_framework_api = NULL;
|
||||
struct _glapi_table * __applegl_api = NULL;
|
||||
|
||||
static void _apple_glapi_create_table(void) {
|
||||
if (__applegl_api)
|
||||
return;
|
||||
|
||||
__ogl_framework_api = _glapi_create_table_from_handle(apple_cgl_get_dl_handle(), "gl");
|
||||
assert(__ogl_framework_api);
|
||||
|
||||
size_t glapi_table_size = _gloffset_COUNT * sizeof(_glapi_proc*);
|
||||
__applegl_api = malloc(glapi_table_size);
|
||||
assert(__applegl_api);
|
||||
memcpy(__applegl_api, __ogl_framework_api, glapi_table_size);
|
||||
|
||||
_glapi_table_patch(__applegl_api, "ReadPixels", __applegl_glReadPixels);
|
||||
_glapi_table_patch(__applegl_api, "CopyPixels", __applegl_glCopyPixels);
|
||||
_glapi_table_patch(__applegl_api, "DrawBuffers", __applegl_glDrawBuffer);
|
||||
_glapi_table_patch(__applegl_api, "Viewport", __applegl_glViewport);
|
||||
}
|
||||
|
||||
void apple_mesa_glapi_set_dispatch(void) {
|
||||
_apple_glapi_create_table();
|
||||
_mesa_glapi_set_dispatch(__applegl_api);
|
||||
}
|
||||
|
||||
void apple_glapi_oglfw_viewport_scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
_apple_glapi_create_table();
|
||||
|
||||
CALL_Viewport(__ogl_framework_api, (x, y, width, height));
|
||||
CALL_Scissor(__ogl_framework_api, (x, y, width, height));
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <inttypes.h>
|
||||
#include "appledri.h"
|
||||
#include "apple_glx.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_cgl.h"
|
||||
|
||||
static bool initialized = false;
|
||||
static int dri_event_base = 0;
|
||||
|
||||
int
|
||||
apple_get_dri_event_base(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
fprintf(stderr,
|
||||
"error: dri_event_base called before apple_init_glx!\n");
|
||||
abort();
|
||||
}
|
||||
return dri_event_base;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_notify_handler(Display * dpy, unsigned int uid, int kind)
|
||||
{
|
||||
|
||||
switch (kind) {
|
||||
case AppleDRISurfaceNotifyDestroyed:
|
||||
apple_glx_diagnostic("%s: surface destroyed %u\n", __func__, uid);
|
||||
apple_glx_surface_destroy(uid);
|
||||
break;
|
||||
|
||||
case AppleDRISurfaceNotifyChanged:{
|
||||
int updated;
|
||||
|
||||
updated = apple_glx_context_surface_changed(uid, pthread_self());
|
||||
|
||||
apple_glx_diagnostic("surface notify updated %d\n", updated);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unhandled kind of event: %d in %s\n", kind, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
xp_client_id
|
||||
apple_glx_get_client_id(void)
|
||||
{
|
||||
static xp_client_id id;
|
||||
|
||||
if (0 == id) {
|
||||
if ((XP_Success != xp_init(XP_IN_BACKGROUND)) ||
|
||||
(Success != xp_get_client_id(&id))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
apple_init_glx(Display * dpy)
|
||||
{
|
||||
int eventBase, errorBase;
|
||||
int major, minor, patch;
|
||||
|
||||
if (!XAppleDRIQueryExtension(dpy, &eventBase, &errorBase))
|
||||
return true;
|
||||
|
||||
if (!XAppleDRIQueryVersion(dpy, &major, &minor, &patch))
|
||||
return true;
|
||||
|
||||
if (initialized)
|
||||
return false;
|
||||
|
||||
apple_glx_log_init();
|
||||
|
||||
apple_glx_log(ASL_LEVEL_INFO, "Initializing libGL.");
|
||||
|
||||
apple_cgl_init();
|
||||
(void) apple_glx_get_client_id();
|
||||
|
||||
XAppleDRISetSurfaceNotifyHandler(surface_notify_handler);
|
||||
|
||||
/* This should really be per display. */
|
||||
dri_event_base = eventBase;
|
||||
initialized = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
apple_glx_swap_buffers(void *ptr)
|
||||
{
|
||||
struct apple_glx_context *ac = ptr;
|
||||
|
||||
apple_cgl.flush_drawable(ac->context_obj);
|
||||
}
|
||||
|
||||
void
|
||||
apple_glx_waitx(Display * dpy, void *ptr)
|
||||
{
|
||||
struct apple_private_context *ac = ptr;
|
||||
|
||||
(void) ac;
|
||||
|
||||
glFlush();
|
||||
glFinish();
|
||||
XSync(dpy, False);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2008 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_GLX_H
|
||||
#define APPLE_GLX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <GL/gl.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#define XP_NO_X_HEADERS
|
||||
#include <Xplugin.h>
|
||||
|
||||
#include "apple_glx_log.h"
|
||||
|
||||
xp_client_id apple_glx_get_client_id(void);
|
||||
bool apple_init_glx(Display * dpy);
|
||||
void apple_glx_swap_buffers(void *ptr);
|
||||
void apple_glx_waitx(Display * dpy, void *ptr);
|
||||
int apple_get_dri_event_base(void);
|
||||
|
||||
void apple_mesa_glapi_set_dispatch(void);
|
||||
void apple_glapi_oglfw_viewport_scissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Get the newer glext.h first
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
|
||||
#include "apple_glx.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "appledri.h"
|
||||
#include "apple_visual.h"
|
||||
#include "apple_cgl.h"
|
||||
#include "apple_glx_drawable.h"
|
||||
|
||||
#include "util/u_debug.h"
|
||||
|
||||
static pthread_mutex_t context_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* This should be locked on creation and destruction of the
|
||||
* apple_glx_contexts.
|
||||
*
|
||||
* It's also locked when the surface_notify_handler is searching
|
||||
* for a uid associated with a surface.
|
||||
*/
|
||||
static struct apple_glx_context *context_list = NULL;
|
||||
|
||||
/* This guards the context_list above. */
|
||||
static void
|
||||
lock_context_list(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_lock(&context_lock);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_lock failure in %s: %d\n",
|
||||
__func__, err);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_context_list(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_unlock(&context_lock);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_unlock failure in %s: %d\n",
|
||||
__func__, err);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
is_context_valid(struct apple_glx_context *ac)
|
||||
{
|
||||
struct apple_glx_context *i;
|
||||
|
||||
lock_context_list();
|
||||
|
||||
for (i = context_list; i; i = i->next) {
|
||||
if (ac == i) {
|
||||
unlock_context_list();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_context_list();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This creates an apple_private_context struct.
|
||||
*
|
||||
* It's typically called to save the struct in a GLXContext.
|
||||
*
|
||||
* This is also where the CGLContextObj is created, and the CGLPixelFormatObj.
|
||||
*/
|
||||
bool
|
||||
apple_glx_create_context(void **ptr, Display * dpy, int screen,
|
||||
const void *mode, void *sharedContext,
|
||||
int *errorptr, bool * x11errorptr)
|
||||
{
|
||||
struct apple_glx_context *ac;
|
||||
struct apple_glx_context *sharedac = sharedContext;
|
||||
CGLError error;
|
||||
|
||||
*ptr = NULL;
|
||||
|
||||
ac = malloc(sizeof *ac);
|
||||
|
||||
if (NULL == ac) {
|
||||
*errorptr = BadAlloc;
|
||||
*x11errorptr = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sharedac && !is_context_valid(sharedac)) {
|
||||
*errorptr = GLXBadContext;
|
||||
*x11errorptr = false;
|
||||
free(ac);
|
||||
return true;
|
||||
}
|
||||
|
||||
ac->context_obj = NULL;
|
||||
ac->pixel_format_obj = NULL;
|
||||
ac->drawable = NULL;
|
||||
ac->thread_id = pthread_self();
|
||||
ac->screen = screen;
|
||||
ac->double_buffered = false;
|
||||
ac->uses_stereo = false;
|
||||
ac->need_update = false;
|
||||
ac->is_current = false;
|
||||
ac->made_current = false;
|
||||
ac->last_surface_window = None;
|
||||
|
||||
apple_visual_create_pfobj(&ac->pixel_format_obj, mode,
|
||||
&ac->double_buffered, &ac->uses_stereo,
|
||||
/*offscreen */ false);
|
||||
|
||||
error = apple_cgl.create_context(ac->pixel_format_obj,
|
||||
sharedac ? sharedac->context_obj : NULL,
|
||||
&ac->context_obj);
|
||||
|
||||
|
||||
if (error) {
|
||||
(void) apple_cgl.destroy_pixel_format(ac->pixel_format_obj);
|
||||
|
||||
free(ac);
|
||||
|
||||
if (kCGLBadMatch == error) {
|
||||
*errorptr = BadMatch;
|
||||
*x11errorptr = true;
|
||||
}
|
||||
else {
|
||||
*errorptr = GLXBadContext;
|
||||
*x11errorptr = false;
|
||||
}
|
||||
|
||||
DebugMessageF("error: %s\n", apple_cgl.error_string(error));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The context creation succeeded, so we can link in the new context. */
|
||||
lock_context_list();
|
||||
|
||||
if (context_list)
|
||||
context_list->previous = ac;
|
||||
|
||||
ac->previous = NULL;
|
||||
ac->next = context_list;
|
||||
context_list = ac;
|
||||
|
||||
*ptr = ac;
|
||||
|
||||
apple_glx_diagnostic("%s: ac %p ac->context_obj %p\n",
|
||||
__func__, (void *) ac, (void *) ac->context_obj);
|
||||
|
||||
unlock_context_list();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
apple_glx_destroy_context(void **ptr, Display * dpy)
|
||||
{
|
||||
struct apple_glx_context *ac = *ptr;
|
||||
|
||||
if (NULL == ac)
|
||||
return;
|
||||
|
||||
apple_glx_diagnostic("%s: ac %p ac->context_obj %p\n",
|
||||
__func__, (void *) ac, (void *) ac->context_obj);
|
||||
|
||||
if (apple_cgl.get_current_context() == ac->context_obj) {
|
||||
apple_glx_diagnostic("%s: context ac->context_obj %p "
|
||||
"is still current!\n", __func__,
|
||||
(void *) ac->context_obj);
|
||||
if (apple_cgl.set_current_context(NULL)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove ac from the context_list as soon as possible. */
|
||||
lock_context_list();
|
||||
|
||||
if (ac->previous) {
|
||||
ac->previous->next = ac->next;
|
||||
}
|
||||
else {
|
||||
context_list = ac->next;
|
||||
}
|
||||
|
||||
if (ac->next) {
|
||||
ac->next->previous = ac->previous;
|
||||
}
|
||||
|
||||
unlock_context_list();
|
||||
|
||||
|
||||
if (apple_cgl.clear_drawable(ac->context_obj)) {
|
||||
fprintf(stderr, "error: while clearing drawable!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* This potentially causes surface_notify_handler to be called in
|
||||
* apple_glx.c...
|
||||
* We can NOT have a lock held at this point. It would result in
|
||||
* an abort due to an attempted deadlock. This is why we earlier
|
||||
* removed the ac pointer from the double-linked list.
|
||||
*/
|
||||
if (ac->drawable) {
|
||||
ac->drawable->destroy(ac->drawable);
|
||||
}
|
||||
|
||||
if (apple_cgl.destroy_pixel_format(ac->pixel_format_obj)) {
|
||||
fprintf(stderr, "error: destroying pixel format in %s\n", __func__);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (apple_cgl.destroy_context(ac->context_obj)) {
|
||||
fprintf(stderr, "error: destroying context_obj in %s\n", __func__);
|
||||
abort();
|
||||
}
|
||||
|
||||
free(ac);
|
||||
|
||||
*ptr = NULL;
|
||||
|
||||
apple_glx_garbage_collect_drawables(dpy);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
apple_glx_make_current_context(Display * dpy, void *oldptr, void *ptr,
|
||||
GLXDrawable drawable)
|
||||
{
|
||||
struct apple_glx_context *oldac = oldptr;
|
||||
struct apple_glx_context *ac = ptr;
|
||||
struct apple_glx_drawable *newagd = NULL;
|
||||
CGLError cglerr;
|
||||
bool same_drawable = false;
|
||||
|
||||
#if 0
|
||||
apple_glx_diagnostic("%s: oldac %p ac %p drawable 0x%lx\n",
|
||||
__func__, (void *) oldac, (void *) ac, drawable);
|
||||
|
||||
apple_glx_diagnostic("%s: oldac->context_obj %p ac->context_obj %p\n",
|
||||
__func__,
|
||||
(void *) (oldac ? oldac->context_obj : NULL),
|
||||
(void *) (ac ? ac->context_obj : NULL));
|
||||
#endif
|
||||
|
||||
/* This a common path for GLUT and other apps, so special case it. */
|
||||
if (ac && ac->drawable && ac->drawable->drawable == drawable) {
|
||||
same_drawable = true;
|
||||
|
||||
if (ac->is_current)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Reset the is_current state of the old context, if non-NULL. */
|
||||
if (oldac && (ac != oldac))
|
||||
oldac->is_current = false;
|
||||
|
||||
if (NULL == ac) {
|
||||
/*Clear the current context for this thread. */
|
||||
apple_cgl.set_current_context(NULL);
|
||||
|
||||
if (oldac) {
|
||||
oldac->is_current = false;
|
||||
|
||||
if (oldac->drawable) {
|
||||
oldac->drawable->destroy(oldac->drawable);
|
||||
oldac->drawable = NULL;
|
||||
}
|
||||
|
||||
/* Invalidate this to prevent surface recreation. */
|
||||
oldac->last_surface_window = None;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (None == drawable) {
|
||||
bool error = false;
|
||||
|
||||
/* Clear the current drawable for this context_obj. */
|
||||
|
||||
if (apple_cgl.set_current_context(ac->context_obj))
|
||||
error = true;
|
||||
|
||||
if (apple_cgl.clear_drawable(ac->context_obj))
|
||||
error = true;
|
||||
|
||||
if (ac->drawable) {
|
||||
ac->drawable->destroy(ac->drawable);
|
||||
ac->drawable = NULL;
|
||||
}
|
||||
|
||||
/* Invalidate this to prevent surface recreation. */
|
||||
ac->last_surface_window = None;
|
||||
|
||||
apple_glx_diagnostic("%s: drawable is None, error is: %d\n",
|
||||
__func__, error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* This is an optimisation to avoid searching for the current drawable. */
|
||||
if (ac->drawable && ac->drawable->drawable == drawable) {
|
||||
newagd = ac->drawable;
|
||||
}
|
||||
else {
|
||||
/* Find the drawable if possible, and retain a reference to it. */
|
||||
newagd =
|
||||
apple_glx_drawable_find(drawable, APPLE_GLX_DRAWABLE_REFERENCE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to destroy the old drawable, so long as the new one
|
||||
* isn't the old.
|
||||
*/
|
||||
if (ac->drawable && !same_drawable) {
|
||||
ac->drawable->destroy(ac->drawable);
|
||||
ac->drawable = NULL;
|
||||
}
|
||||
|
||||
if (NULL == newagd) {
|
||||
if (apple_glx_surface_create(dpy, ac->screen, drawable, &newagd))
|
||||
return true;
|
||||
|
||||
/* The drawable is referenced once by apple_glx_surface_create. */
|
||||
|
||||
/*
|
||||
* FIXME: We actually need 2 references to prevent premature surface
|
||||
* destruction. The problem is that the surface gets destroyed in
|
||||
* the case of the context being reused for another window, and
|
||||
* we then lose the surface contents. Wait for destruction of a
|
||||
* window to destroy a surface.
|
||||
*
|
||||
* Note: this may leave around surfaces we don't want around, if
|
||||
* say we are using X for raster drawing after OpenGL rendering,
|
||||
* but it will be compatible with the old libGL's behavior.
|
||||
*
|
||||
* Someday the X11 and OpenGL rendering must be unified at some
|
||||
* layer. I suspect we can do that via shared memory and
|
||||
* multiple threads in the X server (1 for each context created
|
||||
* by a client). This would also allow users to render from
|
||||
* multiple clients to the same OpenGL surface. In fact it could
|
||||
* all be OpenGL.
|
||||
*
|
||||
*/
|
||||
newagd->reference(newagd);
|
||||
|
||||
/* Save the new drawable with the context structure. */
|
||||
ac->drawable = newagd;
|
||||
}
|
||||
else {
|
||||
/* We are reusing an existing drawable structure. */
|
||||
|
||||
if (same_drawable) {
|
||||
assert(ac->drawable == newagd);
|
||||
/* The drawable_find above retained a reference for us. */
|
||||
}
|
||||
else {
|
||||
ac->drawable = newagd;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid this costly path if this is the same drawable and the
|
||||
* context is already current.
|
||||
*/
|
||||
|
||||
if (same_drawable && ac->is_current) {
|
||||
apple_glx_diagnostic("same_drawable and ac->is_current\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cglerr = apple_cgl.set_current_context(ac->context_obj);
|
||||
|
||||
if (kCGLNoError != cglerr) {
|
||||
fprintf(stderr, "set current error: %s\n",
|
||||
apple_cgl.error_string(cglerr));
|
||||
return true;
|
||||
}
|
||||
|
||||
ac->is_current = true;
|
||||
|
||||
assert(NULL != ac->context_obj);
|
||||
assert(NULL != ac->drawable);
|
||||
|
||||
ac->thread_id = pthread_self();
|
||||
|
||||
/* This will be set if the pending_destroy code indicates it should be: */
|
||||
ac->last_surface_window = None;
|
||||
|
||||
switch (ac->drawable->type) {
|
||||
case APPLE_GLX_DRAWABLE_PBUFFER:
|
||||
case APPLE_GLX_DRAWABLE_SURFACE:
|
||||
case APPLE_GLX_DRAWABLE_PIXMAP:
|
||||
if (ac->drawable->callbacks.make_current) {
|
||||
if (ac->drawable->callbacks.make_current(ac, ac->drawable))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "internal error: invalid drawable type: %d\n",
|
||||
ac->drawable->type);
|
||||
abort();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_is_current_drawable(Display * dpy, void *ptr, GLXDrawable drawable)
|
||||
{
|
||||
struct apple_glx_context *ac = ptr;
|
||||
|
||||
if (ac->drawable && ac->drawable->drawable == drawable) {
|
||||
return true;
|
||||
}
|
||||
else if (NULL == ac->drawable && None != ac->last_surface_window) {
|
||||
apple_glx_context_update(dpy, ac);
|
||||
|
||||
return (ac->drawable && ac->drawable->drawable == drawable);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_copy_context(void *currentptr, void *srcptr, void *destptr,
|
||||
unsigned long mask, int *errorptr, bool * x11errorptr)
|
||||
{
|
||||
struct apple_glx_context *src, *dest;
|
||||
CGLError err;
|
||||
|
||||
src = srcptr;
|
||||
dest = destptr;
|
||||
|
||||
if (src->screen != dest->screen) {
|
||||
*errorptr = BadMatch;
|
||||
*x11errorptr = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dest == currentptr || dest->is_current) {
|
||||
*errorptr = BadAccess;
|
||||
*x11errorptr = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If srcptr is the current context then we should do an implicit glFlush.
|
||||
*/
|
||||
if (currentptr == srcptr)
|
||||
glFlush();
|
||||
|
||||
err = apple_cgl.copy_context(src->context_obj, dest->context_obj,
|
||||
(GLbitfield) mask);
|
||||
|
||||
if (kCGLNoError != err) {
|
||||
*errorptr = GLXBadContext;
|
||||
*x11errorptr = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The value returned is the total number of contexts set to update.
|
||||
* It's meant for debugging/introspection.
|
||||
*/
|
||||
int
|
||||
apple_glx_context_surface_changed(unsigned int uid, pthread_t caller)
|
||||
{
|
||||
struct apple_glx_context *ac;
|
||||
int updated = 0;
|
||||
|
||||
lock_context_list();
|
||||
|
||||
for (ac = context_list; ac; ac = ac->next) {
|
||||
if (ac->drawable && APPLE_GLX_DRAWABLE_SURFACE == ac->drawable->type
|
||||
&& ac->drawable->types.surface.uid == uid) {
|
||||
|
||||
if (caller == ac->thread_id) {
|
||||
apple_glx_diagnostic("caller is the same thread for uid %u\n",
|
||||
uid);
|
||||
|
||||
xp_update_gl_context(ac->context_obj);
|
||||
}
|
||||
else {
|
||||
ac->need_update = true;
|
||||
++updated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unlock_context_list();
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
void
|
||||
apple_glx_context_update(Display * dpy, void *ptr)
|
||||
{
|
||||
struct apple_glx_context *ac = ptr;
|
||||
|
||||
if (NULL == ac->drawable && None != ac->last_surface_window) {
|
||||
bool failed;
|
||||
|
||||
/* Attempt to recreate the surface for a destroyed drawable. */
|
||||
failed =
|
||||
apple_glx_make_current_context(dpy, ac, ac, ac->last_surface_window);
|
||||
|
||||
apple_glx_diagnostic("%s: surface recreation failed? %s\n", __func__,
|
||||
failed ? "YES" : "NO");
|
||||
}
|
||||
|
||||
if (ac->need_update) {
|
||||
xp_update_gl_context(ac->context_obj);
|
||||
ac->need_update = false;
|
||||
|
||||
apple_glx_diagnostic("%s: updating context %p\n", __func__, ptr);
|
||||
}
|
||||
|
||||
if (ac->drawable && APPLE_GLX_DRAWABLE_SURFACE == ac->drawable->type
|
||||
&& ac->drawable->types.surface.pending_destroy) {
|
||||
apple_glx_diagnostic("%s: clearing drawable %p\n", __func__, ptr);
|
||||
apple_cgl.clear_drawable(ac->context_obj);
|
||||
|
||||
if (ac->drawable) {
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
apple_glx_diagnostic("%s: attempting to destroy drawable %p\n",
|
||||
__func__, ptr);
|
||||
apple_glx_diagnostic("%s: ac->drawable->drawable is 0x%lx\n",
|
||||
__func__, ac->drawable->drawable);
|
||||
|
||||
d = ac->drawable;
|
||||
|
||||
ac->last_surface_window = d->drawable;
|
||||
|
||||
ac->drawable = NULL;
|
||||
|
||||
/*
|
||||
* This will destroy the surface drawable if there are
|
||||
* no references to it.
|
||||
* It also subtracts 1 from the reference_count.
|
||||
* If there are references to it, then it's probably made
|
||||
* current in another context.
|
||||
*/
|
||||
d->destroy(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_context_uses_stereo(void *ptr)
|
||||
{
|
||||
struct apple_glx_context *ac = ptr;
|
||||
|
||||
return ac->uses_stereo;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
#ifndef APPLE_GLX_CONTEXT_H
|
||||
#define APPLE_GLX_CONTEXT_H
|
||||
|
||||
/* <rdar://problem/6953344> */
|
||||
#define glTexImage1D glTexImage1D_OSX
|
||||
#define glTexImage2D glTexImage2D_OSX
|
||||
#define glTexImage3D glTexImage3D_OSX
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLContext.h>
|
||||
#undef glTexImage1D
|
||||
#undef glTexImage2D
|
||||
#undef glTexImage3D
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
#define XP_NO_X_HEADERS
|
||||
#include <Xplugin.h>
|
||||
#undef XP_NO_X_HEADERS
|
||||
|
||||
#include "apple_glx_drawable.h"
|
||||
|
||||
struct apple_glx_context
|
||||
{
|
||||
CGLContextObj context_obj;
|
||||
CGLPixelFormatObj pixel_format_obj;
|
||||
struct apple_glx_drawable *drawable;
|
||||
pthread_t thread_id;
|
||||
int screen;
|
||||
bool double_buffered;
|
||||
bool uses_stereo;
|
||||
bool need_update;
|
||||
bool is_current; /* True if the context is current in some thread. */
|
||||
bool made_current; /* True if the context has ever been made current. */
|
||||
|
||||
/*
|
||||
* last_surface is set by the pending_destroy code handler for a drawable.
|
||||
* Due to a CG difference, we have to recreate a surface if the window
|
||||
* is unmapped and mapped again.
|
||||
*/
|
||||
Window last_surface_window;
|
||||
struct apple_glx_context *previous, *next;
|
||||
};
|
||||
|
||||
bool apple_glx_create_context(void **ptr, Display * dpy, int screen,
|
||||
const void *mode, void *sharedContext,
|
||||
int *errorptr, bool * x11errorptr);
|
||||
void apple_glx_destroy_context(void **ptr, Display * dpy);
|
||||
|
||||
bool apple_glx_make_current_context(Display * dpy, void *oldptr, void *ptr,
|
||||
GLXDrawable drawable);
|
||||
bool apple_glx_is_current_drawable(Display * dpy, void *ptr,
|
||||
GLXDrawable drawable);
|
||||
|
||||
bool apple_glx_copy_context(void *currentptr, void *srcptr, void *destptr,
|
||||
unsigned long mask, int *errorptr,
|
||||
bool * x11errorptr);
|
||||
|
||||
int apple_glx_context_surface_changed(unsigned int uid, pthread_t caller);
|
||||
|
||||
void apple_glx_context_update(Display * dpy, void *ptr);
|
||||
|
||||
bool apple_glx_context_uses_stereo(void *ptr);
|
||||
|
||||
#endif /*APPLE_GLX_CONTEXT_H */
|
||||
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include "apple_glx.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_glx_drawable.h"
|
||||
#include "appledri.h"
|
||||
|
||||
static pthread_mutex_t drawables_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct apple_glx_drawable *drawables_list = NULL;
|
||||
|
||||
static void
|
||||
lock_drawables_list(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_lock(&drawables_lock);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_lock failure in %s: %s\n",
|
||||
__func__, strerror(err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_drawables_list(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_unlock(&drawables_lock);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_unlock failure in %s: %s\n",
|
||||
__func__, strerror(err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
struct apple_glx_drawable *
|
||||
apple_glx_find_drawable(Display * dpy, GLXDrawable drawable)
|
||||
{
|
||||
struct apple_glx_drawable *i, *agd = NULL;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (i = drawables_list; i; i = i->next) {
|
||||
if (i->drawable == drawable) {
|
||||
agd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return agd;
|
||||
}
|
||||
|
||||
static void
|
||||
drawable_lock(struct apple_glx_drawable *agd)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_lock(&agd->mutex);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_lock error: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drawable_unlock(struct apple_glx_drawable *d)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = pthread_mutex_unlock(&d->mutex);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_unlock error: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reference_drawable(struct apple_glx_drawable *d)
|
||||
{
|
||||
d->lock(d);
|
||||
d->reference_count++;
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
static void
|
||||
release_drawable(struct apple_glx_drawable *d)
|
||||
{
|
||||
d->lock(d);
|
||||
d->reference_count--;
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
/* The drawables list must be locked prior to calling this. */
|
||||
/* Return true if the drawable was destroyed. */
|
||||
static bool
|
||||
destroy_drawable(struct apple_glx_drawable *d)
|
||||
{
|
||||
int err;
|
||||
|
||||
d->lock(d);
|
||||
|
||||
if (d->reference_count > 0) {
|
||||
d->unlock(d);
|
||||
return false;
|
||||
}
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
if (d->previous) {
|
||||
d->previous->next = d->next;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* The item must be at the head of the list, if it
|
||||
* has no previous pointer.
|
||||
*/
|
||||
drawables_list = d->next;
|
||||
}
|
||||
|
||||
if (d->next)
|
||||
d->next->previous = d->previous;
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
if (d->callbacks.destroy) {
|
||||
/*
|
||||
* Warning: this causes other routines to be called (potentially)
|
||||
* from surface_notify_handler. It's probably best to not have
|
||||
* any locks at this point locked.
|
||||
*/
|
||||
d->callbacks.destroy(d->display, d);
|
||||
}
|
||||
|
||||
apple_glx_diagnostic("%s: freeing %p\n", __func__, (void *) d);
|
||||
|
||||
/* Stupid recursive locks */
|
||||
while (pthread_mutex_unlock(&d->mutex) == 0);
|
||||
|
||||
err = pthread_mutex_destroy(&d->mutex);
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_destroy error: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
free(d);
|
||||
|
||||
/* So that the locks are balanced and the caller correctly unlocks. */
|
||||
lock_drawables_list();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is typically called when a context is destroyed or the current
|
||||
* drawable is made None.
|
||||
*/
|
||||
static bool
|
||||
destroy_drawable_callback(struct apple_glx_drawable *d)
|
||||
{
|
||||
bool result;
|
||||
|
||||
d->lock(d);
|
||||
|
||||
apple_glx_diagnostic("%s: %p ->reference_count before -- %d\n", __func__,
|
||||
(void *) d, d->reference_count);
|
||||
|
||||
d->reference_count--;
|
||||
|
||||
if (d->reference_count > 0) {
|
||||
d->unlock(d);
|
||||
return false;
|
||||
}
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
result = destroy_drawable(d);
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_pbuffer(struct apple_glx_drawable *d)
|
||||
{
|
||||
return APPLE_GLX_DRAWABLE_PBUFFER == d->type;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_pixmap(struct apple_glx_drawable *d)
|
||||
{
|
||||
return APPLE_GLX_DRAWABLE_PIXMAP == d->type;
|
||||
}
|
||||
|
||||
static void
|
||||
common_init(Display * dpy, GLXDrawable drawable, struct apple_glx_drawable *d)
|
||||
{
|
||||
int err;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
d->display = dpy;
|
||||
d->reference_count = 0;
|
||||
d->drawable = drawable;
|
||||
d->type = -1;
|
||||
|
||||
err = pthread_mutexattr_init(&attr);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutexattr_init error: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* There are some patterns that require a recursive mutex,
|
||||
* when working with locks that protect the apple_glx_drawable,
|
||||
* and reference functions like ->reference, and ->release.
|
||||
*/
|
||||
err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "error: setting pthread mutex type: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
err = pthread_mutex_init(&d->mutex, &attr);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "pthread_mutex_init error: %s\n", strerror(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
(void) pthread_mutexattr_destroy(&attr);
|
||||
|
||||
d->lock = drawable_lock;
|
||||
d->unlock = drawable_unlock;
|
||||
|
||||
d->reference = reference_drawable;
|
||||
d->release = release_drawable;
|
||||
|
||||
d->destroy = destroy_drawable_callback;
|
||||
|
||||
d->is_pbuffer = is_pbuffer;
|
||||
d->is_pixmap = is_pixmap;
|
||||
|
||||
d->width = -1;
|
||||
d->height = -1;
|
||||
d->row_bytes = 0;
|
||||
d->path[0] = '\0';
|
||||
d->fd = -1;
|
||||
d->buffer = NULL;
|
||||
d->buffer_length = 0;
|
||||
|
||||
d->previous = NULL;
|
||||
d->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
link_tail(struct apple_glx_drawable *agd)
|
||||
{
|
||||
lock_drawables_list();
|
||||
|
||||
/* Link the new drawable into the global list. */
|
||||
agd->next = drawables_list;
|
||||
|
||||
if (drawables_list)
|
||||
drawables_list->previous = agd;
|
||||
|
||||
drawables_list = agd;
|
||||
|
||||
unlock_drawables_list();
|
||||
}
|
||||
|
||||
/*WARNING: this returns a locked and referenced object. */
|
||||
bool
|
||||
apple_glx_drawable_create(Display * dpy,
|
||||
int screen,
|
||||
GLXDrawable drawable,
|
||||
struct apple_glx_drawable **agdResult,
|
||||
struct apple_glx_drawable_callbacks *callbacks)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
d = calloc(1, sizeof *d);
|
||||
|
||||
if (NULL == d) {
|
||||
perror("malloc");
|
||||
return true;
|
||||
}
|
||||
|
||||
common_init(dpy, drawable, d);
|
||||
d->type = callbacks->type;
|
||||
d->callbacks = *callbacks;
|
||||
|
||||
d->reference(d);
|
||||
d->lock(d);
|
||||
|
||||
link_tail(d);
|
||||
|
||||
apple_glx_diagnostic("%s: new drawable %p\n", __func__, (void *) d);
|
||||
|
||||
*agdResult = d;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int error_count = 0;
|
||||
|
||||
static int
|
||||
error_handler(Display * dpy, XErrorEvent * err)
|
||||
{
|
||||
if (err->error_code == BadWindow) {
|
||||
++error_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
apple_glx_garbage_collect_drawables(Display * dpy)
|
||||
{
|
||||
struct apple_glx_drawable *d, *dnext;
|
||||
Window root;
|
||||
int x, y;
|
||||
unsigned int width, height, bd, depth;
|
||||
int (*old_handler) (Display *, XErrorEvent *);
|
||||
|
||||
|
||||
if (NULL == drawables_list)
|
||||
return;
|
||||
|
||||
old_handler = XSetErrorHandler(error_handler);
|
||||
|
||||
XSync(dpy, False);
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d;) {
|
||||
dnext = d->next;
|
||||
|
||||
d->lock(d);
|
||||
|
||||
if (d->reference_count > 0) {
|
||||
/*
|
||||
* Skip this, because some context still retains a reference
|
||||
* to the drawable.
|
||||
*/
|
||||
d->unlock(d);
|
||||
d = dnext;
|
||||
continue;
|
||||
}
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
error_count = 0;
|
||||
|
||||
/*
|
||||
* Mesa uses XGetWindowAttributes, but some of these things are
|
||||
* most definitely not Windows, and that's against the rules.
|
||||
* XGetGeometry on the other hand is legal with a Pixmap and Window.
|
||||
*/
|
||||
XGetGeometry(dpy, d->drawable, &root, &x, &y, &width, &height, &bd,
|
||||
&depth);
|
||||
|
||||
if (error_count > 0) {
|
||||
/*
|
||||
* Note: this may not actually destroy the drawable.
|
||||
* If another context retains a reference to the drawable
|
||||
* after the reference count test above.
|
||||
*/
|
||||
(void) destroy_drawable(d);
|
||||
error_count = 0;
|
||||
}
|
||||
|
||||
d = dnext;
|
||||
}
|
||||
|
||||
XSetErrorHandler(old_handler);
|
||||
|
||||
unlock_drawables_list();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
apple_glx_get_drawable_count(void)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d; d = d->next)
|
||||
++result;
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct apple_glx_drawable *
|
||||
apple_glx_drawable_find_by_type(GLXDrawable drawable, int type, int flags)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d; d = d->next) {
|
||||
if (d->type == type && d->drawable == drawable) {
|
||||
if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
|
||||
d->reference(d);
|
||||
|
||||
if (flags & APPLE_GLX_DRAWABLE_LOCK)
|
||||
d->lock(d);
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct apple_glx_drawable *
|
||||
apple_glx_drawable_find(GLXDrawable drawable, int flags)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d; d = d->next) {
|
||||
if (d->drawable == drawable) {
|
||||
if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
|
||||
d->reference(d);
|
||||
|
||||
if (flags & APPLE_GLX_DRAWABLE_LOCK)
|
||||
d->lock(d);
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return true if the type is valid for the drawable. */
|
||||
bool
|
||||
apple_glx_drawable_destroy_by_type(Display * dpy,
|
||||
GLXDrawable drawable, int type)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d; d = d->next) {
|
||||
if (drawable == d->drawable && type == d->type) {
|
||||
/*
|
||||
* The user has requested that we destroy this resource.
|
||||
* However, there may be references in the contexts to it, so
|
||||
* release it, and call destroy_drawable which doesn't destroy
|
||||
* if the reference_count is > 0.
|
||||
*/
|
||||
d->release(d);
|
||||
|
||||
apple_glx_diagnostic("%s d->reference_count %d\n",
|
||||
__func__, d->reference_count);
|
||||
|
||||
destroy_drawable(d);
|
||||
unlock_drawables_list();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct apple_glx_drawable *
|
||||
apple_glx_drawable_find_by_uid(unsigned int uid, int flags)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
lock_drawables_list();
|
||||
|
||||
for (d = drawables_list; d; d = d->next) {
|
||||
/* Only surfaces have a uid. */
|
||||
if (APPLE_GLX_DRAWABLE_SURFACE == d->type) {
|
||||
if (d->types.surface.uid == uid) {
|
||||
if (flags & APPLE_GLX_DRAWABLE_REFERENCE)
|
||||
d->reference(d);
|
||||
|
||||
if (flags & APPLE_GLX_DRAWABLE_LOCK)
|
||||
d->lock(d);
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unlock_drawables_list();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
#ifndef APPLE_GLX_DRAWABLE_H
|
||||
#define APPLE_GLX_DRAWABLE_H
|
||||
|
||||
/* Must be first for:
|
||||
* <rdar://problem/6953344>
|
||||
*/
|
||||
#include "apple_glx_context.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include <GL/glx.h>
|
||||
#define XP_NO_X_HEADERS
|
||||
#include <Xplugin.h>
|
||||
#undef XP_NO_X_HEADERS
|
||||
|
||||
enum
|
||||
{
|
||||
APPLE_GLX_DRAWABLE_SURFACE = 1,
|
||||
APPLE_GLX_DRAWABLE_PBUFFER,
|
||||
APPLE_GLX_DRAWABLE_PIXMAP
|
||||
};
|
||||
|
||||
/* The flag for the find routine. */
|
||||
enum
|
||||
{
|
||||
APPLE_GLX_DRAWABLE_LOCK = 2,
|
||||
APPLE_GLX_DRAWABLE_REFERENCE = 4
|
||||
};
|
||||
|
||||
struct apple_glx_context;
|
||||
struct apple_glx_drawable;
|
||||
|
||||
struct apple_glx_surface
|
||||
{
|
||||
xp_surface_id surface_id;
|
||||
unsigned int uid;
|
||||
bool pending_destroy;
|
||||
};
|
||||
|
||||
struct apple_glx_pbuffer
|
||||
{
|
||||
GLXPbuffer xid; /* our pixmap */
|
||||
int width, height;
|
||||
GLint fbconfigID;
|
||||
CGLPBufferObj buffer_obj;
|
||||
unsigned long event_mask;
|
||||
};
|
||||
|
||||
struct apple_glx_pixmap
|
||||
{
|
||||
GLXPixmap xpixmap;
|
||||
void *buffer;
|
||||
int width, height, pitch, /*bytes per pixel */ bpp;
|
||||
size_t size;
|
||||
char path[PATH_MAX];
|
||||
int fd;
|
||||
CGLPixelFormatObj pixel_format_obj;
|
||||
CGLContextObj context_obj;
|
||||
GLint fbconfigID;
|
||||
};
|
||||
|
||||
struct apple_glx_drawable_callbacks
|
||||
{
|
||||
int type;
|
||||
bool(*make_current) (struct apple_glx_context * ac,
|
||||
struct apple_glx_drawable * d);
|
||||
void (*destroy) (Display * dpy, struct apple_glx_drawable * d);
|
||||
};
|
||||
|
||||
struct apple_glx_drawable
|
||||
{
|
||||
Display *display;
|
||||
int reference_count;
|
||||
GLXDrawable drawable;
|
||||
int type; /* APPLE_GLX_DRAWABLE_* */
|
||||
|
||||
union
|
||||
{
|
||||
struct apple_glx_pixmap pixmap;
|
||||
struct apple_glx_pbuffer pbuffer;
|
||||
struct apple_glx_surface surface;
|
||||
} types;
|
||||
|
||||
struct apple_glx_drawable_callbacks callbacks;
|
||||
|
||||
/*
|
||||
* This mutex protects the reference count and any other drawable data.
|
||||
* It's used to prevent an early release of a drawable.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
void (*lock) (struct apple_glx_drawable * agd);
|
||||
void (*unlock) (struct apple_glx_drawable * agd);
|
||||
|
||||
void (*reference) (struct apple_glx_drawable * agd);
|
||||
void (*release) (struct apple_glx_drawable * agd);
|
||||
|
||||
bool(*destroy) (struct apple_glx_drawable * agd);
|
||||
|
||||
bool(*is_pbuffer) (struct apple_glx_drawable * agd);
|
||||
|
||||
bool(*is_pixmap) (struct apple_glx_drawable * agd);
|
||||
|
||||
/*BEGIN These are used for the mixed mode drawing... */
|
||||
int width, height;
|
||||
int row_bytes;
|
||||
char path[PATH_MAX];
|
||||
int fd; /* The file descriptor for this drawable's shared memory. */
|
||||
void *buffer; /* The memory for the drawable. Typically shared memory. */
|
||||
size_t buffer_length;
|
||||
/*END*/ struct apple_glx_drawable *previous, *next;
|
||||
};
|
||||
|
||||
struct apple_glx_context;
|
||||
|
||||
/* May return NULL if not found */
|
||||
struct apple_glx_drawable *apple_glx_find_drawable(Display * dpy,
|
||||
GLXDrawable drawable);
|
||||
|
||||
/* Returns true on error and locks the agd result with a reference. */
|
||||
bool apple_glx_drawable_create(Display * dpy,
|
||||
int screen,
|
||||
GLXDrawable drawable,
|
||||
struct apple_glx_drawable **agd,
|
||||
struct apple_glx_drawable_callbacks
|
||||
*callbacks);
|
||||
|
||||
/* Returns true on error */
|
||||
bool apple_glx_create_drawable(Display * dpy,
|
||||
struct apple_glx_context *ac,
|
||||
GLXDrawable drawable,
|
||||
struct apple_glx_drawable **agd);
|
||||
|
||||
void apple_glx_garbage_collect_drawables(Display * dpy);
|
||||
|
||||
/*
|
||||
* This returns the total number of drawables.
|
||||
* It's mostly intended for debugging and introspection.
|
||||
*/
|
||||
unsigned int apple_glx_get_drawable_count(void);
|
||||
|
||||
struct apple_glx_drawable *apple_glx_drawable_find_by_type(GLXDrawable
|
||||
drawable, int type,
|
||||
int flags);
|
||||
|
||||
struct apple_glx_drawable *apple_glx_drawable_find(GLXDrawable drawable,
|
||||
int flags);
|
||||
|
||||
|
||||
bool apple_glx_drawable_destroy_by_type(Display * dpy, GLXDrawable drawable,
|
||||
int type);
|
||||
|
||||
struct apple_glx_drawable *apple_glx_drawable_find_by_uid(unsigned int uid,
|
||||
int flags);
|
||||
|
||||
/* Surfaces */
|
||||
|
||||
bool apple_glx_surface_create(Display * dpy, int screen, GLXDrawable drawable,
|
||||
struct apple_glx_drawable **resultptr);
|
||||
|
||||
void apple_glx_surface_destroy(unsigned int uid);
|
||||
|
||||
/* Pbuffers */
|
||||
|
||||
/* Returns true if an error occurred. */
|
||||
bool apple_glx_pbuffer_create(Display * dpy, GLXFBConfig config,
|
||||
int width, int height, int *errorcode,
|
||||
GLXPbuffer * pbuf);
|
||||
|
||||
/* Returns true if the pbuffer was invalid. */
|
||||
bool apple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf);
|
||||
|
||||
/* Returns true if the pbuffer was valid and the attribute. */
|
||||
bool apple_glx_pbuffer_query(GLXDrawable d, int attribute,
|
||||
unsigned int *value);
|
||||
|
||||
/* Returns true if the GLXDrawable is a valid GLXPbuffer, and the mask is set. */
|
||||
bool apple_glx_pbuffer_set_event_mask(GLXDrawable d, unsigned long mask);
|
||||
|
||||
/* Returns true if the GLXDrawable is a valid GLXPbuffer, and the *mask is set. */
|
||||
bool apple_glx_pbuffer_get_event_mask(GLXDrawable d, unsigned long *mask);
|
||||
|
||||
|
||||
/* Pixmaps */
|
||||
|
||||
/* mode is a struct glx_config * */
|
||||
/* Returns true if an error occurred. */
|
||||
bool apple_glx_pixmap_create(Display * dpy, int screen, Pixmap pixmap,
|
||||
const void *mode);
|
||||
|
||||
/* Returns true if an error occurred. */
|
||||
bool apple_glx_pixmap_destroy(Display * dpy, Pixmap pixmap);
|
||||
|
||||
bool apple_glx_pixmap_query(GLXPixmap pixmap, int attribute,
|
||||
unsigned int *value);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Apple Inc.
|
||||
*
|
||||
* 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 THE ABOVE LISTED COPYRIGHT
|
||||
* HOLDER(S) 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.
|
||||
*
|
||||
* Except as contained in this notice, the name(s) of the above
|
||||
* copyright holders shall not be used in advertising or otherwise to
|
||||
* promote the sale, use or other dealings in this Software without
|
||||
* prior written authorization.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <asl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx_log.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
static aslclient aslc;
|
||||
|
||||
void apple_glx_log_init(void) {
|
||||
aslc = asl_open(NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void _apple_glx_log(int level, const char *file, const char *function,
|
||||
int line, const char *fmt, ...) {
|
||||
va_list v;
|
||||
va_start(v, fmt);
|
||||
_apple_glx_vlog(level, file, function, line, fmt, v);
|
||||
va_end(v);
|
||||
}
|
||||
|
||||
static const char *
|
||||
_asl_level_string(int level)
|
||||
{
|
||||
if (level == ASL_LEVEL_EMERG) return ASL_STRING_EMERG;
|
||||
if (level == ASL_LEVEL_ALERT) return ASL_STRING_ALERT;
|
||||
if (level == ASL_LEVEL_CRIT) return ASL_STRING_CRIT;
|
||||
if (level == ASL_LEVEL_ERR) return ASL_STRING_ERR;
|
||||
if (level == ASL_LEVEL_WARNING) return ASL_STRING_WARNING;
|
||||
if (level == ASL_LEVEL_NOTICE) return ASL_STRING_NOTICE;
|
||||
if (level == ASL_LEVEL_INFO) return ASL_STRING_INFO;
|
||||
if (level == ASL_LEVEL_DEBUG) return ASL_STRING_DEBUG;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void _apple_glx_vlog(int level, const char *file, const char *function,
|
||||
int line, const char *fmt, va_list args) {
|
||||
aslmsg msg;
|
||||
uint64_t thread = 0;
|
||||
|
||||
if (pthread_is_threaded_np()) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
|
||||
thread = (uint64_t)(uintptr_t)pthread_self();
|
||||
#elif MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||
if (&pthread_threadid_np) {
|
||||
pthread_threadid_np(NULL, &thread);
|
||||
} else {
|
||||
thread = (uint64_t)(uintptr_t)pthread_self();
|
||||
}
|
||||
#else
|
||||
pthread_threadid_np(NULL, &thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
DebugMessageF("%-9s %24s:%-4d %s(%"PRIu64"): ",
|
||||
_asl_level_string(level), file, line, function, thread);
|
||||
|
||||
msg = asl_new(ASL_TYPE_MSG);
|
||||
if (msg) {
|
||||
if (file)
|
||||
asl_set(msg, "File", file);
|
||||
if (function)
|
||||
asl_set(msg, "Function", function);
|
||||
if (line) {
|
||||
char *_line;
|
||||
asprintf(&_line, "%d", line);
|
||||
if (_line) {
|
||||
asl_set(msg, "Line", _line);
|
||||
free(_line);
|
||||
}
|
||||
}
|
||||
if (pthread_is_threaded_np()) {
|
||||
char *_thread;
|
||||
asprintf(&_thread, "%"PRIu64, thread);
|
||||
if (_thread) {
|
||||
asl_set(msg, "Thread", _thread);
|
||||
free(_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asl_vlog(aslc, msg, level, fmt, args);
|
||||
if (msg)
|
||||
asl_free(msg);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Apple Inc.
|
||||
*
|
||||
* 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 THE ABOVE LISTED COPYRIGHT
|
||||
* HOLDER(S) 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.
|
||||
*
|
||||
* Except as contained in this notice, the name(s) of the above
|
||||
* copyright holders shall not be used in advertising or otherwise to
|
||||
* promote the sale, use or other dealings in this Software without
|
||||
* prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_GLX_LOG_H
|
||||
#define APPLE_GLX_LOG_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <asl.h>
|
||||
|
||||
void apple_glx_log_init(void);
|
||||
|
||||
__printflike(5, 6)
|
||||
void _apple_glx_log(int level, const char *file, const char *function,
|
||||
int line, const char *fmt, ...);
|
||||
#define apple_glx_log(l, f, args ...) \
|
||||
_apple_glx_log(l, __FILE__, __func__, __LINE__, f, ## args)
|
||||
|
||||
|
||||
__printflike(5, 0)
|
||||
void _apple_glx_vlog(int level, const char *file, const char *function,
|
||||
int line, const char *fmt, va_list v);
|
||||
#define apple_glx_vlog(l, f, v) \
|
||||
_apple_glx_vlog(l, __FILE__, __func__, __LINE__, f, v)
|
||||
|
||||
/* This is just here to help the transition.
|
||||
* TODO: Replace calls to apple_glx_diagnostic
|
||||
*/
|
||||
#define apple_glx_diagnostic(f, args ...) \
|
||||
apple_glx_log(ASL_LEVEL_DEBUG, f, ## args)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
Copyright (c) 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
/* Must be before OpenGL.framework is included. Remove once fixed:
|
||||
* <rdar://problem/7872773>
|
||||
*/
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#define __gltypes_h_ 1
|
||||
|
||||
/* Must be first for:
|
||||
* <rdar://problem/6953344>
|
||||
*/
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_glx_drawable.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx.h"
|
||||
#include "glxconfig.h"
|
||||
#include "apple_cgl.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
/* mesa defines in glew.h, Apple in glext.h.
|
||||
* Due to namespace nightmares, just do it here.
|
||||
*/
|
||||
#ifndef GL_TEXTURE_RECTANGLE_EXT
|
||||
#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
|
||||
#endif
|
||||
|
||||
static bool pbuffer_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d);
|
||||
|
||||
static void pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d);
|
||||
|
||||
static struct apple_glx_drawable_callbacks callbacks = {
|
||||
.type = APPLE_GLX_DRAWABLE_PBUFFER,
|
||||
.make_current = pbuffer_make_current,
|
||||
.destroy = pbuffer_destroy
|
||||
};
|
||||
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
pbuffer_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
|
||||
CGLError cglerr;
|
||||
|
||||
assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
|
||||
|
||||
cglerr = apple_cgl.set_pbuffer(ac->context_obj, pbuf->buffer_obj, 0, 0, 0);
|
||||
|
||||
if (kCGLNoError != cglerr) {
|
||||
fprintf(stderr, "set_pbuffer: %s\n", apple_cgl.error_string(cglerr));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ac->made_current) {
|
||||
apple_glapi_oglfw_viewport_scissor(0, 0, pbuf->width, pbuf->height);
|
||||
ac->made_current = true;
|
||||
}
|
||||
|
||||
apple_glx_diagnostic("made pbuffer drawable 0x%lx current\n", d->drawable);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
pbuffer_destroy(Display * dpy, struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_pbuffer *pbuf = &d->types.pbuffer;
|
||||
|
||||
assert(APPLE_GLX_DRAWABLE_PBUFFER == d->type);
|
||||
|
||||
apple_glx_diagnostic("destroying pbuffer for drawable 0x%lx\n",
|
||||
d->drawable);
|
||||
|
||||
apple_cgl.destroy_pbuffer(pbuf->buffer_obj);
|
||||
XFreePixmap(dpy, pbuf->xid);
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
apple_glx_pbuffer_destroy(Display * dpy, GLXPbuffer pbuf)
|
||||
{
|
||||
return !apple_glx_drawable_destroy_by_type(dpy, pbuf,
|
||||
APPLE_GLX_DRAWABLE_PBUFFER);
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
apple_glx_pbuffer_create(Display * dpy, GLXFBConfig config,
|
||||
int width, int height, int *errorcode,
|
||||
GLXPbuffer * result)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
struct apple_glx_pbuffer *pbuf = NULL;
|
||||
CGLError err;
|
||||
Window root;
|
||||
int screen;
|
||||
Pixmap xid;
|
||||
struct glx_config *modes = (struct glx_config *) config;
|
||||
|
||||
root = DefaultRootWindow(dpy);
|
||||
screen = DefaultScreen(dpy);
|
||||
|
||||
/*
|
||||
* This pixmap is only used for a persistent XID.
|
||||
* The XC-MISC extension cleans up XIDs and reuses them transparently,
|
||||
* so we need to retain a server-side reference.
|
||||
*/
|
||||
xid = XCreatePixmap(dpy, root, (unsigned int) 1,
|
||||
(unsigned int) 1, DefaultDepth(dpy, screen));
|
||||
|
||||
if (None == xid) {
|
||||
*errorcode = BadAlloc;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (apple_glx_drawable_create(dpy, screen, xid, &d, &callbacks)) {
|
||||
*errorcode = BadAlloc;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The lock is held in d from create onward. */
|
||||
pbuf = &d->types.pbuffer;
|
||||
|
||||
pbuf->xid = xid;
|
||||
pbuf->width = width;
|
||||
pbuf->height = height;
|
||||
|
||||
err = apple_cgl.create_pbuffer(width, height, GL_TEXTURE_RECTANGLE_EXT,
|
||||
(modes->alphaBits > 0) ? GL_RGBA : GL_RGB,
|
||||
0, &pbuf->buffer_obj);
|
||||
|
||||
if (kCGLNoError != err) {
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
*errorcode = BadMatch;
|
||||
return true;
|
||||
}
|
||||
|
||||
pbuf->fbconfigID = modes->fbconfigID;
|
||||
|
||||
pbuf->event_mask = 0;
|
||||
|
||||
*result = pbuf->xid;
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
static bool
|
||||
get_max_size(int *widthresult, int *heightresult)
|
||||
{
|
||||
CGLContextObj oldcontext;
|
||||
GLint ar[2];
|
||||
|
||||
oldcontext = apple_cgl.get_current_context();
|
||||
|
||||
if (!oldcontext) {
|
||||
/*
|
||||
* There is no current context, so we need to make one in order
|
||||
* to call glGetInteger.
|
||||
*/
|
||||
CGLPixelFormatObj pfobj;
|
||||
CGLError err;
|
||||
CGLPixelFormatAttribute attr[10];
|
||||
int c = 0;
|
||||
GLint vsref = 0;
|
||||
CGLContextObj newcontext;
|
||||
|
||||
attr[c++] = kCGLPFAColorSize;
|
||||
attr[c++] = 32;
|
||||
attr[c++] = 0;
|
||||
|
||||
err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref);
|
||||
if (kCGLNoError != err) {
|
||||
DebugMessageF("choose_pixel_format error in %s: %s\n", __func__,
|
||||
apple_cgl.error_string(err));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
err = apple_cgl.create_context(pfobj, NULL, &newcontext);
|
||||
|
||||
if (kCGLNoError != err) {
|
||||
DebugMessageF("create_context error in %s: %s\n", __func__,
|
||||
apple_cgl.error_string(err));
|
||||
|
||||
apple_cgl.destroy_pixel_format(pfobj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
err = apple_cgl.set_current_context(newcontext);
|
||||
|
||||
if (kCGLNoError != err) {
|
||||
DebugMessageF("set_current_context error in %s: %s\n", __func__,
|
||||
apple_cgl.error_string(err));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
|
||||
|
||||
apple_cgl.set_current_context(oldcontext);
|
||||
apple_cgl.destroy_context(newcontext);
|
||||
apple_cgl.destroy_pixel_format(pfobj);
|
||||
}
|
||||
else {
|
||||
/* We have a valid context. */
|
||||
|
||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, ar);
|
||||
}
|
||||
|
||||
*widthresult = ar[0];
|
||||
*heightresult = ar[1];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_pbuffer_query(GLXPbuffer p, int attr, unsigned int *value)
|
||||
{
|
||||
bool result = false;
|
||||
struct apple_glx_drawable *d;
|
||||
struct apple_glx_pbuffer *pbuf;
|
||||
|
||||
d = apple_glx_drawable_find_by_type(p, APPLE_GLX_DRAWABLE_PBUFFER,
|
||||
APPLE_GLX_DRAWABLE_LOCK);
|
||||
|
||||
if (d) {
|
||||
pbuf = &d->types.pbuffer;
|
||||
|
||||
switch (attr) {
|
||||
case GLX_WIDTH:
|
||||
*value = pbuf->width;
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GLX_HEIGHT:
|
||||
*value = pbuf->height;
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GLX_PRESERVED_CONTENTS:
|
||||
*value = true;
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GLX_LARGEST_PBUFFER:{
|
||||
int width, height;
|
||||
if (get_max_size(&width, &height)) {
|
||||
fprintf(stderr, "internal error: "
|
||||
"unable to find the largest pbuffer!\n");
|
||||
}
|
||||
else {
|
||||
*value = width;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GLX_FBCONFIG_ID:
|
||||
*value = pbuf->fbconfigID;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_pbuffer_set_event_mask(GLXDrawable drawable, unsigned long mask)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
bool result = false;
|
||||
|
||||
d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
|
||||
APPLE_GLX_DRAWABLE_LOCK);
|
||||
|
||||
if (d) {
|
||||
d->types.pbuffer.event_mask = mask;
|
||||
result = true;
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_pbuffer_get_event_mask(GLXDrawable drawable, unsigned long *mask)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
bool result = false;
|
||||
|
||||
d = apple_glx_drawable_find_by_type(drawable, APPLE_GLX_DRAWABLE_PBUFFER,
|
||||
APPLE_GLX_DRAWABLE_LOCK);
|
||||
if (d) {
|
||||
*mask = d->types.pbuffer.event_mask;
|
||||
result = true;
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright (c) 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include "apple_glx.h"
|
||||
#include "apple_cgl.h"
|
||||
#include "apple_visual.h"
|
||||
#include "apple_glx_drawable.h"
|
||||
#include "appledri.h"
|
||||
#include "glxconfig.h"
|
||||
|
||||
static bool pixmap_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d);
|
||||
|
||||
static void pixmap_destroy(Display * dpy, struct apple_glx_drawable *d);
|
||||
|
||||
static struct apple_glx_drawable_callbacks callbacks = {
|
||||
.type = APPLE_GLX_DRAWABLE_PIXMAP,
|
||||
.make_current = pixmap_make_current,
|
||||
.destroy = pixmap_destroy
|
||||
};
|
||||
|
||||
static bool
|
||||
pixmap_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d)
|
||||
{
|
||||
CGLError cglerr;
|
||||
struct apple_glx_pixmap *p = &d->types.pixmap;
|
||||
|
||||
assert(APPLE_GLX_DRAWABLE_PIXMAP == d->type);
|
||||
|
||||
cglerr = apple_cgl.set_current_context(p->context_obj);
|
||||
|
||||
if (kCGLNoError != cglerr) {
|
||||
fprintf(stderr, "set current context: %s\n",
|
||||
apple_cgl.error_string(cglerr));
|
||||
return true;
|
||||
}
|
||||
|
||||
cglerr = apple_cgl.set_off_screen(p->context_obj, p->width, p->height,
|
||||
p->pitch, p->buffer);
|
||||
|
||||
if (kCGLNoError != cglerr) {
|
||||
fprintf(stderr, "set off screen: %s\n", apple_cgl.error_string(cglerr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ac->made_current) {
|
||||
apple_glapi_oglfw_viewport_scissor(0, 0, p->width, p->height);
|
||||
ac->made_current = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
pixmap_destroy(Display * dpy, struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_pixmap *p = &d->types.pixmap;
|
||||
|
||||
if (p->pixel_format_obj)
|
||||
(void) apple_cgl.destroy_pixel_format(p->pixel_format_obj);
|
||||
|
||||
if (p->context_obj)
|
||||
(void) apple_cgl.destroy_context(p->context_obj);
|
||||
|
||||
XAppleDRIDestroyPixmap(dpy, p->xpixmap);
|
||||
|
||||
if (p->buffer) {
|
||||
if (munmap(p->buffer, p->size))
|
||||
perror("munmap");
|
||||
|
||||
if (-1 == close(p->fd))
|
||||
perror("close");
|
||||
|
||||
if (shm_unlink(p->path))
|
||||
perror("shm_unlink");
|
||||
}
|
||||
|
||||
apple_glx_diagnostic("destroyed pixmap buffer for: 0x%lx\n", d->drawable);
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
bool
|
||||
apple_glx_pixmap_create(Display * dpy, int screen, Pixmap pixmap,
|
||||
const void *mode)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
struct apple_glx_pixmap *p;
|
||||
bool double_buffered;
|
||||
bool uses_stereo;
|
||||
CGLError error;
|
||||
const struct glx_config *cmodes = mode;
|
||||
|
||||
if (apple_glx_drawable_create(dpy, screen, pixmap, &d, &callbacks))
|
||||
return true;
|
||||
|
||||
/* d is locked and referenced at this point. */
|
||||
|
||||
p = &d->types.pixmap;
|
||||
|
||||
p->xpixmap = pixmap;
|
||||
p->buffer = NULL;
|
||||
|
||||
if (!XAppleDRICreatePixmap(dpy, screen, pixmap,
|
||||
&p->width, &p->height, &p->pitch, &p->bpp,
|
||||
&p->size, p->path, PATH_MAX)) {
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->fd = shm_open(p->path, O_RDWR, 0);
|
||||
|
||||
if (p->fd < 0) {
|
||||
perror("shm_open");
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->buffer = mmap(NULL, p->size, PROT_READ | PROT_WRITE,
|
||||
MAP_FILE | MAP_SHARED, p->fd, 0);
|
||||
|
||||
if (MAP_FAILED == p->buffer) {
|
||||
perror("mmap");
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
apple_visual_create_pfobj(&p->pixel_format_obj, mode, &double_buffered,
|
||||
&uses_stereo, /*offscreen */ true);
|
||||
|
||||
error = apple_cgl.create_context(p->pixel_format_obj, NULL,
|
||||
&p->context_obj);
|
||||
|
||||
if (kCGLNoError != error) {
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->fbconfigID = cmodes->fbconfigID;
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
apple_glx_diagnostic("created: pixmap buffer for 0x%lx\n", d->drawable);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
apple_glx_pixmap_query(GLXPixmap pixmap, int attr, unsigned int *value)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
struct apple_glx_pixmap *p;
|
||||
bool result = false;
|
||||
|
||||
d = apple_glx_drawable_find_by_type(pixmap, APPLE_GLX_DRAWABLE_PIXMAP,
|
||||
APPLE_GLX_DRAWABLE_LOCK);
|
||||
|
||||
if (d) {
|
||||
p = &d->types.pixmap;
|
||||
|
||||
switch (attr) {
|
||||
case GLX_WIDTH:
|
||||
*value = p->width;
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GLX_HEIGHT:
|
||||
*value = p->height;
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GLX_FBCONFIG_ID:
|
||||
*value = p->fbconfigID;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
d->unlock(d);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return true if the type is valid for pixmap. */
|
||||
bool
|
||||
apple_glx_pixmap_destroy(Display * dpy, GLXPixmap pixmap)
|
||||
{
|
||||
return !apple_glx_drawable_destroy_by_type(dpy, pixmap,
|
||||
APPLE_GLX_DRAWABLE_PIXMAP);
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
Copyright (c) 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx.h"
|
||||
#include "appledri.h"
|
||||
#include "apple_glx_drawable.h"
|
||||
|
||||
static bool surface_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d);
|
||||
|
||||
static void surface_destroy(Display * dpy, struct apple_glx_drawable *d);
|
||||
|
||||
|
||||
static struct apple_glx_drawable_callbacks callbacks = {
|
||||
.type = APPLE_GLX_DRAWABLE_SURFACE,
|
||||
.make_current = surface_make_current,
|
||||
.destroy = surface_destroy
|
||||
};
|
||||
|
||||
static void
|
||||
update_viewport_and_scissor(Display * dpy, GLXDrawable drawable)
|
||||
{
|
||||
Window root;
|
||||
int x, y;
|
||||
unsigned int width = 0, height = 0, bd, depth;
|
||||
|
||||
XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth);
|
||||
|
||||
apple_glapi_oglfw_viewport_scissor(0, 0, width, height);
|
||||
}
|
||||
|
||||
static bool
|
||||
surface_make_current(struct apple_glx_context *ac,
|
||||
struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_surface *s = &d->types.surface;
|
||||
xp_error error;
|
||||
|
||||
assert(APPLE_GLX_DRAWABLE_SURFACE == d->type);
|
||||
|
||||
apple_glx_diagnostic("%s: ac->context_obj %p s->surface_id %u\n",
|
||||
__func__, (void *) ac->context_obj, s->surface_id);
|
||||
|
||||
error = xp_attach_gl_context(ac->context_obj, s->surface_id);
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "error: xp_attach_gl_context returned: %d\n", error);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!ac->made_current) {
|
||||
/*
|
||||
* The first time a new context is made current the glViewport
|
||||
* and glScissor should be updated.
|
||||
*/
|
||||
update_viewport_and_scissor(ac->drawable->display,
|
||||
ac->drawable->drawable);
|
||||
ac->made_current = true;
|
||||
}
|
||||
|
||||
apple_glx_diagnostic("%s: drawable 0x%lx\n", __func__, d->drawable);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_destroy(Display * dpy, struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_surface *s = &d->types.surface;
|
||||
|
||||
apple_glx_diagnostic("%s: s->surface_id %u\n", __func__, s->surface_id);
|
||||
|
||||
xp_error error = xp_destroy_surface(s->surface_id);
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "xp_destroy_surface error: %d\n", (int) error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this surface destroy came from the surface being destroyed
|
||||
* on the server. If s->pending_destroy is true, then it did, and
|
||||
* we don't want to try to destroy the surface on the server.
|
||||
*/
|
||||
if (!s->pending_destroy) {
|
||||
/*
|
||||
* Warning: this causes other routines to be called (potentially)
|
||||
* from surface_notify_handler. It's probably best to not have
|
||||
* any locks at this point locked.
|
||||
*/
|
||||
XAppleDRIDestroySurface(d->display, DefaultScreen(d->display),
|
||||
d->drawable);
|
||||
|
||||
apple_glx_diagnostic
|
||||
("%s: destroyed a surface for drawable 0x%lx uid %u\n", __func__,
|
||||
d->drawable, s->uid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
static bool
|
||||
create_surface(Display * dpy, int screen, struct apple_glx_drawable *d)
|
||||
{
|
||||
struct apple_glx_surface *s = &d->types.surface;
|
||||
unsigned int key[2];
|
||||
xp_client_id id;
|
||||
|
||||
id = apple_glx_get_client_id();
|
||||
if (0 == id)
|
||||
return true;
|
||||
|
||||
assert(None != d->drawable);
|
||||
|
||||
s->pending_destroy = false;
|
||||
|
||||
if (XAppleDRICreateSurface(dpy, screen, d->drawable, id, key, &s->uid)) {
|
||||
xp_error error;
|
||||
|
||||
error = xp_import_surface(key, &s->surface_id);
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "error: xp_import_surface returned: %d\n", error);
|
||||
return true;
|
||||
}
|
||||
|
||||
apple_glx_diagnostic("%s: created a surface for drawable 0x%lx"
|
||||
" with uid %u\n", __func__, d->drawable, s->uid);
|
||||
return false; /*success */
|
||||
}
|
||||
|
||||
return true; /* unable to create a surface. */
|
||||
}
|
||||
|
||||
/* Return true if an error occurred. */
|
||||
/* This returns a referenced object via resultptr. */
|
||||
bool
|
||||
apple_glx_surface_create(Display * dpy, int screen,
|
||||
GLXDrawable drawable,
|
||||
struct apple_glx_drawable ** resultptr)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
if (apple_glx_drawable_create(dpy, screen, drawable, &d, &callbacks))
|
||||
return true;
|
||||
|
||||
/* apple_glx_drawable_create creates a locked and referenced object. */
|
||||
|
||||
if (create_surface(dpy, screen, d)) {
|
||||
d->unlock(d);
|
||||
d->destroy(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
*resultptr = d;
|
||||
|
||||
d->unlock(d);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* All surfaces are reference counted, and surfaces are only created
|
||||
* when the window is made current. When all contexts no longer reference
|
||||
* a surface drawable the apple_glx_drawable gets destroyed, and thus
|
||||
* its surface is destroyed.
|
||||
*
|
||||
* However we can make the destruction occur a bit sooner by setting
|
||||
* pending_destroy, which is then checked for in glViewport by
|
||||
* apple_glx_context_update.
|
||||
*/
|
||||
void
|
||||
apple_glx_surface_destroy(unsigned int uid)
|
||||
{
|
||||
struct apple_glx_drawable *d;
|
||||
|
||||
d = apple_glx_drawable_find_by_uid(uid, APPLE_GLX_DRAWABLE_REFERENCE
|
||||
| APPLE_GLX_DRAWABLE_LOCK);
|
||||
|
||||
if (d) {
|
||||
d->types.surface.pending_destroy = true;
|
||||
d->release(d);
|
||||
|
||||
/*
|
||||
* We release 2 references to the surface. One was acquired by
|
||||
* the find, and the other was leftover from a context, or
|
||||
* the surface being displayed, so the destroy() will decrease it
|
||||
* once more.
|
||||
*
|
||||
* If the surface is in a context, it will take one d->destroy(d);
|
||||
* to actually destroy it when the pending_destroy is processed
|
||||
* by a glViewport callback (see apple_glx_context_update()).
|
||||
*/
|
||||
if (!d->destroy(d)) {
|
||||
/* apple_glx_drawable_find_by_uid returns a locked drawable */
|
||||
d->unlock(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
Copyright (c) 2008, 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <GL/gl.h>
|
||||
#include <util/u_debug.h>
|
||||
|
||||
/* <rdar://problem/6953344> */
|
||||
#define glTexImage1D glTexImage1D_OSX
|
||||
#define glTexImage2D glTexImage2D_OSX
|
||||
#define glTexImage3D glTexImage3D_OSX
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/CGLContext.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#undef glTexImage1D
|
||||
#undef glTexImage2D
|
||||
#undef glTexImage3D
|
||||
|
||||
#ifndef kCGLPFAOpenGLProfile
|
||||
#define kCGLPFAOpenGLProfile 99
|
||||
#endif
|
||||
|
||||
#ifndef kCGLOGLPVersion_3_2_Core
|
||||
#define kCGLOGLPVersion_3_2_Core 0x3200
|
||||
#endif
|
||||
|
||||
#include "apple_cgl.h"
|
||||
#include "apple_visual.h"
|
||||
#include "apple_glx.h"
|
||||
#include "glxconfig.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_ATTR = 60
|
||||
};
|
||||
|
||||
static char __crashreporter_info_buff__[4096] = { 0 };
|
||||
static const char *__crashreporter_info__ __attribute__((__used__)) =
|
||||
&__crashreporter_info_buff__[0];
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
|
||||
// This is actually a toolchain requirement, but I'm not sure the correct check,
|
||||
// but it should be fine to just only include it for Leopard and later. This line
|
||||
// just tells the linker to never strip this symbol (such as for space optimization)
|
||||
__asm__ (".desc ___crashreporter_info__, 0x10");
|
||||
#endif
|
||||
|
||||
void
|
||||
apple_visual_create_pfobj(CGLPixelFormatObj * pfobj, const struct glx_config * mode,
|
||||
bool * double_buffered, bool * uses_stereo,
|
||||
bool offscreen)
|
||||
{
|
||||
CGLPixelFormatAttribute attr[MAX_ATTR];
|
||||
int numattr = 0;
|
||||
GLint vsref = 0;
|
||||
CGLError error = 0;
|
||||
bool use_core_profile = debug_get_bool_option("LIBGL_PROFILE_CORE", false);
|
||||
|
||||
if (offscreen) {
|
||||
apple_glx_diagnostic
|
||||
("offscreen rendering enabled. Using kCGLPFAOffScreen\n");
|
||||
|
||||
attr[numattr++] = kCGLPFAOffScreen;
|
||||
}
|
||||
else if (debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false)) {
|
||||
apple_glx_diagnostic
|
||||
("Software rendering requested. Using kCGLRendererGenericFloatID.\n");
|
||||
attr[numattr++] = kCGLPFARendererID;
|
||||
attr[numattr++] = kCGLRendererGenericFloatID;
|
||||
}
|
||||
else if (debug_get_bool_option("LIBGL_ALLOW_SOFTWARE", false)) {
|
||||
apple_glx_diagnostic
|
||||
("Software rendering is not being excluded. Not using kCGLPFAAccelerated.\n");
|
||||
}
|
||||
else {
|
||||
attr[numattr++] = kCGLPFAAccelerated;
|
||||
}
|
||||
|
||||
/*
|
||||
* The program chose a config based on the fbconfigs or visuals.
|
||||
* Those are based on the attributes from CGL, so we probably
|
||||
* do want the closest match for the color, depth, and accum.
|
||||
*/
|
||||
attr[numattr++] = kCGLPFAClosestPolicy;
|
||||
|
||||
if (mode->stereoMode) {
|
||||
attr[numattr++] = kCGLPFAStereo;
|
||||
*uses_stereo = true;
|
||||
}
|
||||
else {
|
||||
*uses_stereo = false;
|
||||
}
|
||||
|
||||
if (!offscreen && mode->doubleBufferMode) {
|
||||
attr[numattr++] = kCGLPFADoubleBuffer;
|
||||
*double_buffered = true;
|
||||
}
|
||||
else {
|
||||
*double_buffered = false;
|
||||
}
|
||||
|
||||
attr[numattr++] = kCGLPFAColorSize;
|
||||
attr[numattr++] = mode->redBits + mode->greenBits + mode->blueBits;
|
||||
attr[numattr++] = kCGLPFAAlphaSize;
|
||||
attr[numattr++] = mode->alphaBits;
|
||||
|
||||
if ((mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits) > 0) {
|
||||
attr[numattr++] = kCGLPFAAccumSize;
|
||||
attr[numattr++] = mode->accumRedBits + mode->accumGreenBits +
|
||||
mode->accumBlueBits + mode->accumAlphaBits;
|
||||
}
|
||||
|
||||
if (mode->depthBits > 0) {
|
||||
attr[numattr++] = kCGLPFADepthSize;
|
||||
attr[numattr++] = mode->depthBits;
|
||||
}
|
||||
|
||||
if (mode->stencilBits > 0) {
|
||||
attr[numattr++] = kCGLPFAStencilSize;
|
||||
attr[numattr++] = mode->stencilBits;
|
||||
}
|
||||
|
||||
if (mode->sampleBuffers > 0) {
|
||||
attr[numattr++] = kCGLPFAMultisample;
|
||||
attr[numattr++] = kCGLPFASampleBuffers;
|
||||
attr[numattr++] = mode->sampleBuffers;
|
||||
attr[numattr++] = kCGLPFASamples;
|
||||
attr[numattr++] = mode->samples;
|
||||
}
|
||||
|
||||
/* Debugging support for Core profiles to support newer versions of OpenGL */
|
||||
if (use_core_profile) {
|
||||
attr[numattr++] = kCGLPFAOpenGLProfile;
|
||||
attr[numattr++] = kCGLOGLPVersion_3_2_Core;
|
||||
}
|
||||
|
||||
attr[numattr++] = 0;
|
||||
|
||||
assert(numattr < MAX_ATTR);
|
||||
|
||||
error = apple_cgl.choose_pixel_format(attr, pfobj, &vsref);
|
||||
|
||||
if ((error == kCGLBadAttribute || vsref == 0) && use_core_profile) {
|
||||
apple_glx_diagnostic
|
||||
("Trying again without CoreProfile: error=%s, vsref=%d\n", apple_cgl.error_string(error), vsref);
|
||||
|
||||
if (!error)
|
||||
apple_cgl.destroy_pixel_format(*pfobj);
|
||||
|
||||
numattr -= 3;
|
||||
attr[numattr++] = 0;
|
||||
|
||||
error = apple_cgl.choose_pixel_format(attr, pfobj, &vsref);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
snprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__),
|
||||
"CGLChoosePixelFormat error: %s\n", apple_cgl.error_string(error));
|
||||
fprintf(stderr, "%s", __crashreporter_info_buff__);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (!*pfobj) {
|
||||
snprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__),
|
||||
"No matching pixelformats found, perhaps try setting LIBGL_ALLOW_SOFTWARE=true\n");
|
||||
fprintf(stderr, "%s", __crashreporter_info_buff__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (c) 2008 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_VISUAL_H
|
||||
#define APPLE_VISUAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include "glxconfig.h"
|
||||
|
||||
void apple_visual_create_pfobj(CGLPixelFormatObj * pfobj, const struct glx_config * mode,
|
||||
bool * double_buffered, bool * uses_stereo,
|
||||
bool offscreen);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (c) 2011 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef APPLE_XGL_API_H
|
||||
|
||||
void __applegl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, void *pixels);
|
||||
void __applegl_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
|
||||
void __applegl_glDrawBuffer(GLenum mode);
|
||||
void __applegl_glDrawBuffers(GLsizei n, const GLenum * bufs);
|
||||
|
||||
void __applegl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright (c) 2008-2011 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file works with the glXMakeContextCurrent readable drawable.
|
||||
*
|
||||
* The way it works is by swapping the currentDrawable for the currentReadable
|
||||
* drawable if they are different.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_xgl_api.h"
|
||||
#include "glapi.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
extern struct _glapi_table * __ogl_framework_api;
|
||||
|
||||
struct apple_xgl_saved_state
|
||||
{
|
||||
bool swapped;
|
||||
};
|
||||
|
||||
static void
|
||||
SetRead(struct apple_xgl_saved_state *saved)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
/*
|
||||
* By default indicate that the state was not swapped, so that UnsetRead
|
||||
* functions correctly.
|
||||
*/
|
||||
saved->swapped = false;
|
||||
|
||||
/*
|
||||
* If the readable drawable isn't the same as the drawable then
|
||||
* the user has requested a readable drawable with glXMakeContextCurrent().
|
||||
* We emulate this behavior by switching the current drawable.
|
||||
*/
|
||||
if (None != gc->currentReadable
|
||||
&& gc->currentReadable != gc->currentDrawable) {
|
||||
Display *dpy = glXGetCurrentDisplay();
|
||||
|
||||
saved->swapped = true;
|
||||
|
||||
if (apple_glx_make_current_context(dpy, gc->driContext, gc->driContext,
|
||||
gc->currentReadable)) {
|
||||
/* An error occurred, so try to restore the old context state. */
|
||||
(void) apple_glx_make_current_context(dpy, gc->driContext, gc->driContext,
|
||||
gc->currentDrawable);
|
||||
saved->swapped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UnsetRead(struct apple_xgl_saved_state *saved)
|
||||
{
|
||||
if (saved->swapped) {
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
Display *dpy = glXGetCurrentDisplay();
|
||||
|
||||
if (apple_glx_make_current_context(dpy, gc->driContext, gc->driContext,
|
||||
gc->currentDrawable)) {
|
||||
/*
|
||||
* An error occurred restoring the drawable.
|
||||
* It's unclear what to do about that.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__applegl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type, void *pixels)
|
||||
{
|
||||
struct apple_xgl_saved_state saved;
|
||||
|
||||
SetRead(&saved);
|
||||
CALL_ReadPixels(__ogl_framework_api, (x, y, width, height, format, type, pixels));
|
||||
|
||||
UnsetRead(&saved);
|
||||
}
|
||||
|
||||
void
|
||||
__applegl_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
|
||||
{
|
||||
struct apple_xgl_saved_state saved;
|
||||
|
||||
SetRead(&saved);
|
||||
|
||||
CALL_CopyPixels(__ogl_framework_api, (x, y, width, height, type));
|
||||
|
||||
UnsetRead(&saved);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (c) 2009-2011 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
/* This should be removed once stereo hardware bugs are fixed
|
||||
* <rdar://problem/6729006>
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_xgl_api.h"
|
||||
#include "glapi.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
extern struct _glapi_table * __ogl_framework_api;
|
||||
|
||||
/*
|
||||
* These are special functions for stereoscopic support
|
||||
* differences in MacOS X.
|
||||
*/
|
||||
void
|
||||
__applegl_glDrawBuffer(GLenum mode)
|
||||
{
|
||||
struct glx_context * gc = __glXGetCurrentContext();
|
||||
|
||||
if (gc != &dummyContext && apple_glx_context_uses_stereo(gc->driContext)) {
|
||||
GLenum buf[2];
|
||||
GLsizei n = 0;
|
||||
|
||||
switch (mode) {
|
||||
case GL_BACK:
|
||||
buf[0] = GL_BACK_LEFT;
|
||||
buf[1] = GL_BACK_RIGHT;
|
||||
n = 2;
|
||||
break;
|
||||
case GL_FRONT:
|
||||
buf[0] = GL_FRONT_LEFT;
|
||||
buf[1] = GL_FRONT_RIGHT;
|
||||
n = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
buf[0] = mode;
|
||||
n = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
CALL_DrawBuffers(__ogl_framework_api, (n, buf));
|
||||
}
|
||||
else {
|
||||
CALL_DrawBuffer(__ogl_framework_api, (mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__applegl_glDrawBuffers(GLsizei n, const GLenum * bufs)
|
||||
{
|
||||
struct glx_context * gc = __glXGetCurrentContext();
|
||||
|
||||
if (gc != &dummyContext && apple_glx_context_uses_stereo(gc->driContext)) {
|
||||
GLenum newbuf[n + 2];
|
||||
GLsizei i, outi = 0;
|
||||
bool have_back = false;
|
||||
bool have_front = false;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (GL_BACK == bufs[i]) {
|
||||
have_back = true;
|
||||
}
|
||||
else if (GL_FRONT == bufs[i]) {
|
||||
have_back = true;
|
||||
}
|
||||
else {
|
||||
newbuf[outi++] = bufs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (have_back) {
|
||||
newbuf[outi++] = GL_BACK_LEFT;
|
||||
newbuf[outi++] = GL_BACK_RIGHT;
|
||||
}
|
||||
|
||||
if (have_front) {
|
||||
newbuf[outi++] = GL_FRONT_LEFT;
|
||||
newbuf[outi++] = GL_FRONT_RIGHT;
|
||||
}
|
||||
|
||||
CALL_DrawBuffers(__ogl_framework_api, (outi, newbuf));
|
||||
}
|
||||
else {
|
||||
CALL_DrawBuffers(__ogl_framework_api, (n, bufs));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (c) 2009-2011 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "apple_glx_context.h"
|
||||
#include "apple_xgl_api.h"
|
||||
#include "glapi.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
extern struct _glapi_table * __ogl_framework_api;
|
||||
|
||||
void
|
||||
__applegl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
Display *dpy = glXGetCurrentDisplay();
|
||||
|
||||
if (gc != &dummyContext && gc->driContext)
|
||||
apple_glx_context_update(dpy, gc->driContext);
|
||||
|
||||
CALL_Viewport(__ogl_framework_api, (x, y, width, height));
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
/* $XFree86: xc/lib/GL/dri/XF86dri.c,v 1.12 2001/08/27 17:40:57 dawes Exp $ */
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
Copyright 2000 VA Linux Systems, Inc.
|
||||
Copyright (c) 2002, 2008 Apple Computer, 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, sub license, 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 NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Kevin E. Martin <[email protected]>
|
||||
* Jens Owen <[email protected]>
|
||||
* Rickard E. (Rik) Faith <[email protected]>
|
||||
*
|
||||
*/
|
||||
|
||||
/* THIS IS NOT AN X CONSORTIUM STANDARD */
|
||||
|
||||
#include <X11/Xlibint.h>
|
||||
#include "appledristr.h"
|
||||
#include <X11/extensions/Xext.h>
|
||||
#include <X11/extensions/extutil.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static XExtensionInfo _appledri_info_data;
|
||||
static XExtensionInfo *appledri_info = &_appledri_info_data;
|
||||
static char *appledri_extension_name = APPLEDRINAME;
|
||||
|
||||
#define AppleDRICheckExtension(dpy,i,val) \
|
||||
XextCheckExtension (dpy, i, appledri_extension_name, val)
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* private utility routines *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
static int close_display(Display * dpy, XExtCodes * extCodes);
|
||||
static Bool wire_to_event(Display * dpy, XEvent * re, xEvent * event);
|
||||
|
||||
static /* const */ XExtensionHooks appledri_extension_hooks = {
|
||||
NULL, /* create_gc */
|
||||
NULL, /* copy_gc */
|
||||
NULL, /* flush_gc */
|
||||
NULL, /* free_gc */
|
||||
NULL, /* create_font */
|
||||
NULL, /* free_font */
|
||||
close_display, /* close_display */
|
||||
wire_to_event, /* wire_to_event */
|
||||
NULL, /* event_to_wire */
|
||||
NULL, /* error */
|
||||
NULL, /* error_string */
|
||||
};
|
||||
|
||||
static
|
||||
XEXT_GENERATE_FIND_DISPLAY(find_display, appledri_info,
|
||||
appledri_extension_name,
|
||||
&appledri_extension_hooks,
|
||||
AppleDRINumberEvents, NULL)
|
||||
|
||||
static XEXT_GENERATE_CLOSE_DISPLAY(close_display, appledri_info)
|
||||
|
||||
static void (*surface_notify_handler) ();
|
||||
|
||||
void *XAppleDRISetSurfaceNotifyHandler(void (*fun) ())
|
||||
{
|
||||
void *old = surface_notify_handler;
|
||||
surface_notify_handler = fun;
|
||||
return old;
|
||||
}
|
||||
|
||||
static Bool
|
||||
wire_to_event(Display *dpy, XEvent *re, xEvent *event)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRINotifyEvent *sevent;
|
||||
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
switch ((event->u.u.type & 0x7f) - info->codes->first_event) {
|
||||
case AppleDRISurfaceNotify:
|
||||
sevent = (xAppleDRINotifyEvent *) event;
|
||||
if (surface_notify_handler != NULL) {
|
||||
(*surface_notify_handler) (dpy, (unsigned int) sevent->arg,
|
||||
(int) sevent->kind);
|
||||
}
|
||||
return False;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* public Apple-DRI Extension routines *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define TRACE(msg) fprintf(stderr, "AppleDRI%s\n", msg);
|
||||
#else
|
||||
#define TRACE(msg)
|
||||
#endif
|
||||
|
||||
|
||||
Bool
|
||||
XAppleDRIQueryExtension(dpy, event_basep, error_basep)
|
||||
Display *dpy;
|
||||
int *event_basep, *error_basep;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
|
||||
TRACE("QueryExtension...");
|
||||
if (XextHasExtension(info)) {
|
||||
*event_basep = info->codes->first_event;
|
||||
*error_basep = info->codes->first_error;
|
||||
TRACE("QueryExtension... return True");
|
||||
return True;
|
||||
}
|
||||
else {
|
||||
TRACE("QueryExtension... return False");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
|
||||
Display *dpy;
|
||||
int *majorVersion;
|
||||
int *minorVersion;
|
||||
int *patchVersion;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRIQueryVersionReply rep;
|
||||
xAppleDRIQueryVersionReq *req;
|
||||
|
||||
TRACE("QueryVersion...");
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRIQueryVersion, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRIQueryVersion;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryVersion... return False");
|
||||
return False;
|
||||
}
|
||||
*majorVersion = rep.majorVersion;
|
||||
*minorVersion = rep.minorVersion;
|
||||
*patchVersion = rep.patchVersion;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryVersion... return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Bool *isCapable;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRIQueryDirectRenderingCapableReply rep;
|
||||
xAppleDRIQueryDirectRenderingCapableReq *req;
|
||||
|
||||
TRACE("QueryDirectRenderingCapable...");
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRIQueryDirectRenderingCapable, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRIQueryDirectRenderingCapable;
|
||||
req->screen = screen;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDirectRenderingCapable... return False");
|
||||
return False;
|
||||
}
|
||||
*isCapable = rep.isCapable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDirectRenderingCapable... return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRIAuthConnection(dpy, screen, magic)
|
||||
Display *dpy;
|
||||
int screen;
|
||||
unsigned int magic;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRIAuthConnectionReq *req;
|
||||
xAppleDRIAuthConnectionReply rep;
|
||||
|
||||
TRACE("AuthConnection...");
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRIAuthConnection, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRIAuthConnection;
|
||||
req->screen = screen;
|
||||
req->magic = magic;
|
||||
rep.authenticated = 0;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.authenticated) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("AuthConnection... return False");
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("AuthConnection... return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRICreateSurface(dpy, screen, drawable, client_id, key, uid)
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Drawable drawable;
|
||||
unsigned int client_id;
|
||||
unsigned int *key;
|
||||
unsigned int *uid;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRICreateSurfaceReply rep;
|
||||
xAppleDRICreateSurfaceReq *req;
|
||||
|
||||
TRACE("CreateSurface...");
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRICreateSurface, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRICreateSurface;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
req->client_id = client_id;
|
||||
rep.key_0 = rep.key_1 = rep.uid = 0;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse) || !rep.key_0) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("CreateSurface... return False");
|
||||
return False;
|
||||
}
|
||||
key[0] = rep.key_0;
|
||||
key[1] = rep.key_1;
|
||||
*uid = rep.uid;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("CreateSurface... return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRIDestroySurface(dpy, screen, drawable)
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Drawable drawable;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRIDestroySurfaceReq *req;
|
||||
|
||||
TRACE("DestroySurface...");
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRIDestroySurface, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRIDestroySurface;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("DestroySurface... return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRICreateSharedBuffer(Display * dpy, int screen, Drawable drawable,
|
||||
Bool doubleSwap, char *path, size_t pathlen,
|
||||
int *width, int *height)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRICreateSharedBufferReq *req;
|
||||
xAppleDRICreateSharedBufferReply rep;
|
||||
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRICreateSharedBuffer, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRICreateSharedBuffer;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
req->doubleSwap = doubleSwap;
|
||||
|
||||
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
puts("REPLY ERROR");
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
|
||||
/* printf("rep.stringLength %d\n", (int) rep.stringLength); */
|
||||
|
||||
if (rep.stringLength > 0 && rep.stringLength <= pathlen) {
|
||||
_XReadPad(dpy, path, rep.stringLength);
|
||||
|
||||
/* printf("path: %s\n", path); */
|
||||
|
||||
*width = rep.width;
|
||||
*height = rep.height;
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return True;
|
||||
}
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRISwapBuffers(Display * dpy, int screen, Drawable drawable)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRISwapBuffersReq *req;
|
||||
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRISwapBuffers, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRISwapBuffers;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XAppleDRICreatePixmap(Display * dpy, int screen, Drawable drawable,
|
||||
int *width, int *height, int *pitch, int *bpp,
|
||||
size_t * size, char *bufname, size_t bufnamesize)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRICreatePixmapReq *req;
|
||||
xAppleDRICreatePixmapReply rep;
|
||||
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRICreatePixmap, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRICreatePixmap;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("rep.stringLength %d\n", (int) rep.stringLength);
|
||||
*/
|
||||
|
||||
if (rep.stringLength > 0 && rep.stringLength <= bufnamesize) {
|
||||
_XReadPad(dpy, bufname, rep.stringLength);
|
||||
|
||||
/* printf("path: %s\n", bufname); */
|
||||
|
||||
*width = rep.width;
|
||||
*height = rep.height;
|
||||
*pitch = rep.pitch;
|
||||
*bpp = rep.bpp;
|
||||
*size = rep.size;
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return True;
|
||||
}
|
||||
else if (rep.stringLength > 0) {
|
||||
_XEatData(dpy, rep.stringLength);
|
||||
}
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call it a drawable, because we really don't know what it is
|
||||
* until it reaches the server, and we should keep that in mind.
|
||||
*/
|
||||
Bool
|
||||
XAppleDRIDestroyPixmap(Display * dpy, Pixmap drawable)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xAppleDRIDestroyPixmapReq *req;
|
||||
|
||||
AppleDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(AppleDRIDestroyPixmap, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_AppleDRIDestroyPixmap;
|
||||
req->drawable = drawable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* $XFree86: xc/lib/GL/dri/xf86dri.h,v 1.7 2000/12/07 20:26:02 dawes Exp $ */
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
Copyright 2000 VA Linux Systems, Inc.
|
||||
Copyright (c) 2002, 2008, 2009 Apple Computer, 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, sub license, 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 NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Kevin E. Martin <[email protected]>
|
||||
* Jens Owen <[email protected]>
|
||||
* Rickard E. (Rik) Faith <[email protected]>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _APPLEDRI_H_
|
||||
#define _APPLEDRI_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xfuncproto.h>
|
||||
|
||||
#define X_AppleDRIQueryVersion 0
|
||||
#define X_AppleDRIQueryDirectRenderingCapable 1
|
||||
#define X_AppleDRICreateSurface 2
|
||||
#define X_AppleDRIDestroySurface 3
|
||||
#define X_AppleDRIAuthConnection 4
|
||||
#define X_AppleDRICreateSharedBuffer 5
|
||||
#define X_AppleDRISwapBuffers 6
|
||||
#define X_AppleDRICreatePixmap 7
|
||||
#define X_AppleDRIDestroyPixmap 8
|
||||
|
||||
/* Requests up to and including 18 were used in a previous version */
|
||||
|
||||
/* Events */
|
||||
#define AppleDRIObsoleteEvent1 0
|
||||
#define AppleDRIObsoleteEvent2 1
|
||||
#define AppleDRIObsoleteEvent3 2
|
||||
#define AppleDRISurfaceNotify 3
|
||||
#define AppleDRINumberEvents 4
|
||||
|
||||
/* Errors */
|
||||
#define AppleDRIClientNotLocal 0
|
||||
#define AppleDRIOperationNotSupported 1
|
||||
#define AppleDRINumberErrors (AppleDRIOperationNotSupported + 1)
|
||||
|
||||
/* Kinds of SurfaceNotify events: */
|
||||
#define AppleDRISurfaceNotifyChanged 0
|
||||
#define AppleDRISurfaceNotifyDestroyed 1
|
||||
|
||||
#ifndef _APPLEDRI_SERVER_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type; /* of event */
|
||||
unsigned long serial; /* # of last request processed by server */
|
||||
Bool send_event; /* true if this came from a SendEvent request */
|
||||
Display *display; /* Display the event was read from */
|
||||
Window window; /* window of event */
|
||||
Time time; /* server timestamp when event happened */
|
||||
int kind; /* subtype of event */
|
||||
int arg;
|
||||
} XAppleDRINotifyEvent;
|
||||
|
||||
_XFUNCPROTOBEGIN
|
||||
Bool XAppleDRIQueryExtension(Display * dpy, int *event_base,
|
||||
int *error_base);
|
||||
|
||||
Bool XAppleDRIQueryVersion(Display * dpy, int *majorVersion,
|
||||
int *minorVersion, int *patchVersion);
|
||||
|
||||
Bool XAppleDRIQueryDirectRenderingCapable(Display * dpy, int screen,
|
||||
Bool * isCapable);
|
||||
|
||||
void *XAppleDRISetSurfaceNotifyHandler(void (*fun) (Display * dpy,
|
||||
unsigned uid, int kind));
|
||||
|
||||
Bool XAppleDRIAuthConnection(Display * dpy, int screen, unsigned int magic);
|
||||
|
||||
Bool XAppleDRICreateSurface(Display * dpy, int screen, Drawable drawable,
|
||||
unsigned int client_id, unsigned int key[2],
|
||||
unsigned int *uid);
|
||||
|
||||
Bool XAppleDRIDestroySurface(Display * dpy, int screen, Drawable drawable);
|
||||
|
||||
Bool XAppleDRISynchronizeSurfaces(Display * dpy);
|
||||
|
||||
Bool XAppleDRICreateSharedBuffer(Display * dpy, int screen, Drawable drawable,
|
||||
Bool doubleSwap, char *path, size_t pathlen,
|
||||
int *width, int *height);
|
||||
|
||||
Bool XAppleDRISwapBuffers(Display * dpy, int screen, Drawable drawable);
|
||||
|
||||
Bool XAppleDRICreatePixmap(Display * dpy, int screen, Drawable drawable,
|
||||
int *width, int *height, int *pitch, int *bpp,
|
||||
size_t * size, char *bufname, size_t bufnamesize);
|
||||
|
||||
Bool XAppleDRIDestroyPixmap(Display * dpy, Pixmap pixmap);
|
||||
|
||||
_XFUNCPROTOEND
|
||||
#endif /* _APPLEDRI_SERVER_ */
|
||||
#endif /* _APPLEDRI_H_ */
|
||||
@@ -0,0 +1,266 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
Copyright 2000 VA Linux Systems, Inc.
|
||||
Copyright (c) 2002, 2008, 2009 Apple Computer, 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, sub license, 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 NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Kevin E. Martin <[email protected]>
|
||||
* Jens Owen <[email protected]>
|
||||
* Rickard E. (Rik) Fiath <[email protected]>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _APPLEDRISTR_H_
|
||||
#define _APPLEDRISTR_H_
|
||||
|
||||
#include "appledri.h"
|
||||
|
||||
#define APPLEDRINAME "Apple-DRI"
|
||||
|
||||
#define APPLE_DRI_MAJOR_VERSION 1 /* current version numbers */
|
||||
#define APPLE_DRI_MINOR_VERSION 0
|
||||
#define APPLE_DRI_PATCH_VERSION 0
|
||||
|
||||
typedef struct _AppleDRIQueryVersion
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRIQueryVersion */
|
||||
CARD16 length B16;
|
||||
} xAppleDRIQueryVersionReq;
|
||||
#define sz_xAppleDRIQueryVersionReq 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD16 majorVersion B16; /* major version of DRI protocol */
|
||||
CARD16 minorVersion B16; /* minor version of DRI protocol */
|
||||
CARD32 patchVersion B32; /* patch version of DRI protocol */
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xAppleDRIQueryVersionReply;
|
||||
#define sz_xAppleDRIQueryVersionReply 32
|
||||
|
||||
typedef struct _AppleDRIQueryDirectRenderingCapable
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
} xAppleDRIQueryDirectRenderingCapableReq;
|
||||
#define sz_xAppleDRIQueryDirectRenderingCapableReq 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
BOOL isCapable;
|
||||
BOOL pad2;
|
||||
BOOL pad3;
|
||||
BOOL pad4;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
CARD32 pad8 B32;
|
||||
CARD32 pad9 B32;
|
||||
} xAppleDRIQueryDirectRenderingCapableReply;
|
||||
#define sz_xAppleDRIQueryDirectRenderingCapableReply 32
|
||||
|
||||
typedef struct _AppleDRIAuthConnection
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRICloseConnection */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 magic B32;
|
||||
} xAppleDRIAuthConnectionReq;
|
||||
#define sz_xAppleDRIAuthConnectionReq 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type;
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 authenticated B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xAppleDRIAuthConnectionReply;
|
||||
#define zx_xAppleDRIAuthConnectionReply 32
|
||||
|
||||
typedef struct _AppleDRICreateSurface
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRICreateSurface */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 drawable B32;
|
||||
CARD32 client_id B32;
|
||||
} xAppleDRICreateSurfaceReq;
|
||||
#define sz_xAppleDRICreateSurfaceReq 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 key_0 B32;
|
||||
CARD32 key_1 B32;
|
||||
CARD32 uid B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xAppleDRICreateSurfaceReply;
|
||||
#define sz_xAppleDRICreateSurfaceReply 32
|
||||
|
||||
typedef struct _AppleDRIDestroySurface
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRIDestroySurface */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 drawable B32;
|
||||
} xAppleDRIDestroySurfaceReq;
|
||||
#define sz_xAppleDRIDestroySurfaceReq 12
|
||||
|
||||
typedef struct _AppleDRINotify
|
||||
{
|
||||
BYTE type; /* always eventBase + event type */
|
||||
BYTE kind;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 time B32; /* time of change */
|
||||
CARD32 pad1 B32;
|
||||
CARD32 arg B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xAppleDRINotifyEvent;
|
||||
#define sz_xAppleDRINotifyEvent 32
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CARD8 reqType;
|
||||
CARD8 driReqType;
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 drawable B32;
|
||||
BOOL doubleSwap;
|
||||
CARD8 pad1, pad2, pad3;
|
||||
} xAppleDRICreateSharedBufferReq;
|
||||
|
||||
#define sz_xAppleDRICreateSharedBufferReq 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type;
|
||||
BYTE data1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 stringLength B32; /* 0 on error */
|
||||
CARD32 width B32;
|
||||
CARD32 height B32;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
} xAppleDRICreateSharedBufferReply;
|
||||
|
||||
#define sz_xAppleDRICreateSharedBufferReply 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CARD8 reqType;
|
||||
CARD8 driReqType;
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 drawable B32;
|
||||
} xAppleDRISwapBuffersReq;
|
||||
|
||||
#define sz_xAppleDRISwapBuffersReq 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CARD8 reqType; /*1 */
|
||||
CARD8 driReqType; /*2 */
|
||||
CARD16 length B16; /*4 */
|
||||
CARD32 screen B32; /*8 */
|
||||
CARD32 drawable B32; /*12 */
|
||||
} xAppleDRICreatePixmapReq;
|
||||
|
||||
#define sz_xAppleDRICreatePixmapReq 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /*1 */
|
||||
BOOL pad1; /*2 */
|
||||
CARD16 sequenceNumber B16; /*4 */
|
||||
CARD32 length B32; /*8 */
|
||||
CARD32 width B32; /*12 */
|
||||
CARD32 height B32; /*16 */
|
||||
CARD32 pitch B32; /*20 */
|
||||
CARD32 bpp B32; /*24 */
|
||||
CARD32 size B32; /*28 */
|
||||
CARD32 stringLength B32; /*32 */
|
||||
} xAppleDRICreatePixmapReply;
|
||||
|
||||
#define sz_xAppleDRICreatePixmapReply 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CARD8 reqType; /*1 */
|
||||
CARD8 driReqType; /*2 */
|
||||
CARD16 length B16; /*4 */
|
||||
CARD32 drawable B32; /*8 */
|
||||
} xAppleDRIDestroyPixmapReq;
|
||||
|
||||
#define sz_xAppleDRIDestroyPixmapReq 8
|
||||
|
||||
#ifdef _APPLEDRI_SERVER_
|
||||
|
||||
void AppleDRISendEvent(
|
||||
#if NeedFunctionPrototypes
|
||||
int /* type */ ,
|
||||
unsigned int /* mask */ ,
|
||||
int /* which */ ,
|
||||
int /* arg */
|
||||
#endif
|
||||
);
|
||||
|
||||
#endif /* _APPLEDRI_SERVER_ */
|
||||
#endif /* _APPLEDRISTR_H_ */
|
||||
@@ -0,0 +1,231 @@
|
||||
#include "glxclient.h"
|
||||
#include "glxextensions.h"
|
||||
#include "glxconfig.h"
|
||||
|
||||
/*
|
||||
** GLX_SGI_swap_control
|
||||
*/
|
||||
int
|
||||
glXSwapIntervalSGI(int interval)
|
||||
{
|
||||
(void) interval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLX_MESA_swap_control
|
||||
*/
|
||||
int
|
||||
glXSwapIntervalMESA(unsigned int interval)
|
||||
{
|
||||
(void) interval;
|
||||
return GLX_BAD_CONTEXT;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glXGetSwapIntervalMESA(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLX_SGI_video_sync
|
||||
*/
|
||||
int
|
||||
glXGetVideoSyncSGI(unsigned int *count)
|
||||
{
|
||||
(void) count;
|
||||
return GLX_BAD_CONTEXT;
|
||||
}
|
||||
|
||||
int
|
||||
glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
|
||||
{
|
||||
(void) count;
|
||||
return GLX_BAD_CONTEXT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GLX_OML_sync_control
|
||||
*/
|
||||
Bool
|
||||
glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
|
||||
int64_t * ust, int64_t * msc, int64_t * sbc)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) ust;
|
||||
(void) msc;
|
||||
(void) sbc;
|
||||
return False;
|
||||
}
|
||||
|
||||
int64_t
|
||||
glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
|
||||
int64_t target_msc, int64_t divisor, int64_t remainder)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) target_msc;
|
||||
(void) divisor;
|
||||
(void) remainder;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
|
||||
int64_t target_msc, int64_t divisor,
|
||||
int64_t remainder, int64_t * ust,
|
||||
int64_t * msc, int64_t * sbc)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) target_msc;
|
||||
(void) divisor;
|
||||
(void) remainder;
|
||||
(void) ust;
|
||||
(void) msc;
|
||||
(void) sbc;
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
|
||||
int64_t target_sbc, int64_t * ust,
|
||||
int64_t * msc, int64_t * sbc)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) target_sbc;
|
||||
(void) ust;
|
||||
(void) msc;
|
||||
(void) sbc;
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) d;
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
_X_EXPORT GLXPixmap
|
||||
glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
|
||||
Pixmap pixmap, Colormap cmap)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) visual;
|
||||
(void) pixmap;
|
||||
(void) cmap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* GLX_MESA_copy_sub_buffer
|
||||
*/
|
||||
void
|
||||
glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) width;
|
||||
(void) height;
|
||||
}
|
||||
|
||||
|
||||
_X_EXPORT void
|
||||
glXQueryGLXPbufferSGIX(Display * dpy, GLXDrawable drawable,
|
||||
int attribute, unsigned int *value)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) drawable;
|
||||
(void) attribute;
|
||||
(void) value;
|
||||
}
|
||||
|
||||
_X_EXPORT GLXDrawable
|
||||
glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfig config,
|
||||
unsigned int width, unsigned int height,
|
||||
int *attrib_list)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) config;
|
||||
(void) width;
|
||||
(void) height;
|
||||
(void) attrib_list;
|
||||
return None;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* GLX_SGIX_fbconfig */
|
||||
_X_EXPORT int
|
||||
glXGetFBConfigAttribSGIX(Display * dpy, void *config, int a, int *b)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) config;
|
||||
(void) a;
|
||||
(void) b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_X_EXPORT void *
|
||||
glXChooseFBConfigSGIX(Display * dpy, int a, int *b, int *c)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) a;
|
||||
(void) b;
|
||||
(void) c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_X_EXPORT GLXPixmap
|
||||
glXCreateGLXPixmapWithConfigSGIX(Display * dpy, void *config, Pixmap p)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) config;
|
||||
(void) p;
|
||||
return None;
|
||||
}
|
||||
|
||||
_X_EXPORT GLXContext
|
||||
glXCreateContextWithConfigSGIX(Display * dpy, void *config, int a,
|
||||
GLXContext b, Bool c)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) config;
|
||||
(void) a;
|
||||
(void) b;
|
||||
(void) c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_X_EXPORT XVisualInfo *
|
||||
glXGetVisualFromFBConfigSGIX(Display * dpy, void *config)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) config;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_X_EXPORT void *
|
||||
glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * visinfo)
|
||||
{
|
||||
(void) dpy;
|
||||
(void) visinfo;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright © 2017 Jon Turney
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# library for native GL on macos
|
||||
files_libappleglx = files(
|
||||
'apple_cgl.c',
|
||||
'apple_cgl.h',
|
||||
'appledri.c',
|
||||
'appledri.h',
|
||||
'appledristr.h',
|
||||
'apple_glapi.c',
|
||||
'apple_glx.c',
|
||||
'apple_glx_context.c',
|
||||
'apple_glx_context.h',
|
||||
'apple_glx_drawable.c',
|
||||
'apple_glx_drawable.h',
|
||||
'apple_glx.h',
|
||||
'apple_glx_log.c',
|
||||
'apple_glx_log.h',
|
||||
'apple_glx_pbuffer.c',
|
||||
'apple_glx_pixmap.c',
|
||||
'apple_glx_surface.c',
|
||||
'apple_visual.c',
|
||||
'apple_visual.h',
|
||||
'apple_xgl_api.h',
|
||||
'apple_xgl_api_read.c',
|
||||
'apple_xgl_api_stereo.c',
|
||||
'apple_xgl_api_viewport.c',
|
||||
'glx_empty.c',
|
||||
)
|
||||
|
||||
dep_xplugin = null_dep
|
||||
if with_dri_platform == 'apple'
|
||||
dep_xplugin = meson.get_compiler('c').find_library('Xplugin')
|
||||
endif
|
||||
|
||||
libappleglx = static_library(
|
||||
'glxapple',
|
||||
[files_libappleglx, main_dispatch_h],
|
||||
include_directories: [inc_mesa, inc_glx, inc_src, inc_include, inc_glapi, inc_gallium, inc_loader],
|
||||
dependencies: [dep_xext, dep_xplugin],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
build_by_default: false,
|
||||
)
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2011 Apple Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg ([email protected])
|
||||
*/
|
||||
|
||||
#if defined(GLX_USE_APPLEGL)
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "apple/apple_glx_context.h"
|
||||
#include "apple/apple_glx.h"
|
||||
#include "apple/apple_cgl.h"
|
||||
#include "glx_error.h"
|
||||
|
||||
static void
|
||||
applegl_destroy_context(struct glx_context *gc)
|
||||
{
|
||||
apple_glx_destroy_context(&gc->driContext, gc->psc->dpy);
|
||||
}
|
||||
|
||||
static int
|
||||
applegl_bind_context(
|
||||
struct glx_context *gc,
|
||||
GLXDrawable draw, GLXDrawable read)
|
||||
{
|
||||
Display *dpy = gc->psc->dpy;
|
||||
bool error = apple_glx_make_current_context(
|
||||
dpy,
|
||||
NULL,
|
||||
gc ? gc->driContext : NULL, draw);
|
||||
|
||||
apple_glx_diagnostic("%s: error %s\n", __func__, error ? "YES" : "NO");
|
||||
if (error)
|
||||
return 1; /* GLXBadContext is the same as Success (0) */
|
||||
|
||||
apple_mesa_glapi_set_dispatch();
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void
|
||||
applegl_unbind_context(struct glx_context *gc)
|
||||
{
|
||||
Display *dpy;
|
||||
bool error;
|
||||
|
||||
/* If we don't have a context, then we have nothing to unbind */
|
||||
if (!gc)
|
||||
return;
|
||||
|
||||
dpy = gc->psc->dpy;
|
||||
|
||||
error = apple_glx_make_current_context(
|
||||
dpy,
|
||||
(gc != &dummyContext) ? gc->driContext : NULL,
|
||||
NULL, None);
|
||||
|
||||
apple_glx_diagnostic("%s: error %s\n", __func__, error ? "YES" : "NO");
|
||||
}
|
||||
|
||||
static void
|
||||
applegl_wait_gl(struct glx_context *gc)
|
||||
{
|
||||
glFinish();
|
||||
}
|
||||
|
||||
static void
|
||||
applegl_wait_x(struct glx_context *gc)
|
||||
{
|
||||
Display *dpy = gc->psc->dpy;
|
||||
apple_glx_waitx(dpy, gc->driContext);
|
||||
}
|
||||
|
||||
void *
|
||||
applegl_get_proc_address(const char *symbol)
|
||||
{
|
||||
return dlsym(apple_cgl_get_dl_handle(), symbol);
|
||||
}
|
||||
|
||||
static const struct glx_context_vtable applegl_context_vtable = {
|
||||
.destroy = applegl_destroy_context,
|
||||
.bind = applegl_bind_context,
|
||||
.unbind = applegl_unbind_context,
|
||||
.wait_gl = applegl_wait_gl,
|
||||
.wait_x = applegl_wait_x,
|
||||
};
|
||||
|
||||
struct glx_context *
|
||||
applegl_create_context(
|
||||
struct glx_screen *psc,
|
||||
struct glx_config *config,
|
||||
struct glx_context *shareList, int renderType)
|
||||
{
|
||||
struct glx_context *gc;
|
||||
int errorcode;
|
||||
bool x11error;
|
||||
Display *dpy = psc->dpy;
|
||||
int screen = psc->scr;
|
||||
|
||||
/* TODO: Integrate this with apple_glx_create_context and make
|
||||
* struct apple_glx_context inherit from struct glx_context. */
|
||||
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
gc = calloc(1, sizeof(*gc));
|
||||
if (gc == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!glx_context_init(gc, psc, config)) {
|
||||
free(gc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gc->vtable = &applegl_context_vtable;
|
||||
gc->driContext = NULL;
|
||||
|
||||
/* TODO: darwin: Integrate with above to do indirect */
|
||||
if (apple_glx_create_context(&gc->driContext, dpy, screen, config,
|
||||
shareList ? shareList->driContext : NULL,
|
||||
&errorcode, &x11error)) {
|
||||
__glXSendError(dpy, errorcode, 0, X_GLXCreateContext, x11error);
|
||||
gc->vtable->destroy(gc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gc->currentContextTag = -1;
|
||||
gc->config = config;
|
||||
gc->isDirect = GL_TRUE;
|
||||
gc->xid = 1; /* Just something not None, so we know when to destroy
|
||||
* it in MakeContextCurrent. */
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
static const struct glx_screen_vtable applegl_screen_vtable = {
|
||||
.create_context = applegl_create_context,
|
||||
.create_context_attribs = NULL,
|
||||
.query_renderer_integer = NULL,
|
||||
.query_renderer_string = NULL,
|
||||
};
|
||||
|
||||
struct glx_screen *
|
||||
applegl_create_screen(int screen, struct glx_display * priv)
|
||||
{
|
||||
struct glx_screen *psc;
|
||||
|
||||
psc = calloc(1, sizeof *psc);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
glx_screen_init(psc, screen, priv);
|
||||
psc->vtable = &applegl_screen_vtable;
|
||||
|
||||
return psc;
|
||||
}
|
||||
|
||||
int
|
||||
applegl_create_display(struct glx_display *glx_dpy)
|
||||
{
|
||||
if(!apple_init_glx(glx_dpy->dpy))
|
||||
return 1;
|
||||
|
||||
return GLXBadContext;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include "indirect_vertex_array.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
|
||||
static void
|
||||
do_enable_disable(GLenum array, GLboolean val)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
unsigned index = 0;
|
||||
|
||||
if (array == GL_TEXTURE_COORD_ARRAY) {
|
||||
index = __glXGetActiveTextureUnit(state);
|
||||
}
|
||||
|
||||
if (!__glXSetArrayEnable(state, array, index, val)) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glEnableClientState(GLenum array)
|
||||
{
|
||||
do_enable_disable(array, GL_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glDisableClientState(GLenum array)
|
||||
{
|
||||
do_enable_disable(array, GL_FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
void
|
||||
__indirect_glPushClientAttrib(GLuint mask)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
__GLXattribute **spp = gc->attributes.stackPointer, *sp;
|
||||
|
||||
if (spp < &gc->attributes.stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]) {
|
||||
if (!(sp = *spp)) {
|
||||
sp = malloc(sizeof(__GLXattribute));
|
||||
if (sp == NULL) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
*spp = sp;
|
||||
}
|
||||
sp->mask = mask;
|
||||
gc->attributes.stackPointer = spp + 1;
|
||||
if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
|
||||
sp->storePack = state->storePack;
|
||||
sp->storeUnpack = state->storeUnpack;
|
||||
}
|
||||
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
|
||||
__glXPushArrayState(state);
|
||||
}
|
||||
}
|
||||
else {
|
||||
__glXSetError(gc, GL_STACK_OVERFLOW);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glPopClientAttrib(void)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
__GLXattribute **spp = gc->attributes.stackPointer, *sp;
|
||||
GLuint mask;
|
||||
|
||||
if (spp > &gc->attributes.stack[0]) {
|
||||
--spp;
|
||||
sp = *spp;
|
||||
assert(sp != 0);
|
||||
mask = sp->mask;
|
||||
gc->attributes.stackPointer = spp;
|
||||
|
||||
if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
|
||||
state->storePack = sp->storePack;
|
||||
state->storeUnpack = sp->storeUnpack;
|
||||
}
|
||||
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
|
||||
__glXPopArrayState(state);
|
||||
}
|
||||
|
||||
sp->mask = 0;
|
||||
}
|
||||
else {
|
||||
__glXSetError(gc, GL_STACK_UNDERFLOW);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include <xcb/glx.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
void
|
||||
glxSendClientInfo(struct glx_display *glx_dpy, int screen)
|
||||
{
|
||||
const unsigned ext_length = strlen("GLX_ARB_create_context");
|
||||
const unsigned prof_length = strlen("_profile");
|
||||
char *gl_extension_string;
|
||||
int gl_extension_length;
|
||||
xcb_connection_t *c;
|
||||
Bool any_screen_has_ARB_create_context = False;
|
||||
Bool any_screen_has_ARB_create_context_profile = False;
|
||||
unsigned i;
|
||||
/* You need GLX_ARB_create_context_profile to get beyond 3.1 anyway */
|
||||
static const uint32_t gl_versions[] = {
|
||||
2, 1,
|
||||
3, 0,
|
||||
3, 1,
|
||||
};
|
||||
/*
|
||||
* This is weird, but it matches what NVIDIA does/expects. For big-GL
|
||||
* below 3.2 there is no such thing as a "profile", so we name them all
|
||||
* with no profile bits. Except we don't name anything lower than 2.1,
|
||||
* since GLX_ARB_create_context_profile says:
|
||||
*
|
||||
* "Only the highest supported version below 3.0 should be sent, since
|
||||
* OpenGL 2.1 is backwards compatible with all earlier versions."
|
||||
*
|
||||
* In order to also support GLES below 3.2, we name every possible GLES
|
||||
* version with the ES2 bit set, which happens to just mean GLES generally
|
||||
* and not a particular major version. 3.2 happens to be a legal version
|
||||
* number for both big-GL and GLES, so it gets all three bits set.
|
||||
* Everything 3.3 and above is big-GL only so gets the core and compat
|
||||
* bits set.
|
||||
*/
|
||||
static const uint32_t gl_versions_profiles[] = {
|
||||
1, 0, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
1, 1, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
2, 0, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
2, 1, 0x0,
|
||||
3, 0, 0x0,
|
||||
3, 0, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
3, 1, 0x0,
|
||||
3, 1, GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
3, 2, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
|
||||
3, 3, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 0, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 1, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 2, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 3, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 4, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 5, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
4, 6, GLX_CONTEXT_CORE_PROFILE_BIT_ARB |
|
||||
GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
};
|
||||
static const char glx_extensions[] =
|
||||
"GLX_ARB_create_context GLX_ARB_create_context_profile";
|
||||
|
||||
/* There are three possible flavors of the client info structure that the
|
||||
* client could send to the server. The version sent depends on the
|
||||
* combination of GLX versions and extensions supported by the client and
|
||||
* the server. This client only supports GLX version >= 1.3.
|
||||
*
|
||||
* Server supports Client sends
|
||||
* ----------------------------------------------------------------------
|
||||
* GLX version = 1.0 Nothing.
|
||||
*
|
||||
* GLX version >= 1.1 struct GLXClientInfo
|
||||
*
|
||||
* GLX version >= 1.4 and
|
||||
* GLX_ARB_create_context struct glXSetClientInfoARB
|
||||
*
|
||||
* GLX version >= 1.4 and
|
||||
* GLX_ARB_create_context_profile struct glXSetClientInfo2ARB
|
||||
*
|
||||
* GLX_ARB_create_context and GLX_ARB_create_context_profile use FBConfigs,
|
||||
* and these only exist in GLX 1.4 or with GLX_SGIX_fbconfig. I can't
|
||||
* imagine an implementation that supports GLX_SGIX_fbconfig and
|
||||
* GLX_ARB_create_context but not GLX 1.4. Making GLX 1.4 a hard
|
||||
* requirement in this case does not seem like a limitation.
|
||||
*/
|
||||
|
||||
/* Determine whether any screen on the server supports either of the
|
||||
* create-context extensions.
|
||||
*/
|
||||
for (i = 0; i < ScreenCount(glx_dpy->dpy); i++) {
|
||||
struct glx_screen *src = glx_dpy->screens[i];
|
||||
|
||||
if (src == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *haystack = src->serverGLXexts;
|
||||
while (haystack != NULL) {
|
||||
const char *match = strstr(haystack, "GLX_ARB_create_context");
|
||||
|
||||
if (match == NULL)
|
||||
break;
|
||||
|
||||
match += ext_length;
|
||||
|
||||
switch (match[0]) {
|
||||
case '\0':
|
||||
case ' ':
|
||||
any_screen_has_ARB_create_context = True;
|
||||
break;
|
||||
|
||||
case '_':
|
||||
if (strncmp(match, "_profile", prof_length) == 0
|
||||
&& (match[prof_length] == '\0'
|
||||
|| match[prof_length] == ' ')) {
|
||||
any_screen_has_ARB_create_context_profile = True;
|
||||
match += prof_length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
haystack = match;
|
||||
}
|
||||
}
|
||||
|
||||
gl_extension_string = __glXGetClientGLExtensionString(screen);
|
||||
gl_extension_length = strlen(gl_extension_string) + 1;
|
||||
|
||||
c = XGetXCBConnection(glx_dpy->dpy);
|
||||
|
||||
/* Depending on the GLX version and the available extensions on the server,
|
||||
* send the correct "flavor" of protocol to the server.
|
||||
*
|
||||
* THE ORDER IS IMPORTANT. We want to send the most recent version of the
|
||||
* protocol that the server can support.
|
||||
*/
|
||||
if (glx_dpy->minorVersion == 4
|
||||
&& any_screen_has_ARB_create_context_profile) {
|
||||
xcb_glx_set_client_info_2arb(c,
|
||||
GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
|
||||
sizeof(gl_versions_profiles)
|
||||
/ (3 * sizeof(gl_versions_profiles[0])),
|
||||
gl_extension_length,
|
||||
strlen(glx_extensions) + 1,
|
||||
gl_versions_profiles,
|
||||
gl_extension_string,
|
||||
glx_extensions);
|
||||
} else if (glx_dpy->minorVersion == 4
|
||||
&& any_screen_has_ARB_create_context) {
|
||||
xcb_glx_set_client_info_arb(c,
|
||||
GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
|
||||
sizeof(gl_versions)
|
||||
/ (2 * sizeof(gl_versions[0])),
|
||||
gl_extension_length,
|
||||
strlen(glx_extensions) + 1,
|
||||
gl_versions,
|
||||
gl_extension_string,
|
||||
glx_extensions);
|
||||
} else {
|
||||
xcb_glx_client_info(c,
|
||||
GLX_MAJOR_VERSION, GLX_MINOR_VERSION,
|
||||
gl_extension_length,
|
||||
gl_extension_string);
|
||||
}
|
||||
|
||||
free(gl_extension_string);
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "glxclient.h"
|
||||
|
||||
/*
|
||||
** Return the number of elements per group of a specified format
|
||||
*/
|
||||
GLint
|
||||
__glElementsPerGroup(GLenum format, GLenum type)
|
||||
{
|
||||
/*
|
||||
** To make row length computation valid for image extraction,
|
||||
** packed pixel types assume elements per group equals one.
|
||||
*/
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_BYTE_3_3_2:
|
||||
case GL_UNSIGNED_BYTE_2_3_3_REV:
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
|
||||
case GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
case GL_UNSIGNED_SHORT_8_8_APPLE:
|
||||
case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
|
||||
case GL_UNSIGNED_INT_8_8_8_8:
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_INT_10_10_10_2:
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||
case GL_UNSIGNED_INT_24_8_NV:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case GL_RGB:
|
||||
case GL_BGR:
|
||||
case GL_RGB_INTEGER_EXT:
|
||||
case GL_BGR_INTEGER_EXT:
|
||||
return 3;
|
||||
case GL_RG:
|
||||
case GL_422_EXT:
|
||||
case GL_422_REV_EXT:
|
||||
case GL_422_AVERAGE_EXT:
|
||||
case GL_422_REV_AVERAGE_EXT:
|
||||
case GL_DEPTH_STENCIL_NV:
|
||||
case GL_YCBCR_422_APPLE:
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE_ALPHA_INTEGER_EXT:
|
||||
return 2;
|
||||
case GL_RGBA:
|
||||
case GL_BGRA:
|
||||
case GL_ABGR_EXT:
|
||||
case GL_RGBA_INTEGER_EXT:
|
||||
case GL_BGRA_INTEGER_EXT:
|
||||
return 4;
|
||||
case GL_COLOR_INDEX:
|
||||
case GL_STENCIL_INDEX:
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_RED:
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
case GL_ALPHA:
|
||||
case GL_LUMINANCE:
|
||||
case GL_INTENSITY:
|
||||
case GL_RED_INTEGER_EXT:
|
||||
case GL_GREEN_INTEGER_EXT:
|
||||
case GL_BLUE_INTEGER_EXT:
|
||||
case GL_ALPHA_INTEGER_EXT:
|
||||
case GL_LUMINANCE_INTEGER_EXT:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes per element, based on the element type (other
|
||||
** than GL_BITMAP).
|
||||
*/
|
||||
GLint
|
||||
__glBytesPerElement(GLenum type)
|
||||
{
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4:
|
||||
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
|
||||
case GL_UNSIGNED_SHORT_5_5_5_1:
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
case GL_UNSIGNED_SHORT_8_8_APPLE:
|
||||
case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
|
||||
return 2;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE_3_3_2:
|
||||
case GL_UNSIGNED_BYTE_2_3_3_REV:
|
||||
return 1;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
case GL_FLOAT:
|
||||
case GL_UNSIGNED_INT_8_8_8_8:
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_INT_10_10_10_2:
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||
case GL_UNSIGNED_INT_24_8_NV:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute memory required for internal packed array of data of given type
|
||||
** and format.
|
||||
*/
|
||||
GLint
|
||||
__glImageSize(GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type, GLenum target)
|
||||
{
|
||||
int bytes_per_row;
|
||||
int components;
|
||||
|
||||
switch (target) {
|
||||
case GL_PROXY_TEXTURE_1D:
|
||||
case GL_PROXY_TEXTURE_2D:
|
||||
case GL_PROXY_TEXTURE_3D:
|
||||
case GL_PROXY_TEXTURE_4D_SGIS:
|
||||
case GL_PROXY_TEXTURE_CUBE_MAP:
|
||||
case GL_PROXY_TEXTURE_RECTANGLE_ARB:
|
||||
case GL_PROXY_HISTOGRAM:
|
||||
case GL_PROXY_COLOR_TABLE:
|
||||
case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
|
||||
case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
|
||||
case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
|
||||
case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0 || depth < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Zero is returned if either format or type are invalid.
|
||||
*/
|
||||
components = __glElementsPerGroup(format, type);
|
||||
if (type == GL_BITMAP) {
|
||||
if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) {
|
||||
bytes_per_row = (width + 7) >> 3;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bytes_per_row = __glBytesPerElement(type) * width;
|
||||
}
|
||||
|
||||
return bytes_per_row * height * depth * components;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include "dri_util.h"
|
||||
#include "glxclient.h"
|
||||
#include "glx_error.h"
|
||||
#include <xcb/glx.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if INT_MAX != 2147483647
|
||||
#error This code requires sizeof(uint32_t) == sizeof(int).
|
||||
#endif
|
||||
|
||||
/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.
|
||||
* This is in case we don't have the updated header.
|
||||
*/
|
||||
#if !defined(X_GLXCreateContextAttribsARB) && \
|
||||
defined(X_GLXCreateContextAtrribsARB)
|
||||
#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB
|
||||
#endif
|
||||
|
||||
GLXContext
|
||||
glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
|
||||
GLXContext share_context, Bool direct,
|
||||
const int *orig_attrib_list)
|
||||
{
|
||||
xcb_connection_t *const c = XGetXCBConnection(dpy);
|
||||
struct glx_config *const cfg = (struct glx_config *) config;
|
||||
struct glx_context *const share = (struct glx_context *) share_context;
|
||||
struct glx_context *gc = NULL;
|
||||
unsigned num_attribs = 0;
|
||||
struct glx_screen *psc;
|
||||
xcb_generic_error_t *err;
|
||||
xcb_void_cookie_t cookie;
|
||||
unsigned error = BadImplementation;
|
||||
uint32_t xid, share_xid;
|
||||
int screen = -1;
|
||||
int *attrib_list = NULL;
|
||||
|
||||
if (dpy == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Count the number of attributes specified by the application. All
|
||||
* attributes appear in pairs, except the terminating None.
|
||||
*/
|
||||
if (orig_attrib_list != NULL) {
|
||||
for (/* empty */; orig_attrib_list[num_attribs * 2] != 0; num_attribs++)
|
||||
/* empty */ ;
|
||||
}
|
||||
|
||||
if (cfg) {
|
||||
screen = cfg->screen;
|
||||
} else {
|
||||
for (unsigned int i = 0; i < num_attribs; i++) {
|
||||
if (orig_attrib_list[i * 2] == GLX_SCREEN)
|
||||
screen = orig_attrib_list[i * 2 + 1];
|
||||
}
|
||||
if (screen == -1) {
|
||||
__glXSendError(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This means that either the caller passed the wrong display pointer or
|
||||
* one of the internal GLX data structures (probably the fbconfig) has an
|
||||
* error. There is nothing sensible to do, so return an error.
|
||||
*/
|
||||
psc = GetGLXScreenConfigs(dpy, screen);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
assert(screen == psc->scr);
|
||||
|
||||
if (orig_attrib_list != NULL) {
|
||||
attrib_list = malloc(sizeof(int) * num_attribs * 2);
|
||||
|
||||
uint8_t clear_ctx_reset_isolation_bit = false;
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
dri2GalliumConfigQueryb(psc->frontend_screen,
|
||||
"glx_clear_context_reset_isolation_bit",
|
||||
&clear_ctx_reset_isolation_bit);
|
||||
#endif
|
||||
for (unsigned i = 0; i < num_attribs; i++) {
|
||||
attrib_list[i * 2] = orig_attrib_list[i * 2];
|
||||
if (clear_ctx_reset_isolation_bit &&
|
||||
attrib_list[i * 2] == GLX_CONTEXT_FLAGS_ARB) {
|
||||
attrib_list[i * 2 + 1] =
|
||||
orig_attrib_list[i * 2 + 1] & ~__DRI_CTX_FLAG_RESET_ISOLATION;
|
||||
} else {
|
||||
attrib_list[i * 2 + 1] =
|
||||
orig_attrib_list[i * 2 + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Some application may request an indirect context but we may want to force a direct
|
||||
* one because Xorg only allows indirect contexts if they were enabled.
|
||||
*/
|
||||
if (!direct &&
|
||||
psc->force_direct_context) {
|
||||
direct = true;
|
||||
}
|
||||
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
gc = applegl_create_context(psc, cfg, share, 0);
|
||||
#else
|
||||
if (direct && psc->vtable->create_context_attribs) {
|
||||
gc = psc->vtable->create_context_attribs(psc, cfg, share, num_attribs,
|
||||
(const uint32_t *) attrib_list,
|
||||
&error);
|
||||
} else if (!direct) {
|
||||
#ifdef GLX_INDIRECT_RENDERING
|
||||
gc = indirect_create_context_attribs(psc, cfg, share, num_attribs,
|
||||
(const uint32_t *) attrib_list,
|
||||
&error);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gc == NULL) {
|
||||
/* Increment dpy->request in order to give a unique serial number to the error.
|
||||
* This may break creating contexts on some video cards, if libx11 <1.7.4 is used.
|
||||
* However, this fixes creating contexts (on some video cards) if libx11 >=1.7.4 is used.
|
||||
*/
|
||||
XNoOp(dpy);
|
||||
/* -1 isn't a legal XID, which is sort of the point, we've failed
|
||||
* before we even got to XID allocation.
|
||||
*/
|
||||
if (error == GLXBadContext || error == GLXBadFBConfig ||
|
||||
error == GLXBadProfileARB)
|
||||
__glXSendError(dpy, error, -1, 0, False);
|
||||
else
|
||||
__glXSendError(dpy, error, -1, 0, True);
|
||||
|
||||
free(attrib_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xid = xcb_generate_id(c);
|
||||
share_xid = (share != NULL) ? share->xid : 0;
|
||||
|
||||
/* The manual pages for glXCreateContext and glXCreateNewContext say:
|
||||
*
|
||||
* "NULL is returned if execution fails on the client side."
|
||||
*
|
||||
* If the server generates an error, the application is supposed to catch
|
||||
* the protocol error and handle it. Part of handling the error is freeing
|
||||
* the possibly non-NULL value returned by this function.
|
||||
*/
|
||||
cookie =
|
||||
xcb_glx_create_context_attribs_arb_checked(c,
|
||||
xid,
|
||||
cfg ? cfg->fbconfigID : 0,
|
||||
screen,
|
||||
share_xid,
|
||||
gc->isDirect,
|
||||
num_attribs,
|
||||
(const uint32_t *)
|
||||
attrib_list);
|
||||
err = xcb_request_check(c, cookie);
|
||||
if (err != NULL) {
|
||||
if (gc)
|
||||
gc->vtable->destroy(gc);
|
||||
gc = NULL;
|
||||
|
||||
__glXSendErrorForXcb(dpy, err);
|
||||
free(err);
|
||||
} else {
|
||||
gc->xid = xid;
|
||||
gc->share_xid = share_xid;
|
||||
}
|
||||
|
||||
free(attrib_list);
|
||||
return (GLXContext) gc;
|
||||
}
|
||||
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* Copyright © 2013 Keith Packard
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions of this code were adapted from dri2_glx.c which carries the
|
||||
* following copyright:
|
||||
*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg ([email protected])
|
||||
*/
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <X11/xshmfence.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
#include <GL/gl.h>
|
||||
#include "glxclient.h"
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "dri_common.h"
|
||||
#include "dri3_priv.h"
|
||||
#include "loader.h"
|
||||
#include "x11_dri3.h"
|
||||
#include "loader_dri_helper.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "dri_util.h"
|
||||
|
||||
static struct dri3_drawable *
|
||||
loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
|
||||
size_t offset = offsetof(struct dri3_drawable, loader_drawable);
|
||||
if (!draw)
|
||||
return NULL;
|
||||
return (struct dri3_drawable *)(((void*) draw) - offset);
|
||||
}
|
||||
|
||||
static void
|
||||
glx_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
|
||||
int width, int height)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
static bool
|
||||
glx_dri3_in_current_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
struct dri3_drawable *priv = loader_drawable_to_dri3_drawable(draw);
|
||||
|
||||
if (!priv)
|
||||
return false;
|
||||
|
||||
struct glx_context *pcp = __glXGetCurrentContext();
|
||||
struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
|
||||
|
||||
return (pcp != &dummyContext) && pcp->psc == &psc->base;
|
||||
}
|
||||
|
||||
static struct dri_context *
|
||||
glx_dri3_get_dri_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
return (gc != &dummyContext) ? gc->driContext : NULL;
|
||||
}
|
||||
|
||||
static struct dri_screen *
|
||||
glx_dri3_get_dri_screen(void)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
struct dri3_screen *psc = (struct dri3_screen *) gc->psc;
|
||||
|
||||
return (gc != &dummyContext && psc) ? psc->base.frontend_screen : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
glx_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
|
||||
{
|
||||
loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER);
|
||||
}
|
||||
|
||||
static const struct loader_dri3_vtable glx_dri3_vtable = {
|
||||
.set_drawable_size = glx_dri3_set_drawable_size,
|
||||
.in_current_context = glx_dri3_in_current_context,
|
||||
.get_dri_context = glx_dri3_get_dri_context,
|
||||
.get_dri_screen = glx_dri3_get_dri_screen,
|
||||
.flush_drawable = glx_dri3_flush_drawable,
|
||||
};
|
||||
|
||||
|
||||
static const struct glx_context_vtable dri3_context_vtable;
|
||||
|
||||
static void
|
||||
dri3_destroy_drawable(__GLXDRIdrawable *base)
|
||||
{
|
||||
struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
|
||||
|
||||
loader_dri3_drawable_fini(&pdraw->loader_drawable);
|
||||
|
||||
free(pdraw);
|
||||
}
|
||||
|
||||
static enum loader_dri3_drawable_type
|
||||
glx_to_loader_dri3_drawable_type(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case GLX_WINDOW_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_WINDOW;
|
||||
case GLX_PIXMAP_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_PIXMAP;
|
||||
case GLX_PBUFFER_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_PBUFFER;
|
||||
default:
|
||||
return LOADER_DRI3_DRAWABLE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static __GLXDRIdrawable *
|
||||
dri3_create_drawable(struct glx_screen *base, XID xDrawable,
|
||||
GLXDrawable drawable, int type,
|
||||
struct glx_config *config_base)
|
||||
{
|
||||
struct dri3_drawable *pdraw;
|
||||
struct dri3_screen *psc = (struct dri3_screen *) base;
|
||||
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
|
||||
bool has_multibuffer = false;
|
||||
|
||||
pdraw = calloc(1, sizeof(*pdraw));
|
||||
if (!pdraw)
|
||||
return NULL;
|
||||
|
||||
pdraw->base.destroyDrawable = dri3_destroy_drawable;
|
||||
pdraw->base.xDrawable = xDrawable;
|
||||
pdraw->base.drawable = drawable;
|
||||
pdraw->base.psc = &psc->base;
|
||||
|
||||
has_multibuffer = base->display->has_multibuffer;
|
||||
|
||||
(void) __glXInitialize(psc->base.dpy);
|
||||
|
||||
if (loader_dri3_drawable_init(XGetXCBConnection(base->dpy),
|
||||
xDrawable,
|
||||
glx_to_loader_dri3_drawable_type(type),
|
||||
psc->base.frontend_screen, psc->driScreenDisplayGPU,
|
||||
has_multibuffer,
|
||||
psc->prefer_back_buffer_reuse,
|
||||
config->driConfig,
|
||||
&glx_dri3_vtable,
|
||||
&pdraw->loader_drawable)) {
|
||||
free(pdraw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdraw->base.dri_drawable = pdraw->loader_drawable.dri_drawable;
|
||||
|
||||
return &pdraw->base;
|
||||
}
|
||||
|
||||
/** dri3_wait_for_msc
|
||||
*
|
||||
* Get the X server to send an event when the target msc/divisor/remainder is
|
||||
* reached.
|
||||
*/
|
||||
static int
|
||||
dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
|
||||
int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
|
||||
loader_dri3_wait_for_msc(&priv->loader_drawable, target_msc, divisor,
|
||||
remainder, ust, msc, sbc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dri3_drawable_get_msc
|
||||
*
|
||||
* Return the current UST/MSC/SBC triplet by asking the server
|
||||
* for an event
|
||||
*/
|
||||
static int
|
||||
dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
|
||||
int64_t *ust, int64_t *msc, int64_t *sbc)
|
||||
{
|
||||
return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc);
|
||||
}
|
||||
|
||||
/** dri3_wait_for_sbc
|
||||
*
|
||||
* Wait for the completed swap buffer count to reach the specified
|
||||
* target. Presumably the application knows that this will be reached with
|
||||
* outstanding complete events, or we're going to be here awhile.
|
||||
*/
|
||||
static int
|
||||
dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
|
||||
int64_t *msc, int64_t *sbc)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
|
||||
return loader_dri3_wait_for_sbc(&priv->loader_drawable, target_sbc,
|
||||
ust, msc, sbc);
|
||||
}
|
||||
|
||||
static void
|
||||
dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
|
||||
int width, int height,
|
||||
Bool flush)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
|
||||
loader_dri3_copy_sub_buffer(&priv->loader_drawable, x, y,
|
||||
width, height, flush);
|
||||
}
|
||||
|
||||
static void
|
||||
dri3_wait_x(struct glx_context *gc)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *)
|
||||
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
||||
|
||||
if (priv)
|
||||
loader_dri3_wait_x(&priv->loader_drawable);
|
||||
}
|
||||
|
||||
static void
|
||||
dri3_wait_gl(struct glx_context *gc)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *)
|
||||
GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
|
||||
|
||||
if (priv)
|
||||
loader_dri3_wait_gl(&priv->loader_drawable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the driver when it needs to update the real front buffer with the
|
||||
* contents of its fake front buffer.
|
||||
*/
|
||||
static void
|
||||
dri3_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
struct loader_dri3_drawable *draw = loaderPrivate;
|
||||
struct dri3_drawable *pdraw = loader_drawable_to_dri3_drawable(draw);
|
||||
struct dri3_screen *psc;
|
||||
|
||||
if (!pdraw)
|
||||
return;
|
||||
|
||||
if (!pdraw->base.psc)
|
||||
return;
|
||||
|
||||
psc = (struct dri3_screen *) pdraw->base.psc;
|
||||
|
||||
(void) __glXInitialize(psc->base.dpy);
|
||||
|
||||
loader_dri3_flush(draw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT);
|
||||
|
||||
dri_invalidate_drawable(driDrawable);
|
||||
loader_dri3_wait_gl(draw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure all pending swapbuffers have been submitted to hardware
|
||||
*
|
||||
* \param driDrawable[in] Pointer to the dri drawable whose swaps we are
|
||||
* flushing.
|
||||
* \param loaderPrivate[in] Pointer to the corresponding struct
|
||||
* loader_dri_drawable.
|
||||
*/
|
||||
static void
|
||||
dri3_flush_swap_buffers(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
struct loader_dri3_drawable *draw = loaderPrivate;
|
||||
struct dri3_drawable *pdraw = loader_drawable_to_dri3_drawable(draw);
|
||||
struct dri3_screen *psc;
|
||||
|
||||
if (!pdraw)
|
||||
return;
|
||||
|
||||
if (!pdraw->base.psc)
|
||||
return;
|
||||
|
||||
psc = (struct dri3_screen *) pdraw->base.psc;
|
||||
|
||||
(void) __glXInitialize(psc->base.dpy);
|
||||
loader_dri3_swapbuffer_barrier(draw);
|
||||
}
|
||||
|
||||
/* The image loader extension record for DRI3
|
||||
*/
|
||||
static const __DRIimageLoaderExtension imageLoaderExtension = {
|
||||
.base = { __DRI_IMAGE_LOADER, 3 },
|
||||
|
||||
.getBuffers = loader_dri3_get_buffers,
|
||||
.flushFrontBuffer = dri3_flush_front_buffer,
|
||||
.flushSwapBuffers = dri3_flush_swap_buffers,
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions[] = {
|
||||
&imageLoaderExtension.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
/** dri3_swap_buffers
|
||||
*
|
||||
* Make the current back buffer visible using the present extension
|
||||
*/
|
||||
static int64_t
|
||||
dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
|
||||
int64_t remainder, Bool flush)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
unsigned flags = __DRI2_FLUSH_DRAWABLE;
|
||||
|
||||
if (flush)
|
||||
flags |= __DRI2_FLUSH_CONTEXT;
|
||||
|
||||
return loader_dri3_swap_buffers_msc(&priv->loader_drawable,
|
||||
target_msc, divisor, remainder,
|
||||
flags, NULL, 0, false);
|
||||
}
|
||||
|
||||
int
|
||||
dri3_get_buffer_age(__GLXDRIdrawable *pdraw);
|
||||
int
|
||||
dri3_get_buffer_age(__GLXDRIdrawable *pdraw)
|
||||
{
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *)pdraw;
|
||||
|
||||
return loader_dri3_query_buffer_age(&priv->loader_drawable);
|
||||
}
|
||||
|
||||
/** dri3_destroy_screen
|
||||
*/
|
||||
static void
|
||||
dri3_deinit_screen(struct glx_screen *base)
|
||||
{
|
||||
struct dri3_screen *psc = (struct dri3_screen *) base;
|
||||
|
||||
/* Free the direct rendering per screen data */
|
||||
if (psc->fd_render_gpu != psc->fd_display_gpu && psc->driScreenDisplayGPU) {
|
||||
loader_dri3_close_screen(psc->driScreenDisplayGPU);
|
||||
driDestroyScreen(psc->driScreenDisplayGPU);
|
||||
}
|
||||
if (psc->fd_render_gpu != psc->fd_display_gpu)
|
||||
close(psc->fd_display_gpu);
|
||||
loader_dri3_close_screen(psc->base.frontend_screen);
|
||||
close(psc->fd_render_gpu);
|
||||
}
|
||||
|
||||
/** dri3_set_swap_interval
|
||||
*
|
||||
* Record the application swap interval specification,
|
||||
*/
|
||||
static int
|
||||
dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
|
||||
{
|
||||
assert(pdraw != NULL);
|
||||
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
|
||||
|
||||
if (!dri_valid_swap_interval(psc->base.frontend_screen, interval))
|
||||
return GLX_BAD_VALUE;
|
||||
|
||||
loader_dri3_set_swap_interval(&priv->loader_drawable, interval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** dri3_get_swap_interval
|
||||
*
|
||||
* Return the stored swap interval
|
||||
*/
|
||||
static int
|
||||
dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
|
||||
{
|
||||
assert(pdraw != NULL);
|
||||
|
||||
struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
|
||||
|
||||
return priv->loader_drawable.swap_interval;
|
||||
}
|
||||
|
||||
static const struct glx_context_vtable dri3_context_vtable = {
|
||||
.destroy = dri_destroy_context,
|
||||
.bind = dri_bind_context,
|
||||
.unbind = dri_unbind_context,
|
||||
.wait_gl = dri3_wait_gl,
|
||||
.wait_x = dri3_wait_x,
|
||||
};
|
||||
|
||||
/** dri3_create_screen
|
||||
*
|
||||
* Initialize DRI3 on the specified screen.
|
||||
*
|
||||
* Opens the DRI device, locates the appropriate DRI driver
|
||||
* and loads that.
|
||||
*
|
||||
* Checks to see if the driver supports the necessary extensions
|
||||
*
|
||||
* Initializes the driver for the screen and sets up our structures
|
||||
*/
|
||||
|
||||
struct glx_screen *
|
||||
dri3_create_screen(int screen, struct glx_display * priv, bool driver_name_is_inferred, bool *return_zink)
|
||||
{
|
||||
xcb_connection_t *c = XGetXCBConnection(priv->dpy);
|
||||
const struct dri_config **driver_configs;
|
||||
struct dri3_screen *psc;
|
||||
__GLXDRIscreen *psp;
|
||||
char *driverName, *driverNameDisplayGPU;
|
||||
*return_zink = false;
|
||||
|
||||
psc = calloc(1, sizeof *psc);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
psc->fd_display_gpu = -1;
|
||||
|
||||
psc->fd_render_gpu = x11_dri3_open(c, RootWindow(priv->dpy, screen), None);
|
||||
if (psc->fd_render_gpu < 0) {
|
||||
int conn_error = xcb_connection_has_error(c);
|
||||
|
||||
glx_screen_cleanup(&psc->base);
|
||||
free(psc);
|
||||
InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
|
||||
|
||||
if (conn_error)
|
||||
ErrorMessageF("Connection closed during DRI3 initialization failure");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
loader_get_user_preferred_fd(&psc->fd_render_gpu, &psc->fd_display_gpu);
|
||||
|
||||
driverName = loader_get_driver_for_fd(psc->fd_render_gpu);
|
||||
if (!driverName) {
|
||||
ErrorMessageF("No driver found\n");
|
||||
goto handle_error;
|
||||
}
|
||||
psc->base.driverName = driverName;
|
||||
|
||||
if (!strcmp(driverName, "zink") && !debug_get_bool_option("LIBGL_KOPPER_DISABLE", false)) {
|
||||
*return_zink = true;
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
if (psc->fd_render_gpu != psc->fd_display_gpu) {
|
||||
driverNameDisplayGPU = loader_get_driver_for_fd(psc->fd_display_gpu);
|
||||
if (driverNameDisplayGPU) {
|
||||
|
||||
/* check if driver name is matching so that non mesa drivers
|
||||
* will not crash. Also need this check since image extension
|
||||
* pointer from render gpu is shared with display gpu. Image
|
||||
* extension pointer is shared because it keeps things simple.
|
||||
*/
|
||||
if (strcmp(driverName, driverNameDisplayGPU) == 0) {
|
||||
psc->driScreenDisplayGPU = driCreateNewScreen3(screen, psc->fd_display_gpu,
|
||||
loader_extensions,
|
||||
DRI_SCREEN_DRI3,
|
||||
&driver_configs, driver_name_is_inferred,
|
||||
priv->has_multibuffer, psc);
|
||||
}
|
||||
|
||||
free(driverNameDisplayGPU);
|
||||
}
|
||||
}
|
||||
priv->driver = GLX_DRIVER_DRI3;
|
||||
|
||||
if (!dri_screen_init(&psc->base, priv, screen, psc->fd_render_gpu, loader_extensions, driver_name_is_inferred)) {
|
||||
ErrorMessageF("glx: failed to create dri3 screen\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
if (psc->fd_render_gpu == psc->fd_display_gpu)
|
||||
psc->driScreenDisplayGPU = psc->base.frontend_screen;
|
||||
|
||||
psc->base.context_vtable = &dri3_context_vtable;
|
||||
psp = &psc->base.driScreen;
|
||||
psp->deinitScreen = dri3_deinit_screen;
|
||||
psp->createDrawable = dri3_create_drawable;
|
||||
psp->swapBuffers = dri3_swap_buffers;
|
||||
|
||||
psp->getDrawableMSC = dri3_drawable_get_msc;
|
||||
psp->waitForMSC = dri3_wait_for_msc;
|
||||
psp->waitForSBC = dri3_wait_for_sbc;
|
||||
psp->setSwapInterval = dri3_set_swap_interval;
|
||||
psp->getSwapInterval = dri3_get_swap_interval;
|
||||
psp->maxSwapInterval = INT_MAX;
|
||||
|
||||
/* when on a different gpu than the server, the server pixmaps
|
||||
* can have a tiling mode we can't read. Thus we can't create
|
||||
* a texture from them.
|
||||
*/
|
||||
psc->base.can_EXT_texture_from_pixmap = psc->fd_render_gpu == psc->fd_display_gpu;
|
||||
psp->copySubBuffer = dri3_copy_sub_buffer;
|
||||
|
||||
InfoMessageF("Using DRI3 for screen %d\n", screen);
|
||||
|
||||
psc->prefer_back_buffer_reuse = 1;
|
||||
if (psc->fd_render_gpu != psc->fd_display_gpu) {
|
||||
unsigned value;
|
||||
if (dri_query_renderer_integer(psc->base.frontend_screen,
|
||||
__DRI2_RENDERER_PREFER_BACK_BUFFER_REUSE,
|
||||
&value) == 0)
|
||||
psc->prefer_back_buffer_reuse = value;
|
||||
}
|
||||
|
||||
|
||||
return &psc->base;
|
||||
|
||||
handle_error:
|
||||
if (!*return_zink)
|
||||
CriticalErrorMessageF("failed to load driver: %s\n", driverName ? driverName : "(null)");
|
||||
|
||||
if (psc->fd_render_gpu != psc->fd_display_gpu && psc->driScreenDisplayGPU)
|
||||
driDestroyScreen(psc->driScreenDisplayGPU);
|
||||
psc->driScreenDisplayGPU = NULL;
|
||||
if (psc->fd_display_gpu >= 0 && psc->fd_render_gpu != psc->fd_display_gpu)
|
||||
close(psc->fd_display_gpu);
|
||||
if (psc->fd_render_gpu >= 0)
|
||||
close(psc->fd_render_gpu);
|
||||
|
||||
glx_screen_cleanup(&psc->base);
|
||||
free(psc);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright © 2013 Keith Packard
|
||||
*
|
||||
* 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 the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
/* This file was derived from dri2_priv.h which carries the following
|
||||
* copyright:
|
||||
*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg ([email protected])
|
||||
*/
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
#include <xcb/sync.h>
|
||||
|
||||
#include "loader_dri3_helper.h"
|
||||
#include "mesa_interface.h"
|
||||
|
||||
struct dri3_screen {
|
||||
struct glx_screen base;
|
||||
|
||||
/* DRI screen is created for display GPU in case of prime gpu offloading.
|
||||
* This screen is used to allocate linear_buffer from
|
||||
* display GPU space in dri3_alloc_render_buffer() function.
|
||||
* In case of not gpu offloading driScreenDisplayGPU will be assigned with
|
||||
* base.frontend_screen.
|
||||
* In case of prime gpu offloading if display and render driver names are different
|
||||
* (potentially not compatible), driScreenDisplayGPU will be NULL but
|
||||
* fd_display_gpu will still hold fd for display driver.
|
||||
*/
|
||||
struct dri_screen *driScreenDisplayGPU;
|
||||
|
||||
/* fd of the GPU used for rendering. */
|
||||
int fd_render_gpu;
|
||||
/* fd of the GPU used for display. If the same GPU is used for display
|
||||
* and rendering, then fd_render_gpu == fd_display_gpu (no need to use
|
||||
* os_same_file_description).
|
||||
*/
|
||||
int fd_display_gpu;
|
||||
bool prefer_back_buffer_reuse;
|
||||
};
|
||||
|
||||
struct dri3_drawable {
|
||||
__GLXDRIdrawable base;
|
||||
struct loader_dri3_drawable loader_drawable;
|
||||
|
||||
/* LIBGL_SHOW_FPS support */
|
||||
uint64_t previous_ust;
|
||||
unsigned frames;
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kevin E. Martin <[email protected]>
|
||||
* Brian Paul <[email protected]>
|
||||
* Kristian Høgsberg ([email protected])
|
||||
*/
|
||||
|
||||
#ifndef _DRI_COMMON_H
|
||||
#define _DRI_COMMON_H
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
|
||||
#include "mesa_interface.h"
|
||||
#include <stdbool.h>
|
||||
#include "loader.h"
|
||||
#include "util/macros.h" /* for PRINTFLIKE */
|
||||
|
||||
typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate;
|
||||
|
||||
struct __GLXDRIconfigPrivateRec
|
||||
{
|
||||
struct glx_config base;
|
||||
const struct dri_config *driConfig;
|
||||
};
|
||||
|
||||
extern struct glx_config *driConvertConfigs(struct glx_config * modes,
|
||||
const struct dri_config ** configs);
|
||||
|
||||
extern void driDestroyConfigs(const struct dri_config **configs);
|
||||
|
||||
extern __GLXDRIdrawable *
|
||||
driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable);
|
||||
|
||||
extern void
|
||||
driReleaseDrawables(struct glx_context *gc);
|
||||
|
||||
struct dri_ctx_attribs {
|
||||
unsigned major_ver;
|
||||
unsigned minor_ver;
|
||||
uint32_t render_type;
|
||||
uint32_t flags;
|
||||
unsigned api;
|
||||
int reset;
|
||||
int release;
|
||||
int no_error;
|
||||
};
|
||||
|
||||
extern const struct glx_screen_vtable dri_screen_vtable;
|
||||
|
||||
extern unsigned
|
||||
dri_context_error_to_glx_error(unsigned error);
|
||||
|
||||
extern int
|
||||
dri_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
|
||||
struct dri_ctx_attribs *dca);
|
||||
|
||||
extern struct glx_context *
|
||||
dri_common_create_context(struct glx_screen *base,
|
||||
struct glx_config *config_base,
|
||||
struct glx_context *shareList,
|
||||
int renderType);
|
||||
|
||||
Bool
|
||||
dri_bind_context(struct glx_context *context, GLXDrawable draw, GLXDrawable read);
|
||||
void
|
||||
dri_unbind_context(struct glx_context *context);
|
||||
void
|
||||
dri_destroy_context(struct glx_context *context);
|
||||
struct glx_context *
|
||||
dri_create_context_attribs(struct glx_screen *base,
|
||||
struct glx_config *config_base,
|
||||
struct glx_context *shareList,
|
||||
unsigned num_attribs,
|
||||
const uint32_t *attribs,
|
||||
unsigned *error);
|
||||
int
|
||||
glx_dri_query_renderer_integer(struct glx_screen *base, int attribute,
|
||||
unsigned int *value);
|
||||
int
|
||||
glx_dri_query_renderer_string(struct glx_screen *base, int attribute,
|
||||
const char **value);
|
||||
char *
|
||||
dri_get_driver_name(struct glx_screen *glx_screen);
|
||||
void
|
||||
dri_bind_tex_image(__GLXDRIdrawable *base, int buffer, const int *attrib_list);
|
||||
bool
|
||||
dri_screen_init(struct glx_screen *psc, struct glx_display *priv, int screen, int fd, const __DRIextension **loader_extensions, bool driver_name_is_inferred);
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
|
||||
#endif /* _DRI_COMMON_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "glx_error.h"
|
||||
#include "mesa_interface.h"
|
||||
#include "dri_util.h"
|
||||
#include "dri_common.h"
|
||||
|
||||
#define __RENDERER(attrib) \
|
||||
{ GLX_RENDERER_##attrib##_MESA, __DRI2_RENDERER_##attrib }
|
||||
|
||||
static const struct {
|
||||
unsigned int glx_attrib, dri2_attrib;
|
||||
} query_renderer_map[] = {
|
||||
__RENDERER(VENDOR_ID),
|
||||
__RENDERER(DEVICE_ID),
|
||||
__RENDERER(VERSION),
|
||||
__RENDERER(ACCELERATED),
|
||||
__RENDERER(VIDEO_MEMORY),
|
||||
__RENDERER(UNIFIED_MEMORY_ARCHITECTURE),
|
||||
__RENDERER(PREFERRED_PROFILE),
|
||||
__RENDERER(OPENGL_CORE_PROFILE_VERSION),
|
||||
__RENDERER(OPENGL_COMPATIBILITY_PROFILE_VERSION),
|
||||
__RENDERER(OPENGL_ES_PROFILE_VERSION),
|
||||
__RENDERER(OPENGL_ES2_PROFILE_VERSION),
|
||||
};
|
||||
|
||||
#undef __RENDERER
|
||||
|
||||
static int
|
||||
dri2_convert_glx_query_renderer_attribs(int attribute)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(query_renderer_map); i++)
|
||||
if (query_renderer_map[i].glx_attrib == attribute)
|
||||
return query_renderer_map[i].dri2_attrib;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert internal dri context profile bits into GLX context profile bits */
|
||||
static inline void
|
||||
dri_convert_context_profile_bits(int attribute, unsigned int *value)
|
||||
{
|
||||
if (attribute == GLX_RENDERER_PREFERRED_PROFILE_MESA) {
|
||||
if (value[0] == (1U << __DRI_API_OPENGL_CORE))
|
||||
value[0] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
else if (value[0] == (1U << __DRI_API_OPENGL))
|
||||
value[0] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
glx_dri_query_renderer_integer(struct glx_screen *base, int attribute,
|
||||
unsigned int *value)
|
||||
{
|
||||
int ret;
|
||||
/* Even though there are invalid values (and
|
||||
* dri2_convert_glx_query_renderer_attribs may return -1), the higher level
|
||||
* GLX code is required to perform the filtering. Assume that we got a
|
||||
* good value.
|
||||
*/
|
||||
const int dri_attribute = dri2_convert_glx_query_renderer_attribs(attribute);
|
||||
|
||||
ret = dri_query_renderer_integer(base->frontend_screen, dri_attribute, value);
|
||||
dri_convert_context_profile_bits(attribute, value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
glx_dri_query_renderer_string(struct glx_screen *base, int attribute,
|
||||
const char **value)
|
||||
{
|
||||
/* Even though queryString only accepts a subset of the possible GLX
|
||||
* queries, the higher level GLX code is required to perform the filtering.
|
||||
* Assume that we got a good value.
|
||||
*/
|
||||
const int dri_attribute = dri2_convert_glx_query_renderer_attribs(attribute);
|
||||
|
||||
return dri_query_renderer_string(base->frontend_screen, dri_attribute, value);
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
* Copyright 2008 George Sapountzis
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
#include <xcb/shm.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include "glxclient.h"
|
||||
#include <dlfcn.h>
|
||||
#include "dri_common.h"
|
||||
#include "drisw_priv.h"
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include "dri3_priv.h"
|
||||
#endif
|
||||
#include <X11/extensions/shmproto.h>
|
||||
#include <assert.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vulkan/vulkan_xcb.h>
|
||||
#include "util/u_debug.h"
|
||||
#include "util/log.h"
|
||||
#include "kopper_interface.h"
|
||||
#include "loader_dri_helper.h"
|
||||
#include "dri_util.h"
|
||||
#include "mesa/glapi/glapi/glapi.h"
|
||||
#include "dispatch.h"
|
||||
#include "x11_display.h"
|
||||
|
||||
static int xshm_error = 0;
|
||||
static int xshm_opcode = -1;
|
||||
|
||||
/**
|
||||
* Catches potential Xlib errors.
|
||||
*/
|
||||
static int
|
||||
handle_xerror(Display *dpy, XErrorEvent *event)
|
||||
{
|
||||
(void) dpy;
|
||||
|
||||
assert(xshm_opcode != -1);
|
||||
if (event->request_code != xshm_opcode)
|
||||
return 0;
|
||||
|
||||
xshm_error = event->error_code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Bool
|
||||
XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
|
||||
{
|
||||
if (pdp->ximage) {
|
||||
XDestroyImage(pdp->ximage);
|
||||
pdp->ximage = NULL;
|
||||
if ((pdp->shminfo.shmid > 0) && (shmid != pdp->shminfo.shmid))
|
||||
XShmDetach(dpy, &pdp->shminfo);
|
||||
}
|
||||
|
||||
if (!xshm_error && shmid >= 0) {
|
||||
pdp->shminfo.shmid = shmid;
|
||||
pdp->ximage = XShmCreateImage(dpy,
|
||||
NULL,
|
||||
pdp->xDepth,
|
||||
ZPixmap, /* format */
|
||||
NULL, /* data */
|
||||
&pdp->shminfo, /* shminfo */
|
||||
0, 0); /* width, height */
|
||||
if (pdp->ximage != NULL) {
|
||||
int (*old_handler)(Display *, XErrorEvent *);
|
||||
|
||||
/* dispatch pending errors */
|
||||
XSync(dpy, False);
|
||||
|
||||
old_handler = XSetErrorHandler(handle_xerror);
|
||||
/* This may trigger the X protocol error we're ready to catch: */
|
||||
XShmAttach(dpy, &pdp->shminfo);
|
||||
XSync(dpy, False);
|
||||
|
||||
if (xshm_error) {
|
||||
/* we are on a remote display, this error is normal, don't print it */
|
||||
XDestroyImage(pdp->ximage);
|
||||
pdp->ximage = NULL;
|
||||
}
|
||||
|
||||
(void) XSetErrorHandler(old_handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdp->ximage == NULL) {
|
||||
pdp->shminfo.shmid = -1;
|
||||
pdp->ximage = XCreateImage(dpy,
|
||||
NULL,
|
||||
pdp->xDepth,
|
||||
ZPixmap, 0, /* format, offset */
|
||||
NULL, /* data */
|
||||
0, 0, /* width, height */
|
||||
32, /* bitmap_pad */
|
||||
0); /* bytes_per_line */
|
||||
}
|
||||
|
||||
/**
|
||||
* swrast does not handle 24-bit depth with 24 bpp, so let X do the
|
||||
* the conversion for us.
|
||||
*/
|
||||
if (pdp->ximage->bits_per_pixel == 24)
|
||||
pdp->ximage->bits_per_pixel = 32;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static void
|
||||
XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
|
||||
{
|
||||
if (pdp->ximage)
|
||||
XDestroyImage(pdp->ximage);
|
||||
|
||||
if (pdp->shminfo.shmid > 0)
|
||||
XShmDetach(dpy, &pdp->shminfo);
|
||||
|
||||
XFreeGC(dpy, pdp->gc);
|
||||
}
|
||||
|
||||
/**
|
||||
* swrast loader functions
|
||||
*/
|
||||
|
||||
static void
|
||||
get_drawable_geometry(struct dri_drawable * draw,
|
||||
int *x, int *y, int *w, int *h,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *pdp = loaderPrivate;
|
||||
__GLXDRIdrawable *pdraw = &(pdp->base);
|
||||
Display *dpy = pdraw->psc->dpy;
|
||||
Drawable drawable;
|
||||
|
||||
Window root;
|
||||
unsigned uw, uh, bw, depth;
|
||||
|
||||
drawable = pdraw->xDrawable;
|
||||
|
||||
XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
|
||||
*w = uw;
|
||||
*h = uh;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastGetDrawableInfo(struct dri_drawable * draw,
|
||||
int *x, int *y, int *w, int *h,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
get_drawable_geometry(draw, x, y, w, h, loaderPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Align renderbuffer pitch.
|
||||
*
|
||||
* This should be chosen by the driver and the loader (libGL, xserver/glx)
|
||||
* should use the driver provided pitch.
|
||||
*
|
||||
* It seems that the xorg loader (that is the xserver loading swrast_dri for
|
||||
* indirect rendering, not client-side libGL) requires that the pitch is
|
||||
* exactly the image width padded to 32 bits. XXX
|
||||
*
|
||||
* The above restriction can probably be overcome by using ScratchPixmap and
|
||||
* CopyArea in the xserver, similar to ShmPutImage, and setting the width of
|
||||
* the scratch pixmap to 'pitch / cpp'.
|
||||
*/
|
||||
static inline int
|
||||
bytes_per_line(unsigned pitch_bits, unsigned mul)
|
||||
{
|
||||
unsigned mask = mul - 1;
|
||||
|
||||
return ((pitch_bits + mask) & ~mask) / 8;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastXPutImage(struct dri_drawable * draw, int op,
|
||||
int srcx, int srcy, int x, int y,
|
||||
int w, int h, int stride,
|
||||
int shmid, char *data, void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *pdp = loaderPrivate;
|
||||
__GLXDRIdrawable *pdraw = &(pdp->base);
|
||||
Display *dpy = pdraw->psc->dpy;
|
||||
Drawable drawable;
|
||||
XImage *ximage;
|
||||
GC gc = pdp->gc;
|
||||
|
||||
if (!pdp->ximage || shmid != pdp->shminfo.shmid) {
|
||||
if (!XCreateDrawable(pdp, shmid, dpy))
|
||||
return;
|
||||
}
|
||||
|
||||
drawable = pdraw->xDrawable;
|
||||
ximage = pdp->ximage;
|
||||
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||
ximage->data = data;
|
||||
|
||||
ximage->width = ximage->bytes_per_line / ((ximage->bits_per_pixel + 7)/ 8);
|
||||
ximage->height = h;
|
||||
|
||||
if (pdp->shminfo.shmid >= 0) {
|
||||
XShmPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h, False);
|
||||
XSync(dpy, False);
|
||||
} else {
|
||||
XPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h);
|
||||
}
|
||||
ximage->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastPutImageShm(struct dri_drawable * draw, int op,
|
||||
int x, int y, int w, int h, int stride,
|
||||
int shmid, char *shmaddr, unsigned offset,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *pdp = loaderPrivate;
|
||||
|
||||
if (!pdp)
|
||||
return;
|
||||
|
||||
pdp->shminfo.shmaddr = shmaddr;
|
||||
swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, shmid,
|
||||
shmaddr + offset, loaderPrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
swrastPutImageShm2(struct dri_drawable * draw, int op,
|
||||
int x, int y,
|
||||
int w, int h, int stride,
|
||||
int shmid, char *shmaddr, unsigned offset,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *pdp = loaderPrivate;
|
||||
|
||||
if (!pdp)
|
||||
return;
|
||||
|
||||
pdp->shminfo.shmaddr = shmaddr;
|
||||
swrastXPutImage(draw, op, x, 0, x, y, w, h, stride, shmid,
|
||||
shmaddr + offset, loaderPrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
swrastPutImage2(struct dri_drawable * draw, int op,
|
||||
int x, int y, int w, int h, int stride,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
if (!loaderPrivate)
|
||||
return;
|
||||
|
||||
swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, -1,
|
||||
data, loaderPrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
swrastPutImage(struct dri_drawable * draw, int op,
|
||||
int x, int y, int w, int h,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
if (!loaderPrivate)
|
||||
return;
|
||||
|
||||
swrastXPutImage(draw, op, 0, 0, x, y, w, h, 0, -1,
|
||||
data, loaderPrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
swrastGetImage2(struct dri_drawable * read,
|
||||
int x, int y, int w, int h, int stride,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *prp = loaderPrivate;
|
||||
__GLXDRIdrawable *pread = &(prp->base);
|
||||
Display *dpy = pread->psc->dpy;
|
||||
Drawable readable;
|
||||
XImage *ximage;
|
||||
|
||||
if (!prp->ximage || prp->shminfo.shmid >= 0) {
|
||||
if (!XCreateDrawable(prp, -1, dpy))
|
||||
return;
|
||||
}
|
||||
|
||||
readable = pread->xDrawable;
|
||||
|
||||
ximage = prp->ximage;
|
||||
ximage->data = data;
|
||||
ximage->width = w;
|
||||
ximage->height = h;
|
||||
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||
|
||||
XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
|
||||
|
||||
ximage->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastGetImage(struct dri_drawable * read,
|
||||
int x, int y, int w, int h,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
swrastGetImageShm2(struct dri_drawable * read,
|
||||
int x, int y, int w, int h,
|
||||
int shmid, void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *prp = loaderPrivate;
|
||||
__GLXDRIdrawable *pread = &(prp->base);
|
||||
Display *dpy = pread->psc->dpy;
|
||||
Drawable readable;
|
||||
XImage *ximage;
|
||||
|
||||
if (!prp->ximage || shmid != prp->shminfo.shmid) {
|
||||
if (!XCreateDrawable(prp, shmid, dpy))
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (prp->shminfo.shmid == -1)
|
||||
return GL_FALSE;
|
||||
readable = pread->xDrawable;
|
||||
|
||||
ximage = prp->ximage;
|
||||
ximage->data = prp->shminfo.shmaddr; /* no offset */
|
||||
ximage->width = w;
|
||||
ximage->height = h;
|
||||
ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||
|
||||
XShmGetImage(dpy, readable, ximage, x, y, ~0L);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastGetImageShm(struct dri_drawable * read,
|
||||
int x, int y, int w, int h,
|
||||
int shmid, void *loaderPrivate)
|
||||
{
|
||||
swrastGetImageShm2(read, x, y, w, h, shmid, loaderPrivate);
|
||||
}
|
||||
|
||||
static const __DRIswrastLoaderExtension swrastLoaderExtension_shm = {
|
||||
.base = {__DRI_SWRAST_LOADER, 6 },
|
||||
|
||||
.getDrawableInfo = swrastGetDrawableInfo,
|
||||
.putImage = swrastPutImage,
|
||||
.getImage = swrastGetImage,
|
||||
.putImage2 = swrastPutImage2,
|
||||
.getImage2 = swrastGetImage2,
|
||||
.putImageShm = swrastPutImageShm,
|
||||
.getImageShm = swrastGetImageShm,
|
||||
.putImageShm2 = swrastPutImageShm2,
|
||||
.getImageShm2 = swrastGetImageShm2,
|
||||
};
|
||||
|
||||
static const __DRIswrastLoaderExtension swrastLoaderExtension = {
|
||||
.base = {__DRI_SWRAST_LOADER, 3 },
|
||||
|
||||
.getDrawableInfo = swrastGetDrawableInfo,
|
||||
.putImage = swrastPutImage,
|
||||
.getImage = swrastGetImage,
|
||||
.putImage2 = swrastPutImage2,
|
||||
.getImage2 = swrastGetImage2,
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct kopper_vk_surface_create_storage) >= sizeof(VkXcbSurfaceCreateInfoKHR), "");
|
||||
|
||||
static void
|
||||
kopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out)
|
||||
{
|
||||
__GLXDRIdrawable *draw = _draw;
|
||||
VkXcbSurfaceCreateInfoKHR *xcb = (VkXcbSurfaceCreateInfoKHR *)&out->bos;
|
||||
|
||||
xcb->sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||
xcb->pNext = NULL;
|
||||
xcb->flags = 0;
|
||||
xcb->connection = XGetXCBConnection(draw->psc->dpy);
|
||||
xcb->window = draw->xDrawable;
|
||||
}
|
||||
|
||||
static void
|
||||
kopperGetDrawableInfo(struct dri_drawable * draw,
|
||||
int *w, int *h,
|
||||
void *loaderPrivate)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
get_drawable_geometry(draw, &x, &y, w, h, loaderPrivate);
|
||||
}
|
||||
|
||||
static const __DRIkopperLoaderExtension kopperLoaderExtension = {
|
||||
.base = { __DRI_KOPPER_LOADER, 1 },
|
||||
|
||||
.SetSurfaceCreateInfo = kopperSetSurfaceCreateInfo,
|
||||
.GetDrawableInfo = kopperGetDrawableInfo,
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions_shm[] = {
|
||||
&swrastLoaderExtension_shm.base,
|
||||
&kopperLoaderExtension.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions_noshm[] = {
|
||||
&swrastLoaderExtension.base,
|
||||
&kopperLoaderExtension.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const __DRIextension *kopper_extensions_noshm[] = {
|
||||
&swrastLoaderExtension.base,
|
||||
&kopperLoaderExtension.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* GLXDRI functions
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
drisw_wait_gl(struct glx_context *context)
|
||||
{
|
||||
CALL_Finish(GET_DISPATCH(), ());
|
||||
}
|
||||
|
||||
static void
|
||||
drisw_wait_x(struct glx_context *context)
|
||||
{
|
||||
XSync(context->currentDpy, False);
|
||||
}
|
||||
|
||||
int
|
||||
kopper_get_buffer_age(__GLXDRIdrawable *pdraw);
|
||||
int
|
||||
kopper_get_buffer_age(__GLXDRIdrawable *pdraw)
|
||||
{
|
||||
return kopperQueryBufferAge(pdraw->dri_drawable);
|
||||
}
|
||||
|
||||
static const struct glx_context_vtable drisw_context_vtable = {
|
||||
.destroy = dri_destroy_context,
|
||||
.bind = dri_bind_context,
|
||||
.unbind = dri_unbind_context,
|
||||
.wait_gl = drisw_wait_gl,
|
||||
.wait_x = drisw_wait_x,
|
||||
};
|
||||
|
||||
static void
|
||||
driswDestroyDrawable(__GLXDRIdrawable * pdraw)
|
||||
{
|
||||
struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
|
||||
|
||||
driDestroyDrawable(pdp->base.dri_drawable);
|
||||
|
||||
XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
|
||||
free(pdp);
|
||||
}
|
||||
|
||||
static __GLXDRIdrawable *
|
||||
driswCreateDrawable(struct glx_screen *base, XID xDrawable,
|
||||
GLXDrawable drawable, int type,
|
||||
struct glx_config *modes)
|
||||
{
|
||||
struct drisw_drawable *pdp;
|
||||
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
|
||||
unsigned depth;
|
||||
struct drisw_screen *psc = (struct drisw_screen *) base;
|
||||
Display *dpy = psc->base.dpy;
|
||||
|
||||
xcb_connection_t *conn = XGetXCBConnection(dpy);
|
||||
xcb_generic_error_t *error;
|
||||
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(conn, xDrawable);
|
||||
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(conn, cookie, &error);
|
||||
if (reply)
|
||||
depth = reply->depth;
|
||||
free(reply);
|
||||
if (!reply || error)
|
||||
return NULL;
|
||||
|
||||
pdp = calloc(1, sizeof(*pdp));
|
||||
if (!pdp)
|
||||
return NULL;
|
||||
|
||||
pdp->base.xDrawable = xDrawable;
|
||||
pdp->base.drawable = drawable;
|
||||
pdp->base.psc = &psc->base;
|
||||
pdp->config = modes;
|
||||
pdp->gc = XCreateGC(dpy, xDrawable, 0, NULL);
|
||||
pdp->xDepth = 0;
|
||||
|
||||
/* Use the visual depth, if this fbconfig corresponds to a visual */
|
||||
if (pdp->config->visualID != 0) {
|
||||
int matches = 0;
|
||||
XVisualInfo *visinfo, template;
|
||||
|
||||
template.visualid = pdp->config->visualID;
|
||||
template.screen = pdp->config->screen;
|
||||
visinfo = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask,
|
||||
&template, &matches);
|
||||
|
||||
if (visinfo && matches) {
|
||||
pdp->xDepth = visinfo->depth;
|
||||
XFree(visinfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, or if XGetVisualInfo failed, ask the server */
|
||||
if (pdp->xDepth == 0) {
|
||||
pdp->xDepth = depth;
|
||||
}
|
||||
|
||||
pdp->swapInterval = dri_get_initial_swap_interval(psc->base.frontend_screen);
|
||||
/* Create a new drawable */
|
||||
pdp->base.dri_drawable = dri_create_drawable(psc->base.frontend_screen, config->driConfig, !(type & GLX_WINDOW_BIT), pdp);
|
||||
if (psc->kopper)
|
||||
kopperSetSwapInterval(pdp->base.dri_drawable, pdp->swapInterval);
|
||||
|
||||
if (!pdp->base.dri_drawable) {
|
||||
XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
|
||||
free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdp->base.destroyDrawable = driswDestroyDrawable;
|
||||
|
||||
return &pdp->base;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
driswSwapBuffers(__GLXDRIdrawable * pdraw,
|
||||
int64_t target_msc, int64_t divisor, int64_t remainder,
|
||||
Bool flush)
|
||||
{
|
||||
struct drisw_screen *psc = (struct drisw_screen *) pdraw->psc;
|
||||
|
||||
(void) target_msc;
|
||||
(void) divisor;
|
||||
(void) remainder;
|
||||
|
||||
if (psc->kopper)
|
||||
return kopperSwapBuffers(pdraw->dri_drawable, flush ? __DRI2_FLUSH_CONTEXT : 0);
|
||||
|
||||
if (flush) {
|
||||
CALL_Flush(GET_DISPATCH(), ());
|
||||
}
|
||||
|
||||
driSwapBuffers(pdraw->dri_drawable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drisw_copy_sub_buffer(__GLXDRIdrawable * pdraw,
|
||||
int x, int y, int width, int height, Bool flush)
|
||||
{
|
||||
if (flush) {
|
||||
CALL_Flush(GET_DISPATCH(), ());
|
||||
}
|
||||
|
||||
driswCopySubBuffer(pdraw->dri_drawable, x, y, width, height);
|
||||
}
|
||||
|
||||
static int
|
||||
driswKopperSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
|
||||
{
|
||||
struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
|
||||
struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
|
||||
|
||||
if (!dri_valid_swap_interval(psc->base.frontend_screen, interval))
|
||||
return GLX_BAD_VALUE;
|
||||
|
||||
kopperSetSwapInterval(pdp->base.dri_drawable, interval);
|
||||
pdp->swapInterval = interval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
kopperGetSwapInterval(__GLXDRIdrawable *pdraw)
|
||||
{
|
||||
struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
|
||||
|
||||
return pdp->swapInterval;
|
||||
}
|
||||
|
||||
static int
|
||||
kopperWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
|
||||
int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
|
||||
{
|
||||
return kopperGetSyncValues(pdraw->dri_drawable, target_msc, divisor, remainder, ust, msc, sbc);
|
||||
}
|
||||
|
||||
static int
|
||||
kopperGetDrawableMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
|
||||
int64_t *ust, int64_t *msc, int64_t *sbc)
|
||||
{
|
||||
return kopperGetSyncValues(pdraw->dri_drawable, 0, 0, 0, ust, msc, sbc);
|
||||
}
|
||||
|
||||
|
||||
struct glx_screen *
|
||||
driswCreateScreen(int screen, struct glx_display *priv, enum glx_driver glx_driver, bool driver_name_is_inferred)
|
||||
{
|
||||
__GLXDRIscreen *psp;
|
||||
struct drisw_screen *psc;
|
||||
const __DRIextension **loader_extensions_local;
|
||||
bool kopper_disable = debug_get_bool_option("LIBGL_KOPPER_DISABLE", false);
|
||||
|
||||
/* this is only relevant if zink bits are set */
|
||||
glx_driver &= (GLX_DRIVER_ZINK_INFER | GLX_DRIVER_ZINK_YES);
|
||||
const char *driver = glx_driver && !kopper_disable ? "zink" : "swrast";
|
||||
|
||||
psc = calloc(1, sizeof *psc);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
psc->kopper = !strcmp(driver, "zink");
|
||||
psc->base.driverName = strdup(driver);
|
||||
|
||||
if (glx_driver)
|
||||
loader_extensions_local = kopper_extensions_noshm;
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
else if (!x11_xcb_display_supports_xshm(XGetXCBConnection(priv->dpy)))
|
||||
loader_extensions_local = loader_extensions_noshm;
|
||||
#endif
|
||||
else
|
||||
loader_extensions_local = loader_extensions_shm;
|
||||
priv->driver = glx_driver ? GLX_DRIVER_ZINK_YES : GLX_DRIVER_SW;
|
||||
|
||||
if (!dri_screen_init(&psc->base, priv, screen, -1, loader_extensions_local, driver_name_is_inferred)) {
|
||||
if (!glx_driver || !driver_name_is_inferred)
|
||||
ErrorMessageF("glx: failed to create drisw screen\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
psc->base.context_vtable = &drisw_context_vtable;
|
||||
psp = &psc->base.driScreen;
|
||||
psc->base.can_EXT_texture_from_pixmap = true;
|
||||
psp->createDrawable = driswCreateDrawable;
|
||||
psp->swapBuffers = driswSwapBuffers;
|
||||
|
||||
if (!glx_driver)
|
||||
psp->copySubBuffer = drisw_copy_sub_buffer;
|
||||
|
||||
if (psc->kopper) {
|
||||
psp->setSwapInterval = driswKopperSetSwapInterval;
|
||||
psp->getSwapInterval = kopperGetSwapInterval;
|
||||
psp->maxSwapInterval = 1;
|
||||
psp->getDrawableMSC = kopperGetDrawableMSC;
|
||||
psp->waitForMSC = kopperWaitForMSC;
|
||||
}
|
||||
|
||||
return &psc->base;
|
||||
|
||||
handle_error:
|
||||
|
||||
glx_screen_cleanup(&psc->base);
|
||||
free(psc);
|
||||
|
||||
if (glx_driver & GLX_DRIVER_ZINK_YES && !driver_name_is_inferred)
|
||||
CriticalErrorMessageF("failed to load driver: %s\n", driver);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
@@ -0,0 +1,55 @@
|
||||
/* This file was derived from drisw_glx.c which carries the following
|
||||
* copyright:
|
||||
*
|
||||
* Copyright 2008 George Sapountzis
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DRISW_PRIV_H
|
||||
#define DRISW_PRIV_H
|
||||
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include "kopper_interface.h"
|
||||
|
||||
struct drisw_display
|
||||
{
|
||||
};
|
||||
|
||||
struct drisw_screen
|
||||
{
|
||||
struct glx_screen base;
|
||||
|
||||
bool kopper;
|
||||
};
|
||||
|
||||
struct drisw_drawable
|
||||
{
|
||||
__GLXDRIdrawable base;
|
||||
|
||||
GC gc;
|
||||
struct glx_config *config;
|
||||
XImage *ximage;
|
||||
XShmSegmentInfo shminfo;
|
||||
int xDepth;
|
||||
int swapInterval;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "glx_error.h"
|
||||
#include "dri_common.h"
|
||||
#include "util/macros.h"
|
||||
#include "windows/xwindowsdri.h"
|
||||
#include "windows/windowsgl.h"
|
||||
|
||||
struct driwindows_context
|
||||
{
|
||||
struct glx_context base;
|
||||
windowsContext *windowsContext;
|
||||
};
|
||||
|
||||
struct driwindows_config
|
||||
{
|
||||
struct glx_config base;
|
||||
int pxfi;
|
||||
};
|
||||
|
||||
struct driwindows_screen
|
||||
{
|
||||
struct glx_screen base;
|
||||
struct dri_screen *driScreen;
|
||||
int event_base;
|
||||
Bool copySubBuffer;
|
||||
};
|
||||
|
||||
struct driwindows_drawable
|
||||
{
|
||||
__GLXDRIdrawable base;
|
||||
windowsDrawable *windowsDrawable;
|
||||
};
|
||||
|
||||
/**
|
||||
* GLXDRI functions
|
||||
*/
|
||||
|
||||
static void
|
||||
driwindows_destroy_context(struct glx_context *context)
|
||||
{
|
||||
struct driwindows_context *pcp = (struct driwindows_context *) context;
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
free((char *) context->extensions);
|
||||
|
||||
windows_destroy_context(pcp->windowsContext);
|
||||
|
||||
free(pcp);
|
||||
}
|
||||
|
||||
static int
|
||||
driwindows_bind_context(struct glx_context *context, GLXDrawable draw, GLXDrawable read)
|
||||
{
|
||||
struct driwindows_context *pcp = (struct driwindows_context *) context;
|
||||
struct driwindows_drawable *pdraw, *pread;
|
||||
|
||||
pdraw = (struct driwindows_drawable *) driFetchDrawable(context, draw);
|
||||
pread = (struct driwindows_drawable *) driFetchDrawable(context, read);
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (pdraw == NULL || pread == NULL)
|
||||
return GLXBadDrawable;
|
||||
|
||||
if (windows_bind_context(pcp->windowsContext,
|
||||
pdraw->windowsDrawable, pread->windowsDrawable))
|
||||
return Success;
|
||||
|
||||
return GLXBadContext;
|
||||
}
|
||||
|
||||
static void
|
||||
driwindows_unbind_context(struct glx_context *context)
|
||||
{
|
||||
struct driwindows_context *pcp = (struct driwindows_context *) context;
|
||||
|
||||
windows_unbind_context(pcp->windowsContext);
|
||||
}
|
||||
|
||||
static const struct glx_context_vtable driwindows_context_vtable = {
|
||||
.destroy = driwindows_destroy_context,
|
||||
.bind = driwindows_bind_context,
|
||||
.unbind = driwindows_unbind_context,
|
||||
.wait_gl = NULL,
|
||||
.wait_x = NULL,
|
||||
};
|
||||
|
||||
static struct glx_context *
|
||||
driwindows_create_context(struct glx_screen *base,
|
||||
struct glx_config *config_base,
|
||||
struct glx_context *shareList, int renderType)
|
||||
{
|
||||
struct driwindows_context *pcp, *pcp_shared;
|
||||
struct driwindows_config *config = (struct driwindows_config *) config_base;
|
||||
struct driwindows_screen *psc = (struct driwindows_screen *) base;
|
||||
windowsContext *shared = NULL;
|
||||
|
||||
/* Check the renderType value */
|
||||
if (!validate_renderType_against_config(config_base, renderType))
|
||||
return NULL;
|
||||
|
||||
if (shareList) {
|
||||
/* If the shareList context is not on this renderer, we cannot possibly
|
||||
* create a context that shares with it.
|
||||
*/
|
||||
if (shareList->vtable->destroy != driwindows_destroy_context) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp_shared = (struct driwindows_context *) shareList;
|
||||
shared = pcp_shared->windowsContext;
|
||||
}
|
||||
|
||||
pcp = calloc(1, sizeof *pcp);
|
||||
if (pcp == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
|
||||
free(pcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp->base.renderType = renderType;
|
||||
|
||||
InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
|
||||
|
||||
pcp->windowsContext = windows_create_context(config->pxfi, shared);
|
||||
|
||||
if (!pcp->windowsContext) {
|
||||
free(pcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp->base.vtable = &driwindows_context_vtable;
|
||||
|
||||
return &pcp->base;
|
||||
}
|
||||
|
||||
static struct glx_context *
|
||||
driwindows_create_context_attribs(struct glx_screen *base,
|
||||
struct glx_config *config_base,
|
||||
struct glx_context *shareList,
|
||||
unsigned num_attribs,
|
||||
const uint32_t *attribs,
|
||||
unsigned *error)
|
||||
{
|
||||
struct driwindows_context *pcp, *pcp_shared;
|
||||
struct driwindows_config *config = (struct driwindows_config *) config_base;
|
||||
struct driwindows_screen *psc = (struct driwindows_screen *) base;
|
||||
windowsContext *shared = NULL;
|
||||
|
||||
int i;
|
||||
uint32_t renderType = GLX_RGBA_TYPE;
|
||||
|
||||
/* Extract renderType from attribs */
|
||||
for (i = 0; i < num_attribs; i++) {
|
||||
switch (attribs[i * 2]) {
|
||||
case GLX_RENDER_TYPE:
|
||||
renderType = attribs[i * 2 + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Perhaps we should map GLX tokens to WGL tokens, but they appear to have
|
||||
identical values, so far
|
||||
*/
|
||||
|
||||
if (!config_base)
|
||||
return NULL;
|
||||
|
||||
/* Check the renderType value */
|
||||
if (!validate_renderType_against_config(config_base, renderType)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (shareList) {
|
||||
/* If the shareList context is not on this renderer, we cannot possibly
|
||||
* create a context that shares with it.
|
||||
*/
|
||||
if (shareList->vtable->destroy != driwindows_destroy_context) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp_shared = (struct driwindows_context *) shareList;
|
||||
shared = pcp_shared->windowsContext;
|
||||
}
|
||||
|
||||
pcp = calloc(1, sizeof *pcp);
|
||||
if (pcp == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
|
||||
free(pcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp->base.renderType = renderType;
|
||||
|
||||
InfoMessageF("visualID %x, fbConfigID %x -> pxfi %d\n", config_base->visualID, config_base->fbconfigID, config->pxfi);
|
||||
|
||||
pcp->windowsContext = windows_create_context_attribs(config->pxfi,
|
||||
shared,
|
||||
(const int *)attribs);
|
||||
if (pcp->windowsContext == NULL) {
|
||||
free(pcp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcp->base.vtable = &driwindows_context_vtable;
|
||||
|
||||
return &pcp->base;
|
||||
}
|
||||
|
||||
static void
|
||||
driwindowsDestroyDrawable(__GLXDRIdrawable * pdraw)
|
||||
{
|
||||
struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
|
||||
|
||||
windows_destroy_drawable(pdp->windowsDrawable);
|
||||
|
||||
free(pdp);
|
||||
}
|
||||
|
||||
static __GLXDRIdrawable *
|
||||
driwindowsCreateDrawable(struct glx_screen *base, XID xDrawable,
|
||||
GLXDrawable drawable, int type,
|
||||
struct glx_config *modes)
|
||||
{
|
||||
struct driwindows_drawable *pdp;
|
||||
struct driwindows_screen *psc = (struct driwindows_screen *) base;
|
||||
|
||||
pdp = calloc(1, sizeof(*pdp));
|
||||
if (!pdp)
|
||||
return NULL;
|
||||
|
||||
pdp->base.xDrawable = xDrawable;
|
||||
pdp->base.drawable = drawable;
|
||||
pdp->base.psc = &psc->base;
|
||||
|
||||
/*
|
||||
By this stage, the X drawable already exists, but the GLX drawable may
|
||||
not.
|
||||
|
||||
Query the server with the XID to find the correct HWND, HPBUFFERARB or
|
||||
HBITMAP
|
||||
*/
|
||||
|
||||
unsigned int drawable_type;
|
||||
void *handle;
|
||||
|
||||
if (!XWindowsDRIQueryDrawable(psc->base.dpy, base->scr, drawable, &drawable_type, &handle))
|
||||
{
|
||||
free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* No handle found is a failure */
|
||||
if (!handle) {
|
||||
free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a new drawable */
|
||||
pdp->windowsDrawable = windows_create_drawable(drawable_type, handle);
|
||||
|
||||
if (!pdp->windowsDrawable) {
|
||||
free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdp->base.destroyDrawable = driwindowsDestroyDrawable;
|
||||
|
||||
return &pdp->base;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
driwindowsSwapBuffers(__GLXDRIdrawable * pdraw,
|
||||
int64_t target_msc, int64_t divisor, int64_t remainder,
|
||||
Bool flush)
|
||||
{
|
||||
struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
|
||||
|
||||
(void) target_msc;
|
||||
(void) divisor;
|
||||
(void) remainder;
|
||||
|
||||
if (flush) {
|
||||
glFlush();
|
||||
}
|
||||
|
||||
windows_swap_buffers(pdp->windowsDrawable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
driwindowsCopySubBuffer(__GLXDRIdrawable * pdraw,
|
||||
int x, int y, int width, int height, Bool flush)
|
||||
{
|
||||
struct driwindows_drawable *pdp = (struct driwindows_drawable *) pdraw;
|
||||
|
||||
if (flush) {
|
||||
glFlush();
|
||||
}
|
||||
|
||||
windows_copy_subbuffer(pdp->windowsDrawable, x, y, width, height);
|
||||
}
|
||||
|
||||
static const struct glx_screen_vtable driwindows_screen_vtable = {
|
||||
.create_context = driwindows_create_context,
|
||||
.create_context_attribs = driwindows_create_context_attribs,
|
||||
.query_renderer_integer = NULL,
|
||||
.query_renderer_string = NULL,
|
||||
};
|
||||
|
||||
static Bool
|
||||
driwindowsBindExtensions(struct driwindows_screen *psc)
|
||||
{
|
||||
Bool result = 1;
|
||||
|
||||
const struct
|
||||
{
|
||||
char *wglext;
|
||||
char *glxext;
|
||||
Bool mandatory;
|
||||
} extensionMap[] = {
|
||||
{ "WGL_ARB_make_current_read", "GLX_SGI_make_current_read", 0 },
|
||||
{ "WGL_EXT_swap_control", "GLX_SGI_swap_control", 0 },
|
||||
{ "WGL_EXT_swap_control", "GLX_MESA_swap_control", 0 },
|
||||
// { "WGL_ARB_render_texture", "GLX_EXT_texture_from_pixmap", 0 },
|
||||
// Not exactly equivalent, needs some more glue to be written
|
||||
{ "WGL_ARB_pbuffer", "GLX_SGIX_pbuffer", 1 },
|
||||
{ "WGL_ARB_multisample", "GLX_ARB_multisample", 1 },
|
||||
{ "WGL_ARB_multisample", "GLX_SGIS_multisample", 1 },
|
||||
{ "WGL_ARB_create_context", "GLX_ARB_create_context", 0 },
|
||||
{ "WGL_ARB_create_context_profile", "GLX_ARB_create_context_profile", 0 },
|
||||
{ "WGL_ARB_create_context_robustness", "GLX_ARB_create_context_robustness", 0 },
|
||||
{ "WGL_EXT_create_context_es2_profile", "GLX_EXT_create_context_es2_profile", 0 },
|
||||
};
|
||||
|
||||
char *wgl_extensions;
|
||||
char *gl_extensions;
|
||||
int i;
|
||||
|
||||
windows_extensions(&gl_extensions, &wgl_extensions);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(extensionMap); i++) {
|
||||
if (strstr(wgl_extensions, extensionMap[i].wglext)) {
|
||||
__glXEnableDirectExtension(&psc->base, extensionMap[i].glxext);
|
||||
InfoMessageF("enabled %s\n", extensionMap[i].glxext);
|
||||
}
|
||||
else if (extensionMap[i].mandatory) {
|
||||
ErrorMessageF("required WGL extension %s is missing\n", extensionMap[i].wglext);
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Because it pre-dates WGL_EXT_extensions_string, GL_WIN_swap_hint might
|
||||
only be in GL_EXTENSIONS
|
||||
*/
|
||||
if (strstr(gl_extensions, "GL_WIN_swap_hint")) {
|
||||
psc->copySubBuffer = 1;
|
||||
__glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
|
||||
InfoMessageF("enabled GLX_MESA_copy_sub_buffer\n");
|
||||
}
|
||||
|
||||
free(gl_extensions);
|
||||
free(wgl_extensions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct glx_config *
|
||||
driwindowsMapConfigs(struct glx_display *priv, int screen, struct glx_config *configs, struct glx_config *fbconfigs)
|
||||
{
|
||||
struct glx_config head, *tail, *m;
|
||||
|
||||
tail = &head;
|
||||
head.next = NULL;
|
||||
|
||||
for (m = configs; m; m = m->next) {
|
||||
int fbconfigID = GLX_DONT_CARE;
|
||||
if (fbconfigs) {
|
||||
/*
|
||||
visuals have fbconfigID of GLX_DONT_CARE, so search for a fbconfig
|
||||
with matching visualID and get the fbconfigID from there
|
||||
*/
|
||||
struct glx_config *f;
|
||||
for (f = fbconfigs; f; f = f->next) {
|
||||
if (f->visualID == m->visualID)
|
||||
fbconfigID = f->fbconfigID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fbconfigID = m->fbconfigID;
|
||||
}
|
||||
|
||||
int pxfi;
|
||||
XWindowsDRIFBConfigToPixelFormat(priv->dpy, screen, fbconfigID, &pxfi);
|
||||
if (pxfi == 0)
|
||||
continue;
|
||||
|
||||
struct driwindows_config *config = malloc(sizeof(*config));
|
||||
|
||||
tail->next = &config->base;
|
||||
if (tail->next == NULL)
|
||||
continue;
|
||||
|
||||
config->base = *m;
|
||||
config->pxfi = pxfi;
|
||||
|
||||
tail = tail->next;
|
||||
}
|
||||
|
||||
return head.next;
|
||||
}
|
||||
|
||||
struct glx_screen *
|
||||
driwindowsCreateScreen(int screen, struct glx_display *priv, bool driver_name_is_inferred)
|
||||
{
|
||||
__GLXDRIscreen *psp;
|
||||
struct driwindows_screen *psc;
|
||||
struct glx_config *configs = NULL, *visuals = NULL;
|
||||
int directCapable;
|
||||
int eventBase, errorBase;
|
||||
int major, minor, patch;
|
||||
|
||||
/* Verify server has Windows-DRI extension */
|
||||
if (!XWindowsDRIQueryExtension(priv->dpy, &eventBase, &errorBase)) {
|
||||
ErrorMessageF("Windows-DRI extension not available\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!XWindowsDRIQueryVersion(priv->dpy, &major, &minor, &patch)) {
|
||||
ErrorMessageF("Fetching Windows-DRI extension version failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!windows_check_renderer()) {
|
||||
ErrorMessageF("Windows-DRI extension disabled for GDI Generic renderer\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
psc = calloc(1, sizeof *psc);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!glx_screen_init(&psc->base, screen, priv)) {
|
||||
free(psc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!XWindowsDRIQueryDirectRenderingCapable(psc->base.dpy, screen, &directCapable) ||
|
||||
!directCapable) {
|
||||
ErrorMessageF("Screen is not Windows-DRI capable\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
/* discover native supported extensions */
|
||||
if (!driwindowsBindExtensions(psc)) {
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
/* Augment configs with pxfi information */
|
||||
configs = driwindowsMapConfigs(priv, screen, psc->base.configs, NULL);
|
||||
visuals = driwindowsMapConfigs(priv, screen, psc->base.visuals, configs);
|
||||
|
||||
if (!configs || !visuals) {
|
||||
ErrorMessageF("No fbConfigs or visuals found\n");
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
glx_config_destroy_list(psc->base.configs);
|
||||
psc->base.configs = configs;
|
||||
glx_config_destroy_list(psc->base.visuals);
|
||||
psc->base.visuals = visuals;
|
||||
|
||||
psc->base.vtable = &driwindows_screen_vtable;
|
||||
psp = &psc->base.driScreen;
|
||||
psp->createDrawable = driwindowsCreateDrawable;
|
||||
psp->swapBuffers = driwindowsSwapBuffers;
|
||||
|
||||
if (psc->copySubBuffer)
|
||||
psp->copySubBuffer = driwindowsCopySubBuffer;
|
||||
|
||||
priv->driver = GLX_DRIVER_WINDOWS;
|
||||
|
||||
return &psc->base;
|
||||
|
||||
handle_error:
|
||||
glx_screen_cleanup(&psc->base);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
|
||||
/*
|
||||
** Routines to pack evaluator maps into the transport buffer. Maps are
|
||||
** allowed to have extra arbitrary data, so these routines extract just
|
||||
** the information that the GL needs.
|
||||
*/
|
||||
|
||||
void
|
||||
__glFillMap1f(GLint k, GLint order, GLint stride,
|
||||
const GLfloat * points, GLubyte * pc)
|
||||
{
|
||||
if (stride == k) {
|
||||
/* Just copy the data */
|
||||
__GLX_PUT_FLOAT_ARRAY(0, points, order * k);
|
||||
}
|
||||
else {
|
||||
GLint i;
|
||||
|
||||
for (i = 0; i < order; i++) {
|
||||
__GLX_PUT_FLOAT_ARRAY(0, points, k);
|
||||
points += stride;
|
||||
pc += k * __GLX_SIZE_FLOAT32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__glFillMap1d(GLint k, GLint order, GLint stride,
|
||||
const GLdouble * points, GLubyte * pc)
|
||||
{
|
||||
if (stride == k) {
|
||||
/* Just copy the data */
|
||||
__GLX_PUT_DOUBLE_ARRAY(0, points, order * k);
|
||||
}
|
||||
else {
|
||||
GLint i;
|
||||
for (i = 0; i < order; i++) {
|
||||
__GLX_PUT_DOUBLE_ARRAY(0, points, k);
|
||||
points += stride;
|
||||
pc += k * __GLX_SIZE_FLOAT64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__glFillMap2f(GLint k, GLint majorOrder, GLint minorOrder,
|
||||
GLint majorStride, GLint minorStride,
|
||||
const GLfloat * points, GLfloat * data)
|
||||
{
|
||||
GLint i, j, x;
|
||||
|
||||
if ((minorStride == k) && (majorStride == minorOrder * k)) {
|
||||
/* Just copy the data */
|
||||
__GLX_MEM_COPY(data, points, majorOrder * majorStride *
|
||||
__GLX_SIZE_FLOAT32);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < majorOrder; i++) {
|
||||
for (j = 0; j < minorOrder; j++) {
|
||||
for (x = 0; x < k; x++) {
|
||||
data[x] = points[x];
|
||||
}
|
||||
points += minorStride;
|
||||
data += k;
|
||||
}
|
||||
points += majorStride - minorStride * minorOrder;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__glFillMap2d(GLint k, GLint majorOrder, GLint minorOrder,
|
||||
GLint majorStride, GLint minorStride,
|
||||
const GLdouble * points, GLdouble * data)
|
||||
{
|
||||
int i, j, x;
|
||||
|
||||
if ((minorStride == k) && (majorStride == minorOrder * k)) {
|
||||
/* Just copy the data */
|
||||
__GLX_MEM_COPY(data, points, majorOrder * majorStride *
|
||||
__GLX_SIZE_FLOAT64);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __GLX_ALIGN64
|
||||
x = k * __GLX_SIZE_FLOAT64;
|
||||
#endif
|
||||
for (i = 0; i < majorOrder; i++) {
|
||||
for (j = 0; j < minorOrder; j++) {
|
||||
#ifdef __GLX_ALIGN64
|
||||
__GLX_MEM_COPY(data, points, x);
|
||||
#else
|
||||
for (x = 0; x < k; x++) {
|
||||
data[x] = points[x];
|
||||
}
|
||||
#endif
|
||||
points += minorStride;
|
||||
data += k;
|
||||
}
|
||||
points += majorStride - minorStride * minorOrder;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED BY gen_scrn_dispatch.pl
|
||||
* DO NOT EDIT!!
|
||||
*/
|
||||
#ifndef __glxlibglvnd_dispatchindex_h__
|
||||
#define __glxlibglvnd_dispatchindex_h__
|
||||
|
||||
typedef enum __GLXdispatchIndex {
|
||||
DI_BindSwapBarrierSGIX,
|
||||
DI_BindTexImageEXT,
|
||||
// ChooseFBConfig implemented by libglvnd
|
||||
DI_ChooseFBConfigSGIX,
|
||||
// ChooseVisual implemented by libglvnd
|
||||
// CopyContext implemented by libglvnd
|
||||
DI_CopySubBufferMESA,
|
||||
// CreateContext implemented by libglvnd
|
||||
DI_CreateContextAttribsARB,
|
||||
DI_CreateContextWithConfigSGIX,
|
||||
DI_CreateGLXPbufferSGIX,
|
||||
// CreateGLXPixmap implemented by libglvnd
|
||||
DI_CreateGLXPixmapMESA,
|
||||
DI_CreateGLXPixmapWithConfigSGIX,
|
||||
// CreateNewContext implemented by libglvnd
|
||||
// CreatePbuffer implemented by libglvnd
|
||||
// CreatePixmap implemented by libglvnd
|
||||
// CreateWindow implemented by libglvnd
|
||||
// DestroyContext implemented by libglvnd
|
||||
DI_DestroyGLXPbufferSGIX,
|
||||
// DestroyGLXPixmap implemented by libglvnd
|
||||
// DestroyPbuffer implemented by libglvnd
|
||||
// DestroyPixmap implemented by libglvnd
|
||||
// DestroyWindow implemented by libglvnd
|
||||
// FreeContextEXT implemented by libglvnd
|
||||
DI_GLInteropExportObjectMESA,
|
||||
DI_GLInteropFlushObjectsMESA,
|
||||
DI_GLInteropQueryDeviceInfoMESA,
|
||||
// GetClientString implemented by libglvnd
|
||||
// GetConfig implemented by libglvnd
|
||||
DI_GetContextIDEXT,
|
||||
// GetCurrentContext implemented by libglvnd
|
||||
// GetCurrentDisplay implemented by libglvnd
|
||||
DI_GetCurrentDisplayEXT,
|
||||
// GetCurrentDrawable implemented by libglvnd
|
||||
// GetCurrentReadDrawable implemented by libglvnd
|
||||
DI_GetDriverConfig,
|
||||
// GetFBConfigAttrib implemented by libglvnd
|
||||
DI_GetFBConfigAttribSGIX,
|
||||
DI_GetFBConfigFromVisualSGIX,
|
||||
// GetFBConfigs implemented by libglvnd
|
||||
DI_GetMscRateOML,
|
||||
// GetProcAddress implemented by libglvnd
|
||||
// GetProcAddressARB implemented by libglvnd
|
||||
DI_GetScreenDriver,
|
||||
// GetSelectedEvent implemented by libglvnd
|
||||
DI_GetSelectedEventSGIX,
|
||||
DI_GetSwapIntervalMESA,
|
||||
DI_GetSyncValuesOML,
|
||||
DI_GetVideoSyncSGI,
|
||||
// GetVisualFromFBConfig implemented by libglvnd
|
||||
DI_GetVisualFromFBConfigSGIX,
|
||||
// ImportContextEXT implemented by libglvnd
|
||||
// IsDirect implemented by libglvnd
|
||||
DI_JoinSwapGroupSGIX,
|
||||
// MakeContextCurrent implemented by libglvnd
|
||||
// MakeCurrent implemented by libglvnd
|
||||
// QueryContext implemented by libglvnd
|
||||
DI_QueryContextInfoEXT,
|
||||
DI_QueryCurrentRendererIntegerMESA,
|
||||
DI_QueryCurrentRendererStringMESA,
|
||||
// QueryDrawable implemented by libglvnd
|
||||
// QueryExtension implemented by libglvnd
|
||||
// QueryExtensionsString implemented by libglvnd
|
||||
DI_QueryGLXPbufferSGIX,
|
||||
DI_QueryMaxSwapBarriersSGIX,
|
||||
DI_QueryRendererIntegerMESA,
|
||||
DI_QueryRendererStringMESA,
|
||||
// QueryServerString implemented by libglvnd
|
||||
// QueryVersion implemented by libglvnd
|
||||
DI_ReleaseBuffersMESA,
|
||||
DI_ReleaseTexImageEXT,
|
||||
// SelectEvent implemented by libglvnd
|
||||
DI_SelectEventSGIX,
|
||||
// SwapBuffers implemented by libglvnd
|
||||
DI_SwapBuffersMscOML,
|
||||
DI_SwapIntervalEXT,
|
||||
DI_SwapIntervalMESA,
|
||||
DI_SwapIntervalSGI,
|
||||
// UseXFont implemented by libglvnd
|
||||
DI_WaitForMscOML,
|
||||
DI_WaitForSbcOML,
|
||||
// WaitGL implemented by libglvnd
|
||||
DI_WaitVideoSyncSGI,
|
||||
// WaitX implemented by libglvnd
|
||||
DI_LAST_INDEX
|
||||
} __GLXdispatchIndex;
|
||||
|
||||
#endif // __glxlibglvnd_dispatchindex_h__
|
||||
@@ -0,0 +1,4 @@
|
||||
__glx_Main
|
||||
MesaGLInteropGLXExportObject
|
||||
MesaGLInteropGLXFlushObjects
|
||||
MesaGLInteropGLXQueryDeviceInfo
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright (c) 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/extensions/extutil.h>
|
||||
#include <X11/extensions/Xext.h>
|
||||
#include "glxclient.h"
|
||||
#include "glx_error.h"
|
||||
|
||||
void
|
||||
__glXSendError(Display * dpy, int_fast8_t errorCode, uint_fast32_t resourceID,
|
||||
uint_fast16_t minorCode, bool coreX11error)
|
||||
{
|
||||
struct glx_display *glx_dpy = __glXInitialize(dpy);
|
||||
xError error;
|
||||
|
||||
assert(glx_dpy);
|
||||
|
||||
LockDisplay(dpy);
|
||||
|
||||
error.type = X_Error;
|
||||
|
||||
if (coreX11error) {
|
||||
error.errorCode = errorCode;
|
||||
}
|
||||
else {
|
||||
error.errorCode = glx_dpy->codes.first_error + errorCode;
|
||||
}
|
||||
|
||||
error.sequenceNumber = dpy->request;
|
||||
error.resourceID = resourceID;
|
||||
error.minorCode = minorCode;
|
||||
error.majorCode = glx_dpy->codes.major_opcode;
|
||||
|
||||
_XError(dpy, &error);
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
}
|
||||
|
||||
void
|
||||
__glXSendErrorForXcb(Display * dpy, const xcb_generic_error_t *err)
|
||||
{
|
||||
xError error;
|
||||
|
||||
LockDisplay(dpy);
|
||||
|
||||
error.type = X_Error;
|
||||
error.errorCode = err->error_code;
|
||||
error.sequenceNumber = err->sequence;
|
||||
error.resourceID = err->resource_id;
|
||||
error.minorCode = err->minor_code;
|
||||
error.majorCode = err->major_code;
|
||||
|
||||
_XError(dpy, &error);
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2009 Apple Inc.
|
||||
|
||||
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 THE ABOVE LISTED COPYRIGHT
|
||||
HOLDER(S) 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.
|
||||
|
||||
Except as contained in this notice, the name(s) of the above
|
||||
copyright holders shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Software without
|
||||
prior written authorization.
|
||||
*/
|
||||
|
||||
#ifndef GLX_ERROR_H
|
||||
#define GLX_ERROR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void __glXSendError(Display * dpy, int_fast8_t errorCode,
|
||||
uint_fast32_t resourceID, uint_fast16_t minorCode,
|
||||
bool coreX11error);
|
||||
|
||||
void __glXSendErrorForXcb(Display * dpy,
|
||||
const xcb_generic_error_t *err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2004
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glx_query.c
|
||||
* Generic utility functions to query internal data from the server.
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
|
||||
# include <X11/Xlib-xcb.h>
|
||||
# include <xcb/xcb.h>
|
||||
# include <xcb/glx.h>
|
||||
|
||||
|
||||
/**
|
||||
* Exchange a protocol request for glXQueryServerString.
|
||||
*/
|
||||
char *
|
||||
__glXQueryServerString(Display * dpy, CARD32 screen, CARD32 name)
|
||||
{
|
||||
xcb_connection_t *c = XGetXCBConnection(dpy);
|
||||
xcb_glx_query_server_string_reply_t *reply =
|
||||
xcb_glx_query_server_string_reply(c,
|
||||
xcb_glx_query_server_string(c,
|
||||
screen,
|
||||
name),
|
||||
NULL);
|
||||
|
||||
if (!reply)
|
||||
return NULL;
|
||||
|
||||
/* The spec doesn't mention this, but the Xorg server replies with
|
||||
* a string already terminated with '\0'. */
|
||||
uint32_t len = xcb_glx_query_server_string_string_length(reply);
|
||||
char *buf = malloc(len);
|
||||
memcpy(buf, xcb_glx_query_server_string_string(reply), len);
|
||||
free(reply);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange a protocol request for glGetString.
|
||||
*/
|
||||
char *
|
||||
__glXGetString(Display * dpy, CARD32 contextTag, CARD32 name)
|
||||
{
|
||||
xcb_connection_t *c = XGetXCBConnection(dpy);
|
||||
xcb_glx_get_string_reply_t *reply = xcb_glx_get_string_reply(c,
|
||||
xcb_glx_get_string
|
||||
(c,
|
||||
contextTag,
|
||||
name),
|
||||
NULL);
|
||||
|
||||
if (!reply)
|
||||
return NULL;
|
||||
|
||||
/* The spec doesn't mention this, but the Xorg server replies with
|
||||
* a string already terminated with '\0'. */
|
||||
uint32_t len = xcb_glx_get_string_string_length(reply);
|
||||
char *buf = malloc(len);
|
||||
memcpy(buf, xcb_glx_get_string_string(reply), len);
|
||||
free(reply);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,803 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxclient.h
|
||||
* Direct rendering support added by Precision Insight, Inc.
|
||||
*
|
||||
* \author Kevin E. Martin <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef _GLX_client_h_
|
||||
#define _GLX_client_h_
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/Xfuncproto.h>
|
||||
#include <X11/extensions/extutil.h>
|
||||
#define GLX_GLXEXT_PROTOTYPES
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include "GL/glxproto.h"
|
||||
#include "glxconfig.h"
|
||||
#include "glxhash.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/u_thread.h"
|
||||
#include "util/set.h"
|
||||
#include "loader.h"
|
||||
#include "glxextensions.h"
|
||||
|
||||
/* bits */
|
||||
enum glx_driver {
|
||||
GLX_DRIVER_NONE = 0,
|
||||
GLX_DRIVER_ZINK_INFER = (1<<0),
|
||||
GLX_DRIVER_SW = (1<<1),
|
||||
GLX_DRIVER_DRI3 = (1<<2),
|
||||
GLX_DRIVER_WINDOWS = (1<<3),
|
||||
GLX_DRIVER_ZINK_YES = (1<<4),
|
||||
};
|
||||
|
||||
#if USE_LIBGLVND
|
||||
#define _GLX_PUBLIC _X_HIDDEN
|
||||
#else
|
||||
#define _GLX_PUBLIC _X_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void glx_message(int level, const char *f, ...) PRINTFLIKE(2, 3);
|
||||
|
||||
#define DebugMessageF(...) glx_message(_LOADER_DEBUG, __VA_ARGS__)
|
||||
#define InfoMessageF(...) glx_message(_LOADER_INFO, __VA_ARGS__)
|
||||
#define ErrorMessageF(...) glx_message(_LOADER_WARNING, __VA_ARGS__)
|
||||
#define CriticalErrorMessageF(...) glx_message(_LOADER_FATAL, __VA_ARGS__)
|
||||
|
||||
|
||||
#define GLX_MAJOR_VERSION 1 /* current version numbers */
|
||||
#define GLX_MINOR_VERSION 4
|
||||
|
||||
struct glx_display;
|
||||
struct glx_context;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
|
||||
extern void DRI_glXUseXFont(struct glx_context *ctx,
|
||||
Font font, int first, int count, int listbase);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
|
||||
/**
|
||||
* Display dependent methods. This structure is initialized during the
|
||||
* \c driCreateDisplay call.
|
||||
*/
|
||||
typedef struct __GLXDRIdisplay __GLXDRIdisplay;
|
||||
typedef struct __GLXDRIscreenRec __GLXDRIscreen;
|
||||
typedef struct __GLXDRIdrawableRec __GLXDRIdrawable;
|
||||
|
||||
struct __GLXDRIscreenRec {
|
||||
|
||||
void (*deinitScreen)(struct glx_screen *psc);
|
||||
|
||||
__GLXDRIdrawable *(*createDrawable)(struct glx_screen *psc,
|
||||
XID drawable,
|
||||
GLXDrawable glxDrawable,
|
||||
int type,
|
||||
struct glx_config *config);
|
||||
|
||||
int64_t (*swapBuffers)(__GLXDRIdrawable *pdraw, int64_t target_msc,
|
||||
int64_t divisor, int64_t remainder, Bool flush);
|
||||
void (*copySubBuffer)(__GLXDRIdrawable *pdraw,
|
||||
int x, int y, int width, int height, Bool flush);
|
||||
int (*getDrawableMSC)(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
|
||||
int64_t *ust, int64_t *msc, int64_t *sbc);
|
||||
int (*waitForMSC)(__GLXDRIdrawable *pdraw, int64_t target_msc,
|
||||
int64_t divisor, int64_t remainder, int64_t *ust,
|
||||
int64_t *msc, int64_t *sbc);
|
||||
int (*waitForSBC)(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
|
||||
int64_t *msc, int64_t *sbc);
|
||||
int (*setSwapInterval)(__GLXDRIdrawable *pdraw, int interval);
|
||||
int (*getSwapInterval)(__GLXDRIdrawable *pdraw);
|
||||
void (*bindTexImage)(__GLXDRIdrawable *pdraw, int buffer, const int *attribs);
|
||||
|
||||
int maxSwapInterval;
|
||||
};
|
||||
|
||||
struct __GLXDRIdrawableRec
|
||||
{
|
||||
void (*destroyDrawable) (__GLXDRIdrawable * drawable);
|
||||
|
||||
XID xDrawable;
|
||||
XID drawable;
|
||||
struct glx_screen *psc;
|
||||
GLenum textureTarget;
|
||||
GLenum textureFormat; /* EXT_texture_from_pixmap support */
|
||||
unsigned long eventMask;
|
||||
int refcount;
|
||||
|
||||
struct dri_drawable *dri_drawable;
|
||||
};
|
||||
|
||||
/*
|
||||
** Function to create and DRI display data and initialize the display
|
||||
** dependent methods.
|
||||
*/
|
||||
extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy, enum glx_driver glx_driver);
|
||||
extern __GLXDRIdisplay *dri3_create_display(Display * dpy);
|
||||
extern __GLXDRIdisplay *driwindowsCreateDisplay(Display * dpy);
|
||||
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
struct glx_screen *dri3_create_screen(int screen, struct glx_display * priv, bool driver_name_is_inferred, bool *return_zink);
|
||||
void dri3_destroy_display(__GLXDRIdisplay * dpy);
|
||||
|
||||
|
||||
bool dri2CheckSupport(Display *dpy);
|
||||
struct glx_screen *dri2CreateScreen(int screen, struct glx_display * priv, bool driver_name_is_inferred);
|
||||
void dri2DestroyDisplay(__GLXDRIdisplay * dpy);
|
||||
|
||||
struct glx_screen *driswCreateScreen(int screen, struct glx_display *priv, enum glx_driver driver, bool driver_name_is_inferred);
|
||||
void driswDestroyDisplay(__GLXDRIdisplay * dpy);
|
||||
#endif
|
||||
|
||||
#ifdef GLX_USE_WINDOWSGL
|
||||
struct glx_screen *driwindowsCreateScreen(int screen, struct glx_display *priv, bool driver_name_is_inferred);
|
||||
void driwindowsDestroyDisplay(__GLXDRIdisplay * dpy);
|
||||
#endif
|
||||
/*
|
||||
**
|
||||
*/
|
||||
extern void dri2InvalidateBuffers(Display *dpy, XID drawable);
|
||||
extern unsigned dri2GetSwapEventType(Display *dpy, XID drawable);
|
||||
|
||||
/*
|
||||
** Functions to obtain driver configuration information from a direct
|
||||
** rendering client application
|
||||
*/
|
||||
extern const char *glXGetScreenDriver(Display * dpy, int scrNum);
|
||||
|
||||
extern const char *glXGetDriverConfig(const char *driverName);
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#define __GL_CLIENT_ATTRIB_STACK_DEPTH 16
|
||||
|
||||
typedef struct __GLXpixelStoreModeRec
|
||||
{
|
||||
GLboolean swapEndian;
|
||||
GLboolean lsbFirst;
|
||||
GLuint rowLength;
|
||||
GLuint imageHeight;
|
||||
GLuint imageDepth;
|
||||
GLuint skipRows;
|
||||
GLuint skipPixels;
|
||||
GLuint skipImages;
|
||||
GLuint alignment;
|
||||
} __GLXpixelStoreMode;
|
||||
|
||||
|
||||
typedef struct __GLXattributeRec
|
||||
{
|
||||
GLuint mask;
|
||||
|
||||
/**
|
||||
* Pixel storage state. Most of the pixel store mode state is kept
|
||||
* here and used by the client code to manage the packing and
|
||||
* unpacking of data sent to/received from the server.
|
||||
*/
|
||||
__GLXpixelStoreMode storePack, storeUnpack;
|
||||
|
||||
/**
|
||||
* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
|
||||
* disabled?
|
||||
*/
|
||||
GLboolean NoDrawArraysProtocol;
|
||||
|
||||
/**
|
||||
* Vertex Array storage state. The vertex array component
|
||||
* state is stored here and is used to manage the packing of
|
||||
* DrawArrays data sent to the server.
|
||||
*/
|
||||
struct array_state_vector *array_state;
|
||||
} __GLXattribute;
|
||||
|
||||
typedef struct __GLXattributeMachineRec
|
||||
{
|
||||
__GLXattribute *stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];
|
||||
__GLXattribute **stackPointer;
|
||||
} __GLXattributeMachine;
|
||||
|
||||
struct mesa_glinterop_device_info;
|
||||
struct mesa_glinterop_export_in;
|
||||
struct mesa_glinterop_export_out;
|
||||
struct mesa_glinterop_flush_out;
|
||||
|
||||
struct glx_context_vtable {
|
||||
void (*destroy)(struct glx_context *ctx);
|
||||
int (*bind)(struct glx_context *context, GLXDrawable draw, GLXDrawable read);
|
||||
void (*unbind)(struct glx_context *context);
|
||||
void (*wait_gl)(struct glx_context *ctx);
|
||||
void (*wait_x)(struct glx_context *ctx);
|
||||
};
|
||||
|
||||
/**
|
||||
* GLX state that needs to be kept on the client. One of these records
|
||||
* exist for each context that has been made current by this client.
|
||||
*/
|
||||
struct glx_context
|
||||
{
|
||||
/**
|
||||
* \name Drawing command buffer.
|
||||
*
|
||||
* Drawing commands are packed into this buffer before being sent as a
|
||||
* single GLX protocol request. The buffer is sent when it overflows or
|
||||
* is flushed by \c __glXFlushRenderBuffer. \c pc is the next location
|
||||
* in the buffer to be filled. \c limit is described above in the buffer
|
||||
* slop discussion.
|
||||
*
|
||||
* Commands that require large amounts of data to be transferred will
|
||||
* also use this buffer to hold a header that describes the large
|
||||
* command.
|
||||
*
|
||||
* These must be the first 6 fields since they are static initialized
|
||||
* in the dummy context in glxext.c
|
||||
*/
|
||||
/*@{ */
|
||||
GLubyte *buf;
|
||||
GLubyte *pc;
|
||||
GLubyte *limit;
|
||||
GLubyte *bufEnd;
|
||||
GLint bufSize;
|
||||
/*@} */
|
||||
|
||||
const struct glx_context_vtable *vtable;
|
||||
|
||||
/**
|
||||
* The XID of this rendering context. When the context is created a
|
||||
* new XID is allocated. This is set to None when the context is
|
||||
* destroyed but is still current to some thread. In this case the
|
||||
* context will be freed on next MakeCurrent.
|
||||
*/
|
||||
XID xid;
|
||||
|
||||
/**
|
||||
* The XID of the \c shareList context.
|
||||
*/
|
||||
XID share_xid;
|
||||
|
||||
struct glx_screen *psc;
|
||||
|
||||
/**
|
||||
* \c GL_TRUE if the context was created with ImportContext, which
|
||||
* means the server-side context was created by another X client.
|
||||
*/
|
||||
GLboolean imported;
|
||||
|
||||
/**
|
||||
* The context tag returned by MakeCurrent when this context is made
|
||||
* current. This tag is used to identify the context that a thread has
|
||||
* current so that proper server context management can be done. It is
|
||||
* used for all context specific commands (i.e., \c Render, \c RenderLarge,
|
||||
* \c WaitX, \c WaitGL, \c UseXFont, and \c MakeCurrent (for the old
|
||||
* context)).
|
||||
*/
|
||||
GLXContextTag currentContextTag;
|
||||
|
||||
/**
|
||||
* \name Rendering mode
|
||||
*
|
||||
* The rendering mode is kept on the client as well as the server.
|
||||
* When \c glRenderMode is called, the buffer associated with the
|
||||
* previous rendering mode (feedback or select) is filled.
|
||||
*/
|
||||
/*@{ */
|
||||
GLenum renderMode;
|
||||
GLfloat *feedbackBuf;
|
||||
GLuint *selectBuf;
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* Client side attribs.
|
||||
*/
|
||||
__GLXattributeMachine attributes;
|
||||
|
||||
/**
|
||||
* Client side error code. This is set when client side gl API
|
||||
* routines need to set an error because of a bad enumerant or
|
||||
* running out of memory, etc.
|
||||
*/
|
||||
GLenum error;
|
||||
|
||||
/**
|
||||
* Whether this context does direct rendering.
|
||||
*/
|
||||
Bool isDirect;
|
||||
|
||||
/* Backend private state for the context */
|
||||
void *driContext;
|
||||
|
||||
/**
|
||||
* \c dpy of current display for this context. Will be \c NULL if not
|
||||
* current to any display, or if this is the "dummy context".
|
||||
*/
|
||||
Display *currentDpy;
|
||||
|
||||
/**
|
||||
* The current drawable for this context. Will be None if this
|
||||
* context is not current to any drawable. currentReadable is below.
|
||||
*/
|
||||
GLXDrawable currentDrawable;
|
||||
|
||||
/**
|
||||
* \name GL Constant Strings
|
||||
*
|
||||
* Constant strings that describe the server implementation
|
||||
* These pertain to GL attributes, not to be confused with
|
||||
* GLX versioning attributes.
|
||||
*/
|
||||
/*@{ */
|
||||
GLubyte *vendor;
|
||||
GLubyte *renderer;
|
||||
GLubyte *version;
|
||||
GLubyte *extensions;
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* Maximum small render command size. This is the smaller of 64k and
|
||||
* the size of the above buffer.
|
||||
*/
|
||||
GLint maxSmallRenderCommandSize;
|
||||
|
||||
/**
|
||||
* Major opcode for the extension. Copied here so a lookup isn't
|
||||
* needed.
|
||||
*/
|
||||
GLint majorOpcode;
|
||||
|
||||
/**
|
||||
* Pointer to the config used to create this context.
|
||||
*/
|
||||
struct glx_config *config;
|
||||
|
||||
/**
|
||||
* The current read-drawable for this context. Will be None if this
|
||||
* context is not current to any drawable.
|
||||
*
|
||||
* \since Internal API version 20030606.
|
||||
*/
|
||||
GLXDrawable currentReadable;
|
||||
|
||||
/**
|
||||
* Pointer to client-state data that is private to libGL. This is only
|
||||
* used for indirect rendering contexts.
|
||||
*
|
||||
* No internal API version change was made for this change. Client-side
|
||||
* drivers should NEVER use this data or even care that it exists.
|
||||
*/
|
||||
void *client_state_private;
|
||||
|
||||
/**
|
||||
* Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.
|
||||
*/
|
||||
int renderType;
|
||||
|
||||
/**
|
||||
* \name Raw server GL version
|
||||
*
|
||||
* True core GL version supported by the server. This is the raw value
|
||||
* returned by the server, and it may not reflect what is actually
|
||||
* supported (or reported) by the client-side library.
|
||||
*/
|
||||
/*@{ */
|
||||
int server_major; /**< Major version number. */
|
||||
int server_minor; /**< Minor version number. */
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* GLX_ARB_create_context_no_error setting for this context.
|
||||
* This needs to be kept here to enforce shared context rules.
|
||||
*/
|
||||
Bool noError;
|
||||
|
||||
char gl_extension_bits[__GL_EXT_BYTES];
|
||||
};
|
||||
|
||||
extern Bool
|
||||
glx_context_init(struct glx_context *gc,
|
||||
struct glx_screen *psc, struct glx_config *fbconfig);
|
||||
|
||||
#define __glXSetError(gc,code) \
|
||||
if (!(gc)->error) { \
|
||||
(gc)->error = code; \
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/**
|
||||
* The size of the largest drawing command known to the implementation
|
||||
* that will use the GLXRender GLX command. In this case it is
|
||||
* \c glPolygonStipple.
|
||||
*/
|
||||
#define __GLX_MAX_SMALL_RENDER_CMD_SIZE 156
|
||||
|
||||
/**
|
||||
* To keep the implementation fast, the code uses a "limit" pointer
|
||||
* to determine when the drawing command buffer is too full to hold
|
||||
* another fixed size command. This constant defines the amount of
|
||||
* space that must always be available in the drawing command buffer
|
||||
* at all times for the implementation to work. It is important that
|
||||
* the number be just large enough, but not so large as to reduce the
|
||||
* efficacy of the buffer. The "+32" is just to keep the code working
|
||||
* in case somebody counts wrong.
|
||||
*/
|
||||
#define __GLX_BUFFER_LIMIT_SIZE (__GLX_MAX_SMALL_RENDER_CMD_SIZE + 32)
|
||||
|
||||
/**
|
||||
* This implementation uses a smaller threshold for switching
|
||||
* to the RenderLarge protocol than the protocol requires so that
|
||||
* large copies don't occur.
|
||||
*/
|
||||
#define __GLX_RENDER_CMD_SIZE_LIMIT 4096
|
||||
|
||||
/**
|
||||
* One of these records exists per screen of the display. It contains
|
||||
* a pointer to the config data for that screen (if the screen supports GL).
|
||||
*/
|
||||
struct glx_screen_vtable {
|
||||
struct glx_context *(*create_context)(struct glx_screen *psc,
|
||||
struct glx_config *config,
|
||||
struct glx_context *shareList,
|
||||
int renderType);
|
||||
|
||||
/* The error outparameter abuses the fact that the only possible errors are
|
||||
* GLXBadContext (0), GLXBadFBConfig (9), GLXBadProfileARB (13), BadValue
|
||||
* (2), BadMatch (8), and BadAlloc (11). Since those don't collide we just
|
||||
* use them directly rather than try to offset or use a sign convention.
|
||||
*/
|
||||
struct glx_context *(*create_context_attribs)(struct glx_screen *psc,
|
||||
struct glx_config *config,
|
||||
struct glx_context *shareList,
|
||||
unsigned num_attrib,
|
||||
const uint32_t *attribs,
|
||||
unsigned *error);
|
||||
int (*query_renderer_integer)(struct glx_screen *psc,
|
||||
int attribute,
|
||||
unsigned int *value);
|
||||
int (*query_renderer_string)(struct glx_screen *psc,
|
||||
int attribute,
|
||||
const char **value);
|
||||
|
||||
char *(*get_driver_name)(struct glx_screen *psc);
|
||||
};
|
||||
|
||||
struct glx_screen
|
||||
{
|
||||
const struct glx_screen_vtable *vtable;
|
||||
const struct glx_context_vtable *context_vtable;
|
||||
|
||||
/**
|
||||
* \name Storage for the GLX vendor, version, and extension strings
|
||||
*/
|
||||
/*@{ */
|
||||
const char *serverGLXexts;
|
||||
const char *serverGLXvendor;
|
||||
const char *serverGLXversion;
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* GLX extension string to be reported to applications. This is the
|
||||
* set of extensions that the application can actually use.
|
||||
*/
|
||||
char *effectiveGLXexts;
|
||||
|
||||
struct glx_display *display;
|
||||
|
||||
Display *dpy;
|
||||
int scr;
|
||||
bool force_direct_context;
|
||||
bool allow_invalid_glx_destroy_window;
|
||||
bool keep_native_window_glx_drawable;
|
||||
bool can_EXT_texture_from_pixmap;
|
||||
|
||||
char *driverName;
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
/**
|
||||
* Per screen direct rendering interface functions and data.
|
||||
*/
|
||||
__GLXDRIscreen driScreen;
|
||||
struct dri_screen *frontend_screen;
|
||||
const struct dri_config **driver_configs;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Linked list of glx visuals and fbconfigs for this screen.
|
||||
*/
|
||||
struct glx_config *visuals, *configs;
|
||||
|
||||
/**
|
||||
* Per-screen dynamic GLX extension tracking. The \c direct_support
|
||||
* field only contains enough bits for 64 extensions. Should libGL
|
||||
* ever need to track more than 64 GLX extensions, we can safely grow
|
||||
* this field. The \c struct glx_screen structure is not used outside
|
||||
* libGL.
|
||||
*/
|
||||
/*@{ */
|
||||
unsigned char direct_support[__GLX_EXT_BYTES];
|
||||
GLboolean ext_list_first_time;
|
||||
|
||||
unsigned char glx_force_enabled[__GLX_EXT_BYTES];
|
||||
unsigned char glx_force_disabled[__GLX_EXT_BYTES];
|
||||
|
||||
unsigned char gl_force_enabled[__GL_EXT_BYTES];
|
||||
unsigned char gl_force_disabled[__GL_EXT_BYTES];
|
||||
/*@} */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Per display private data. One of these records exists for each display
|
||||
* that is using the OpenGL (GLX) extension.
|
||||
*/
|
||||
struct glx_display
|
||||
{
|
||||
struct glx_display *next;
|
||||
|
||||
enum glx_driver driver;
|
||||
|
||||
/* The extension protocol codes */
|
||||
XExtCodes codes;
|
||||
|
||||
/**
|
||||
* Back pointer to the display
|
||||
*/
|
||||
Display *dpy;
|
||||
|
||||
/**
|
||||
* \name Minor Version
|
||||
*
|
||||
* Minor version returned by the server during initialization. The major
|
||||
* version is asserted to be 1 during extension setup.
|
||||
*/
|
||||
/*@{ */
|
||||
int minorVersion;
|
||||
/*@} */
|
||||
|
||||
/**
|
||||
* Configurations of visuals for all screens on this display.
|
||||
* Also, per screen data which now includes the server \c GLX_EXTENSION
|
||||
* string.
|
||||
*/
|
||||
struct glx_screen **screens;
|
||||
|
||||
__glxHashTable *glXDrawHash;
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
__glxHashTable *drawHash;
|
||||
|
||||
/**
|
||||
* GLXDrawable created from native window and about to be released.
|
||||
*/
|
||||
struct set *zombieGLXDrawable;
|
||||
|
||||
__glxHashTable *dri2Hash;
|
||||
bool has_multibuffer;
|
||||
#endif
|
||||
#ifdef GLX_USE_WINDOWSGL
|
||||
__GLXDRIdisplay *windowsdriDisplay;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct glx_drawable {
|
||||
XID xDrawable;
|
||||
XID drawable;
|
||||
|
||||
uint32_t lastEventSbc;
|
||||
int64_t eventSbcWrap;
|
||||
};
|
||||
|
||||
extern int
|
||||
glx_screen_init(struct glx_screen *psc,
|
||||
int screen, struct glx_display * priv);
|
||||
extern void
|
||||
glx_screen_cleanup(struct glx_screen *psc);
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
extern __GLXDRIdrawable *
|
||||
dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id);
|
||||
#endif
|
||||
|
||||
extern GLubyte *__glXFlushRenderBuffer(struct glx_context *, GLubyte *);
|
||||
|
||||
extern void __glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
|
||||
GLint totalRequests,
|
||||
const GLvoid * data, GLint dataLen);
|
||||
|
||||
extern void __glXSendLargeCommand(struct glx_context *, const GLvoid *, GLint,
|
||||
const GLvoid *, GLint);
|
||||
|
||||
/* Initialize the GLX extension for dpy */
|
||||
extern struct glx_display *__glXInitialize(Display *);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern int __glXDebug;
|
||||
|
||||
/* This is per-thread storage in an MT environment */
|
||||
|
||||
extern void __glXSetCurrentContext(struct glx_context * c);
|
||||
|
||||
extern __THREAD_INITIAL_EXEC void *__glX_tls_Context;
|
||||
|
||||
# define __glXGetCurrentContext() __glX_tls_Context
|
||||
|
||||
extern void __glXSetCurrentContextNull(void);
|
||||
|
||||
|
||||
/*
|
||||
** Global lock for all threads in this address space using the GLX
|
||||
** extension
|
||||
*/
|
||||
extern pthread_mutex_t __glXmutex;
|
||||
#define __glXLock() pthread_mutex_lock(&__glXmutex)
|
||||
#define __glXUnlock() pthread_mutex_unlock(&__glXmutex)
|
||||
|
||||
/*
|
||||
** Setup for a command. Initialize the extension for dpy if necessary.
|
||||
*/
|
||||
extern CARD8 __glXSetupForCommand(Display * dpy);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** Data conversion and packing support.
|
||||
*/
|
||||
|
||||
extern const GLuint __glXDefaultPixelStore[9];
|
||||
|
||||
/* Send an image to the server using RenderLarge. */
|
||||
extern void __glXSendLargeImage(struct glx_context * gc, GLint compsize, GLint dim,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid * src, GLubyte * pc,
|
||||
GLubyte * modes);
|
||||
|
||||
/* Return the size, in bytes, of some pixel data */
|
||||
extern GLint __glImageSize(GLint, GLint, GLint, GLenum, GLenum, GLenum);
|
||||
|
||||
/* Return the number of elements per group of a specified format*/
|
||||
extern GLint __glElementsPerGroup(GLenum format, GLenum type);
|
||||
|
||||
/* Return the number of bytes per element, based on the element type (other
|
||||
** than GL_BITMAP).
|
||||
*/
|
||||
extern GLint __glBytesPerElement(GLenum type);
|
||||
|
||||
/*
|
||||
** Fill the transport buffer with the data from the users buffer,
|
||||
** applying some of the pixel store modes (unpack modes) to the data
|
||||
** first. As a side effect of this call, the "modes" field is
|
||||
** updated to contain the modes needed by the server to decode the
|
||||
** sent data.
|
||||
*/
|
||||
extern void __glFillImage(struct glx_context *, GLint, GLint, GLint, GLint, GLenum,
|
||||
GLenum, const GLvoid *, GLubyte *, GLubyte *);
|
||||
|
||||
/* Copy map data with a stride into a packed buffer */
|
||||
extern void __glFillMap1f(GLint, GLint, GLint, const GLfloat *, GLubyte *);
|
||||
extern void __glFillMap1d(GLint, GLint, GLint, const GLdouble *, GLubyte *);
|
||||
extern void __glFillMap2f(GLint, GLint, GLint, GLint, GLint,
|
||||
const GLfloat *, GLfloat *);
|
||||
extern void __glFillMap2d(GLint, GLint, GLint, GLint, GLint,
|
||||
const GLdouble *, GLdouble *);
|
||||
|
||||
/*
|
||||
** Empty an image out of the reply buffer into the clients memory applying
|
||||
** the pack modes to pack back into the clients requested format.
|
||||
*/
|
||||
extern void __glEmptyImage(struct glx_context *, GLint, GLint, GLint, GLint, GLenum,
|
||||
GLenum, const GLubyte *, GLvoid *);
|
||||
|
||||
|
||||
/*
|
||||
** Allocate and Initialize Vertex Array client state, and free.
|
||||
*/
|
||||
extern void __glXInitVertexArrayState(struct glx_context *);
|
||||
extern void __glXFreeVertexArrayState(struct glx_context *);
|
||||
|
||||
extern void glxSendClientInfo(struct glx_display *glx_dpy, int screen);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern void __glXInitializeVisualConfigFromTags(struct glx_config * config,
|
||||
int count, const INT32 * bp,
|
||||
Bool tagged_only,
|
||||
Bool fbconfig_style_tags);
|
||||
|
||||
extern char *__glXQueryServerString(Display *dpy, CARD32 screen, CARD32 name);
|
||||
extern char *__glXGetString(Display *dpy, CARD32 screen, CARD32 name);
|
||||
|
||||
extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
|
||||
int32_t * numerator,
|
||||
int32_t * denominator);
|
||||
|
||||
#if defined(GLX_DIRECT_RENDERING) && (!defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE))
|
||||
extern GLboolean
|
||||
__glxGetMscRate(struct glx_screen *psc,
|
||||
int32_t * numerator, int32_t * denominator);
|
||||
|
||||
/* So that dri2.c:DRI2WireToEvent() can access
|
||||
* glx_info->codes->first_event */
|
||||
XExtDisplayInfo *__glXFindDisplay (Display *dpy);
|
||||
|
||||
extern __GLXDRIdrawable *
|
||||
GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable);
|
||||
#endif
|
||||
|
||||
extern struct glx_screen *GetGLXScreenConfigs(Display * dpy, int scrn);
|
||||
|
||||
#ifdef GLX_USE_APPLEGL
|
||||
extern struct glx_screen *
|
||||
applegl_create_screen(int screen, struct glx_display * priv);
|
||||
|
||||
extern struct glx_context *
|
||||
applegl_create_context(struct glx_screen *psc,
|
||||
struct glx_config *mode,
|
||||
struct glx_context *shareList, int renderType);
|
||||
|
||||
extern int
|
||||
applegl_create_display(struct glx_display *display);
|
||||
|
||||
extern void *
|
||||
applegl_get_proc_address(const char *symbol);
|
||||
#endif
|
||||
|
||||
extern Bool validate_renderType_against_config(const struct glx_config *config,
|
||||
int renderType);
|
||||
|
||||
|
||||
extern struct glx_drawable *GetGLXDrawable(Display *dpy, GLXDrawable drawable);
|
||||
extern int InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw,
|
||||
XID xDrawable, GLXDrawable drawable);
|
||||
extern void DestroyGLXDrawable(Display *dpy, GLXDrawable drawable);
|
||||
|
||||
extern struct glx_context dummyContext;
|
||||
|
||||
extern struct glx_screen *
|
||||
indirect_create_screen(int screen, struct glx_display * priv);
|
||||
extern struct glx_context *
|
||||
indirect_create_context(struct glx_screen *psc,
|
||||
struct glx_config *mode,
|
||||
struct glx_context *shareList, int renderType);
|
||||
extern struct glx_context *
|
||||
indirect_create_context_attribs(struct glx_screen *base,
|
||||
struct glx_config *config_base,
|
||||
struct glx_context *shareList,
|
||||
unsigned num_attribs,
|
||||
const uint32_t *attribs,
|
||||
unsigned *error);
|
||||
|
||||
|
||||
extern int __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
|
||||
int attribute, unsigned int *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !__GLX_client_h__ */
|
||||
+2468
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2003
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxconfig.c
|
||||
* Utility routines for working with \c struct glx_config structures. At
|
||||
* some point most or all of these functions will be moved to the Mesa
|
||||
* code base.
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "glxconfig.h"
|
||||
|
||||
#define NUM_VISUAL_TYPES 6
|
||||
|
||||
/**
|
||||
* Get data from a GLX config
|
||||
*
|
||||
* \param mode GL context mode whose data is to be returned.
|
||||
* \param attribute Attribute of \c mode that is to be returned.
|
||||
* \param value_return Location to store the data member of \c mode.
|
||||
* \return If \c attribute is a valid attribute of \c mode, zero is
|
||||
* returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned.
|
||||
*/
|
||||
int
|
||||
glx_config_get(struct glx_config * mode, int attribute, int *value_return)
|
||||
{
|
||||
switch (attribute) {
|
||||
case GLX_USE_GL:
|
||||
*value_return = GL_TRUE;
|
||||
return 0;
|
||||
case GLX_BUFFER_SIZE:
|
||||
*value_return = mode->rgbBits;
|
||||
return 0;
|
||||
case GLX_RGBA:
|
||||
*value_return = !(mode->renderType & GLX_COLOR_INDEX_BIT);
|
||||
return 0;
|
||||
case GLX_RED_SIZE:
|
||||
*value_return = mode->redBits;
|
||||
return 0;
|
||||
case GLX_GREEN_SIZE:
|
||||
*value_return = mode->greenBits;
|
||||
return 0;
|
||||
case GLX_BLUE_SIZE:
|
||||
*value_return = mode->blueBits;
|
||||
return 0;
|
||||
case GLX_ALPHA_SIZE:
|
||||
*value_return = mode->alphaBits;
|
||||
return 0;
|
||||
case GLX_DOUBLEBUFFER:
|
||||
*value_return = mode->doubleBufferMode;
|
||||
return 0;
|
||||
case GLX_STEREO:
|
||||
*value_return = mode->stereoMode;
|
||||
return 0;
|
||||
case GLX_AUX_BUFFERS:
|
||||
*value_return = mode->numAuxBuffers;
|
||||
return 0;
|
||||
case GLX_DEPTH_SIZE:
|
||||
*value_return = mode->depthBits;
|
||||
return 0;
|
||||
case GLX_STENCIL_SIZE:
|
||||
*value_return = mode->stencilBits;
|
||||
return 0;
|
||||
case GLX_ACCUM_RED_SIZE:
|
||||
*value_return = mode->accumRedBits;
|
||||
return 0;
|
||||
case GLX_ACCUM_GREEN_SIZE:
|
||||
*value_return = mode->accumGreenBits;
|
||||
return 0;
|
||||
case GLX_ACCUM_BLUE_SIZE:
|
||||
*value_return = mode->accumBlueBits;
|
||||
return 0;
|
||||
case GLX_ACCUM_ALPHA_SIZE:
|
||||
*value_return = mode->accumAlphaBits;
|
||||
return 0;
|
||||
case GLX_LEVEL:
|
||||
*value_return = mode->level;
|
||||
return 0;
|
||||
#ifndef GLX_USE_APPLEGL /* This isn't supported by CGL. */
|
||||
case GLX_TRANSPARENT_TYPE_EXT:
|
||||
*value_return = mode->transparentPixel;
|
||||
return 0;
|
||||
#endif
|
||||
case GLX_TRANSPARENT_RED_VALUE:
|
||||
*value_return = mode->transparentRed;
|
||||
return 0;
|
||||
case GLX_TRANSPARENT_GREEN_VALUE:
|
||||
*value_return = mode->transparentGreen;
|
||||
return 0;
|
||||
case GLX_TRANSPARENT_BLUE_VALUE:
|
||||
*value_return = mode->transparentBlue;
|
||||
return 0;
|
||||
case GLX_TRANSPARENT_ALPHA_VALUE:
|
||||
*value_return = mode->transparentAlpha;
|
||||
return 0;
|
||||
case GLX_TRANSPARENT_INDEX_VALUE:
|
||||
*value_return = mode->transparentIndex;
|
||||
return 0;
|
||||
case GLX_X_VISUAL_TYPE:
|
||||
*value_return = mode->visualType;
|
||||
return 0;
|
||||
case GLX_CONFIG_CAVEAT:
|
||||
*value_return = mode->visualRating;
|
||||
return 0;
|
||||
case GLX_VISUAL_ID:
|
||||
*value_return = mode->visualID;
|
||||
return 0;
|
||||
case GLX_DRAWABLE_TYPE:
|
||||
*value_return = mode->drawableType;
|
||||
return 0;
|
||||
case GLX_RENDER_TYPE:
|
||||
*value_return = mode->renderType;
|
||||
return 0;
|
||||
case GLX_X_RENDERABLE:
|
||||
*value_return = mode->xRenderable;
|
||||
return 0;
|
||||
case GLX_FBCONFIG_ID:
|
||||
*value_return = mode->fbconfigID;
|
||||
return 0;
|
||||
case GLX_MAX_PBUFFER_WIDTH:
|
||||
*value_return = 4096; /* _EGL_MAX_PBUFFER_WIDTH */
|
||||
return 0;
|
||||
case GLX_MAX_PBUFFER_HEIGHT:
|
||||
*value_return = 4096; /* _EGL_MAX_PBUFFER_HEIGHT */
|
||||
return 0;
|
||||
case GLX_MAX_PBUFFER_PIXELS:
|
||||
*value_return = mode->maxPbufferPixels;
|
||||
return 0;
|
||||
#ifndef GLX_USE_APPLEGL /* These aren't supported by CGL. */
|
||||
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
|
||||
*value_return = mode->optimalPbufferWidth;
|
||||
return 0;
|
||||
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
|
||||
*value_return = mode->optimalPbufferHeight;
|
||||
return 0;
|
||||
#endif
|
||||
case GLX_SAMPLE_BUFFERS_SGIS:
|
||||
*value_return = mode->sampleBuffers;
|
||||
return 0;
|
||||
case GLX_SAMPLES_SGIS:
|
||||
*value_return = mode->samples;
|
||||
return 0;
|
||||
case GLX_BIND_TO_TEXTURE_RGB_EXT:
|
||||
*value_return = mode->bindToTextureRgb;
|
||||
return 0;
|
||||
case GLX_BIND_TO_TEXTURE_RGBA_EXT:
|
||||
*value_return = mode->bindToTextureRgba;
|
||||
return 0;
|
||||
case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
|
||||
*value_return = mode->bindToMipmapTexture == GL_TRUE ? GL_TRUE :
|
||||
GL_FALSE;
|
||||
return 0;
|
||||
case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
|
||||
*value_return = mode->bindToTextureTargets;
|
||||
return 0;
|
||||
case GLX_Y_INVERTED_EXT:
|
||||
*value_return = mode->yInverted;
|
||||
return 0;
|
||||
case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
|
||||
*value_return = mode->sRGBCapable;
|
||||
return 0;
|
||||
case GLX_FLOAT_COMPONENTS_NV:
|
||||
*value_return = mode->floatComponentsNV;
|
||||
return 0;
|
||||
|
||||
/* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX.
|
||||
* It is ONLY for communication between the GLX client and the GLX
|
||||
* server.
|
||||
*/
|
||||
case GLX_VISUAL_SELECT_GROUP_SGIX:
|
||||
default:
|
||||
return GLX_BAD_ATTRIBUTE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a linked list of \c struct glx_config structures. The fields of
|
||||
* each structure will be initialized to "reasonable" default values. In
|
||||
* most cases this is the default value defined by table 3.4 of the GLX
|
||||
* 1.3 specification. This means that most values are either initialized to
|
||||
* zero or \c GLX_DONT_CARE (which is -1). As support for additional
|
||||
* extensions is added, the new values will be initialized to appropriate
|
||||
* values from the extension specification.
|
||||
*
|
||||
* \param count Number of structures to allocate.
|
||||
* \returns A pointer to the first element in a linked list of \c count
|
||||
* structures on success, or \c NULL on failure.
|
||||
*/
|
||||
struct glx_config *
|
||||
glx_config_create_list(unsigned count)
|
||||
{
|
||||
const size_t size = sizeof(struct glx_config);
|
||||
struct glx_config *base = NULL;
|
||||
struct glx_config **next;
|
||||
unsigned i;
|
||||
|
||||
next = &base;
|
||||
for (i = 0; i < count; i++) {
|
||||
*next = calloc(1, size);
|
||||
if (*next == NULL) {
|
||||
glx_config_destroy_list(base);
|
||||
base = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
(*next)->visualID = GLX_DONT_CARE;
|
||||
(*next)->visualType = GLX_DONT_CARE;
|
||||
(*next)->visualRating = GLX_NONE;
|
||||
(*next)->transparentPixel = GLX_NONE;
|
||||
(*next)->transparentRed = GLX_DONT_CARE;
|
||||
(*next)->transparentGreen = GLX_DONT_CARE;
|
||||
(*next)->transparentBlue = GLX_DONT_CARE;
|
||||
(*next)->transparentAlpha = GLX_DONT_CARE;
|
||||
(*next)->transparentIndex = GLX_DONT_CARE;
|
||||
(*next)->xRenderable = GLX_DONT_CARE;
|
||||
(*next)->fbconfigID = GLX_DONT_CARE;
|
||||
(*next)->bindToTextureRgb = GLX_DONT_CARE;
|
||||
(*next)->bindToTextureRgba = GLX_DONT_CARE;
|
||||
(*next)->bindToMipmapTexture = GLX_DONT_CARE;
|
||||
(*next)->bindToTextureTargets = GLX_DONT_CARE;
|
||||
(*next)->yInverted = GLX_DONT_CARE;
|
||||
(*next)->sRGBCapable = GL_FALSE;
|
||||
|
||||
next = &((*next)->next);
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
void
|
||||
glx_config_destroy_list(struct glx_config *configs)
|
||||
{
|
||||
while (configs != NULL) {
|
||||
struct glx_config *const next = configs->next;
|
||||
|
||||
free(configs);
|
||||
configs = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a context mode matching a Visual ID.
|
||||
*
|
||||
* \param modes List list of context-mode structures to be searched.
|
||||
* \param vid Visual ID to be found.
|
||||
* \returns A pointer to a context-mode in \c modes if \c vid was found in
|
||||
* the list, or \c NULL if it was not.
|
||||
*/
|
||||
|
||||
struct glx_config *
|
||||
glx_config_find_visual(struct glx_config *configs, int vid)
|
||||
{
|
||||
struct glx_config *c;
|
||||
|
||||
for (c = configs; c != NULL; c = c->next)
|
||||
if (c->visualID == vid)
|
||||
return c;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct glx_config *
|
||||
glx_config_find_fbconfig(struct glx_config *configs, int fbid)
|
||||
{
|
||||
struct glx_config *c;
|
||||
|
||||
for (c = configs; c != NULL; c = c->next)
|
||||
if (c->fbconfigID == fbid)
|
||||
return c;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2003
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glcontextmodes.h
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef GLCONTEXTMODES_H
|
||||
#define GLCONTEXTMODES_H
|
||||
|
||||
struct glx_config {
|
||||
struct glx_config * next;
|
||||
|
||||
GLuint doubleBufferMode;
|
||||
GLuint stereoMode;
|
||||
|
||||
GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
|
||||
GLuint redMask, greenMask, blueMask, alphaMask;
|
||||
GLuint redShift, greenShift, blueShift, alphaShift;
|
||||
GLint rgbBits; /* total bits for rgb */
|
||||
GLint indexBits; /* total bits for colorindex */
|
||||
|
||||
GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
|
||||
GLint depthBits;
|
||||
GLint stencilBits;
|
||||
|
||||
GLint numAuxBuffers;
|
||||
|
||||
GLint level;
|
||||
|
||||
/* GLX */
|
||||
GLint visualID;
|
||||
GLint visualType; /**< One of the GLX X visual types. (i.e.,
|
||||
* \c GLX_TRUE_COLOR, etc.)
|
||||
*/
|
||||
|
||||
/* EXT_visual_rating / GLX 1.2 */
|
||||
GLint visualRating;
|
||||
|
||||
/* EXT_visual_info / GLX 1.2 */
|
||||
GLint transparentPixel;
|
||||
/* colors are floats scaled to ints */
|
||||
GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
|
||||
GLint transparentIndex;
|
||||
|
||||
/* ARB_multisample / SGIS_multisample */
|
||||
GLint sampleBuffers;
|
||||
GLint samples;
|
||||
|
||||
/* SGIX_fbconfig / GLX 1.3 */
|
||||
GLint drawableType;
|
||||
GLint renderType;
|
||||
GLint xRenderable;
|
||||
GLint fbconfigID;
|
||||
|
||||
/* SGIX_pbuffer / GLX 1.3 */
|
||||
GLint maxPbufferWidth;
|
||||
GLint maxPbufferHeight;
|
||||
GLint maxPbufferPixels;
|
||||
GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
|
||||
GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
|
||||
|
||||
/* SGIX_visual_select_group */
|
||||
GLint visualSelectGroup;
|
||||
|
||||
GLint screen;
|
||||
|
||||
/* EXT_texture_from_pixmap */
|
||||
GLint bindToTextureRgb;
|
||||
GLint bindToTextureRgba;
|
||||
GLint bindToMipmapTexture;
|
||||
GLint bindToTextureTargets;
|
||||
GLint yInverted;
|
||||
|
||||
/* EXT_framebuffer_sRGB */
|
||||
GLint sRGBCapable;
|
||||
|
||||
/* NV_float_buffer */
|
||||
GLint floatComponentsNV;
|
||||
};
|
||||
|
||||
extern GLint _gl_convert_from_x_visual_type(int visualType);
|
||||
|
||||
extern int
|
||||
glx_config_get(struct glx_config * mode, int attribute, int *value_return);
|
||||
extern struct glx_config *
|
||||
glx_config_create_list(unsigned count);
|
||||
extern void
|
||||
glx_config_destroy_list(struct glx_config *configs);
|
||||
extern struct glx_config *
|
||||
glx_config_find_visual(struct glx_config *configs, int vid);
|
||||
extern struct glx_config *
|
||||
glx_config_find_fbconfig(struct glx_config *configs, int fbid);
|
||||
|
||||
#endif /* GLCONTEXTMODES_H */
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxcurrent.c
|
||||
* Client-side GLX interface for current context management.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "glapi.h"
|
||||
#include "glx_error.h"
|
||||
|
||||
/*
|
||||
** We setup some dummy structures here so that the API can be used
|
||||
** even if no context is current.
|
||||
*/
|
||||
|
||||
static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
|
||||
static struct glx_context_vtable dummyVtable;
|
||||
/*
|
||||
** Dummy context used by small commands when there is no current context.
|
||||
** All the
|
||||
** gl and glx entry points are designed to operate as nop's when using
|
||||
** the dummy context structure.
|
||||
*/
|
||||
struct glx_context dummyContext = {
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[0],
|
||||
&dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
|
||||
sizeof(dummyBuffer),
|
||||
&dummyVtable
|
||||
};
|
||||
|
||||
/*
|
||||
* Current context management and locking
|
||||
*/
|
||||
|
||||
pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Per-thread GLX context pointer.
|
||||
*
|
||||
* \c __glXSetCurrentContext is written is such a way that this pointer can
|
||||
* \b never be \c NULL. This is important! Because of this
|
||||
* \c __glXGetCurrentContext can be implemented as trivial macro.
|
||||
*/
|
||||
__THREAD_INITIAL_EXEC void *__glX_tls_Context = &dummyContext;
|
||||
|
||||
void
|
||||
__glXSetCurrentContext(struct glx_context * c)
|
||||
{
|
||||
__glX_tls_Context = (c != NULL) ? c : &dummyContext;
|
||||
}
|
||||
|
||||
void
|
||||
__glXSetCurrentContextNull(void)
|
||||
{
|
||||
__glXSetCurrentContext(&dummyContext);
|
||||
#if defined(GLX_DIRECT_RENDERING)
|
||||
_mesa_glapi_set_dispatch(NULL); /* no-op functions */
|
||||
_mesa_glapi_set_context(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
_GLX_PUBLIC GLXContext
|
||||
glXGetCurrentContext(void)
|
||||
{
|
||||
struct glx_context *cx = __glXGetCurrentContext();
|
||||
|
||||
if (cx == &dummyContext) {
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
return (GLXContext) cx;
|
||||
}
|
||||
}
|
||||
|
||||
_GLX_PUBLIC GLXDrawable
|
||||
glXGetCurrentDrawable(void)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
return gc->currentDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a particular context current.
|
||||
*
|
||||
* \note This is in this file so that it can access dummyContext.
|
||||
*/
|
||||
static Bool
|
||||
MakeContextCurrent(Display * dpy, GLXDrawable draw,
|
||||
GLXDrawable read, GLXContext gc_user,
|
||||
int opcode)
|
||||
{
|
||||
struct glx_context *gc = (struct glx_context *) gc_user;
|
||||
struct glx_context *oldGC = __glXGetCurrentContext();
|
||||
int ret = GL_TRUE;
|
||||
|
||||
/* Make sure that the new context has a nonzero ID. In the request,
|
||||
* a zero context ID is used only to mean that we bind to no current
|
||||
* context.
|
||||
*/
|
||||
if ((gc != NULL) && (gc->xid == None)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* can't have only one be 0 */
|
||||
if (!!draw != !!read) {
|
||||
__glXSendError(dpy, BadMatch, None, opcode, True);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (oldGC == gc &&
|
||||
gc->currentDrawable == draw && gc->currentReadable == read)
|
||||
return True;
|
||||
|
||||
__glXLock();
|
||||
|
||||
if (oldGC != &dummyContext) {
|
||||
oldGC->vtable->unbind(oldGC);
|
||||
oldGC->currentDpy = NULL;
|
||||
|
||||
if (oldGC->xid == None) {
|
||||
/* We are switching away from a context that was
|
||||
* previously destroyed, so we need to free the memory
|
||||
* for the old handle. */
|
||||
oldGC->vtable->destroy(oldGC);
|
||||
}
|
||||
}
|
||||
|
||||
__glXSetCurrentContextNull();
|
||||
|
||||
if (gc) {
|
||||
/* GLX spec 3.3: If ctx is current to some other thread, then
|
||||
* glXMakeContextCurrent will generate a BadAccess error
|
||||
*/
|
||||
if (gc->currentDpy)
|
||||
{
|
||||
__glXUnlock();
|
||||
__glXSendError(dpy, BadAccess, None, opcode, True);
|
||||
return False;
|
||||
}
|
||||
/* Attempt to bind the context. We do this before mucking with
|
||||
* gc and __glXSetCurrentContext to properly handle our state in
|
||||
* case of an error.
|
||||
*
|
||||
* If an error occurs, set the Null context since we've already
|
||||
* blown away our old context. The caller is responsible for
|
||||
* figuring out how to handle setting a valid context.
|
||||
*/
|
||||
if (gc->vtable->bind(gc, draw, read) != Success) {
|
||||
ret = GL_FALSE;
|
||||
} else {
|
||||
gc->currentDpy = dpy;
|
||||
gc->currentDrawable = draw;
|
||||
gc->currentReadable = read;
|
||||
__glXSetCurrentContext(gc);
|
||||
}
|
||||
}
|
||||
|
||||
__glXUnlock();
|
||||
|
||||
if (!ret)
|
||||
__glXSendError(dpy, GLXBadContext, None, opcode, False);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
_GLX_PUBLIC Bool
|
||||
glXMakeCurrent(Display * dpy, GLXDrawable draw, GLXContext gc)
|
||||
{
|
||||
return MakeContextCurrent(dpy, draw, draw, gc, X_GLXMakeCurrent);
|
||||
}
|
||||
|
||||
_GLX_PUBLIC Bool
|
||||
glXMakeContextCurrent(Display *dpy, GLXDrawable d, GLXDrawable r,
|
||||
GLXContext ctx)
|
||||
{
|
||||
return MakeContextCurrent(dpy, d, r, ctx, X_GLXMakeContextCurrent);
|
||||
}
|
||||
|
||||
_GLX_PUBLIC Bool
|
||||
glXMakeCurrentReadSGI(Display *dpy, GLXDrawable d, GLXDrawable r,
|
||||
GLXContext ctx)
|
||||
{
|
||||
return MakeContextCurrent(dpy, d, r, ctx, X_GLXvop_MakeCurrentReadSGI);
|
||||
}
|
||||
+1242
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2002, 2004
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxextensions.c
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include <X11/extensions/extutil.h>
|
||||
#include <X11/extensions/Xext.h>
|
||||
#include <string.h>
|
||||
#include "glxextensions.h"
|
||||
|
||||
#include "util/driconf.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#define SET_BIT(m,b) (m[ (b) / 8 ] |= (1U << ((b) % 8)))
|
||||
#define CLR_BIT(m,b) (m[ (b) / 8 ] &= ~(1U << ((b) % 8)))
|
||||
#define IS_SET(m,b) ((m[ (b) / 8 ] & (1U << ((b) % 8))) != 0)
|
||||
#define GLX(n) "GLX_" # n, 4 + sizeof( # n ) - 1, PASTE2(n,_bit)
|
||||
#define GL(n) "GL_" # n, 3 + sizeof( # n ) - 1, GL_ ## n ## _bit
|
||||
#define Y 1
|
||||
#define N 0
|
||||
#define EXT_ENABLED(bit,supported) (IS_SET( supported, bit ))
|
||||
|
||||
|
||||
struct extension_info
|
||||
{
|
||||
const char *const name;
|
||||
unsigned name_len;
|
||||
|
||||
unsigned char bit;
|
||||
|
||||
/**
|
||||
* The direct-renderer (e.g., i965_dri.so) supports this extension.
|
||||
*
|
||||
* For cases where all of the infrastructure to support the extension is a
|
||||
* required part of the loader/driver interface, this can default to Y.
|
||||
* For most cases, extended functionality, usually in the form of DRI2
|
||||
* extensions, is necessary to support the extension. The loader will set
|
||||
* the flag true if all the requirements are met.
|
||||
*
|
||||
* If the display is capable of direct rendering, ::direct_support is
|
||||
* required for the extension to be enabled.
|
||||
*/
|
||||
unsigned char direct_support;
|
||||
|
||||
/**
|
||||
* The extension only functions with direct-rendering contexts
|
||||
*
|
||||
* The extension has no GLX protocol, and, therefore, no explicit
|
||||
* dependency on the server. The functionality is contained entirely in
|
||||
* the client library and the direct renderer. A few of the swap-related
|
||||
* extensions are intended to behave this way.
|
||||
*/
|
||||
unsigned char direct_only;
|
||||
};
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static const struct extension_info known_glx_extensions[] = {
|
||||
{ GLX(ARB_context_flush_control), N, N },
|
||||
{ GLX(ARB_create_context), N, N },
|
||||
{ GLX(ARB_create_context_no_error), N, N },
|
||||
{ GLX(ARB_create_context_profile), N, N },
|
||||
{ GLX(ARB_create_context_robustness), N, N },
|
||||
{ GLX(ARB_fbconfig_float), Y, N },
|
||||
{ GLX(ARB_framebuffer_sRGB), Y, N },
|
||||
{ GLX(ARB_get_proc_address), N, N },
|
||||
{ GLX(ARB_multisample), Y, N },
|
||||
{ GLX(EXT_buffer_age), N, Y },
|
||||
{ GLX(EXT_create_context_es2_profile), N, N },
|
||||
{ GLX(EXT_create_context_es_profile), N, N },
|
||||
{ GLX(EXT_fbconfig_packed_float), Y, N },
|
||||
{ GLX(EXT_framebuffer_sRGB), Y, N },
|
||||
{ GLX(EXT_import_context), Y, N },
|
||||
{ GLX(EXT_no_config_context), N, N },
|
||||
{ GLX(EXT_swap_control), N, Y },
|
||||
{ GLX(EXT_swap_control_tear), N, Y },
|
||||
{ GLX(EXT_texture_from_pixmap), N, N },
|
||||
{ GLX(EXT_visual_info), Y, N },
|
||||
{ GLX(EXT_visual_rating), Y, N },
|
||||
{ GLX(ATI_pixel_format_float), N, N },
|
||||
{ GLX(INTEL_swap_event), N, N },
|
||||
{ GLX(MESA_copy_sub_buffer), N, N },
|
||||
{ GLX(MESA_gl_interop), N, Y },
|
||||
{ GLX(MESA_query_renderer), N, Y },
|
||||
{ GLX(MESA_swap_control), N, Y },
|
||||
{ GLX(NV_float_buffer), N, N },
|
||||
{ GLX(OML_sync_control), N, Y },
|
||||
{ GLX(SGIS_multisample), Y, N },
|
||||
{ GLX(SGIX_fbconfig), Y, N },
|
||||
{ GLX(SGIX_pbuffer), Y, N },
|
||||
{ GLX(SGIX_visual_select_group), Y, N },
|
||||
{ GLX(SGI_make_current_read), N, N },
|
||||
{ GLX(SGI_swap_control), N, N },
|
||||
{ GLX(SGI_video_sync), N, Y },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const struct extension_info known_gl_extensions[] = {
|
||||
{ GL(ARB_depth_texture), N, N },
|
||||
{ GL(ARB_draw_buffers), N, N },
|
||||
{ GL(ARB_fragment_program), N, N },
|
||||
{ GL(ARB_fragment_program_shadow), N, N },
|
||||
{ GL(ARB_framebuffer_object), N, N },
|
||||
{ GL(ARB_imaging), N, N },
|
||||
{ GL(ARB_multisample), N, N },
|
||||
{ GL(ARB_multitexture), N, N },
|
||||
{ GL(ARB_occlusion_query), N, N },
|
||||
{ GL(ARB_point_parameters), N, N },
|
||||
{ GL(ARB_point_sprite), N, N },
|
||||
{ GL(ARB_shadow), N, N },
|
||||
{ GL(ARB_shadow_ambient), N, N },
|
||||
{ GL(ARB_texture_border_clamp), N, N },
|
||||
{ GL(ARB_texture_compression), N, N },
|
||||
{ GL(ARB_texture_cube_map), N, N },
|
||||
{ GL(ARB_texture_env_add), N, N },
|
||||
{ GL(ARB_texture_env_combine), N, N },
|
||||
{ GL(ARB_texture_env_crossbar), N, N },
|
||||
{ GL(ARB_texture_env_dot3), N, N },
|
||||
{ GL(ARB_texture_filter_anisotropic), N, N },
|
||||
{ GL(ARB_texture_mirrored_repeat), N, N },
|
||||
{ GL(ARB_texture_non_power_of_two), N, N },
|
||||
{ GL(ARB_texture_rectangle), N, N },
|
||||
{ GL(ARB_texture_rg), N, N },
|
||||
{ GL(ARB_transpose_matrix), N, N },
|
||||
{ GL(ARB_vertex_program), N, N },
|
||||
{ GL(ARB_window_pos), N, N },
|
||||
{ GL(EXT_abgr), N, N },
|
||||
{ GL(EXT_bgra), N, N },
|
||||
{ GL(EXT_blend_color), N, N },
|
||||
{ GL(EXT_blend_equation_separate), N, N },
|
||||
{ GL(EXT_blend_func_separate), N, N },
|
||||
{ GL(EXT_blend_logic_op), N, N },
|
||||
{ GL(EXT_blend_minmax), N, N },
|
||||
{ GL(EXT_blend_subtract), N, N },
|
||||
{ GL(EXT_clip_volume_hint), N, N },
|
||||
{ GL(EXT_copy_texture), N, N },
|
||||
{ GL(EXT_draw_range_elements), N, N },
|
||||
{ GL(EXT_fog_coord), N, N },
|
||||
{ GL(EXT_framebuffer_blit), N, N },
|
||||
{ GL(EXT_framebuffer_multisample), N, N },
|
||||
{ GL(EXT_framebuffer_object), N, N },
|
||||
{ GL(EXT_framebuffer_sRGB), N, N },
|
||||
{ GL(EXT_multi_draw_arrays), N, N },
|
||||
{ GL(EXT_packed_depth_stencil), N, N },
|
||||
{ GL(EXT_packed_pixels), N, N },
|
||||
{ GL(EXT_paletted_texture), N, N },
|
||||
{ GL(EXT_point_parameters), N, N },
|
||||
{ GL(EXT_polygon_offset), N, N },
|
||||
{ GL(EXT_rescale_normal), N, N },
|
||||
{ GL(EXT_secondary_color), N, N },
|
||||
{ GL(EXT_separate_specular_color), N, N },
|
||||
{ GL(EXT_shadow_funcs), N, N },
|
||||
{ GL(EXT_shared_texture_palette), N, N },
|
||||
{ GL(EXT_stencil_two_side), N, N },
|
||||
{ GL(EXT_stencil_wrap), N, N },
|
||||
{ GL(EXT_subtexture), N, N },
|
||||
{ GL(EXT_texture), N, N },
|
||||
{ GL(EXT_texture3D), N, N },
|
||||
{ GL(EXT_texture_compression_dxt1), N, N },
|
||||
{ GL(EXT_texture_compression_s3tc), N, N },
|
||||
{ GL(EXT_texture_edge_clamp), N, N },
|
||||
{ GL(EXT_texture_env_add), N, N },
|
||||
{ GL(EXT_texture_env_combine), N, N },
|
||||
{ GL(EXT_texture_env_dot3), N, N },
|
||||
{ GL(EXT_texture_filter_anisotropic), N, N },
|
||||
{ GL(EXT_texture_integer), N, N },
|
||||
{ GL(EXT_texture_lod), N, N },
|
||||
{ GL(EXT_texture_lod_bias), N, N },
|
||||
{ GL(EXT_texture_mirror_clamp), N, N },
|
||||
{ GL(EXT_texture_rectangle), N, N },
|
||||
{ GL(EXT_vertex_array), N, N },
|
||||
{ GL(3DFX_texture_compression_FXT1), N, N },
|
||||
{ GL(APPLE_packed_pixels), N, N },
|
||||
{ GL(APPLE_ycbcr_422), N, N },
|
||||
{ GL(ATI_draw_buffers), N, N },
|
||||
{ GL(ATI_text_fragment_shader), N, N },
|
||||
{ GL(ATI_texture_env_combine3), N, N },
|
||||
{ GL(ATI_texture_float), N, N },
|
||||
{ GL(ATI_texture_mirror_once), N, N },
|
||||
{ GL(ATIX_texture_env_combine3), N, N },
|
||||
{ GL(HP_convolution_border_modes), N, N },
|
||||
{ GL(HP_occlusion_test), N, N },
|
||||
{ GL(IBM_cull_vertex), N, N },
|
||||
{ GL(IBM_pixel_filter_hint), N, N },
|
||||
{ GL(IBM_rasterpos_clip), N, N },
|
||||
{ GL(IBM_texture_clamp_nodraw), N, N },
|
||||
{ GL(IBM_texture_mirrored_repeat), N, N },
|
||||
{ GL(INGR_blend_func_separate), N, N },
|
||||
{ GL(INGR_interlace_read), N, N },
|
||||
{ GL(MESA_pack_invert), N, N },
|
||||
{ GL(MESA_ycbcr_texture), N, N },
|
||||
{ GL(NV_blend_square), N, N },
|
||||
{ GL(NV_copy_depth_to_color), N, N },
|
||||
{ GL(NV_depth_clamp), N, N },
|
||||
{ GL(NV_fog_distance), N, N },
|
||||
{ GL(NV_fragment_program), N, N },
|
||||
{ GL(NV_fragment_program_option), N, N },
|
||||
{ GL(NV_fragment_program2), N, N },
|
||||
{ GL(NV_light_max_exponent), N, N },
|
||||
{ GL(NV_multisample_filter_hint), N, N },
|
||||
{ GL(NV_packed_depth_stencil), N, N },
|
||||
{ GL(NV_point_sprite), N, N },
|
||||
{ GL(NV_texgen_reflection), N, N },
|
||||
{ GL(NV_texture_compression_vtc), N, N },
|
||||
{ GL(NV_texture_env_combine4), N, N },
|
||||
{ GL(NV_texture_rectangle), N, N },
|
||||
{ GL(OES_read_format), N, N },
|
||||
{ GL(OES_compressed_paletted_texture), N, N },
|
||||
{ GL(SGI_color_matrix), N, N },
|
||||
{ GL(SGI_color_table), N, N },
|
||||
{ GL(SGI_texture_color_table), N, N },
|
||||
{ GL(SGIS_generate_mipmap), N, N },
|
||||
{ GL(SGIS_multisample), N, N },
|
||||
{ GL(SGIS_texture_border_clamp), N, N },
|
||||
{ GL(SGIS_texture_edge_clamp), N, N },
|
||||
{ GL(SGIS_texture_lod), N, N },
|
||||
{ GL(SGIX_blend_alpha_minmax), N, N },
|
||||
{ GL(SGIX_clipmap), N, N },
|
||||
{ GL(SGIX_depth_texture), N, N },
|
||||
{ GL(SGIX_fog_offset), N, N },
|
||||
{ GL(SGIX_shadow), N, N },
|
||||
{ GL(SGIX_shadow_ambient), N, N },
|
||||
{ GL(SGIX_texture_coordinate_clamp), N, N },
|
||||
{ GL(SGIX_texture_lod_bias), N, N },
|
||||
{ GL(SGIX_texture_range), N, N },
|
||||
{ GL(SGIX_texture_scale_bias), N, N },
|
||||
{ GL(SGIX_vertex_preclip), N, N },
|
||||
{ GL(SGIX_vertex_preclip_hint), N, N },
|
||||
{ GL(SGIX_ycrcb), N, N },
|
||||
{ GL(SUN_convolution_border_modes), N, N },
|
||||
{ GL(SUN_multi_draw_arrays), N, N },
|
||||
{ GL(SUN_slice_accum), N, N },
|
||||
{ NULL }
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
/* global bit-fields of available extensions and their characteristics */
|
||||
static unsigned char client_glx_only[__GLX_EXT_BYTES];
|
||||
static unsigned char direct_glx_only[__GLX_EXT_BYTES];
|
||||
|
||||
/**
|
||||
* Bits representing the set of extensions that are enabled by default in all
|
||||
* direct rendering drivers.
|
||||
*/
|
||||
static unsigned char direct_glx_support[__GLX_EXT_BYTES];
|
||||
|
||||
/* client extensions string */
|
||||
static const char *__glXGLXClientExtensions = NULL;
|
||||
|
||||
static void __glXExtensionsCtr(void);
|
||||
static void __glXExtensionsCtrScreen(struct glx_screen * psc);
|
||||
static void __glXProcessServerString(const struct extension_info *ext,
|
||||
const char *server_string,
|
||||
unsigned char *server_support);
|
||||
|
||||
/**
|
||||
* Find an extension in the list based on its name.
|
||||
*
|
||||
* \param ext List of extensions where to search.
|
||||
* \param name Name of the extension.
|
||||
* \param name_len Length, in characters, of the extension name.
|
||||
*/
|
||||
static const struct extension_info *
|
||||
find_extension(const struct extension_info *ext, const char *name,
|
||||
unsigned name_len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; ext[i].name != NULL; i++) {
|
||||
if ((name_len == ext[i].name_len)
|
||||
&& (strncmp(ext[i].name, name, name_len) == 0)) {
|
||||
return &ext[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a GLX extension.
|
||||
*
|
||||
* \param name Name of the extension.
|
||||
* \param name_len Length, in characters, of the extension name.
|
||||
* \param state New state (either enabled or disabled) of the extension.
|
||||
* \param supported Table in which the state of the extension is to be set.
|
||||
*/
|
||||
static void
|
||||
set_glx_extension(const struct extension_info *ext_list,
|
||||
const char *name, unsigned name_len, GLboolean state,
|
||||
unsigned char *supported)
|
||||
{
|
||||
const struct extension_info *ext = find_extension(ext_list, name, name_len);
|
||||
if (!ext)
|
||||
return;
|
||||
|
||||
if (state) {
|
||||
SET_BIT(supported, ext->bit);
|
||||
} else {
|
||||
CLR_BIT(supported, ext->bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define NUL '\0'
|
||||
#define SEPARATOR ' '
|
||||
|
||||
/**
|
||||
* Convert the server's extension string to a bit-field.
|
||||
*
|
||||
* \param server_string GLX extension string from the server.
|
||||
* \param server_support Bit-field of supported extensions.
|
||||
*
|
||||
* \note
|
||||
* This function is used to process both GLX and GL extension strings. The
|
||||
* bit-fields used to track each of these have different sizes. Therefore,
|
||||
* the data pointed by \c server_support must be preinitialized to zero.
|
||||
*/
|
||||
static void
|
||||
__glXProcessServerString(const struct extension_info *ext,
|
||||
const char *server_string,
|
||||
unsigned char *server_support)
|
||||
{
|
||||
unsigned base;
|
||||
unsigned len;
|
||||
|
||||
for (base = 0; server_string[base] != NUL; /* empty */ ) {
|
||||
/* Determine the length of the next extension name.
|
||||
*/
|
||||
for (len = 0; (server_string[base + len] != SEPARATOR)
|
||||
&& (server_string[base + len] != NUL); len++) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
/* Set the bit for the extension in the server_support table.
|
||||
*/
|
||||
set_glx_extension(ext, &server_string[base], len, GL_TRUE,
|
||||
server_support);
|
||||
|
||||
|
||||
/* Advance to the next extension string. This means that we skip
|
||||
* over the previous string and any trialing white-space.
|
||||
*/
|
||||
for (base += len; (server_string[base] == SEPARATOR)
|
||||
&& (server_string[base] != NUL); base++) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__glXEnableDirectExtension(struct glx_screen * psc, const char *name)
|
||||
{
|
||||
__glXExtensionsCtr();
|
||||
__glXExtensionsCtrScreen(psc);
|
||||
|
||||
set_glx_extension(known_glx_extensions,
|
||||
name, strlen(name), GL_TRUE, psc->direct_support);
|
||||
}
|
||||
|
||||
static void
|
||||
__ParseExtensionOverride(struct glx_screen *psc,
|
||||
const struct extension_info *ext_list,
|
||||
unsigned char *force_enable,
|
||||
unsigned char *force_disable,
|
||||
const char *override)
|
||||
{
|
||||
const struct extension_info *ext;
|
||||
char *env, *field;
|
||||
|
||||
if (override == NULL)
|
||||
return;
|
||||
|
||||
/* Copy env_const because strtok() is destructive. */
|
||||
env = strdup(override);
|
||||
if (env == NULL)
|
||||
return;
|
||||
|
||||
for (field = strtok(env, " "); field!= NULL; field = strtok(NULL, " ")) {
|
||||
GLboolean enable;
|
||||
|
||||
switch (field[0]) {
|
||||
case '+':
|
||||
enable = GL_TRUE;
|
||||
++field;
|
||||
break;
|
||||
case '-':
|
||||
enable = GL_FALSE;
|
||||
++field;
|
||||
break;
|
||||
default:
|
||||
enable = GL_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
ext = find_extension(ext_list, field, strlen(field));
|
||||
if (ext) {
|
||||
if (enable)
|
||||
SET_BIT(force_enable, ext->bit);
|
||||
else
|
||||
SET_BIT(force_disable, ext->bit);
|
||||
} else {
|
||||
fprintf(stderr, "WARNING: Trying to %s the unknown extension '%s'\n",
|
||||
enable ? "enable" : "disable", field);
|
||||
}
|
||||
}
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parse the list of GLX extensions that the user wants to
|
||||
* force-enable/disable by using \c override, and write the results to the
|
||||
* screen's context.
|
||||
*
|
||||
* \param psc Pointer to GLX per-screen record.
|
||||
* \param override A space-separated list of extensions to enable or disable.
|
||||
* The list is processed thus:
|
||||
* - Enable recognized extension names that are prefixed with '+'.
|
||||
* - Disable recognized extension names that are prefixed with '-'.
|
||||
* - Enable recognized extension names that are not prefixed.
|
||||
*/
|
||||
void
|
||||
__glXParseExtensionOverride(struct glx_screen *psc, const char *override)
|
||||
{
|
||||
__ParseExtensionOverride(psc, known_glx_extensions, psc->glx_force_enabled,
|
||||
psc->glx_force_disabled, override);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parse the list of GL extensions that the user wants to
|
||||
* force-enable/disable by using \c override, and write the results to the
|
||||
* screen's context.
|
||||
*
|
||||
* \param psc Pointer to GLX per-screen record.
|
||||
* \param override A space-separated list of extensions to enable or disable.
|
||||
* The list is processed thus:
|
||||
* - Enable recognized extension names that are prefixed with '+'.
|
||||
* - Disable recognized extension names that are prefixed with '-'.
|
||||
* - Enable recognized extension names that are not prefixed.
|
||||
*/
|
||||
void
|
||||
__IndirectGlParseExtensionOverride(struct glx_screen *psc, const char *override)
|
||||
{
|
||||
__ParseExtensionOverride(psc, known_gl_extensions, psc->gl_force_enabled,
|
||||
psc->gl_force_disabled, override);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize global extension support tables.
|
||||
*/
|
||||
|
||||
static void
|
||||
__glXExtensionsCtr(void)
|
||||
{
|
||||
unsigned i;
|
||||
static GLboolean ext_list_first_time = GL_TRUE;
|
||||
|
||||
|
||||
if (ext_list_first_time) {
|
||||
ext_list_first_time = GL_FALSE;
|
||||
|
||||
(void) memset(direct_glx_support, 0, sizeof(direct_glx_support));
|
||||
(void) memset(client_glx_only, 0, sizeof(client_glx_only));
|
||||
(void) memset(direct_glx_only, 0, sizeof(direct_glx_only));
|
||||
|
||||
SET_BIT(client_glx_only, ARB_get_proc_address_bit);
|
||||
for (i = 0; known_glx_extensions[i].name != NULL; i++) {
|
||||
const unsigned bit = known_glx_extensions[i].bit;
|
||||
|
||||
if (known_glx_extensions[i].direct_support) {
|
||||
SET_BIT(direct_glx_support, bit);
|
||||
}
|
||||
|
||||
if (known_glx_extensions[i].direct_only) {
|
||||
SET_BIT(direct_glx_only, bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure that per-screen direct-support table is initialized.
|
||||
*
|
||||
* \param psc Pointer to GLX per-screen record.
|
||||
*/
|
||||
|
||||
static void
|
||||
__glXExtensionsCtrScreen(struct glx_screen * psc)
|
||||
{
|
||||
if (psc->ext_list_first_time) {
|
||||
psc->ext_list_first_time = GL_FALSE;
|
||||
(void) memcpy(psc->direct_support, direct_glx_support,
|
||||
sizeof(direct_glx_support));
|
||||
(void) memset(psc->glx_force_enabled, 0,
|
||||
sizeof(psc->glx_force_enabled));
|
||||
(void) memset(psc->glx_force_disabled, 0,
|
||||
sizeof(psc->glx_force_disabled));
|
||||
(void) memset(psc->gl_force_enabled, 0,
|
||||
sizeof(psc->gl_force_enabled));
|
||||
(void) memset(psc->gl_force_disabled, 0,
|
||||
sizeof(psc->gl_force_disabled));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a certain extension is enabled on a given screen.
|
||||
*
|
||||
* \param psc Pointer to GLX per-screen record.
|
||||
* \param bit Bit index in the direct-support table.
|
||||
* \returns If the extension bit is enabled for the screen, \c GL_TRUE is
|
||||
* returned. If the extension bit is not enabled or if \c psc is
|
||||
* \c NULL, then \c GL_FALSE is returned.
|
||||
*/
|
||||
GLboolean
|
||||
__glXExtensionBitIsEnabled(struct glx_screen * psc, unsigned bit)
|
||||
{
|
||||
GLboolean enabled = GL_FALSE;
|
||||
|
||||
if (psc != NULL) {
|
||||
__glXExtensionsCtr();
|
||||
__glXExtensionsCtrScreen(psc);
|
||||
enabled = EXT_ENABLED(bit, psc->direct_support);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a certain extension is enabled in a given context.
|
||||
*
|
||||
*/
|
||||
GLboolean
|
||||
__glExtensionBitIsEnabled(struct glx_context *gc, unsigned bit)
|
||||
{
|
||||
GLboolean enabled = GL_FALSE;
|
||||
|
||||
if (gc != NULL) {
|
||||
enabled = EXT_ENABLED(bit, gc->gl_extension_bits);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a bit-field to a string of supported extensions.
|
||||
*/
|
||||
static char *
|
||||
__glXGetStringFromTable(const struct extension_info *ext,
|
||||
const unsigned char *filter)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned ext_str_len;
|
||||
char *ext_str;
|
||||
char *point;
|
||||
|
||||
|
||||
ext_str_len = 0;
|
||||
for (i = 0; ext[i].name != NULL; i++) {
|
||||
if (!filter || EXT_ENABLED(ext[i].bit, filter)) {
|
||||
ext_str_len += ext[i].name_len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
ext_str = malloc(ext_str_len + 1);
|
||||
if (ext_str != NULL) {
|
||||
point = ext_str;
|
||||
|
||||
for (i = 0; ext[i].name != NULL; i++) {
|
||||
if (!filter || EXT_ENABLED(ext[i].bit, filter)) {
|
||||
(void) memcpy(point, ext[i].name, ext[i].name_len);
|
||||
point += ext[i].name_len;
|
||||
|
||||
*point = ' ';
|
||||
point++;
|
||||
}
|
||||
}
|
||||
|
||||
*point = '\0';
|
||||
}
|
||||
|
||||
return ext_str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the string of client library supported extensions.
|
||||
*/
|
||||
const char *
|
||||
__glXGetClientExtensions(Display *dpy)
|
||||
{
|
||||
if (__glXGLXClientExtensions == NULL) {
|
||||
__glXExtensionsCtr();
|
||||
__glXGLXClientExtensions = __glXGetStringFromTable(known_glx_extensions,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return __glXGLXClientExtensions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the list of application usable extensions. The resulting
|
||||
* string is stored in \c psc->effectiveGLXexts.
|
||||
*
|
||||
* \param psc Pointer to GLX per-screen record.
|
||||
* \param display_is_direct_capable True if the display is capable of
|
||||
* direct rendering.
|
||||
*/
|
||||
|
||||
void
|
||||
__glXCalculateUsableExtensions(struct glx_screen * psc,
|
||||
GLboolean display_is_direct_capable)
|
||||
{
|
||||
unsigned char server_support[__GLX_EXT_BYTES];
|
||||
unsigned char usable[__GLX_EXT_BYTES];
|
||||
unsigned i;
|
||||
|
||||
__glXExtensionsCtr();
|
||||
__glXExtensionsCtrScreen(psc);
|
||||
|
||||
(void) memset(server_support, 0, sizeof(server_support));
|
||||
__glXProcessServerString(known_glx_extensions,
|
||||
psc->serverGLXexts, server_support);
|
||||
|
||||
|
||||
/* An extension is supported if the client-side (i.e., libGL) supports
|
||||
* it and the "server" supports it. In this case that means that either
|
||||
* the true server supports it or it is only for direct-rendering and
|
||||
* the direct rendering driver supports it.
|
||||
*
|
||||
* If the display is not capable of direct rendering, then the extension
|
||||
* is enabled if and only if the client-side library and the server
|
||||
* support it.
|
||||
*/
|
||||
|
||||
if (display_is_direct_capable) {
|
||||
for (i = 0; i < __GLX_EXT_BYTES; i++) {
|
||||
/* Enable extensions that the client supports that only have a client-side
|
||||
* component.
|
||||
*/
|
||||
unsigned char u = client_glx_only[i];
|
||||
|
||||
/* Enable extensions that are supported for direct rendering, and either
|
||||
* are supported by the server or only have a direct-rendering component.
|
||||
*/
|
||||
u |= psc->direct_support[i] & (server_support[i] | direct_glx_only[i]);
|
||||
|
||||
/* Finally, apply driconf options to force some extension bits either
|
||||
* enabled or disabled.
|
||||
*/
|
||||
u |= psc->glx_force_enabled[i];
|
||||
u &= ~psc->glx_force_disabled[i];
|
||||
|
||||
usable[i] = u;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < __GLX_EXT_BYTES; i++) {
|
||||
/* Enable extensions that the client supports that only have a
|
||||
* client-side component.
|
||||
*/
|
||||
unsigned char u = client_glx_only[i];
|
||||
|
||||
/* Enable extensions that the client and server both support */
|
||||
u |= server_support[i];
|
||||
|
||||
/* Finally, apply driconf options to force some extension bits either
|
||||
* enabled or disabled.
|
||||
*/
|
||||
u |= psc->glx_force_enabled[i];
|
||||
u &= ~psc->glx_force_disabled[i];
|
||||
|
||||
usable[i] = u;
|
||||
}
|
||||
}
|
||||
|
||||
psc->effectiveGLXexts = __glXGetStringFromTable(known_glx_extensions,
|
||||
usable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the list of application usable extensions. The resulting
|
||||
* string is stored in \c gc->extensions.
|
||||
*
|
||||
* \param gc Pointer to GLX context.
|
||||
* \param server_string Extension string from the server.
|
||||
*/
|
||||
|
||||
void
|
||||
__glXCalculateUsableGLExtensions(struct glx_context * gc,
|
||||
const char *server_string)
|
||||
{
|
||||
struct glx_screen *psc = gc->psc;
|
||||
unsigned char server_support[__GL_EXT_BYTES];
|
||||
unsigned char usable[__GL_EXT_BYTES];
|
||||
unsigned i;
|
||||
|
||||
(void) memset(server_support, 0, sizeof(server_support));
|
||||
__glXProcessServerString(known_gl_extensions, server_string,
|
||||
server_support);
|
||||
|
||||
/* These extensions are wholly inside the client-side indirect code */
|
||||
(void) memset(usable, 0, sizeof(usable));
|
||||
SET_BIT(usable, GL_ARB_transpose_matrix_bit);
|
||||
SET_BIT(usable, GL_EXT_draw_range_elements_bit);
|
||||
SET_BIT(usable, GL_EXT_multi_draw_arrays_bit);
|
||||
SET_BIT(usable, GL_SUN_multi_draw_arrays_bit);
|
||||
|
||||
for (i = 0; i < __GL_EXT_BYTES; i++) {
|
||||
/* Usable if the server supports it, or if it's been forced on */
|
||||
usable[i] = server_support[i] | psc->gl_force_enabled[i];
|
||||
|
||||
/* But not if it's been forced off */
|
||||
usable[i] &= ~psc->gl_force_disabled[i];
|
||||
}
|
||||
|
||||
gc->extensions = (unsigned char *)
|
||||
__glXGetStringFromTable(known_gl_extensions, usable);
|
||||
(void) memcpy(gc->gl_extension_bits, usable, sizeof(usable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string representing the set of extensions supported by the client
|
||||
* library. This is currently only used to send the list of extensions
|
||||
* supported by the client to the server.
|
||||
*/
|
||||
char *
|
||||
__glXGetClientGLExtensionString(int screen)
|
||||
{
|
||||
if (screen < 0)
|
||||
return strdup("");
|
||||
|
||||
return __glXGetStringFromTable(known_gl_extensions, NULL);
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2002, 2004
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glxextensions.h
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef GLX_GLXEXTENSIONS_H
|
||||
#define GLX_GLXEXTENSIONS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
ARB_context_flush_control_bit = 0,
|
||||
ARB_create_context_bit,
|
||||
ARB_create_context_no_error_bit,
|
||||
ARB_create_context_profile_bit,
|
||||
ARB_create_context_robustness_bit,
|
||||
ARB_fbconfig_float_bit,
|
||||
ARB_get_proc_address_bit,
|
||||
ARB_multisample_bit,
|
||||
EXT_buffer_age_bit,
|
||||
EXT_create_context_es2_profile_bit,
|
||||
EXT_create_context_es_profile_bit,
|
||||
EXT_fbconfig_packed_float_bit,
|
||||
EXT_framebuffer_sRGB_bit,
|
||||
EXT_import_context_bit,
|
||||
EXT_no_config_context_bit,
|
||||
EXT_swap_control_bit,
|
||||
EXT_swap_control_tear_bit,
|
||||
EXT_texture_from_pixmap_bit,
|
||||
EXT_visual_info_bit,
|
||||
EXT_visual_rating_bit,
|
||||
ATI_pixel_format_float_bit,
|
||||
INTEL_swap_event_bit,
|
||||
MESA_copy_sub_buffer_bit,
|
||||
MESA_gl_interop_bit,
|
||||
MESA_query_renderer_bit,
|
||||
MESA_swap_control_bit,
|
||||
MESA_swap_frame_usage_bit,
|
||||
NV_float_buffer_bit,
|
||||
OML_sync_control_bit,
|
||||
SGIS_multisample_bit,
|
||||
SGIX_fbconfig_bit,
|
||||
SGIX_pbuffer_bit,
|
||||
SGIX_visual_select_group_bit,
|
||||
SGI_make_current_read_bit,
|
||||
SGI_swap_control_bit,
|
||||
SGI_video_sync_bit,
|
||||
|
||||
__NUM_GLX_EXTS,
|
||||
};
|
||||
|
||||
#define __GLX_EXT_BYTES ((__NUM_GLX_EXTS + 7) / 8)
|
||||
|
||||
/* From the GLX perspective, the ARB and EXT extensions are identical. Use a
|
||||
* single bit for both.
|
||||
*/
|
||||
#define ARB_framebuffer_sRGB_bit EXT_framebuffer_sRGB_bit
|
||||
|
||||
enum
|
||||
{
|
||||
GL_ARB_depth_texture_bit = 0,
|
||||
GL_ARB_draw_buffers_bit,
|
||||
GL_ARB_fragment_program_bit,
|
||||
GL_ARB_fragment_program_shadow_bit,
|
||||
GL_ARB_framebuffer_object_bit,
|
||||
GL_ARB_imaging_bit,
|
||||
GL_ARB_multisample_bit,
|
||||
GL_ARB_multitexture_bit,
|
||||
GL_ARB_occlusion_query_bit,
|
||||
GL_ARB_point_parameters_bit,
|
||||
GL_ARB_point_sprite_bit,
|
||||
GL_ARB_shadow_bit,
|
||||
GL_ARB_shadow_ambient_bit,
|
||||
GL_ARB_texture_border_clamp_bit,
|
||||
GL_ARB_texture_cube_map_bit,
|
||||
GL_ARB_texture_compression_bit,
|
||||
GL_ARB_texture_env_add_bit,
|
||||
GL_ARB_texture_env_combine_bit,
|
||||
GL_ARB_texture_env_crossbar_bit,
|
||||
GL_ARB_texture_env_dot3_bit,
|
||||
GL_ARB_texture_filter_anisotropic_bit,
|
||||
GL_ARB_texture_mirrored_repeat_bit,
|
||||
GL_ARB_texture_non_power_of_two_bit,
|
||||
GL_ARB_texture_rectangle_bit,
|
||||
GL_ARB_texture_rg_bit,
|
||||
GL_ARB_transpose_matrix_bit,
|
||||
GL_ARB_vertex_buffer_object_bit,
|
||||
GL_ARB_vertex_program_bit,
|
||||
GL_ARB_window_pos_bit,
|
||||
GL_EXT_abgr_bit,
|
||||
GL_EXT_bgra_bit,
|
||||
GL_EXT_blend_color_bit,
|
||||
GL_EXT_blend_equation_separate_bit,
|
||||
GL_EXT_blend_func_separate_bit,
|
||||
GL_EXT_blend_logic_op_bit,
|
||||
GL_EXT_blend_minmax_bit,
|
||||
GL_EXT_blend_subtract_bit,
|
||||
GL_EXT_clip_volume_hint_bit,
|
||||
GL_EXT_compiled_vertex_array_bit,
|
||||
GL_EXT_convolution_bit,
|
||||
GL_EXT_copy_texture_bit,
|
||||
GL_EXT_cull_vertex_bit,
|
||||
GL_EXT_depth_bounds_test_bit,
|
||||
GL_EXT_draw_range_elements_bit,
|
||||
GL_EXT_fog_coord_bit,
|
||||
GL_EXT_framebuffer_blit_bit,
|
||||
GL_EXT_framebuffer_multisample_bit,
|
||||
GL_EXT_framebuffer_object_bit,
|
||||
GL_EXT_framebuffer_sRGB_bit,
|
||||
GL_EXT_multi_draw_arrays_bit,
|
||||
GL_EXT_packed_depth_stencil_bit,
|
||||
GL_EXT_packed_pixels_bit,
|
||||
GL_EXT_paletted_texture_bit,
|
||||
GL_EXT_pixel_buffer_object_bit,
|
||||
GL_EXT_polygon_offset_bit,
|
||||
GL_EXT_rescale_normal_bit,
|
||||
GL_EXT_secondary_color_bit,
|
||||
GL_EXT_separate_specular_color_bit,
|
||||
GL_EXT_shadow_funcs_bit,
|
||||
GL_EXT_shared_texture_palette_bit,
|
||||
GL_EXT_stencil_two_side_bit,
|
||||
GL_EXT_stencil_wrap_bit,
|
||||
GL_EXT_subtexture_bit,
|
||||
GL_EXT_texture_bit,
|
||||
GL_EXT_texture3D_bit,
|
||||
GL_EXT_texture_compression_dxt1_bit,
|
||||
GL_EXT_texture_compression_s3tc_bit,
|
||||
GL_EXT_texture_edge_clamp_bit,
|
||||
GL_EXT_texture_env_combine_bit,
|
||||
GL_EXT_texture_env_dot3_bit,
|
||||
GL_EXT_texture_integer_bit,
|
||||
GL_EXT_texture_lod_bit,
|
||||
GL_EXT_texture_lod_bias_bit,
|
||||
GL_EXT_texture_mirror_clamp_bit,
|
||||
GL_EXT_vertex_array_bit,
|
||||
GL_3DFX_texture_compression_FXT1_bit,
|
||||
GL_APPLE_packed_pixels_bit,
|
||||
GL_APPLE_ycbcr_422_bit,
|
||||
GL_ATI_text_fragment_shader_bit,
|
||||
GL_ATI_texture_env_combine3_bit,
|
||||
GL_ATI_texture_float_bit,
|
||||
GL_ATI_texture_mirror_once_bit,
|
||||
GL_HP_convolution_border_modes_bit,
|
||||
GL_HP_occlusion_test_bit,
|
||||
GL_IBM_cull_vertex_bit,
|
||||
GL_IBM_pixel_filter_hint_bit,
|
||||
GL_IBM_rasterpos_clip_bit,
|
||||
GL_IBM_texture_clamp_nodraw_bit,
|
||||
GL_INGR_interlace_read_bit,
|
||||
GL_MESA_pack_invert_bit,
|
||||
GL_MESA_ycbcr_texture_bit,
|
||||
GL_NV_blend_square_bit,
|
||||
GL_NV_copy_depth_to_color_bit,
|
||||
GL_NV_depth_clamp_bit,
|
||||
GL_NV_fog_distance_bit,
|
||||
GL_NV_fragment_program_bit,
|
||||
GL_NV_fragment_program_option_bit,
|
||||
GL_NV_fragment_program2_bit,
|
||||
GL_NV_light_max_exponent_bit,
|
||||
GL_NV_multisample_filter_hint_bit,
|
||||
GL_NV_packed_depth_stencil_bit,
|
||||
GL_NV_point_sprite_bit,
|
||||
GL_NV_texgen_reflection_bit,
|
||||
GL_NV_texture_compression_vtc_bit,
|
||||
GL_NV_texture_env_combine4_bit,
|
||||
GL_OES_compressed_paletted_texture_bit,
|
||||
GL_OES_read_format_bit,
|
||||
GL_SGI_color_matrix_bit,
|
||||
GL_SGI_color_table_bit,
|
||||
GL_SGI_texture_color_table_bit,
|
||||
GL_SGIS_generate_mipmap_bit,
|
||||
GL_SGIS_multisample_bit,
|
||||
GL_SGIS_texture_lod_bit,
|
||||
GL_SGIX_blend_alpha_minmax_bit,
|
||||
GL_SGIX_clipmap_bit,
|
||||
GL_SGIX_depth_texture_bit,
|
||||
GL_SGIX_fog_offset_bit,
|
||||
GL_SGIX_shadow_bit,
|
||||
GL_SGIX_texture_coordinate_clamp_bit,
|
||||
GL_SGIX_texture_lod_bias_bit,
|
||||
GL_SGIX_texture_range_bit,
|
||||
GL_SGIX_texture_scale_bias_bit,
|
||||
GL_SGIX_vertex_preclip_bit,
|
||||
GL_SGIX_vertex_preclip_hint_bit,
|
||||
GL_SGIX_ycrcb_bit,
|
||||
GL_SUN_convolution_border_modes_bit,
|
||||
GL_SUN_slice_accum_bit,
|
||||
|
||||
/* This *MUST* go here. If it gets put after the duplicate values it will
|
||||
* get the value after the last duplicate.
|
||||
*/
|
||||
__NUM_GL_EXTS,
|
||||
|
||||
|
||||
/* Alias extension bits. These extensions exist in either vendor-specific
|
||||
* or EXT form and were later promoted to either EXT or ARB form. In all
|
||||
* cases, the meaning (to GLX) is *exactly* the same. That's why
|
||||
* EXT_texture_env_combine is *NOT* an alias of ARB_texture_env_combine and
|
||||
* EXT_texture_env_dot3 is *NOT* an alias of ARB_texture_env_dot3. Be
|
||||
* careful! When in doubt, src/mesa/main/extensions.c is a great reference.
|
||||
*/
|
||||
|
||||
GL_ATI_blend_equation_separate_bit = GL_EXT_blend_equation_separate_bit,
|
||||
GL_ATI_draw_buffers_bit = GL_ARB_draw_buffers_bit,
|
||||
GL_ATIX_texture_env_combine3_bit = GL_ATI_texture_env_combine3_bit,
|
||||
GL_EXT_point_parameters_bit = GL_ARB_point_parameters_bit,
|
||||
GL_EXT_texture_env_add_bit = GL_ARB_texture_env_add_bit,
|
||||
GL_EXT_texture_filter_anisotropic_bit = GL_ARB_texture_filter_anisotropic_bit,
|
||||
GL_EXT_texture_rectangle_bit = GL_ARB_texture_rectangle_bit,
|
||||
GL_IBM_texture_mirrored_repeat_bit = GL_ARB_texture_mirrored_repeat_bit,
|
||||
GL_INGR_blend_func_separate_bit = GL_EXT_blend_func_separate_bit,
|
||||
GL_MESA_window_pos_bit = GL_ARB_window_pos_bit,
|
||||
GL_NV_texture_rectangle_bit = GL_ARB_texture_rectangle_bit,
|
||||
GL_SGIS_texture_border_clamp_bit = GL_ARB_texture_border_clamp_bit,
|
||||
GL_SGIS_texture_edge_clamp_bit = GL_EXT_texture_edge_clamp_bit,
|
||||
GL_SGIX_shadow_ambient_bit = GL_ARB_shadow_ambient_bit,
|
||||
GL_SUN_multi_draw_arrays_bit = GL_EXT_multi_draw_arrays_bit
|
||||
};
|
||||
|
||||
#define __GL_EXT_BYTES ((__NUM_GL_EXTS + 7) / 8)
|
||||
|
||||
struct glx_screen;
|
||||
struct glx_context;
|
||||
|
||||
extern GLboolean __glXExtensionBitIsEnabled(struct glx_screen *psc,
|
||||
unsigned bit);
|
||||
extern const char *__glXGetClientExtensions(Display *dpy);
|
||||
extern void __glXCalculateUsableExtensions(struct glx_screen *psc,
|
||||
GLboolean
|
||||
display_is_direct_capable);
|
||||
|
||||
extern void __glXParseExtensionOverride(struct glx_screen *psc,
|
||||
const char *override);
|
||||
extern void __IndirectGlParseExtensionOverride(struct glx_screen *psc,
|
||||
const char *override);
|
||||
extern void __glXCalculateUsableGLExtensions(struct glx_context *gc,
|
||||
const char *server_string);
|
||||
extern char *__glXGetClientGLExtensionString(int screen);
|
||||
|
||||
extern GLboolean __glExtensionBitIsEnabled(struct glx_context *gc,
|
||||
unsigned bit);
|
||||
|
||||
extern void
|
||||
__glXEnableDirectExtension(struct glx_screen *psc, const char *name);
|
||||
|
||||
|
||||
/* GLX_ALIAS should be used for functions with a non-void return type.
|
||||
GLX_ALIAS_VOID is for functions with a void return type. */
|
||||
# ifdef HAVE_FUNC_ATTRIBUTE_ALIAS
|
||||
# define GLX_ALIAS(return_type, real_func, proto_args, args, aliased_func) \
|
||||
return_type real_func proto_args \
|
||||
__attribute__ ((alias( # aliased_func ) ));
|
||||
# define GLX_ALIAS_VOID(real_func, proto_args, args, aliased_func) \
|
||||
GLX_ALIAS(void, real_func, proto_args, args, aliased_func)
|
||||
# else
|
||||
# define GLX_ALIAS(return_type, real_func, proto_args, args, aliased_func) \
|
||||
return_type real_func proto_args \
|
||||
{ return aliased_func args ; }
|
||||
# define GLX_ALIAS_VOID(real_func, proto_args, args, aliased_func) \
|
||||
void real_func proto_args \
|
||||
{ aliased_func args ; }
|
||||
# endif /* HAVE_FUNC_ATTRIBUTE_ALIAS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GLX_GLXEXTENSIONS_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "glvnd/libglxabi.h"
|
||||
|
||||
#include "glxglvnd.h"
|
||||
|
||||
static Bool __glXGLVNDIsScreenSupported(Display *dpy, int screen)
|
||||
{
|
||||
/* TODO: Think of a better heuristic... */
|
||||
return True;
|
||||
}
|
||||
|
||||
static void *__glXGLVNDGetProcAddress(const GLubyte *procName)
|
||||
{
|
||||
return glXGetProcAddressARB(procName);
|
||||
}
|
||||
|
||||
static int
|
||||
compare(const void *l, const void *r)
|
||||
{
|
||||
const char *s = *(const char **)r;
|
||||
return strcmp(l, s);
|
||||
}
|
||||
|
||||
static unsigned FindGLXFunction(const GLubyte *name)
|
||||
{
|
||||
const char * const *match;
|
||||
|
||||
match = bsearch(name, __glXDispatchTableStrings, DI_FUNCTION_COUNT,
|
||||
sizeof(const char *), compare);
|
||||
|
||||
if (match == NULL)
|
||||
return DI_FUNCTION_COUNT;
|
||||
|
||||
return match - __glXDispatchTableStrings;
|
||||
}
|
||||
|
||||
static void *__glXGLVNDGetDispatchAddress(const GLubyte *procName)
|
||||
{
|
||||
unsigned internalIndex = FindGLXFunction(procName);
|
||||
|
||||
return (void*)__glXDispatchFunctions[internalIndex];
|
||||
}
|
||||
|
||||
static void __glXGLVNDSetDispatchIndex(const GLubyte *procName, int index)
|
||||
{
|
||||
unsigned internalIndex = FindGLXFunction(procName);
|
||||
|
||||
if (internalIndex == DI_FUNCTION_COUNT)
|
||||
return; /* unknown or static dispatch */
|
||||
|
||||
__glXDispatchTableIndices[internalIndex] = index;
|
||||
}
|
||||
|
||||
_X_EXPORT Bool __glx_Main(uint32_t version, const __GLXapiExports *exports,
|
||||
__GLXvendorInfo *vendor, __GLXapiImports *imports)
|
||||
{
|
||||
static Bool initDone = False;
|
||||
|
||||
if (GLX_VENDOR_ABI_GET_MAJOR_VERSION(version) !=
|
||||
GLX_VENDOR_ABI_MAJOR_VERSION ||
|
||||
GLX_VENDOR_ABI_GET_MINOR_VERSION(version) <
|
||||
GLX_VENDOR_ABI_MINOR_VERSION)
|
||||
return False;
|
||||
|
||||
if (!initDone) {
|
||||
initDone = True;
|
||||
__glXGLVNDAPIExports = exports;
|
||||
|
||||
imports->isScreenSupported = __glXGLVNDIsScreenSupported;
|
||||
imports->getProcAddress = __glXGLVNDGetProcAddress;
|
||||
imports->getDispatchAddress = __glXGLVNDGetDispatchAddress;
|
||||
imports->setDispatchIndex = __glXGLVNDSetDispatchIndex;
|
||||
imports->notifyError = NULL;
|
||||
imports->isPatchSupported = NULL;
|
||||
imports->initiatePatch = NULL;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _glx_lib_glvnd_h_
|
||||
#define _glx_lib_glvnd_h_
|
||||
|
||||
typedef struct __GLXapiExportsRec __GLXapiExports;
|
||||
|
||||
extern const __GLXapiExports *__glXGLVNDAPIExports;
|
||||
|
||||
extern const int DI_FUNCTION_COUNT;
|
||||
|
||||
extern const void * const __glXDispatchFunctions[];
|
||||
extern int __glXDispatchTableIndices[];
|
||||
extern const char * const __glXDispatchTableStrings[];
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef __glx_glvnd_dispatch_funcs_h__
|
||||
#define __glx_glvnd_dispatch_funcs_h__
|
||||
/*
|
||||
* Helper functions used by g_glxglvnddispatchfuncs.c.
|
||||
*/
|
||||
#include "glvnd/libglxabi.h"
|
||||
#include "glxglvnd.h"
|
||||
|
||||
#define __VND __glXGLVNDAPIExports
|
||||
|
||||
static inline int AddFBConfigMapping(Display *dpy, GLXFBConfig config,
|
||||
__GLXvendorInfo *vendor)
|
||||
{
|
||||
return __VND->addVendorFBConfigMapping(dpy, config, vendor);
|
||||
}
|
||||
|
||||
static inline int AddFBConfigsMapping(Display *dpy, const GLXFBConfig *ret,
|
||||
int *nelements, __GLXvendorInfo *vendor)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (!nelements || !ret)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < *nelements; i++) {
|
||||
r = __VND->addVendorFBConfigMapping(dpy, ret[i], vendor);
|
||||
if (r) {
|
||||
for (; i >= 0; i--)
|
||||
__VND->removeVendorFBConfigMapping(dpy, ret[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int AddDrawableMapping(Display *dpy, GLXDrawable drawable,
|
||||
__GLXvendorInfo *vendor)
|
||||
{
|
||||
return __VND->addVendorDrawableMapping(dpy, drawable, vendor);
|
||||
}
|
||||
|
||||
static inline int AddContextMapping(Display *dpy, GLXContext ctx,
|
||||
__GLXvendorInfo *vendor)
|
||||
{
|
||||
return __VND->addVendorContextMapping(dpy, ctx, vendor);
|
||||
}
|
||||
|
||||
static inline __GLXvendorInfo *GetDispatchFromDrawable(Display *dpy,
|
||||
GLXDrawable drawable)
|
||||
{
|
||||
return __VND->vendorFromDrawable(dpy, drawable);
|
||||
}
|
||||
|
||||
static inline __GLXvendorInfo *GetDispatchFromContext(GLXContext ctx)
|
||||
{
|
||||
return __VND->vendorFromContext(ctx);
|
||||
}
|
||||
|
||||
static inline __GLXvendorInfo *GetDispatchFromFBConfig(Display *dpy, GLXFBConfig config)
|
||||
{
|
||||
return __VND->vendorFromFBConfig(dpy, config);
|
||||
}
|
||||
|
||||
static inline __GLXvendorInfo *GetDispatchFromVisual(Display *dpy,
|
||||
const XVisualInfo *visual)
|
||||
{
|
||||
return __VND->getDynDispatch(dpy, visual->screen);
|
||||
}
|
||||
|
||||
#endif // __glx_glvnd_dispatch_funcs_h__
|
||||
@@ -0,0 +1,473 @@
|
||||
/* glxhash.c -- Small hash table support for integer -> integer mapping
|
||||
* Taken from libdrm.
|
||||
*
|
||||
* Created: Sun Apr 18 09:35:45 1999 by [email protected]
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* 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
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <[email protected]>
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file contains a straightforward implementation of a fixed-sized
|
||||
* hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
|
||||
* collision resolution. There are two potentially interesting things
|
||||
* about this implementation:
|
||||
*
|
||||
* 1) The table is power-of-two sized. Prime sized tables are more
|
||||
* traditional, but do not have a significant advantage over power-of-two
|
||||
* sized table, especially when double hashing is not used for collision
|
||||
* resolution.
|
||||
*
|
||||
* 2) The hash computation uses a table of random integers [Hanson97,
|
||||
* pp. 39-41].
|
||||
*
|
||||
* FUTURE ENHANCEMENTS
|
||||
*
|
||||
* With a table size of 512, the current implementation is sufficient for a
|
||||
* few hundred keys. Since this is well above the expected size of the
|
||||
* tables for which this implementation was designed, the implementation of
|
||||
* dynamic hash tables was postponed until the need arises. A common (and
|
||||
* naive) approach to dynamic hash table implementation simply creates a
|
||||
* new hash table when necessary, rehashes all the data into the new table,
|
||||
* and destroys the old table. The approach in [Larson88] is superior in
|
||||
* two ways: 1) only a portion of the table is expanded when needed,
|
||||
* distributing the expansion cost over several insertions, and 2) portions
|
||||
* of the table can be locked, enabling a scalable thread-safe
|
||||
* implementation.
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Hanson97] David R. Hanson. C Interfaces and Implementations:
|
||||
* Techniques for Creating Reusable Software. Reading, Massachusetts:
|
||||
* Addison-Wesley, 1997.
|
||||
*
|
||||
* [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
|
||||
* Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
|
||||
*
|
||||
* [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
|
||||
* 1988, pp. 446-457.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glxhash.h"
|
||||
#include <X11/Xfuncproto.h>
|
||||
|
||||
#define HASH_MAIN 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HASH_MAGIC 0xdeadbeef
|
||||
#define HASH_DEBUG 0
|
||||
#define HASH_SIZE 512 /* Good for about 100 entries */
|
||||
/* If you change this value, you probably
|
||||
have to change the HashHash hashing
|
||||
function! */
|
||||
|
||||
#define HASH_ALLOC malloc
|
||||
#define HASH_FREE free
|
||||
#ifndef HAVE_RANDOM_R
|
||||
#define HASH_RANDOM_DECL char *ps, rs[256]
|
||||
#define HASH_RANDOM_INIT(seed) ps = initstate(seed, rs, sizeof(rs))
|
||||
#define HASH_RANDOM random()
|
||||
#define HASH_RANDOM_DESTROY setstate(ps)
|
||||
#else
|
||||
#define HASH_RANDOM_DECL struct random_data rd; int32_t rv; char rs[256]
|
||||
#define HASH_RANDOM_INIT(seed) \
|
||||
do { \
|
||||
(void) memset(&rd, 0, sizeof(rd)); \
|
||||
(void) initstate_r(seed, rs, sizeof(rs), &rd); \
|
||||
} while(0)
|
||||
#define HASH_RANDOM ((void) random_r(&rd, &rv), rv)
|
||||
#define HASH_RANDOM_DESTROY
|
||||
#endif
|
||||
|
||||
typedef struct __glxHashBucket
|
||||
{
|
||||
unsigned long key;
|
||||
void *value;
|
||||
struct __glxHashBucket *next;
|
||||
} __glxHashBucket, *__glxHashBucketPtr;
|
||||
|
||||
typedef struct __glxHashTable *__glxHashTablePtr;
|
||||
struct __glxHashTable
|
||||
{
|
||||
unsigned long magic;
|
||||
unsigned long hits; /* At top of linked list */
|
||||
unsigned long partials; /* Not at top of linked list */
|
||||
unsigned long misses; /* Not in table */
|
||||
__glxHashBucketPtr buckets[HASH_SIZE];
|
||||
int p0;
|
||||
__glxHashBucketPtr p1;
|
||||
};
|
||||
|
||||
static unsigned long
|
||||
HashHash(unsigned long key)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
unsigned long tmp = key;
|
||||
static int init = 0;
|
||||
static unsigned long scatter[256];
|
||||
int i;
|
||||
|
||||
if (!init) {
|
||||
HASH_RANDOM_DECL;
|
||||
HASH_RANDOM_INIT(37);
|
||||
for (i = 0; i < 256; i++)
|
||||
scatter[i] = HASH_RANDOM;
|
||||
HASH_RANDOM_DESTROY;
|
||||
++init;
|
||||
}
|
||||
|
||||
while (tmp) {
|
||||
hash = (hash << 1) + scatter[tmp & 0xff];
|
||||
tmp >>= 8;
|
||||
}
|
||||
|
||||
hash %= HASH_SIZE;
|
||||
#if HASH_DEBUG
|
||||
printf("Hash(%d) = %d\n", key, hash);
|
||||
#endif
|
||||
return hash;
|
||||
}
|
||||
|
||||
__glxHashTable *
|
||||
__glxHashCreate(void)
|
||||
{
|
||||
__glxHashTablePtr table;
|
||||
int i;
|
||||
|
||||
table = HASH_ALLOC(sizeof(*table));
|
||||
if (!table)
|
||||
return NULL;
|
||||
table->magic = HASH_MAGIC;
|
||||
table->hits = 0;
|
||||
table->partials = 0;
|
||||
table->misses = 0;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++)
|
||||
table->buckets[i] = NULL;
|
||||
return table;
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashDestroy(__glxHashTable * t)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
__glxHashBucketPtr bucket;
|
||||
__glxHashBucketPtr next;
|
||||
int i;
|
||||
|
||||
if (table->magic != HASH_MAGIC)
|
||||
return -1; /* Bad magic */
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
for (bucket = table->buckets[i]; bucket;) {
|
||||
next = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
bucket = next;
|
||||
}
|
||||
}
|
||||
HASH_FREE(table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the bucket and organize the list so that this bucket is at the
|
||||
top. */
|
||||
|
||||
static __glxHashBucketPtr
|
||||
HashFind(__glxHashTablePtr table, unsigned long key, unsigned long *h)
|
||||
{
|
||||
unsigned long hash = HashHash(key);
|
||||
__glxHashBucketPtr prev = NULL;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (h)
|
||||
*h = hash;
|
||||
|
||||
for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
|
||||
if (bucket->key == key) {
|
||||
if (prev) {
|
||||
/* Organize */
|
||||
prev->next = bucket->next;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
++table->partials;
|
||||
}
|
||||
else {
|
||||
++table->hits;
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
prev = bucket;
|
||||
}
|
||||
++table->misses;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashLookup(__glxHashTable * t, unsigned long key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (!table || table->magic != HASH_MAGIC)
|
||||
return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, NULL);
|
||||
if (!bucket)
|
||||
return 1; /* Not found */
|
||||
*value = bucket->value;
|
||||
return 0; /* Found */
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashInsert(__glxHashTable * t, unsigned long key, void *value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
__glxHashBucketPtr bucket;
|
||||
unsigned long hash;
|
||||
|
||||
if (table->magic != HASH_MAGIC)
|
||||
return -1; /* Bad magic */
|
||||
|
||||
if (HashFind(table, key, &hash))
|
||||
return 1; /* Already in table */
|
||||
|
||||
bucket = HASH_ALLOC(sizeof(*bucket));
|
||||
if (!bucket)
|
||||
return -1; /* Error */
|
||||
bucket->key = key;
|
||||
bucket->value = value;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
#if HASH_DEBUG
|
||||
printf("Inserted %d at %d/%p\n", key, hash, bucket);
|
||||
#endif
|
||||
return 0; /* Added to table */
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashDelete(__glxHashTable * t, unsigned long key)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
unsigned long hash;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
if (table->magic != HASH_MAGIC)
|
||||
return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, &hash);
|
||||
|
||||
if (!bucket)
|
||||
return 1; /* Not found */
|
||||
|
||||
table->buckets[hash] = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashNext(__glxHashTable * t, unsigned long *key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
|
||||
while (table->p0 < HASH_SIZE) {
|
||||
if (table->p1) {
|
||||
*key = table->p1->key;
|
||||
*value = table->p1->value;
|
||||
table->p1 = table->p1->next;
|
||||
return 1;
|
||||
}
|
||||
table->p1 = table->buckets[table->p0];
|
||||
++table->p0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__glxHashFirst(__glxHashTable * t, unsigned long *key, void **value)
|
||||
{
|
||||
__glxHashTablePtr table = (__glxHashTablePtr) t;
|
||||
|
||||
if (table->magic != HASH_MAGIC)
|
||||
return -1; /* Bad magic */
|
||||
|
||||
table->p0 = 0;
|
||||
table->p1 = table->buckets[0];
|
||||
return __glxHashNext(table, key, value);
|
||||
}
|
||||
|
||||
#if HASH_MAIN
|
||||
#define DIST_LIMIT 10
|
||||
static int dist[DIST_LIMIT];
|
||||
|
||||
static void
|
||||
clear_dist(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DIST_LIMIT; i++)
|
||||
dist[i] = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
count_entries(__glxHashBucketPtr bucket)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (; bucket; bucket = bucket->next)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
update_dist(int count)
|
||||
{
|
||||
if (count >= DIST_LIMIT)
|
||||
++dist[DIST_LIMIT - 1];
|
||||
else
|
||||
++dist[count];
|
||||
}
|
||||
|
||||
static void
|
||||
compute_dist(__glxHashTablePtr table)
|
||||
{
|
||||
int i;
|
||||
__glxHashBucketPtr bucket;
|
||||
|
||||
printf("Hits = %ld, partials = %ld, misses = %ld\n",
|
||||
table->hits, table->partials, table->misses);
|
||||
clear_dist();
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
bucket = table->buckets[i];
|
||||
update_dist(count_entries(bucket));
|
||||
}
|
||||
for (i = 0; i < DIST_LIMIT; i++) {
|
||||
if (i != DIST_LIMIT - 1)
|
||||
printf("%5d %10d\n", i, dist[i]);
|
||||
else
|
||||
printf("other %10d\n", dist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_table(__glxHashTablePtr table, unsigned long key, unsigned long value)
|
||||
{
|
||||
unsigned long retval = 0;
|
||||
int retcode = __glxHashLookup(table, key, &retval);
|
||||
|
||||
switch (retcode) {
|
||||
case -1:
|
||||
printf("Bad magic = 0x%08lx:"
|
||||
" key = %lu, expected = %lu, returned = %lu\n",
|
||||
table->magic, key, value, retval);
|
||||
break;
|
||||
case 1:
|
||||
printf("Not found: key = %lu, expected = %lu returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
case 0:
|
||||
if (value != retval)
|
||||
printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
default:
|
||||
printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
|
||||
retcode, key, value, retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
__glxHashTablePtr table;
|
||||
int i;
|
||||
|
||||
printf("\n***** 256 consecutive integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 256; i++)
|
||||
__glxHashInsert(table, i, i);
|
||||
for (i = 0; i < 256; i++)
|
||||
check_table(table, i, i);
|
||||
for (i = 256; i >= 0; i--)
|
||||
check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 consecutive integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 1024; i++)
|
||||
__glxHashInsert(table, i, i);
|
||||
for (i = 0; i < 1024; i++)
|
||||
check_table(table, i, i);
|
||||
for (i = 1024; i >= 0; i--)
|
||||
check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
|
||||
table = __glxHashCreate();
|
||||
for (i = 0; i < 1024; i++)
|
||||
__glxHashInsert(table, i * 4096, i);
|
||||
for (i = 0; i < 1024; i++)
|
||||
check_table(table, i * 4096, i);
|
||||
for (i = 1024; i >= 0; i--)
|
||||
check_table(table, i * 4096, i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 1024 random integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++)
|
||||
__glxHashInsert(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++)
|
||||
check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++)
|
||||
check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
printf("\n***** 5000 random integers ****\n");
|
||||
table = __glxHashCreate();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++)
|
||||
__glxHashInsert(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++)
|
||||
check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++)
|
||||
check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
__glxHashDestroy(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _GLX_HASH_H_
|
||||
#define _GLX_HASH_H_
|
||||
|
||||
|
||||
typedef struct __glxHashTable __glxHashTable;
|
||||
|
||||
/* Hash table routines */
|
||||
extern __glxHashTable *__glxHashCreate(void);
|
||||
extern int __glxHashDestroy(__glxHashTable * t);
|
||||
extern int __glxHashLookup(__glxHashTable * t, unsigned long key,
|
||||
void **value);
|
||||
extern int __glxHashInsert(__glxHashTable * t, unsigned long key,
|
||||
void *value);
|
||||
extern int __glxHashDelete(__glxHashTable * t, unsigned long key);
|
||||
extern int __glxHashFirst(__glxHashTable * t, unsigned long *key,
|
||||
void **value);
|
||||
extern int __glxHashNext(__glxHashTable * t, unsigned long *key,
|
||||
void **value);
|
||||
|
||||
#endif /* _GLX_HASH_H_ */
|
||||
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Soft-
|
||||
* ware"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, provided that the above copyright
|
||||
* notice(s) and this permission notice appear in all copies of the Soft-
|
||||
* ware and that both the above copyright notice(s) and this permission
|
||||
* notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
|
||||
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
|
||||
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
|
||||
* QUENTIAL 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 PERFOR-
|
||||
* MANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder shall
|
||||
* not be used in advertising or otherwise to promote the sale, use or
|
||||
* other dealings in this Software without prior written authorization of
|
||||
* the copyright holder.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg ([email protected])
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "glapi.h"
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
|
||||
|
||||
extern struct _glapi_table *__glXNewIndirectAPI(void);
|
||||
|
||||
/*
|
||||
** All indirect rendering contexts will share the same indirect dispatch table.
|
||||
*/
|
||||
static struct _glapi_table *IndirectAPI = NULL;
|
||||
|
||||
static void
|
||||
__glFreeAttributeState(struct glx_context * gc)
|
||||
{
|
||||
__GLXattribute *sp, **spp;
|
||||
|
||||
for (spp = &gc->attributes.stack[0];
|
||||
spp < &gc->attributes.stack[__GL_CLIENT_ATTRIB_STACK_DEPTH]; spp++) {
|
||||
sp = *spp;
|
||||
if (sp) {
|
||||
free((char *) sp);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
indirect_destroy_context(struct glx_context *gc)
|
||||
{
|
||||
__glXFreeVertexArrayState(gc);
|
||||
|
||||
free((char *) gc->vendor);
|
||||
free((char *) gc->renderer);
|
||||
free((char *) gc->version);
|
||||
free((char *) gc->extensions);
|
||||
__glFreeAttributeState(gc);
|
||||
free((char *) gc->buf);
|
||||
free((char *) gc->client_state_private);
|
||||
free((char *) gc);
|
||||
}
|
||||
|
||||
static Bool
|
||||
SendMakeCurrentRequest(Display * dpy, GLXContextID gc_id,
|
||||
GLXContextTag gc_tag, GLXDrawable draw,
|
||||
GLXDrawable read, GLXContextTag *out_tag)
|
||||
{
|
||||
xGLXMakeCurrentReply reply;
|
||||
Bool ret;
|
||||
int opcode = __glXSetupForCommand(dpy);
|
||||
|
||||
LockDisplay(dpy);
|
||||
|
||||
if (draw == read) {
|
||||
xGLXMakeCurrentReq *req;
|
||||
|
||||
GetReq(GLXMakeCurrent, req);
|
||||
req->reqType = opcode;
|
||||
req->glxCode = X_GLXMakeCurrent;
|
||||
req->drawable = draw;
|
||||
req->context = gc_id;
|
||||
req->oldContextTag = gc_tag;
|
||||
}
|
||||
else {
|
||||
xGLXMakeContextCurrentReq *req;
|
||||
|
||||
GetReq(GLXMakeContextCurrent, req);
|
||||
req->reqType = opcode;
|
||||
req->glxCode = X_GLXMakeContextCurrent;
|
||||
req->drawable = draw;
|
||||
req->readdrawable = read;
|
||||
req->context = gc_id;
|
||||
req->oldContextTag = gc_tag;
|
||||
}
|
||||
|
||||
ret = _XReply(dpy, (xReply *) &reply, 0, False);
|
||||
|
||||
if (out_tag)
|
||||
*out_tag = reply.contextTag;
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
indirect_bind_context(struct glx_context *gc,
|
||||
GLXDrawable draw, GLXDrawable read)
|
||||
{
|
||||
Display *dpy = gc->psc->dpy;
|
||||
Bool sent;
|
||||
|
||||
sent = SendMakeCurrentRequest(dpy, gc->xid, 0, draw, read,
|
||||
&gc->currentContextTag);
|
||||
|
||||
if (sent) {
|
||||
if (!IndirectAPI)
|
||||
IndirectAPI = __glXNewIndirectAPI();
|
||||
_mesa_glapi_set_dispatch(IndirectAPI);
|
||||
|
||||
/* The indirect vertex array state must to be initialised after we
|
||||
* have setup the context, as it needs to query server attributes.
|
||||
*
|
||||
* At the point this is called gc->currentDpy is not initialized
|
||||
* nor is the thread's current context actually set. Hence the
|
||||
* cleverness before the GetString calls.
|
||||
*/
|
||||
__GLXattribute *state = gc->client_state_private;
|
||||
if (state && state->array_state == NULL) {
|
||||
gc->currentDpy = gc->psc->dpy;
|
||||
__glXSetCurrentContext(gc);
|
||||
__indirect_glGetString(GL_EXTENSIONS);
|
||||
__indirect_glGetString(GL_VERSION);
|
||||
__glXInitVertexArrayState(gc);
|
||||
}
|
||||
}
|
||||
|
||||
return !sent;
|
||||
}
|
||||
|
||||
static void
|
||||
indirect_unbind_context(struct glx_context *gc)
|
||||
{
|
||||
Display *dpy = gc->psc->dpy;
|
||||
|
||||
SendMakeCurrentRequest(dpy, None, gc->currentContextTag, None, None, NULL);
|
||||
gc->currentContextTag = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
indirect_wait_gl(struct glx_context *gc)
|
||||
{
|
||||
xGLXWaitGLReq *req;
|
||||
Display *dpy = gc->currentDpy;
|
||||
|
||||
/* Flush any pending commands out */
|
||||
__glXFlushRenderBuffer(gc, gc->pc);
|
||||
|
||||
/* Send the glXWaitGL request */
|
||||
LockDisplay(dpy);
|
||||
GetReq(GLXWaitGL, req);
|
||||
req->reqType = gc->majorOpcode;
|
||||
req->glxCode = X_GLXWaitGL;
|
||||
req->contextTag = gc->currentContextTag;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
|
||||
static void
|
||||
indirect_wait_x(struct glx_context *gc)
|
||||
{
|
||||
xGLXWaitXReq *req;
|
||||
Display *dpy = gc->currentDpy;
|
||||
|
||||
/* Flush any pending commands out */
|
||||
__glXFlushRenderBuffer(gc, gc->pc);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(GLXWaitX, req);
|
||||
req->reqType = gc->majorOpcode;
|
||||
req->glxCode = X_GLXWaitX;
|
||||
req->contextTag = gc->currentContextTag;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
|
||||
static const struct glx_context_vtable indirect_context_vtable = {
|
||||
.destroy = indirect_destroy_context,
|
||||
.bind = indirect_bind_context,
|
||||
.unbind = indirect_unbind_context,
|
||||
.wait_gl = indirect_wait_gl,
|
||||
.wait_x = indirect_wait_x,
|
||||
};
|
||||
|
||||
struct glx_context *
|
||||
indirect_create_context(struct glx_screen *psc,
|
||||
struct glx_config *mode,
|
||||
struct glx_context *shareList, int renderType)
|
||||
{
|
||||
unsigned error = 0;
|
||||
const uint32_t attribs[] = { GLX_RENDER_TYPE, renderType };
|
||||
|
||||
return indirect_create_context_attribs(psc, mode, shareList,
|
||||
1, attribs, &error);
|
||||
}
|
||||
|
||||
/**
|
||||
* \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
|
||||
* function called \c __glXAllocateClientState that allocates the memory and
|
||||
* does all the initialization (including the pixel pack / unpack).
|
||||
*/
|
||||
struct glx_context *
|
||||
indirect_create_context_attribs(struct glx_screen *psc,
|
||||
struct glx_config *mode,
|
||||
struct glx_context *shareList,
|
||||
unsigned num_attribs,
|
||||
const uint32_t *attribs,
|
||||
unsigned *error)
|
||||
{
|
||||
struct glx_context *gc;
|
||||
int bufSize;
|
||||
CARD8 opcode;
|
||||
__GLXattribute *state;
|
||||
int i, renderType = GLX_RGBA_TYPE;
|
||||
uint32_t mask = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||
uint32_t major = 1;
|
||||
uint32_t minor = 0;
|
||||
|
||||
opcode = __glXSetupForCommand(psc->dpy);
|
||||
if (!opcode) {
|
||||
*error = BadImplementation;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_attribs; i++) {
|
||||
uint32_t attr = attribs[i*2], val = attribs[i*2 + 1];
|
||||
|
||||
if (attr == GLX_RENDER_TYPE)
|
||||
renderType = val;
|
||||
if (attr == GLX_CONTEXT_PROFILE_MASK_ARB)
|
||||
mask = val;
|
||||
if (attr == GLX_CONTEXT_MAJOR_VERSION_ARB)
|
||||
major = val;
|
||||
if (attr == GLX_CONTEXT_MINOR_VERSION_ARB)
|
||||
minor = val;
|
||||
}
|
||||
|
||||
/* We have no indirect support for core or ES contexts, and our compat
|
||||
* context support is limited to GL 1.4.
|
||||
*/
|
||||
if (mask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB ||
|
||||
major != 1 ||
|
||||
minor > 4) {
|
||||
*error = GLXBadFBConfig;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We can't share with a direct context */
|
||||
if (shareList && shareList->isDirect)
|
||||
return NULL;
|
||||
|
||||
/* Allocate our context record */
|
||||
gc = calloc(1, sizeof *gc);
|
||||
if (!gc) {
|
||||
*error = BadAlloc;
|
||||
/* Out of memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glx_context_init(gc, psc, mode);
|
||||
gc->isDirect = GL_FALSE;
|
||||
gc->vtable = &indirect_context_vtable;
|
||||
state = calloc(1, sizeof(struct __GLXattributeRec));
|
||||
gc->renderType = renderType;
|
||||
|
||||
if (state == NULL) {
|
||||
/* Out of memory */
|
||||
*error = BadAlloc;
|
||||
free(gc);
|
||||
return NULL;
|
||||
}
|
||||
gc->client_state_private = state;
|
||||
state->NoDrawArraysProtocol = debug_get_bool_option("LIBGL_NO_DRAWARRAYS", false);
|
||||
|
||||
/*
|
||||
** Create a temporary buffer to hold GLX rendering commands. The size
|
||||
** of the buffer is selected so that the maximum number of GLX rendering
|
||||
** commands can fit in a single X packet and still have room in the X
|
||||
** packet for the GLXRenderReq header.
|
||||
*/
|
||||
|
||||
bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
|
||||
gc->buf = malloc(bufSize);
|
||||
if (!gc->buf) {
|
||||
*error = BadAlloc;
|
||||
free(gc->client_state_private);
|
||||
free(gc);
|
||||
return NULL;
|
||||
}
|
||||
gc->bufSize = bufSize;
|
||||
|
||||
/* Fill in the new context */
|
||||
gc->renderMode = GL_RENDER;
|
||||
|
||||
state->storePack.alignment = 4;
|
||||
state->storeUnpack.alignment = 4;
|
||||
|
||||
gc->attributes.stackPointer = &gc->attributes.stack[0];
|
||||
|
||||
gc->pc = gc->buf;
|
||||
gc->bufEnd = gc->buf + bufSize;
|
||||
gc->isDirect = GL_FALSE;
|
||||
if (__glXDebug) {
|
||||
/*
|
||||
** Set limit register so that there will be one command per packet
|
||||
*/
|
||||
gc->limit = gc->buf;
|
||||
}
|
||||
else {
|
||||
gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
|
||||
}
|
||||
gc->majorOpcode = opcode;
|
||||
|
||||
/*
|
||||
** Constrain the maximum drawing command size allowed to be
|
||||
** transferred using the X_GLXRender protocol request. First
|
||||
** constrain by a software limit, then constrain by the protocol
|
||||
** limit.
|
||||
*/
|
||||
gc->maxSmallRenderCommandSize = MIN3(bufSize, __GLX_RENDER_CMD_SIZE_LIMIT,
|
||||
__GLX_MAX_RENDER_CMD_SIZE);
|
||||
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
static const struct glx_screen_vtable indirect_screen_vtable = {
|
||||
.create_context = indirect_create_context,
|
||||
.create_context_attribs = indirect_create_context_attribs,
|
||||
.query_renderer_integer = NULL,
|
||||
.query_renderer_string = NULL,
|
||||
};
|
||||
|
||||
struct glx_screen *
|
||||
indirect_create_screen(int screen, struct glx_display * priv)
|
||||
{
|
||||
struct glx_screen *psc;
|
||||
|
||||
psc = calloc(1, sizeof *psc);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
glx_screen_init(psc, screen, priv);
|
||||
psc->vtable = &indirect_screen_vtable;
|
||||
|
||||
return psc;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
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, sub license, 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 NON-INFRINGEMENT.
|
||||
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Kevin E. Martin <[email protected]>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INDIRECT_INIT_H_
|
||||
#define _INDIRECT_INIT_H_
|
||||
|
||||
#include "glxclient.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct _glapi_table *__glXNewIndirectAPI(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* _INDIRECT_INIT_H_ */
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2004
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file glx_texture_compression.c
|
||||
* Contains the routines required to implement GLX protocol for
|
||||
* ARB_texture_compression and related extensions.
|
||||
*
|
||||
* \sa http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_compression.txt
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
#include "packsingle.h"
|
||||
#include "indirect.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetCompressedTexImage(GLenum target, GLint level,
|
||||
GLvoid * img)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXGetTexImageReply reply;
|
||||
size_t image_bytes;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetCompressedTexImage, 8);
|
||||
__GLX_SINGLE_PUT_LONG(0, target);
|
||||
__GLX_SINGLE_PUT_LONG(4, level);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
|
||||
image_bytes = reply.width;
|
||||
assert(image_bytes <= ((4 * reply.length) - 0));
|
||||
assert(image_bytes >= ((4 * reply.length) - 3));
|
||||
|
||||
if (image_bytes != 0) {
|
||||
_XRead(dpy, (char *) img, image_bytes);
|
||||
if (image_bytes < (4 * reply.length)) {
|
||||
_XEatData(dpy, (4 * reply.length) - image_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal function used for \c glCompressedTexImage1D and
|
||||
* \c glCompressedTexImage2D.
|
||||
*/
|
||||
static void
|
||||
CompressedTexImage1D2D(GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid * data, CARD32 rop)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (gc->currentDpy == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((target == GL_PROXY_TEXTURE_1D)
|
||||
|| (target == GL_PROXY_TEXTURE_2D)
|
||||
|| (target == GL_PROXY_TEXTURE_CUBE_MAP)) {
|
||||
compsize = 0;
|
||||
}
|
||||
else {
|
||||
compsize = image_size;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD(__GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + compsize);
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
__GLX_BEGIN_VARIABLE(rop, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_LONG(8, level);
|
||||
__GLX_PUT_LONG(12, internal_format);
|
||||
__GLX_PUT_LONG(16, width);
|
||||
__GLX_PUT_LONG(20, height);
|
||||
__GLX_PUT_LONG(24, border);
|
||||
__GLX_PUT_LONG(28, image_size);
|
||||
if (compsize != 0) {
|
||||
__GLX_PUT_CHAR_ARRAY(__GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE,
|
||||
data, image_size);
|
||||
}
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
assert(compsize != 0);
|
||||
|
||||
__GLX_BEGIN_VARIABLE_LARGE(rop, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_LONG(12, level);
|
||||
__GLX_PUT_LONG(16, internal_format);
|
||||
__GLX_PUT_LONG(20, width);
|
||||
__GLX_PUT_LONG(24, height);
|
||||
__GLX_PUT_LONG(28, border);
|
||||
__GLX_PUT_LONG(32, image_size);
|
||||
__glXSendLargeCommand(gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXIMAGE_CMD_HDR_SIZE + 4,
|
||||
data, image_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal function used for \c glCompressedTexSubImage1D and
|
||||
* \c glCompressedTexSubImage2D.
|
||||
*/
|
||||
static void
|
||||
CompressedTexSubImage1D2D(GLenum target, GLint level,
|
||||
GLsizei xoffset, GLsizei yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid * data, CARD32 rop)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (gc->currentDpy == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target == GL_PROXY_TEXTURE_3D) {
|
||||
compsize = 0;
|
||||
}
|
||||
else {
|
||||
compsize = image_size;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD(__GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + compsize);
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
__GLX_BEGIN_VARIABLE(rop, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_LONG(8, level);
|
||||
__GLX_PUT_LONG(12, xoffset);
|
||||
__GLX_PUT_LONG(16, yoffset);
|
||||
__GLX_PUT_LONG(20, width);
|
||||
__GLX_PUT_LONG(24, height);
|
||||
__GLX_PUT_LONG(28, format);
|
||||
__GLX_PUT_LONG(32, image_size);
|
||||
if (compsize != 0) {
|
||||
__GLX_PUT_CHAR_ARRAY(__GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE,
|
||||
data, image_size);
|
||||
}
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
assert(compsize != 0);
|
||||
|
||||
__GLX_BEGIN_VARIABLE_LARGE(rop, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_LONG(12, level);
|
||||
__GLX_PUT_LONG(16, xoffset);
|
||||
__GLX_PUT_LONG(20, yoffset);
|
||||
__GLX_PUT_LONG(24, width);
|
||||
__GLX_PUT_LONG(28, height);
|
||||
__GLX_PUT_LONG(32, format);
|
||||
__GLX_PUT_LONG(36, image_size);
|
||||
__glXSendLargeCommand(gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXSUBIMAGE_CMD_HDR_SIZE + 4,
|
||||
data, image_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage1D(GLenum target, GLint level,
|
||||
GLenum internal_format, GLsizei width,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid * data)
|
||||
{
|
||||
CompressedTexImage1D2D(target, level, internal_format, width, 0,
|
||||
border, image_size, data,
|
||||
X_GLrop_CompressedTexImage1D);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage2D(GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint border, GLsizei image_size,
|
||||
const GLvoid * data)
|
||||
{
|
||||
CompressedTexImage1D2D(target, level, internal_format, width, height,
|
||||
border, image_size, data,
|
||||
X_GLrop_CompressedTexImage2D);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexImage3D(GLenum target, GLint level,
|
||||
GLenum internal_format,
|
||||
GLsizei width, GLsizei height,
|
||||
GLsizei depth, GLint border,
|
||||
GLsizei image_size, const GLvoid * data)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (gc->currentDpy == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD(__GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + image_size);
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_CompressedTexImage3D, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_LONG(8, level);
|
||||
__GLX_PUT_LONG(12, internal_format);
|
||||
__GLX_PUT_LONG(16, width);
|
||||
__GLX_PUT_LONG(20, height);
|
||||
__GLX_PUT_LONG(24, depth);
|
||||
__GLX_PUT_LONG(28, border);
|
||||
__GLX_PUT_LONG(32, image_size);
|
||||
if (image_size != 0) {
|
||||
__GLX_PUT_CHAR_ARRAY(__GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE,
|
||||
data, image_size);
|
||||
}
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_CompressedTexImage3D, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_LONG(12, level);
|
||||
__GLX_PUT_LONG(16, internal_format);
|
||||
__GLX_PUT_LONG(20, width);
|
||||
__GLX_PUT_LONG(24, height);
|
||||
__GLX_PUT_LONG(28, depth);
|
||||
__GLX_PUT_LONG(32, border);
|
||||
__GLX_PUT_LONG(36, image_size);
|
||||
__glXSendLargeCommand(gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXIMAGE_3D_CMD_HDR_SIZE + 4,
|
||||
data, image_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage1D(GLenum target, GLint level,
|
||||
GLint xoffset,
|
||||
GLsizei width,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid * data)
|
||||
{
|
||||
CompressedTexSubImage1D2D(target, level, xoffset, 0, width, 0,
|
||||
format, image_size, data,
|
||||
X_GLrop_CompressedTexSubImage1D);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage2D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid * data)
|
||||
{
|
||||
CompressedTexSubImage1D2D(target, level, xoffset, yoffset, width, height,
|
||||
format, image_size, data,
|
||||
X_GLrop_CompressedTexSubImage2D);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glCompressedTexSubImage3D(GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLint zoffset, GLsizei width,
|
||||
GLsizei height, GLsizei depth,
|
||||
GLenum format, GLsizei image_size,
|
||||
const GLvoid * data)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (gc->currentDpy == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cmdlen = __GLX_PAD(__GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE
|
||||
+ image_size);
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_CompressedTexSubImage3D, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_LONG(8, level);
|
||||
__GLX_PUT_LONG(12, xoffset);
|
||||
__GLX_PUT_LONG(16, yoffset);
|
||||
__GLX_PUT_LONG(20, zoffset);
|
||||
__GLX_PUT_LONG(24, width);
|
||||
__GLX_PUT_LONG(28, height);
|
||||
__GLX_PUT_LONG(32, depth);
|
||||
__GLX_PUT_LONG(36, format);
|
||||
__GLX_PUT_LONG(40, image_size);
|
||||
if (image_size != 0) {
|
||||
__GLX_PUT_CHAR_ARRAY(__GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE,
|
||||
data, image_size);
|
||||
}
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_CompressedTexSubImage3D, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_LONG(12, level);
|
||||
__GLX_PUT_LONG(16, xoffset);
|
||||
__GLX_PUT_LONG(20, yoffset);
|
||||
__GLX_PUT_LONG(24, zoffset);
|
||||
__GLX_PUT_LONG(28, width);
|
||||
__GLX_PUT_LONG(32, height);
|
||||
__GLX_PUT_LONG(36, depth);
|
||||
__GLX_PUT_LONG(40, format);
|
||||
__GLX_PUT_LONG(44, image_size);
|
||||
__glXSendLargeCommand(gc, gc->pc,
|
||||
__GLX_COMPRESSED_TEXSUBIMAGE_3D_CMD_HDR_SIZE + 4,
|
||||
data, image_size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2004
|
||||
* 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "indirect.h"
|
||||
|
||||
static void
|
||||
TransposeMatrixf(const GLfloat s[16], GLfloat d[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
d[i * 4 + j] = s[j * 4 + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
TransposeMatrixd(const GLdouble s[16], GLdouble d[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
d[i * 4 + j] = s[j * 4 + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glLoadTransposeMatrixd(const GLdouble * m)
|
||||
{
|
||||
GLdouble mt[16];
|
||||
|
||||
TransposeMatrixd(m, mt);
|
||||
__indirect_glLoadMatrixd(mt);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glLoadTransposeMatrixf(const GLfloat * m)
|
||||
{
|
||||
GLfloat mt[16];
|
||||
|
||||
TransposeMatrixf(m, mt);
|
||||
__indirect_glLoadMatrixf(mt);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glMultTransposeMatrixd(const GLdouble * m)
|
||||
{
|
||||
GLdouble mt[16];
|
||||
|
||||
TransposeMatrixd(m, mt);
|
||||
__indirect_glMultMatrixd(mt);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glMultTransposeMatrixf(const GLfloat * m)
|
||||
{
|
||||
GLfloat mt[16];
|
||||
|
||||
TransposeMatrixf(m, mt);
|
||||
__indirect_glMultMatrixf(mt);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2004, 2005
|
||||
* 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM,
|
||||
* AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#ifndef INDIRECT_VERTEX_ARRAY_H
|
||||
#define INDIRECT_VERTEX_ARRAY_H
|
||||
|
||||
extern const GLuint __glXTypeSize_table[16];
|
||||
|
||||
#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
|
||||
? 0 : __glXTypeSize_table[ (e) & 0x0f ])
|
||||
|
||||
extern void __glXArrayDisableAll(__GLXattribute * state);
|
||||
|
||||
extern GLboolean __glXSetArrayEnable(__GLXattribute * state,
|
||||
GLenum key, unsigned index,
|
||||
GLboolean enable);
|
||||
|
||||
extern GLboolean __glXGetArrayEnable(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
GLintptr * dest);
|
||||
extern GLboolean __glXGetArraySize(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
GLintptr * dest);
|
||||
extern GLboolean __glXGetArrayType(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
GLintptr * dest);
|
||||
extern GLboolean __glXGetArrayStride(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
GLintptr * dest);
|
||||
extern GLboolean __glXGetArrayPointer(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
void **dest);
|
||||
extern GLboolean __glXGetArrayNormalized(const __GLXattribute * const state,
|
||||
GLenum key, unsigned index,
|
||||
GLintptr * dest);
|
||||
|
||||
extern void __glXPushArrayState(__GLXattribute * state);
|
||||
extern void __glXPopArrayState(__GLXattribute * state);
|
||||
|
||||
extern GLuint __glXGetActiveTextureUnit(const __GLXattribute * const state);
|
||||
|
||||
#endif /* INDIRECT_VERTEX_ARRAY_H */
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2004, 2005
|
||||
* 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM,
|
||||
* AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#ifndef _INDIRECT_VA_PRIVATE_
|
||||
#define _INDIRECT_VA_PRIVATE_
|
||||
|
||||
/**
|
||||
* \file indirect_va_private.h
|
||||
*
|
||||
* \author Ian Romanick <[email protected]>
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include <GL/glxproto.h>
|
||||
|
||||
|
||||
/**
|
||||
* State descriptor for a single array of vertex data.
|
||||
*/
|
||||
struct array_state
|
||||
{
|
||||
/**
|
||||
* Pointer to the application supplied data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* Enum representing the type of the application supplied data.
|
||||
*/
|
||||
GLenum data_type;
|
||||
|
||||
/**
|
||||
* Stride value supplied by the application. This value is not used
|
||||
* internally. It is only kept so that it can be queried by the
|
||||
* application using glGet*v.
|
||||
*/
|
||||
GLsizei user_stride;
|
||||
|
||||
/**
|
||||
* Calculated size, in bytes, of a single element in the array. This
|
||||
* is calculated based on \c count and the size of the data type
|
||||
* represented by \c data_type.
|
||||
*/
|
||||
GLsizei element_size;
|
||||
|
||||
/**
|
||||
* Actual byte-stride from one element to the next. This value will
|
||||
* be equal to either \c user_stride or \c element_stride.
|
||||
*/
|
||||
GLsizei true_stride;
|
||||
|
||||
/**
|
||||
* Number of data values in each element.
|
||||
*/
|
||||
GLint count;
|
||||
|
||||
/**
|
||||
* "Normalized" data is on the range [0,1] (unsigned) or [-1,1] (signed).
|
||||
* This is used for mapping integral types to floating point types.
|
||||
*/
|
||||
GLboolean normalized;
|
||||
|
||||
/**
|
||||
* Pre-calculated GLX protocol command header.
|
||||
* This contains two 16-bit words: the command length and the command
|
||||
* opcode.
|
||||
*/
|
||||
uint16_t header[2];
|
||||
|
||||
/**
|
||||
* Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
|
||||
* to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean enabled;
|
||||
|
||||
/**
|
||||
* For multi-arrayed data (e.g., texture coordinates, generic vertex
|
||||
* program attributes, etc.), this specifies which array this is.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
/**
|
||||
* Per-array-type key. For most arrays, this will be the GL enum for
|
||||
* that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
|
||||
* for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
|
||||
* etc.).
|
||||
*/
|
||||
GLenum key;
|
||||
|
||||
/**
|
||||
* If this array can be used with the "classic" \c glDrawArrays protocol,
|
||||
* this is set to \c GL_TRUE. Otherwise, it is set to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean old_DrawArrays_possible;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Array state that is pushed / popped by \c glPushClientAttrib and
|
||||
* \c glPopClientAttrib.
|
||||
*/
|
||||
struct array_stack_state
|
||||
{
|
||||
/**
|
||||
* Pointer to the application supplied data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* Enum representing the type of the application supplied data.
|
||||
*/
|
||||
GLenum data_type;
|
||||
|
||||
/**
|
||||
* Stride value supplied by the application. This value is not used
|
||||
* internally. It is only kept so that it can be queried by the
|
||||
* application using glGet*v.
|
||||
*/
|
||||
GLsizei user_stride;
|
||||
|
||||
/**
|
||||
* Number of data values in each element.
|
||||
*/
|
||||
GLint count;
|
||||
|
||||
/**
|
||||
* Per-array-type key. For most arrays, this will be the GL enum for
|
||||
* that array (e.g., GL_VERTEX_ARRAY for vertex data, GL_NORMAL_ARRAY
|
||||
* for normal data, GL_TEXTURE_COORD_ARRAY for texture coordinate data,
|
||||
* etc.).
|
||||
*/
|
||||
GLenum key;
|
||||
|
||||
/**
|
||||
* For multi-arrayed data (e.g., texture coordinates, generic vertex
|
||||
* program attributes, etc.), this specifies which array this is.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
/**
|
||||
* Set to \c GL_TRUE if this array is enabled. Otherwise, it is set
|
||||
* to \c GL_FALSE.
|
||||
*/
|
||||
GLboolean enabled;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Collection of all the vertex array state.
|
||||
*/
|
||||
struct array_state_vector
|
||||
{
|
||||
/**
|
||||
* Number of arrays tracked by \c ::arrays.
|
||||
*/
|
||||
size_t num_arrays;
|
||||
|
||||
/**
|
||||
* Array of vertex array state. This array contains all of the valid
|
||||
* vertex arrays. If a vertex array isn't in this array, then it isn't
|
||||
* valid. For example, if an implementation does not support
|
||||
* EXT_fog_coord, there won't be a GL_FOG_COORD_ARRAY entry in this
|
||||
* array.
|
||||
*/
|
||||
struct array_state *arrays;
|
||||
|
||||
/**
|
||||
* Number of currently enabled client-side arrays. The value of this
|
||||
* field is only valid if \c array_info_cache_valid is true.
|
||||
*/
|
||||
size_t enabled_client_array_count;
|
||||
|
||||
/**
|
||||
* \name ARRAY_INFO cache.
|
||||
*
|
||||
* These fields track the state of the ARRAY_INFO cache. The
|
||||
* \c array_info_cache_size is the size of the actual data stored in
|
||||
* \c array_info_cache. \c array_info_cache_buffer_size is the size of
|
||||
* the buffer. This will always be greater than or equal to
|
||||
* \c array_info_cache_size.
|
||||
*
|
||||
* \note
|
||||
* There are some bytes of extra data before \c array_info_cache that is
|
||||
* used to hold the header for RenderLarge commands. This is
|
||||
* \b not included in \c array_info_cache_size or
|
||||
* \c array_info_cache_buffer_size. \c array_info_cache_base stores a
|
||||
* pointer to the true start of the buffer (i.e., what malloc returned).
|
||||
*/
|
||||
/*@{ */
|
||||
size_t array_info_cache_size;
|
||||
size_t array_info_cache_buffer_size;
|
||||
void *array_info_cache;
|
||||
void *array_info_cache_base;
|
||||
/*@} */
|
||||
|
||||
|
||||
/**
|
||||
* Is the cache of ARRAY_INFO data valid? The cache can become invalid
|
||||
* when one of several state changes occur. Among these changes are
|
||||
* modifying the array settings for an enabled array and enabling /
|
||||
* disabling an array.
|
||||
*/
|
||||
GLboolean array_info_cache_valid;
|
||||
|
||||
/**
|
||||
* Is it possible to use the GL 1.1 / EXT_vertex_arrays protocol? Use
|
||||
* of this protocol is disabled with really old servers (i.e., servers
|
||||
* that don't support GL 1.1 or EXT_vertex_arrays) or when an environment
|
||||
* variable is set.
|
||||
*
|
||||
* \todo
|
||||
* GL 1.1 and EXT_vertex_arrays use identical protocol, but have different
|
||||
* opcodes for \c glDrawArrays. For servers that advertise one or the
|
||||
* other, there should be a way to select which opcode to use.
|
||||
*/
|
||||
GLboolean old_DrawArrays_possible;
|
||||
|
||||
/**
|
||||
* Is it possible to use the new GL X.X / ARB_vertex_buffer_object
|
||||
* protocol?
|
||||
*
|
||||
* \todo
|
||||
* This protocol has not yet been defined by the ARB, but is currently a
|
||||
* work in progress. This field is a place-holder.
|
||||
*/
|
||||
GLboolean new_DrawArrays_possible;
|
||||
|
||||
/**
|
||||
* Active texture unit set by \c glClientActiveTexture.
|
||||
*
|
||||
* \sa __glXGetActiveTextureUnit
|
||||
*/
|
||||
unsigned active_texture_unit;
|
||||
|
||||
/**
|
||||
* Number of supported texture units. Even if ARB_multitexture /
|
||||
* GL 1.3 are not supported, this will be at least 1. When multitexture
|
||||
* is supported, this will be the value queried by calling
|
||||
* \c glGetIntegerv with \c GL_MAX_TEXTURE_UNITS.
|
||||
*
|
||||
* \todo
|
||||
* Investigate if this should be the value of \c GL_MAX_TEXTURE_COORDS
|
||||
* instead (if GL 2.0 / ARB_fragment_shader / ARB_fragment_program /
|
||||
* NV_fragment_program are supported).
|
||||
*/
|
||||
unsigned num_texture_units;
|
||||
|
||||
/**
|
||||
* Number of generic vertex program attribs. If GL_ARB_vertex_program
|
||||
* is not supported, this will be zero. Otherwise it will be the value
|
||||
* queries by calling \c glGetProgramiv with \c GL_VERTEX_PROGRAM_ARB
|
||||
* and \c GL_MAX_PROGRAM_ATTRIBS_ARB.
|
||||
*/
|
||||
unsigned num_vertex_program_attribs;
|
||||
|
||||
/**
|
||||
* \n Methods for implementing various GL functions.
|
||||
*
|
||||
* These method pointers are only valid \c array_info_cache_valid is set.
|
||||
* When each function starts, it much check \c array_info_cache_valid.
|
||||
* If it is not set, it must call \c fill_array_info_cache and call
|
||||
* the new method.
|
||||
*
|
||||
* \sa fill_array_info_cache
|
||||
*
|
||||
* \todo
|
||||
* Write code to plug these functions directly into the dispatch table.
|
||||
*/
|
||||
/*@{ */
|
||||
void (*DrawArrays) (GLenum, GLint, GLsizei);
|
||||
void (*DrawElements) (GLenum mode, GLsizei count, GLenum type,
|
||||
const GLvoid * indices);
|
||||
/*@} */
|
||||
|
||||
struct array_stack_state *stack;
|
||||
unsigned active_texture_unit_stack[__GL_CLIENT_ATTRIB_STACK_DEPTH];
|
||||
unsigned stack_index;
|
||||
};
|
||||
|
||||
#endif /* _INDIRECT_VA_PRIVATE_ */
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2005
|
||||
* 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM,
|
||||
* AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <GL/gl.h>
|
||||
#include "indirect.h"
|
||||
#include "glxclient.h"
|
||||
#include "indirect_vertex_array.h"
|
||||
#include <GL/glxproto.h>
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
# define __builtin_expect(x, y) x
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_vertex_attrib_enable(GLuint index, GLboolean val)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
|
||||
if (!__glXSetArrayEnable(state, GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB,
|
||||
index, val)) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glEnableVertexAttribArray(GLuint index)
|
||||
{
|
||||
do_vertex_attrib_enable(index, GL_TRUE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glDisableVertexAttribArray(GLuint index)
|
||||
{
|
||||
do_vertex_attrib_enable(index, GL_FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_parameter(unsigned opcode, unsigned size, GLenum target, GLuint index,
|
||||
void *params)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
Display *const dpy = gc->currentDpy;
|
||||
const GLuint cmdlen = 12;
|
||||
|
||||
if (__builtin_expect(dpy != NULL, 1)) {
|
||||
GLubyte const *pc = __glXSetupVendorRequest(gc,
|
||||
X_GLXVendorPrivateWithReply,
|
||||
opcode, cmdlen);
|
||||
|
||||
*((GLenum *) (pc + 0)) = target;
|
||||
*((GLuint *) (pc + 4)) = index;
|
||||
*((GLuint *) (pc + 8)) = 0;
|
||||
|
||||
(void) __glXReadReply(dpy, size, params, GL_FALSE);
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetProgramEnvParameterfvARB(GLenum target, GLuint index,
|
||||
GLfloat * params)
|
||||
{
|
||||
get_parameter(1296, 4, target, index, params);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetProgramEnvParameterdvARB(GLenum target, GLuint index,
|
||||
GLdouble * params)
|
||||
{
|
||||
get_parameter(1297, 8, target, index, params);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetProgramLocalParameterfvARB(GLenum target, GLuint index,
|
||||
GLfloat * params)
|
||||
{
|
||||
get_parameter(1305, 4, target, index, params);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetProgramLocalParameterdvARB(GLenum target, GLuint index,
|
||||
GLdouble * params)
|
||||
{
|
||||
get_parameter(1306, 8, target, index, params);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetVertexAttribPointerv(GLuint index, GLenum pname,
|
||||
GLvoid ** pointer)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
|
||||
if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
}
|
||||
|
||||
if (!__glXGetArrayPointer(state, GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB,
|
||||
index, pointer)) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the selected attribute from the vertex array state vector.
|
||||
*
|
||||
* \returns
|
||||
* On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
|
||||
*/
|
||||
static GLboolean
|
||||
get_attrib_array_data(__GLXattribute * state, GLuint index, GLenum cap,
|
||||
GLintptr * data)
|
||||
{
|
||||
GLboolean retval = GL_FALSE;
|
||||
const GLenum attrib = GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB;
|
||||
|
||||
switch (cap) {
|
||||
case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
|
||||
retval = __glXGetArrayEnable(state, attrib, index, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
|
||||
retval = __glXGetArraySize(state, attrib, index, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
|
||||
retval = __glXGetArrayStride(state, attrib, index, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
|
||||
retval = __glXGetArrayType(state, attrib, index, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
|
||||
retval = __glXGetArrayNormalized(state, attrib, index, data);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_vertex_attrib(struct glx_context * gc, unsigned vop,
|
||||
GLuint index, GLenum pname, xReply * reply)
|
||||
{
|
||||
Display *const dpy = gc->currentDpy;
|
||||
GLubyte *const pc = __glXSetupVendorRequest(gc,
|
||||
X_GLXVendorPrivateWithReply,
|
||||
vop, 8);
|
||||
|
||||
*((uint32_t *) (pc + 0)) = index;
|
||||
*((uint32_t *) (pc + 4)) = pname;
|
||||
|
||||
(void) _XReply(dpy, reply, 0, False);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetVertexAttribiv(GLuint index, GLenum pname, GLint * params)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
Display *const dpy = gc->currentDpy;
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
xGLXSingleReply reply;
|
||||
|
||||
|
||||
get_vertex_attrib(gc, 1303, index, pname, (xReply *) & reply);
|
||||
|
||||
if (reply.size != 0) {
|
||||
GLintptr data;
|
||||
|
||||
|
||||
if (get_attrib_array_data(state, index, pname, &data)) {
|
||||
*params = (GLint) data;
|
||||
}
|
||||
else {
|
||||
if (reply.size == 1) {
|
||||
*params = (GLint) reply.pad3;
|
||||
}
|
||||
else {
|
||||
_XRead(dpy, (void *) params, 4 * reply.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetVertexAttribfv(GLuint index, GLenum pname,
|
||||
GLfloat * params)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
Display *const dpy = gc->currentDpy;
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
xGLXSingleReply reply;
|
||||
|
||||
|
||||
get_vertex_attrib(gc, 1302, index, pname, (xReply *) & reply);
|
||||
|
||||
if (reply.size != 0) {
|
||||
GLintptr data;
|
||||
|
||||
|
||||
if (get_attrib_array_data(state, index, pname, &data)) {
|
||||
*params = (GLfloat) data;
|
||||
}
|
||||
else {
|
||||
if (reply.size == 1) {
|
||||
(void) memcpy(params, &reply.pad3, sizeof(GLfloat));
|
||||
}
|
||||
else {
|
||||
_XRead(dpy, (void *) params, 4 * reply.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetVertexAttribdv(GLuint index, GLenum pname,
|
||||
GLdouble * params)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
Display *const dpy = gc->currentDpy;
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
xGLXSingleReply reply;
|
||||
|
||||
|
||||
get_vertex_attrib(gc, 1301, index, pname, (xReply *) & reply);
|
||||
|
||||
if (reply.size != 0) {
|
||||
GLintptr data;
|
||||
|
||||
|
||||
if (get_attrib_array_data(state, index, pname, &data)) {
|
||||
*params = (GLdouble) data;
|
||||
}
|
||||
else {
|
||||
if (reply.size == 1) {
|
||||
(void) memcpy(params, &reply.pad3, sizeof(GLdouble));
|
||||
}
|
||||
else {
|
||||
_XRead(dpy, (void *) params, 8 * reply.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* (C) Copyright IBM Corporation 2004
|
||||
* 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT, IBM,
|
||||
* AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "indirect.h"
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2d(GLdouble x, GLdouble y)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2i(GLint x, GLint y)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2f(GLfloat x, GLfloat y)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2s(GLshort x, GLshort y)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2dv(const GLdouble * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2fv(const GLfloat * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2iv(const GLint * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos2sv(const GLshort * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3d(GLdouble x, GLdouble y, GLdouble z)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3i(GLint x, GLint y, GLint z)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3s(GLshort x, GLshort y, GLshort z)
|
||||
{
|
||||
__indirect_glWindowPos3f(x, y, z);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3dv(const GLdouble * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3iv(const GLint * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glWindowPos3sv(const GLshort * p)
|
||||
{
|
||||
__indirect_glWindowPos3f(p[0], p[1], p[2]);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,162 @@
|
||||
# Copyright © 2017-2019 Intel Corporation
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
inc_glx = include_directories('.')
|
||||
|
||||
subdir('apple')
|
||||
if with_dri_platform == 'windows'
|
||||
subdir('windows')
|
||||
endif
|
||||
|
||||
files_libglx = files(
|
||||
'clientattrib.c',
|
||||
'clientinfo.c',
|
||||
'compsize.c',
|
||||
'create_context.c',
|
||||
'dri_common.c',
|
||||
'dri_common.h',
|
||||
'dri_common_query_renderer.c',
|
||||
'drisw_glx.c',
|
||||
'drisw_priv.h',
|
||||
'eval.c',
|
||||
'glxclient.h',
|
||||
'glxcmds.c',
|
||||
'glxconfig.c',
|
||||
'glxconfig.h',
|
||||
'glxcurrent.c',
|
||||
'glx_error.c',
|
||||
'glx_error.h',
|
||||
'glxext.c',
|
||||
'glxextensions.c',
|
||||
'glxextensions.h',
|
||||
'glxhash.c',
|
||||
'glxhash.h',
|
||||
'glx_pbuffer.c',
|
||||
'glx_query.c',
|
||||
'indirect_glx.c',
|
||||
'indirect_init.h',
|
||||
'indirect_texture_compression.c',
|
||||
'indirect_transpose_matrix.c',
|
||||
'indirect_vertex_array.c',
|
||||
'indirect_vertex_array.h',
|
||||
'indirect_vertex_array_priv.h',
|
||||
'indirect_vertex_program.c',
|
||||
'indirect_window_pos.c',
|
||||
'packrender.h',
|
||||
'packsingle.h',
|
||||
'pixel.c',
|
||||
'pixelstore.c',
|
||||
'query_renderer.c',
|
||||
'render2.c',
|
||||
'renderpix.c',
|
||||
'single2.c',
|
||||
'vertarr.c',
|
||||
'xfont.c',
|
||||
)
|
||||
|
||||
extra_libs_libglx = []
|
||||
extra_deps_libgl = []
|
||||
extra_ld_args_libgl = []
|
||||
|
||||
if with_dri_platform == 'drm' or with_dri_platform == 'pseudo-drm'
|
||||
files_libglx += files('dri3_glx.c', 'dri3_priv.h')
|
||||
endif
|
||||
|
||||
if with_dri_platform == 'apple'
|
||||
files_libglx += files('applegl_glx.c')
|
||||
extra_libs_libglx += libappleglx
|
||||
elif with_dri_platform == 'windows'
|
||||
files_libglx += files('driwindows_glx.c')
|
||||
extra_libs_libglx += [
|
||||
libwindowsdri,
|
||||
libwindowsglx,
|
||||
]
|
||||
extra_deps_libgl = [
|
||||
meson.get_compiler('c').find_library('gdi32'),
|
||||
meson.get_compiler('c').find_library('opengl32')
|
||||
]
|
||||
extra_ld_args_libgl = '-Wl,--disable-stdcall-fixup'
|
||||
endif
|
||||
|
||||
if not with_glvnd
|
||||
gl_lib_name = 'GL'
|
||||
gl_lib_version = '1.2.0'
|
||||
else
|
||||
gl_lib_name = 'GLX_@0@'.format(glvnd_vendor_name)
|
||||
gl_lib_version = '0.0.0'
|
||||
files_libglx += files(
|
||||
'g_glxglvnddispatchfuncs.c',
|
||||
'g_glxglvnddispatchindices.h',
|
||||
'glxglvnd.c',
|
||||
'glxglvnd.h',
|
||||
'glxglvnddispatchfuncs.h',
|
||||
)
|
||||
endif
|
||||
|
||||
glx_gallium_link = []
|
||||
if with_dri
|
||||
glx_gallium_link += libgallium_dri
|
||||
endif
|
||||
if with_platform_windows
|
||||
glx_gallium_link += libgallium_wgl
|
||||
endif
|
||||
libglx = static_library(
|
||||
'glx',
|
||||
[files_libglx, glx_generated, main_dispatch_h],
|
||||
include_directories : [inc_include, inc_src, inc_glapi, inc_loader, inc_loader_x11,
|
||||
inc_gallium, inc_mesa, inc_st_dri, inc_gallium_aux],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
link_with : [
|
||||
libloader, libloader_x11,
|
||||
extra_libs_libglx, glx_gallium_link
|
||||
],
|
||||
dependencies : [
|
||||
idep_mesautil, idep_xmlconfig,
|
||||
dep_libdrm, dep_glproto, dep_x11, dep_xext, dep_glvnd, dep_xxf86vm, dep_xshmfence,
|
||||
],
|
||||
)
|
||||
|
||||
# libglapi_bridge contains GL functions that we need to export from libGL.so.
|
||||
# Other than that, we don't need it.
|
||||
libgl_link = with_glvnd ? [] : [libglapi_bridge]
|
||||
|
||||
libgl = shared_library(
|
||||
gl_lib_name,
|
||||
[],
|
||||
link_whole : [libglx, libgl_link],
|
||||
link_args : [ld_args_bsymbolic, ld_args_gc_sections, extra_ld_args_libgl],
|
||||
dependencies : [
|
||||
dep_libdrm, dep_dl, dep_m, dep_thread, dep_x11, dep_xcb_glx, dep_xcb,
|
||||
dep_x11_xcb, dep_xext, dep_xxf86vm, dep_xcb_shm, extra_deps_libgl,
|
||||
],
|
||||
version : gl_lib_version,
|
||||
darwin_versions : '4.0.0',
|
||||
install : true,
|
||||
)
|
||||
|
||||
if not with_glvnd
|
||||
pkg.generate(
|
||||
name : 'glx',
|
||||
description : 'Mesa GLX Library',
|
||||
version : meson.project_version(),
|
||||
libraries : libgl,
|
||||
libraries_private : gl_priv_libs,
|
||||
requires_private : gl_priv_reqs,
|
||||
variables : ['glx_tls=yes'],
|
||||
)
|
||||
endif
|
||||
|
||||
if with_symbols_check
|
||||
libgl_symbols_file = with_glvnd ? 'glvnd-symbols.txt' : 'libgl-symbols.txt'
|
||||
|
||||
test(
|
||||
'libGL-ABI-check',
|
||||
symbols_check,
|
||||
args : [
|
||||
'--lib', libgl,
|
||||
'--symbols-file', files(libgl_symbols_file),
|
||||
symbols_check_args,
|
||||
],
|
||||
suite : ['glx'],
|
||||
)
|
||||
endif
|
||||
@@ -0,0 +1,180 @@
|
||||
#ifndef __GLX_packrender_h__
|
||||
#define __GLX_packrender_h__
|
||||
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
|
||||
/*
|
||||
** The macros in this header convert the client machine's native data types to
|
||||
** wire protocol data types. The header is part of the porting layer of the
|
||||
** client library, and it is intended that hardware vendors will rewrite this
|
||||
** header to suit their own machines.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Pad a count of bytes to the nearest multiple of 4. The X protocol
|
||||
** transfers data in 4 byte quantities, so this macro is used to
|
||||
** insure the right amount of data being sent.
|
||||
*/
|
||||
#define __GLX_PAD(a) (((a)+3) & ~3)
|
||||
|
||||
/*
|
||||
** Network size parameters
|
||||
*/
|
||||
#define sz_double 8
|
||||
|
||||
/* Setup for all commands */
|
||||
#define __GLX_DECLARE_VARIABLES() \
|
||||
struct glx_context *gc; \
|
||||
GLubyte *pc, *pixelHeaderPC; \
|
||||
GLuint compsize, cmdlen
|
||||
|
||||
#define __GLX_LOAD_VARIABLES() \
|
||||
gc = __glXGetCurrentContext(); \
|
||||
pc = gc->pc; \
|
||||
/* Muffle compilers */ \
|
||||
cmdlen = 0; (void)cmdlen; \
|
||||
compsize = 0; (void)compsize; \
|
||||
pixelHeaderPC = NULL; (void)pixelHeaderPC
|
||||
|
||||
/*
|
||||
** Variable sized command support macro. This macro is used by calls
|
||||
** that are potentially larger than __GLX_SMALL_RENDER_CMD_SIZE.
|
||||
** Because of their size, they may not automatically fit in the buffer.
|
||||
** If the buffer can't hold the command then it is flushed so that
|
||||
** the command will fit in the next buffer.
|
||||
*/
|
||||
#define __GLX_BEGIN_VARIABLE(opcode,size) \
|
||||
if (pc + (size) > gc->bufEnd) { \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
} \
|
||||
__GLX_PUT_SHORT(0,size); \
|
||||
__GLX_PUT_SHORT(2,opcode)
|
||||
|
||||
#define __GLX_BEGIN_VARIABLE_LARGE(opcode,size) \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
__GLX_PUT_LONG(0,size); \
|
||||
__GLX_PUT_LONG(4,opcode)
|
||||
|
||||
#define __GLX_BEGIN_VARIABLE_WITH_PIXEL(opcode,size) \
|
||||
if (pc + (size) > gc->bufEnd) { \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
} \
|
||||
__GLX_PUT_SHORT(0,size); \
|
||||
__GLX_PUT_SHORT(2,opcode); \
|
||||
pc += __GLX_RENDER_HDR_SIZE; \
|
||||
pixelHeaderPC = pc; \
|
||||
pc += __GLX_PIXEL_HDR_SIZE
|
||||
|
||||
#define __GLX_BEGIN_VARIABLE_LARGE_WITH_PIXEL(opcode,size) \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
__GLX_PUT_LONG(0,size); \
|
||||
__GLX_PUT_LONG(4,opcode); \
|
||||
pc += __GLX_RENDER_LARGE_HDR_SIZE; \
|
||||
pixelHeaderPC = pc; \
|
||||
pc += __GLX_PIXEL_HDR_SIZE
|
||||
|
||||
#define __GLX_BEGIN_VARIABLE_WITH_PIXEL_3D(opcode,size) \
|
||||
if (pc + (size) > gc->bufEnd) { \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
} \
|
||||
__GLX_PUT_SHORT(0,size); \
|
||||
__GLX_PUT_SHORT(2,opcode); \
|
||||
pc += __GLX_RENDER_HDR_SIZE; \
|
||||
pixelHeaderPC = pc; \
|
||||
pc += __GLX_PIXEL_3D_HDR_SIZE
|
||||
|
||||
#define __GLX_BEGIN_VARIABLE_LARGE_WITH_PIXEL_3D(opcode,size) \
|
||||
pc = __glXFlushRenderBuffer(gc, pc); \
|
||||
__GLX_PUT_LONG(0,size); \
|
||||
__GLX_PUT_LONG(4,opcode); \
|
||||
pc += __GLX_RENDER_LARGE_HDR_SIZE; \
|
||||
pixelHeaderPC = pc; \
|
||||
pc += __GLX_PIXEL_3D_HDR_SIZE
|
||||
|
||||
/*
|
||||
** Fixed size command support macro. This macro is used by calls that
|
||||
** are never larger than __GLX_SMALL_RENDER_CMD_SIZE. Because they
|
||||
** always fit in the buffer, and because the buffer promises to
|
||||
** maintain enough room for them, we don't need to check for space
|
||||
** before doing the storage work.
|
||||
*/
|
||||
#define __GLX_BEGIN(opcode,size) \
|
||||
__GLX_PUT_SHORT(0,size); \
|
||||
__GLX_PUT_SHORT(2,opcode)
|
||||
|
||||
/*
|
||||
** Finish a rendering command by advancing the pc. If the pc is now past
|
||||
** the limit pointer then there is no longer room for a
|
||||
** __GLX_SMALL_RENDER_CMD_SIZE sized command, which will break the
|
||||
** assumptions present in the __GLX_BEGIN macro. In this case the
|
||||
** rendering buffer is flushed out into the X protocol stream (which may
|
||||
** or may not do I/O).
|
||||
*/
|
||||
#define __GLX_END(size) \
|
||||
pc += size; \
|
||||
if (pc > gc->limit) { \
|
||||
(void) __glXFlushRenderBuffer(gc, pc); \
|
||||
} else { \
|
||||
gc->pc = pc; \
|
||||
}
|
||||
|
||||
/* Array copy macros */
|
||||
#define __GLX_MEM_COPY(dest,src,bytes) \
|
||||
if (src && dest) \
|
||||
memcpy(dest, src, bytes)
|
||||
|
||||
/* Single item copy macros */
|
||||
#define __GLX_PUT_CHAR(offset,a) \
|
||||
do { \
|
||||
int8_t __tmp = (a); \
|
||||
memcpy((pc + (offset)), &__tmp, 1); \
|
||||
} while (0)
|
||||
|
||||
#define __GLX_PUT_SHORT(offset,a) \
|
||||
do { \
|
||||
int16_t __tmp = (a); \
|
||||
memcpy((pc + (offset)), &__tmp, 2); \
|
||||
} while (0)
|
||||
|
||||
#define __GLX_PUT_LONG(offset,a) \
|
||||
do { \
|
||||
int32_t __tmp = (a); \
|
||||
memcpy((pc + (offset)), &__tmp, 4); \
|
||||
} while (0)
|
||||
|
||||
#define __GLX_PUT_FLOAT(offset,a) \
|
||||
do { \
|
||||
float __tmp = (a); \
|
||||
memcpy((pc + (offset)), &__tmp, 4); \
|
||||
} while (0)
|
||||
|
||||
#define __GLX_PUT_DOUBLE(offset,a) \
|
||||
do { \
|
||||
double __tmp = (a); \
|
||||
memcpy((pc + (offset)), &__tmp, 8); \
|
||||
} while (0)
|
||||
|
||||
#define __GLX_PUT_CHAR_ARRAY(offset,a,alen) \
|
||||
__GLX_MEM_COPY(pc + offset, a, alen * __GLX_SIZE_INT8)
|
||||
|
||||
#define __GLX_PUT_SHORT_ARRAY(offset,a,alen) \
|
||||
__GLX_MEM_COPY(pc + offset, a, alen * __GLX_SIZE_INT16)
|
||||
|
||||
#define __GLX_PUT_LONG_ARRAY(offset,a,alen) \
|
||||
__GLX_MEM_COPY(pc + offset, a, alen * __GLX_SIZE_INT32)
|
||||
|
||||
#define __GLX_PUT_FLOAT_ARRAY(offset,a,alen) \
|
||||
__GLX_MEM_COPY(pc + offset, a, alen * __GLX_SIZE_FLOAT32)
|
||||
|
||||
#define __GLX_PUT_DOUBLE_ARRAY(offset,a,alen) \
|
||||
__GLX_MEM_COPY(pc + offset, a, alen * __GLX_SIZE_FLOAT64)
|
||||
|
||||
|
||||
#endif /* !__GLX_packrender_h__ */
|
||||
@@ -0,0 +1,129 @@
|
||||
#ifndef __GLX_packsingle_h__
|
||||
#define __GLX_packsingle_h__
|
||||
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
|
||||
/*
|
||||
** The macros in this header convert wire protocol data types to the client
|
||||
** machine's native data types. The header is part of the porting layer of
|
||||
** the client library, and it is intended that hardware vendors will rewrite
|
||||
** this header to suit their own machines.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Dummy define to make the GetReqExtra macro happy. The value is not
|
||||
** used, but instead the code in __GLX_SINGLE_BEGIN issues its own store
|
||||
** to req->reqType with the proper code (our extension code).
|
||||
*/
|
||||
#define X_GLXSingle 0
|
||||
|
||||
/* Declare common variables used during a single command */
|
||||
#define __GLX_SINGLE_DECLARE_VARIABLES() \
|
||||
struct glx_context *gc = __glXGetCurrentContext(); \
|
||||
GLubyte *pc, *pixelHeaderPC; \
|
||||
GLuint compsize, cmdlen; \
|
||||
Display *dpy = gc->currentDpy; \
|
||||
xGLXSingleReq *req
|
||||
|
||||
#define __GLX_SINGLE_LOAD_VARIABLES() \
|
||||
pc = gc->pc; \
|
||||
/* Muffle compilers */ \
|
||||
pixelHeaderPC = NULL; (void)pixelHeaderPC; \
|
||||
compsize = 0; (void)compsize; \
|
||||
cmdlen = 0; (void)cmdlen
|
||||
|
||||
/* Start a single command */
|
||||
#define __GLX_SINGLE_BEGIN(opcode,bytes) \
|
||||
if (dpy) { \
|
||||
(void) __glXFlushRenderBuffer(gc, pc); \
|
||||
LockDisplay(dpy); \
|
||||
GetReqExtra(GLXSingle,bytes,req); \
|
||||
req->reqType = gc->majorOpcode; \
|
||||
req->glxCode = opcode; \
|
||||
req->contextTag = gc->currentContextTag; \
|
||||
pc = ((GLubyte *)(req) + sz_xGLXSingleReq)
|
||||
|
||||
/* End a single command */
|
||||
#define __GLX_SINGLE_END() \
|
||||
UnlockDisplay(dpy); \
|
||||
SyncHandle(); \
|
||||
}
|
||||
|
||||
/* Store data to sending for a single command */
|
||||
#define __GLX_SINGLE_PUT_CHAR(offset,a) \
|
||||
*((INT8 *) (pc + offset)) = a
|
||||
|
||||
#define __GLX_SINGLE_PUT_SHORT(offset,a) \
|
||||
*((INT16 *) (pc + offset)) = a
|
||||
|
||||
#define __GLX_SINGLE_PUT_LONG(offset,a) \
|
||||
*((INT32 *) (pc + offset)) = a
|
||||
|
||||
#define __GLX_SINGLE_PUT_FLOAT(offset,a) \
|
||||
*((FLOAT32 *) (pc + offset)) = a
|
||||
|
||||
/* Read support macros */
|
||||
#define __GLX_SINGLE_READ_XREPLY() \
|
||||
(void) _XReply(dpy, (xReply*) &reply, 0, False)
|
||||
|
||||
#define __GLX_SINGLE_GET_RETVAL(a,cast) \
|
||||
a = (cast) reply.retval
|
||||
|
||||
#define __GLX_SINGLE_GET_SIZE(a) \
|
||||
a = (GLint) reply.size
|
||||
|
||||
#define __GLX_SINGLE_GET_CHAR(p) \
|
||||
memcpy((p), &reply.pad3, 1);
|
||||
|
||||
#define __GLX_SINGLE_GET_SHORT(p) \
|
||||
memcpy((p), &reply.pad3, 2);
|
||||
|
||||
#define __GLX_SINGLE_GET_LONG(p) \
|
||||
memcpy((p), &reply.pad3, 4);
|
||||
|
||||
#define __GLX_SINGLE_GET_FLOAT(p) \
|
||||
memcpy((p), &reply.pad3, 4);
|
||||
|
||||
#define __GLX_SINGLE_GET_DOUBLE(p) \
|
||||
memcpy((p), &reply.pad3, 8);
|
||||
|
||||
/* Get an array of typed data */
|
||||
#define __GLX_SINGLE_GET_VOID_ARRAY(a,alen) \
|
||||
{ \
|
||||
GLint slop = alen*__GLX_SIZE_INT8 & 3; \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_INT8); \
|
||||
if (slop) _XEatData(dpy,4-slop); \
|
||||
}
|
||||
|
||||
#define __GLX_SINGLE_GET_CHAR_ARRAY(a,alen) \
|
||||
{ \
|
||||
GLint slop = alen*__GLX_SIZE_INT8 & 3; \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_INT8); \
|
||||
if (slop) _XEatData(dpy,4-slop); \
|
||||
}
|
||||
|
||||
|
||||
#define __GLX_SINGLE_GET_SHORT_ARRAY(a,alen) \
|
||||
{ \
|
||||
GLint slop = (alen*__GLX_SIZE_INT16) & 3; \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_INT16); \
|
||||
if (slop) _XEatData(dpy,4-slop); \
|
||||
}
|
||||
|
||||
#define __GLX_SINGLE_GET_LONG_ARRAY(a,alen) \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_INT32);
|
||||
|
||||
#define __GLX_SINGLE_GET_FLOAT_ARRAY(a,alen) \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_FLOAT32);
|
||||
|
||||
#define __GLX_SINGLE_GET_DOUBLE_ARRAY(a,alen) \
|
||||
_XRead(dpy,(char *)a,alen*__GLX_SIZE_FLOAT64);
|
||||
|
||||
#endif /* !__GLX_packsingle_h__ */
|
||||
+438
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
|
||||
static const GLubyte MsbToLsbTable[256] = {
|
||||
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
|
||||
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
|
||||
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
|
||||
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
|
||||
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
|
||||
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
|
||||
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
|
||||
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
|
||||
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
|
||||
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
|
||||
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
|
||||
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
|
||||
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
|
||||
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
|
||||
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
|
||||
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
|
||||
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
|
||||
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
|
||||
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
|
||||
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
|
||||
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
|
||||
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
|
||||
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
|
||||
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
|
||||
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
|
||||
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
|
||||
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
|
||||
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
|
||||
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
|
||||
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
|
||||
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
|
||||
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
|
||||
};
|
||||
|
||||
static const GLubyte LowBitsMask[9] = {
|
||||
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
|
||||
};
|
||||
|
||||
static const GLubyte HighBitsMask[9] = {
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Copy bitmap data from clients packed memory applying unpacking modes as the
|
||||
** data is transferred into the destImage buffer. Return in modes the
|
||||
** set of pixel modes that are to be done by the server.
|
||||
*/
|
||||
static void
|
||||
FillBitmap(struct glx_context * gc, GLint width, GLint height,
|
||||
GLenum format, const GLvoid * userdata, GLubyte * destImage)
|
||||
{
|
||||
const __GLXattribute *state = gc->client_state_private;
|
||||
GLint rowLength = state->storeUnpack.rowLength;
|
||||
GLint alignment = state->storeUnpack.alignment;
|
||||
GLint skipPixels = state->storeUnpack.skipPixels;
|
||||
GLint skipRows = state->storeUnpack.skipRows;
|
||||
GLint lsbFirst = state->storeUnpack.lsbFirst;
|
||||
GLint elementsLeft, bitOffset, currentByte, nextByte, highBitMask;
|
||||
GLint lowBitMask, i;
|
||||
GLint components, groupsPerRow, rowSize, padding, elementsPerRow;
|
||||
const GLubyte *start, *iter;
|
||||
|
||||
if (rowLength > 0) {
|
||||
groupsPerRow = rowLength;
|
||||
}
|
||||
else {
|
||||
groupsPerRow = width;
|
||||
}
|
||||
components = __glElementsPerGroup(format, GL_BITMAP);
|
||||
rowSize = (groupsPerRow * components + 7) >> 3;
|
||||
padding = (rowSize % alignment);
|
||||
if (padding) {
|
||||
rowSize += alignment - padding;
|
||||
}
|
||||
start = ((const GLubyte *) userdata) + skipRows * rowSize +
|
||||
((skipPixels * components) >> 3);
|
||||
bitOffset = (skipPixels * components) & 7;
|
||||
highBitMask = LowBitsMask[8 - bitOffset];
|
||||
lowBitMask = HighBitsMask[bitOffset];
|
||||
elementsPerRow = width * components;
|
||||
for (i = 0; i < height; i++) {
|
||||
elementsLeft = elementsPerRow;
|
||||
iter = start;
|
||||
while (elementsLeft) {
|
||||
/* First retrieve low bits from current byte */
|
||||
if (lsbFirst) {
|
||||
currentByte = MsbToLsbTable[iter[0]];
|
||||
}
|
||||
else {
|
||||
currentByte = iter[0];
|
||||
}
|
||||
if (bitOffset) {
|
||||
/* Need to read next byte to finish current byte */
|
||||
if (elementsLeft > (8 - bitOffset)) {
|
||||
if (lsbFirst) {
|
||||
nextByte = MsbToLsbTable[iter[1]];
|
||||
}
|
||||
else {
|
||||
nextByte = iter[1];
|
||||
}
|
||||
currentByte =
|
||||
((currentByte & highBitMask) << bitOffset) |
|
||||
((nextByte & lowBitMask) >> (8 - bitOffset));
|
||||
}
|
||||
else {
|
||||
currentByte = ((currentByte & highBitMask) << bitOffset);
|
||||
}
|
||||
}
|
||||
if (elementsLeft >= 8) {
|
||||
*destImage = currentByte;
|
||||
elementsLeft -= 8;
|
||||
}
|
||||
else {
|
||||
*destImage = currentByte & HighBitsMask[elementsLeft];
|
||||
elementsLeft = 0;
|
||||
}
|
||||
destImage++;
|
||||
iter++;
|
||||
}
|
||||
start += rowSize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract array from user's data applying all pixel store modes.
|
||||
** The internal packed array format used has LSB_FIRST = FALSE and
|
||||
** ALIGNMENT = 1.
|
||||
*/
|
||||
void
|
||||
__glFillImage(struct glx_context * gc, GLint dim, GLint width, GLint height,
|
||||
GLint depth, GLenum format, GLenum type,
|
||||
const GLvoid * userdata, GLubyte * newimage, GLubyte * modes)
|
||||
{
|
||||
const __GLXattribute *state = gc->client_state_private;
|
||||
GLint rowLength = state->storeUnpack.rowLength;
|
||||
GLint imageHeight = state->storeUnpack.imageHeight;
|
||||
GLint alignment = state->storeUnpack.alignment;
|
||||
GLint skipPixels = state->storeUnpack.skipPixels;
|
||||
GLint skipRows = state->storeUnpack.skipRows;
|
||||
GLint skipImages = state->storeUnpack.skipImages;
|
||||
GLint swapBytes = state->storeUnpack.swapEndian;
|
||||
GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize;
|
||||
GLint elementsPerRow, imageSize, rowsPerImage, h, i, j, k;
|
||||
const GLubyte *start, *iter, *itera, *iterb, *iterc;
|
||||
GLubyte *iter2;
|
||||
|
||||
if (type == GL_BITMAP) {
|
||||
FillBitmap(gc, width, height, format, userdata, newimage);
|
||||
}
|
||||
else {
|
||||
components = __glElementsPerGroup(format, type);
|
||||
if (rowLength > 0) {
|
||||
groupsPerRow = rowLength;
|
||||
}
|
||||
else {
|
||||
groupsPerRow = width;
|
||||
}
|
||||
if (imageHeight > 0) {
|
||||
rowsPerImage = imageHeight;
|
||||
}
|
||||
else {
|
||||
rowsPerImage = height;
|
||||
}
|
||||
|
||||
elementSize = __glBytesPerElement(type);
|
||||
groupSize = elementSize * components;
|
||||
if (elementSize == 1)
|
||||
swapBytes = 0;
|
||||
|
||||
rowSize = groupsPerRow * groupSize;
|
||||
padding = (rowSize % alignment);
|
||||
if (padding) {
|
||||
rowSize += alignment - padding;
|
||||
}
|
||||
imageSize = rowSize * rowsPerImage;
|
||||
start = ((const GLubyte *) userdata) + skipImages * imageSize +
|
||||
skipRows * rowSize + skipPixels * groupSize;
|
||||
iter2 = newimage;
|
||||
elementsPerRow = width * components;
|
||||
|
||||
if (swapBytes) {
|
||||
itera = start;
|
||||
for (h = 0; h < depth; h++) {
|
||||
iterb = itera;
|
||||
for (i = 0; i < height; i++) {
|
||||
iterc = iterb;
|
||||
for (j = 0; j < elementsPerRow; j++) {
|
||||
for (k = 1; k <= elementSize; k++) {
|
||||
iter2[k - 1] = iterc[elementSize - k];
|
||||
}
|
||||
iter2 += elementSize;
|
||||
iterc += elementSize;
|
||||
}
|
||||
iterb += rowSize;
|
||||
}
|
||||
itera += imageSize;
|
||||
}
|
||||
}
|
||||
else {
|
||||
itera = start;
|
||||
for (h = 0; h < depth; h++) {
|
||||
if (rowSize == elementsPerRow * elementSize) {
|
||||
/* Ha! This is mondo easy! */
|
||||
__GLX_MEM_COPY(iter2, itera,
|
||||
elementsPerRow * elementSize * height);
|
||||
iter2 += elementsPerRow * elementSize * height;
|
||||
}
|
||||
else {
|
||||
iter = itera;
|
||||
for (i = 0; i < height; i++) {
|
||||
__GLX_MEM_COPY(iter2, iter, elementsPerRow * elementSize);
|
||||
iter2 += elementsPerRow * elementSize;
|
||||
iter += rowSize;
|
||||
}
|
||||
}
|
||||
itera += imageSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup store modes that describe what we just did */
|
||||
if (modes) {
|
||||
if (dim < 3) {
|
||||
(void) memcpy(modes, __glXDefaultPixelStore + 4, 20);
|
||||
}
|
||||
else {
|
||||
(void) memcpy(modes, __glXDefaultPixelStore + 0, 36);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Empty a bitmap in LSB_FIRST=GL_FALSE and ALIGNMENT=4 format packing it
|
||||
** into the clients memory using the pixel store PACK modes.
|
||||
*/
|
||||
static void
|
||||
EmptyBitmap(struct glx_context * gc, GLint width, GLint height,
|
||||
GLenum format, const GLubyte * sourceImage, GLvoid * userdata)
|
||||
{
|
||||
const __GLXattribute *state = gc->client_state_private;
|
||||
GLint rowLength = state->storePack.rowLength;
|
||||
GLint alignment = state->storePack.alignment;
|
||||
GLint skipPixels = state->storePack.skipPixels;
|
||||
GLint skipRows = state->storePack.skipRows;
|
||||
GLint lsbFirst = state->storePack.lsbFirst;
|
||||
GLint components, groupsPerRow, rowSize, padding, elementsPerRow;
|
||||
GLint sourceRowSize, sourcePadding, sourceSkip;
|
||||
GLubyte *start, *iter;
|
||||
GLint elementsLeft, bitOffset, currentByte, highBitMask, lowBitMask;
|
||||
GLint writeMask, i;
|
||||
GLubyte writeByte;
|
||||
|
||||
components = __glElementsPerGroup(format, GL_BITMAP);
|
||||
if (rowLength > 0) {
|
||||
groupsPerRow = rowLength;
|
||||
}
|
||||
else {
|
||||
groupsPerRow = width;
|
||||
}
|
||||
|
||||
rowSize = (groupsPerRow * components + 7) >> 3;
|
||||
padding = (rowSize % alignment);
|
||||
if (padding) {
|
||||
rowSize += alignment - padding;
|
||||
}
|
||||
sourceRowSize = (width * components + 7) >> 3;
|
||||
sourcePadding = (sourceRowSize % 4);
|
||||
if (sourcePadding) {
|
||||
sourceSkip = 4 - sourcePadding;
|
||||
}
|
||||
else {
|
||||
sourceSkip = 0;
|
||||
}
|
||||
start = ((GLubyte *) userdata) + skipRows * rowSize +
|
||||
((skipPixels * components) >> 3);
|
||||
bitOffset = (skipPixels * components) & 7;
|
||||
highBitMask = LowBitsMask[8 - bitOffset];
|
||||
lowBitMask = HighBitsMask[bitOffset];
|
||||
elementsPerRow = width * components;
|
||||
for (i = 0; i < height; i++) {
|
||||
elementsLeft = elementsPerRow;
|
||||
iter = start;
|
||||
writeMask = highBitMask;
|
||||
writeByte = 0;
|
||||
while (elementsLeft) {
|
||||
/* Set up writeMask (to write to current byte) */
|
||||
if (elementsLeft + bitOffset < 8) {
|
||||
/* Need to trim writeMask */
|
||||
writeMask &= HighBitsMask[bitOffset + elementsLeft];
|
||||
}
|
||||
|
||||
if (lsbFirst) {
|
||||
currentByte = MsbToLsbTable[iter[0]];
|
||||
}
|
||||
else {
|
||||
currentByte = iter[0];
|
||||
}
|
||||
|
||||
if (bitOffset) {
|
||||
writeByte |= (sourceImage[0] >> bitOffset);
|
||||
currentByte = (currentByte & ~writeMask) |
|
||||
(writeByte & writeMask);
|
||||
writeByte = (sourceImage[0] << (8 - bitOffset));
|
||||
}
|
||||
else {
|
||||
currentByte = (currentByte & ~writeMask) |
|
||||
(sourceImage[0] & writeMask);
|
||||
}
|
||||
|
||||
if (lsbFirst) {
|
||||
iter[0] = MsbToLsbTable[currentByte];
|
||||
}
|
||||
else {
|
||||
iter[0] = currentByte;
|
||||
}
|
||||
|
||||
if (elementsLeft >= 8) {
|
||||
elementsLeft -= 8;
|
||||
}
|
||||
else {
|
||||
elementsLeft = 0;
|
||||
}
|
||||
sourceImage++;
|
||||
iter++;
|
||||
writeMask = 0xff;
|
||||
}
|
||||
if (writeByte) {
|
||||
/* Some data left over that still needs writing */
|
||||
writeMask &= lowBitMask;
|
||||
if (lsbFirst) {
|
||||
currentByte = MsbToLsbTable[iter[0]];
|
||||
}
|
||||
else {
|
||||
currentByte = iter[0];
|
||||
}
|
||||
currentByte = (currentByte & ~writeMask) | (writeByte & writeMask);
|
||||
if (lsbFirst) {
|
||||
iter[0] = MsbToLsbTable[currentByte];
|
||||
}
|
||||
else {
|
||||
iter[0] = currentByte;
|
||||
}
|
||||
}
|
||||
start += rowSize;
|
||||
sourceImage += sourceSkip;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Insert array into user's data applying all pixel store modes.
|
||||
** The packed array format from the server is LSB_FIRST = FALSE,
|
||||
** SWAP_BYTES = the current pixel storage pack mode, and ALIGNMENT = 4.
|
||||
** Named __glEmptyImage() because it is the opposite of __glFillImage().
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
void
|
||||
__glEmptyImage(struct glx_context * gc, GLint dim, GLint width, GLint height,
|
||||
GLint depth, GLenum format, GLenum type,
|
||||
const GLubyte * sourceImage, GLvoid * userdata)
|
||||
{
|
||||
const __GLXattribute *state = gc->client_state_private;
|
||||
GLint rowLength = state->storePack.rowLength;
|
||||
GLint imageHeight = state->storePack.imageHeight;
|
||||
GLint alignment = state->storePack.alignment;
|
||||
GLint skipPixels = state->storePack.skipPixels;
|
||||
GLint skipRows = state->storePack.skipRows;
|
||||
GLint skipImages = state->storePack.skipImages;
|
||||
GLint components, elementSize, rowSize, padding, groupsPerRow, groupSize;
|
||||
GLint elementsPerRow, sourceRowSize, sourcePadding, h, i;
|
||||
GLint imageSize, rowsPerImage;
|
||||
GLubyte *start, *iter, *itera;
|
||||
|
||||
if (type == GL_BITMAP) {
|
||||
EmptyBitmap(gc, width, height, format, sourceImage, userdata);
|
||||
}
|
||||
else {
|
||||
components = __glElementsPerGroup(format, type);
|
||||
if (rowLength > 0) {
|
||||
groupsPerRow = rowLength;
|
||||
}
|
||||
else {
|
||||
groupsPerRow = width;
|
||||
}
|
||||
if (imageHeight > 0) {
|
||||
rowsPerImage = imageHeight;
|
||||
}
|
||||
else {
|
||||
rowsPerImage = height;
|
||||
}
|
||||
elementSize = __glBytesPerElement(type);
|
||||
groupSize = elementSize * components;
|
||||
rowSize = groupsPerRow * groupSize;
|
||||
padding = (rowSize % alignment);
|
||||
if (padding) {
|
||||
rowSize += alignment - padding;
|
||||
}
|
||||
sourceRowSize = width * groupSize;
|
||||
sourcePadding = (sourceRowSize % 4);
|
||||
if (sourcePadding) {
|
||||
sourceRowSize += 4 - sourcePadding;
|
||||
}
|
||||
imageSize = sourceRowSize * rowsPerImage;
|
||||
start = ((GLubyte *) userdata) + skipImages * imageSize +
|
||||
skipRows * rowSize + skipPixels * groupSize;
|
||||
elementsPerRow = width * components;
|
||||
|
||||
itera = start;
|
||||
for (h = 0; h < depth; h++) {
|
||||
if ((rowSize == sourceRowSize) && (sourcePadding == 0)) {
|
||||
/* Ha! This is mondo easy! */
|
||||
__GLX_MEM_COPY(itera, sourceImage,
|
||||
elementsPerRow * elementSize * height);
|
||||
sourceImage += elementsPerRow * elementSize * height;
|
||||
}
|
||||
else {
|
||||
iter = itera;
|
||||
for (i = 0; i < height; i++) {
|
||||
__GLX_MEM_COPY(iter, sourceImage,
|
||||
elementsPerRow * elementSize);
|
||||
sourceImage += sourceRowSize;
|
||||
iter += rowSize;
|
||||
}
|
||||
}
|
||||
itera += imageSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include "util/rounding.h"
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
# define __builtin_expect(x, y) x
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Send glPixelStore command to the server
|
||||
*
|
||||
* \param gc Current GLX context
|
||||
* \param sop Either \c X_GLsop_PixelStoref or \c X_GLsop_PixelStorei
|
||||
* \param pname Selector of which pixel parameter is to be set.
|
||||
* \param param Value that \c pname is set to.
|
||||
*
|
||||
* \sa __indirect_glPixelStorei, __indirect_glPixelStoref
|
||||
*/
|
||||
static void
|
||||
send_PixelStore(struct glx_context * gc, unsigned sop, GLenum pname,
|
||||
const void *param)
|
||||
{
|
||||
Display *const dpy = gc->currentDpy;
|
||||
const GLuint cmdlen = 8;
|
||||
if (__builtin_expect(dpy != NULL, 1)) {
|
||||
GLubyte const *pc = __glXSetupSingleRequest(gc, sop, cmdlen);
|
||||
(void) memcpy((void *) (pc + 0), (void *) (&pname), 4);
|
||||
(void) memcpy((void *) (pc + 4), param, 4);
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Specify parameters that control the storage format of pixel arrays.
|
||||
*/
|
||||
void
|
||||
__indirect_glPixelStoref(GLenum pname, GLfloat param)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = gc->client_state_private;
|
||||
Display *dpy = gc->currentDpy;
|
||||
GLuint a;
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_PACK_ROW_LENGTH:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.rowLength = a;
|
||||
break;
|
||||
case GL_PACK_IMAGE_HEIGHT:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.imageHeight = a;
|
||||
break;
|
||||
case GL_PACK_SKIP_ROWS:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipRows = a;
|
||||
break;
|
||||
case GL_PACK_SKIP_PIXELS:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipPixels = a;
|
||||
break;
|
||||
case GL_PACK_SKIP_IMAGES:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipImages = a;
|
||||
break;
|
||||
case GL_PACK_ALIGNMENT:
|
||||
a = _mesa_lroundevenf(param);
|
||||
switch (a) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
state->storePack.alignment = a;
|
||||
break;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GL_PACK_SWAP_BYTES:
|
||||
state->storePack.swapEndian = (param != 0);
|
||||
break;
|
||||
case GL_PACK_LSB_FIRST:
|
||||
state->storePack.lsbFirst = (param != 0);
|
||||
break;
|
||||
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.rowLength = a;
|
||||
break;
|
||||
case GL_UNPACK_IMAGE_HEIGHT:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.imageHeight = a;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_ROWS:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipRows = a;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_PIXELS:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipPixels = a;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_IMAGES:
|
||||
a = _mesa_lroundevenf(param);
|
||||
if (((GLint) a) < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipImages = a;
|
||||
break;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
a = _mesa_lroundevenf(param);
|
||||
switch (a) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
state->storeUnpack.alignment = a;
|
||||
break;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GL_UNPACK_SWAP_BYTES:
|
||||
state->storeUnpack.swapEndian = (param != 0);
|
||||
break;
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
state->storeUnpack.lsbFirst = (param != 0);
|
||||
break;
|
||||
|
||||
/* Group all of the pixel store modes that need to be sent to the
|
||||
* server here. Care must be used to only send modes to the server that
|
||||
* won't affect the size of the data sent to or received from the
|
||||
* server. GL_PACK_INVERT_MESA is safe in this respect, but other,
|
||||
* future modes may not be.
|
||||
*/
|
||||
case GL_PACK_INVERT_MESA:
|
||||
send_PixelStore(gc, X_GLsop_PixelStoref, pname, ¶m);
|
||||
break;
|
||||
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glPixelStorei(GLenum pname, GLint param)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = gc->client_state_private;
|
||||
Display *dpy = gc->currentDpy;
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_PACK_ROW_LENGTH:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.rowLength = param;
|
||||
break;
|
||||
case GL_PACK_IMAGE_HEIGHT:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.imageHeight = param;
|
||||
break;
|
||||
case GL_PACK_SKIP_ROWS:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipRows = param;
|
||||
break;
|
||||
case GL_PACK_SKIP_PIXELS:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipPixels = param;
|
||||
break;
|
||||
case GL_PACK_SKIP_IMAGES:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storePack.skipImages = param;
|
||||
break;
|
||||
case GL_PACK_ALIGNMENT:
|
||||
switch (param) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
state->storePack.alignment = param;
|
||||
break;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GL_PACK_SWAP_BYTES:
|
||||
state->storePack.swapEndian = (param != 0);
|
||||
break;
|
||||
case GL_PACK_LSB_FIRST:
|
||||
state->storePack.lsbFirst = (param != 0);
|
||||
break;
|
||||
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.rowLength = param;
|
||||
break;
|
||||
case GL_UNPACK_IMAGE_HEIGHT:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.imageHeight = param;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_ROWS:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipRows = param;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_PIXELS:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipPixels = param;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_IMAGES:
|
||||
if (param < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
state->storeUnpack.skipImages = param;
|
||||
break;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
switch (param) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
state->storeUnpack.alignment = param;
|
||||
break;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GL_UNPACK_SWAP_BYTES:
|
||||
state->storeUnpack.swapEndian = (param != 0);
|
||||
break;
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
state->storeUnpack.lsbFirst = (param != 0);
|
||||
break;
|
||||
|
||||
/* Group all of the pixel store modes that need to be sent to the
|
||||
* server here. Care must be used to only send modes to the server that
|
||||
* won't affect the size of the data sent to or received from the
|
||||
* server. GL_PACK_INVERT_MESA is safe in this respect, but other,
|
||||
* future modes may not be.
|
||||
*/
|
||||
case GL_PACK_INVERT_MESA:
|
||||
send_PixelStore(gc, X_GLsop_PixelStorei, pname, ¶m);
|
||||
break;
|
||||
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "glxclient.h"
|
||||
#include "glx_error.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static Bool
|
||||
__glXQueryRendererInteger(struct glx_screen *psc, int attribute,
|
||||
unsigned int *value)
|
||||
{
|
||||
unsigned int values_for_query = 0;
|
||||
unsigned int buffer[32];
|
||||
int err;
|
||||
|
||||
/* This probably means the caller is trying to use an extension function
|
||||
* that isn't actually supported.
|
||||
*/
|
||||
if (psc->vtable->query_renderer_integer == NULL)
|
||||
return False;
|
||||
|
||||
switch (attribute) {
|
||||
case GLX_RENDERER_VENDOR_ID_MESA:
|
||||
case GLX_RENDERER_DEVICE_ID_MESA:
|
||||
values_for_query = 1;
|
||||
break;
|
||||
case GLX_RENDERER_VERSION_MESA:
|
||||
values_for_query = 3;
|
||||
break;
|
||||
case GLX_RENDERER_ACCELERATED_MESA:
|
||||
case GLX_RENDERER_VIDEO_MEMORY_MESA:
|
||||
case GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA:
|
||||
case GLX_RENDERER_PREFERRED_PROFILE_MESA:
|
||||
values_for_query = 1;
|
||||
break;
|
||||
case GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA:
|
||||
case GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA:
|
||||
case GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA:
|
||||
case GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA:
|
||||
values_for_query = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
return False;
|
||||
}
|
||||
|
||||
err = psc->vtable->query_renderer_integer(psc, attribute, buffer);
|
||||
|
||||
/* If there was no error, copy the correct number of values from the driver
|
||||
* out to the application.
|
||||
*/
|
||||
if (err == 0)
|
||||
memcpy(value, buffer, sizeof(unsigned int) * values_for_query);
|
||||
|
||||
return err == 0;
|
||||
}
|
||||
|
||||
Bool
|
||||
glXQueryRendererIntegerMESA(Display *dpy, int screen,
|
||||
int renderer, int attribute,
|
||||
unsigned int *value)
|
||||
{
|
||||
struct glx_screen *psc;
|
||||
|
||||
if (dpy == NULL)
|
||||
return False;
|
||||
|
||||
/* This probably means the caller passed the wrong display pointer or
|
||||
* screen number.
|
||||
*/
|
||||
psc = GetGLXScreenConfigs(dpy, screen);
|
||||
if (psc == NULL)
|
||||
return False;
|
||||
|
||||
/* Right now only a single renderer per display / screen combination is
|
||||
* supported.
|
||||
*/
|
||||
if (renderer != 0)
|
||||
return False;
|
||||
|
||||
return __glXQueryRendererInteger(psc, attribute, value);
|
||||
}
|
||||
|
||||
Bool
|
||||
glXQueryCurrentRendererIntegerMESA(int attribute, unsigned int *value)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
if (gc == &dummyContext)
|
||||
return False;
|
||||
|
||||
return __glXQueryRendererInteger(gc->psc, attribute, value);
|
||||
}
|
||||
|
||||
static const char *
|
||||
__glXQueryRendererString(struct glx_screen *psc, int attribute)
|
||||
{
|
||||
const char *value;
|
||||
int err;
|
||||
|
||||
/* This probably means the caller is trying to use an extension function
|
||||
* that isn't actually supported.
|
||||
*/
|
||||
if (psc->vtable->query_renderer_integer == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (attribute) {
|
||||
case GLX_RENDERER_VENDOR_ID_MESA:
|
||||
case GLX_RENDERER_DEVICE_ID_MESA:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = psc->vtable->query_renderer_string(psc, attribute, &value);
|
||||
return (err == 0) ? value : NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
glXQueryRendererStringMESA(Display *dpy, int screen,
|
||||
int renderer, int attribute)
|
||||
{
|
||||
struct glx_screen *psc;
|
||||
|
||||
if (dpy == NULL)
|
||||
return NULL;
|
||||
|
||||
/* This probably means the caller passed the wrong display pointer or
|
||||
* screen number.
|
||||
*/
|
||||
psc = GetGLXScreenConfigs(dpy, screen);
|
||||
if (psc == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Right now only a single renderer per display / screen combination is
|
||||
* supported.
|
||||
*/
|
||||
if (renderer != 0)
|
||||
return NULL;
|
||||
|
||||
return __glXQueryRendererString(psc, attribute);
|
||||
}
|
||||
|
||||
const char *
|
||||
glXQueryCurrentRendererStringMESA(int attribute)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
|
||||
if (gc == &dummyContext)
|
||||
return NULL;
|
||||
|
||||
return __glXQueryRendererString(gc->psc, attribute);
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
|
||||
|
||||
#include "packrender.h"
|
||||
#include "indirect.h"
|
||||
#include "indirect_size.h"
|
||||
|
||||
/*
|
||||
** This file contains routines that might need to be transported as
|
||||
** GLXRender or GLXRenderLarge commands, and these commands don't
|
||||
** use the pixel header. See renderpix.c for those routines.
|
||||
*/
|
||||
|
||||
void
|
||||
__indirect_glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride,
|
||||
GLint order, const GLdouble * pnts)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
GLint k;
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
k = __glMap1d_size(target);
|
||||
if (k == 0) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
else if (stride < k || order <= 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
compsize = k * order * __GLX_SIZE_FLOAT64;
|
||||
cmdlen = 28 + compsize;
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
/* Use GLXRender protocol to send small command */
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_Map1d, cmdlen);
|
||||
__GLX_PUT_DOUBLE(4, u1);
|
||||
__GLX_PUT_DOUBLE(12, u2);
|
||||
__GLX_PUT_LONG(20, target);
|
||||
__GLX_PUT_LONG(24, order);
|
||||
/*
|
||||
** NOTE: the doubles that follow are not aligned because of 3
|
||||
** longs preceding
|
||||
*/
|
||||
__glFillMap1d(k, order, stride, pnts, (pc + 28));
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
/* Use GLXRenderLarge protocol to send command */
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_Map1d, cmdlen + 4);
|
||||
__GLX_PUT_DOUBLE(8, u1);
|
||||
__GLX_PUT_DOUBLE(16, u2);
|
||||
__GLX_PUT_LONG(24, target);
|
||||
__GLX_PUT_LONG(28, order);
|
||||
|
||||
/*
|
||||
** NOTE: the doubles that follow are not aligned because of 3
|
||||
** longs preceding
|
||||
*/
|
||||
if (stride != k) {
|
||||
GLubyte *buf;
|
||||
|
||||
buf = malloc(compsize);
|
||||
if (!buf) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
__glFillMap1d(k, order, stride, pnts, buf);
|
||||
__glXSendLargeCommand(gc, pc, 32, buf, compsize);
|
||||
free((char *) buf);
|
||||
}
|
||||
else {
|
||||
/* Data is already packed. Just send it out */
|
||||
__glXSendLargeCommand(gc, pc, 32, pnts, compsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride,
|
||||
GLint order, const GLfloat * pnts)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
GLint k;
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
k = __glMap1f_size(target);
|
||||
if (k == 0) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
else if (stride < k || order <= 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
compsize = k * order * __GLX_SIZE_FLOAT32;
|
||||
cmdlen = 20 + compsize;
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
/*
|
||||
** The order that arguments are packed is different from the order
|
||||
** for glMap1d.
|
||||
*/
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
/* Use GLXRender protocol to send small command */
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_Map1f, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_FLOAT(8, u1);
|
||||
__GLX_PUT_FLOAT(12, u2);
|
||||
__GLX_PUT_LONG(16, order);
|
||||
__glFillMap1f(k, order, stride, pnts, (GLubyte *) (pc + 20));
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
/* Use GLXRenderLarge protocol to send command */
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_Map1f, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_FLOAT(12, u1);
|
||||
__GLX_PUT_FLOAT(16, u2);
|
||||
__GLX_PUT_LONG(20, order);
|
||||
|
||||
if (stride != k) {
|
||||
GLubyte *buf;
|
||||
|
||||
buf = malloc(compsize);
|
||||
if (!buf) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
__glFillMap1f(k, order, stride, pnts, buf);
|
||||
__glXSendLargeCommand(gc, pc, 24, buf, compsize);
|
||||
free((char *) buf);
|
||||
}
|
||||
else {
|
||||
/* Data is already packed. Just send it out */
|
||||
__glXSendLargeCommand(gc, pc, 24, pnts, compsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustr,
|
||||
GLint uord, GLdouble v1, GLdouble v2, GLint vstr,
|
||||
GLint vord, const GLdouble * pnts)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
GLint k;
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
k = __glMap2d_size(target);
|
||||
if (k == 0) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
else if (vstr < k || ustr < k || vord <= 0 || uord <= 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
compsize = k * uord * vord * __GLX_SIZE_FLOAT64;
|
||||
cmdlen = 48 + compsize;
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
/* Use GLXRender protocol to send small command */
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_Map2d, cmdlen);
|
||||
__GLX_PUT_DOUBLE(4, u1);
|
||||
__GLX_PUT_DOUBLE(12, u2);
|
||||
__GLX_PUT_DOUBLE(20, v1);
|
||||
__GLX_PUT_DOUBLE(28, v2);
|
||||
__GLX_PUT_LONG(36, target);
|
||||
__GLX_PUT_LONG(40, uord);
|
||||
__GLX_PUT_LONG(44, vord);
|
||||
/*
|
||||
** Pack into a u-major ordering.
|
||||
** NOTE: the doubles that follow are not aligned because of 5
|
||||
** longs preceding
|
||||
*/
|
||||
__glFillMap2d(k, uord, vord, ustr, vstr, pnts, (GLdouble *) (pc + 48));
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
/* Use GLXRenderLarge protocol to send command */
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_Map2d, cmdlen + 4);
|
||||
__GLX_PUT_DOUBLE(8, u1);
|
||||
__GLX_PUT_DOUBLE(16, u2);
|
||||
__GLX_PUT_DOUBLE(24, v1);
|
||||
__GLX_PUT_DOUBLE(32, v2);
|
||||
__GLX_PUT_LONG(40, target);
|
||||
__GLX_PUT_LONG(44, uord);
|
||||
__GLX_PUT_LONG(48, vord);
|
||||
|
||||
/*
|
||||
** NOTE: the doubles that follow are not aligned because of 5
|
||||
** longs preceding
|
||||
*/
|
||||
if ((vstr != k) || (ustr != k * vord)) {
|
||||
GLdouble *buf;
|
||||
|
||||
buf = malloc(compsize);
|
||||
if (!buf) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** Pack into a u-major ordering.
|
||||
*/
|
||||
__glFillMap2d(k, uord, vord, ustr, vstr, pnts, buf);
|
||||
__glXSendLargeCommand(gc, pc, 52, buf, compsize);
|
||||
free((char *) buf);
|
||||
}
|
||||
else {
|
||||
/* Data is already packed. Just send it out */
|
||||
__glXSendLargeCommand(gc, pc, 52, pnts, compsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustr,
|
||||
GLint uord, GLfloat v1, GLfloat v2, GLint vstr, GLint vord,
|
||||
const GLfloat * pnts)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
GLint k;
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
k = __glMap2f_size(target);
|
||||
if (k == 0) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
else if (vstr < k || ustr < k || vord <= 0 || uord <= 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
compsize = k * uord * vord * __GLX_SIZE_FLOAT32;
|
||||
cmdlen = 32 + compsize;
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
/*
|
||||
** The order that arguments are packed is different from the order
|
||||
** for glMap2d.
|
||||
*/
|
||||
if (cmdlen <= gc->maxSmallRenderCommandSize) {
|
||||
/* Use GLXRender protocol to send small command */
|
||||
__GLX_BEGIN_VARIABLE(X_GLrop_Map2f, cmdlen);
|
||||
__GLX_PUT_LONG(4, target);
|
||||
__GLX_PUT_FLOAT(8, u1);
|
||||
__GLX_PUT_FLOAT(12, u2);
|
||||
__GLX_PUT_LONG(16, uord);
|
||||
__GLX_PUT_FLOAT(20, v1);
|
||||
__GLX_PUT_FLOAT(24, v2);
|
||||
__GLX_PUT_LONG(28, vord);
|
||||
/*
|
||||
** Pack into a u-major ordering.
|
||||
*/
|
||||
__glFillMap2f(k, uord, vord, ustr, vstr, pnts, (GLfloat *) (pc + 32));
|
||||
__GLX_END(cmdlen);
|
||||
}
|
||||
else {
|
||||
/* Use GLXRenderLarge protocol to send command */
|
||||
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_Map2f, cmdlen + 4);
|
||||
__GLX_PUT_LONG(8, target);
|
||||
__GLX_PUT_FLOAT(12, u1);
|
||||
__GLX_PUT_FLOAT(16, u2);
|
||||
__GLX_PUT_LONG(20, uord);
|
||||
__GLX_PUT_FLOAT(24, v1);
|
||||
__GLX_PUT_FLOAT(28, v2);
|
||||
__GLX_PUT_LONG(32, vord);
|
||||
|
||||
if ((vstr != k) || (ustr != k * vord)) {
|
||||
GLfloat *buf;
|
||||
|
||||
buf = malloc(compsize);
|
||||
if (!buf) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
** Pack into a u-major ordering.
|
||||
*/
|
||||
__glFillMap2f(k, uord, vord, ustr, vstr, pnts, buf);
|
||||
__glXSendLargeCommand(gc, pc, 36, buf, compsize);
|
||||
free((char *) buf);
|
||||
}
|
||||
else {
|
||||
/* Data is already packed. Just send it out */
|
||||
__glXSendLargeCommand(gc, pc, 36, pnts, compsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glEnable(GLenum cap)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
switch (cap) {
|
||||
case GL_COLOR_ARRAY:
|
||||
case GL_EDGE_FLAG_ARRAY:
|
||||
case GL_INDEX_ARRAY:
|
||||
case GL_NORMAL_ARRAY:
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
case GL_VERTEX_ARRAY:
|
||||
case GL_SECONDARY_COLOR_ARRAY:
|
||||
case GL_FOG_COORD_ARRAY:
|
||||
__indirect_glEnableClientState(cap);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
__GLX_BEGIN(X_GLrop_Enable, 8);
|
||||
__GLX_PUT_LONG(4, cap);
|
||||
__GLX_END(8);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glDisable(GLenum cap)
|
||||
{
|
||||
__GLX_DECLARE_VARIABLES();
|
||||
|
||||
__GLX_LOAD_VARIABLES();
|
||||
if (!gc->currentDpy)
|
||||
return;
|
||||
|
||||
switch (cap) {
|
||||
case GL_COLOR_ARRAY:
|
||||
case GL_EDGE_FLAG_ARRAY:
|
||||
case GL_INDEX_ARRAY:
|
||||
case GL_NORMAL_ARRAY:
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
case GL_VERTEX_ARRAY:
|
||||
case GL_SECONDARY_COLOR_ARRAY:
|
||||
case GL_FOG_COORD_ARRAY:
|
||||
__indirect_glDisableClientState(cap);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
__GLX_BEGIN(X_GLrop_Disable, 8);
|
||||
__GLX_PUT_LONG(4, cap);
|
||||
__GLX_END(8);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* (C) Copyright IBM Corporation 2005
|
||||
* 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, sub license,
|
||||
* 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM,
|
||||
* AND/OR THEIR SUPPLIERS 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.
|
||||
*/
|
||||
|
||||
#include "packrender.h"
|
||||
#include "indirect.h"
|
||||
|
||||
/**
|
||||
* Send a large image to the server. If necessary, a buffer is allocated
|
||||
* to hold the unpacked data that is copied from the clients memory.
|
||||
*
|
||||
* \param gc Current GLX context
|
||||
* \param compsize Size, in bytes, of the image portion
|
||||
* \param dim Number of dimensions of the image
|
||||
* \param width Width of the image
|
||||
* \param height Height of the image, must be 1 for 1D images
|
||||
* \param depth Depth of the image, must be 1 for 1D or 2D images
|
||||
* \param format Format of the image
|
||||
* \param type Data type of the image
|
||||
* \param src Pointer to the image data
|
||||
* \param pc Pointer to end of the command header
|
||||
* \param modes Pointer to the pixel unpack data
|
||||
*
|
||||
* \todo
|
||||
* Modify this function so that \c NULL images are sent using
|
||||
* \c __glXSendLargeChunk instead of __glXSendLargeCommand. Doing this
|
||||
* will eliminate the need to allocate a buffer for that case.
|
||||
*/
|
||||
void
|
||||
__glXSendLargeImage(struct glx_context * gc, GLint compsize, GLint dim,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLenum format, GLenum type, const GLvoid * src,
|
||||
GLubyte * pc, GLubyte * modes)
|
||||
{
|
||||
/* Allocate a temporary holding buffer */
|
||||
GLubyte *buf = malloc(compsize);
|
||||
if (!buf) {
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Apply pixel store unpack modes to copy data into buf */
|
||||
if (src != NULL) {
|
||||
__glFillImage(gc, dim, width, height, depth, format, type,
|
||||
src, buf, modes);
|
||||
}
|
||||
else {
|
||||
if (dim < 3) {
|
||||
(void) memcpy(modes, __glXDefaultPixelStore + 4, 20);
|
||||
}
|
||||
else {
|
||||
(void) memcpy(modes, __glXDefaultPixelStore + 0, 36);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send large command */
|
||||
__glXSendLargeCommand(gc, gc->pc, pc - gc->pc, buf, compsize);
|
||||
|
||||
/* Free buffer */
|
||||
free((char *) buf);
|
||||
}
|
||||
@@ -0,0 +1,843 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "glxclient.h"
|
||||
#include "packsingle.h"
|
||||
#include "glxextensions.h"
|
||||
#include "indirect.h"
|
||||
#include "indirect_vertex_array.h"
|
||||
#include "glapi.h"
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/glx.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include "dispatch.h"
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
# define __builtin_expect(x, y) x
|
||||
#endif
|
||||
|
||||
/* Used for GL_ARB_transpose_matrix */
|
||||
static void
|
||||
TransposeMatrixf(GLfloat m[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
GLfloat tmp = m[i * 4 + j];
|
||||
m[i * 4 + j] = m[j * 4 + i];
|
||||
m[j * 4 + i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for GL_ARB_transpose_matrix */
|
||||
static void
|
||||
TransposeMatrixb(GLboolean m[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
GLboolean tmp = m[i * 4 + j];
|
||||
m[i * 4 + j] = m[j * 4 + i];
|
||||
m[j * 4 + i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for GL_ARB_transpose_matrix */
|
||||
static void
|
||||
TransposeMatrixd(GLdouble m[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
GLdouble tmp = m[i * 4 + j];
|
||||
m[i * 4 + j] = m[j * 4 + i];
|
||||
m[j * 4 + i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for GL_ARB_transpose_matrix */
|
||||
static void
|
||||
TransposeMatrixi(GLint m[16])
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
GLint tmp = m[i * 4 + j];
|
||||
m[i * 4 + j] = m[j * 4 + i];
|
||||
m[j * 4 + i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remap a transpose-matrix enum to a non-transpose-matrix enum. Enums
|
||||
* that are not transpose-matrix enums are unaffected.
|
||||
*/
|
||||
static GLenum
|
||||
RemapTransposeEnum(GLenum e)
|
||||
{
|
||||
switch (e) {
|
||||
case GL_TRANSPOSE_MODELVIEW_MATRIX:
|
||||
case GL_TRANSPOSE_PROJECTION_MATRIX:
|
||||
case GL_TRANSPOSE_TEXTURE_MATRIX:
|
||||
return e - (GL_TRANSPOSE_MODELVIEW_MATRIX - GL_MODELVIEW_MATRIX);
|
||||
case GL_TRANSPOSE_COLOR_MATRIX:
|
||||
return GL_COLOR_MATRIX;
|
||||
default:
|
||||
return e;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
GLenum
|
||||
__indirect_glGetError(void)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
GLuint retval = GL_NO_ERROR;
|
||||
xGLXGetErrorReply reply;
|
||||
|
||||
if (gc->error) {
|
||||
/* Use internal error first */
|
||||
retval = gc->error;
|
||||
gc->error = GL_NO_ERROR;
|
||||
return retval;
|
||||
}
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetError, 0);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
retval = reply.error;
|
||||
__GLX_SINGLE_END();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the selected attribute from the client state.
|
||||
*
|
||||
* \returns
|
||||
* On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
|
||||
*/
|
||||
static GLboolean
|
||||
get_client_data(struct glx_context * gc, GLenum cap, GLintptr * data)
|
||||
{
|
||||
GLboolean retval = GL_TRUE;
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
const GLint tex_unit = __glXGetActiveTextureUnit(state);
|
||||
|
||||
|
||||
switch (cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
case GL_NORMAL_ARRAY:
|
||||
case GL_COLOR_ARRAY:
|
||||
case GL_INDEX_ARRAY:
|
||||
case GL_EDGE_FLAG_ARRAY:
|
||||
case GL_SECONDARY_COLOR_ARRAY:
|
||||
case GL_FOG_COORD_ARRAY:
|
||||
retval = __glXGetArrayEnable(state, cap, 0, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ARRAY_SIZE:
|
||||
retval = __glXGetArraySize(state, GL_VERTEX_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_COLOR_ARRAY_SIZE:
|
||||
retval = __glXGetArraySize(state, GL_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_SECONDARY_COLOR_ARRAY_SIZE:
|
||||
retval = __glXGetArraySize(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_VERTEX_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_NORMAL_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_NORMAL_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_INDEX_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_INDEX_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_COLOR_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_SECONDARY_COLOR_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_FOG_COORD_ARRAY_TYPE:
|
||||
retval = __glXGetArrayType(state, GL_FOG_COORD_ARRAY, 0, data);
|
||||
break;
|
||||
|
||||
case GL_VERTEX_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_VERTEX_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_NORMAL_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_NORMAL_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_INDEX_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_INDEX_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_EDGE_FLAG_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_EDGE_FLAG_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_COLOR_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_SECONDARY_COLOR_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_SECONDARY_COLOR_ARRAY, 0, data);
|
||||
break;
|
||||
case GL_FOG_COORD_ARRAY_STRIDE:
|
||||
retval = __glXGetArrayStride(state, GL_FOG_COORD_ARRAY, 0, data);
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
retval =
|
||||
__glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY_SIZE:
|
||||
retval =
|
||||
__glXGetArraySize(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY_TYPE:
|
||||
retval =
|
||||
__glXGetArrayType(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY_STRIDE:
|
||||
retval =
|
||||
__glXGetArrayStride(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data);
|
||||
break;
|
||||
|
||||
case GL_MAX_ELEMENTS_VERTICES:
|
||||
case GL_MAX_ELEMENTS_INDICES:
|
||||
retval = GL_TRUE;
|
||||
*data = ~0UL;
|
||||
break;
|
||||
|
||||
|
||||
case GL_PACK_ROW_LENGTH:
|
||||
*data = (GLintptr) state->storePack.rowLength;
|
||||
break;
|
||||
case GL_PACK_IMAGE_HEIGHT:
|
||||
*data = (GLintptr) state->storePack.imageHeight;
|
||||
break;
|
||||
case GL_PACK_SKIP_ROWS:
|
||||
*data = (GLintptr) state->storePack.skipRows;
|
||||
break;
|
||||
case GL_PACK_SKIP_PIXELS:
|
||||
*data = (GLintptr) state->storePack.skipPixels;
|
||||
break;
|
||||
case GL_PACK_SKIP_IMAGES:
|
||||
*data = (GLintptr) state->storePack.skipImages;
|
||||
break;
|
||||
case GL_PACK_ALIGNMENT:
|
||||
*data = (GLintptr) state->storePack.alignment;
|
||||
break;
|
||||
case GL_PACK_SWAP_BYTES:
|
||||
*data = (GLintptr) state->storePack.swapEndian;
|
||||
break;
|
||||
case GL_PACK_LSB_FIRST:
|
||||
*data = (GLintptr) state->storePack.lsbFirst;
|
||||
break;
|
||||
case GL_UNPACK_ROW_LENGTH:
|
||||
*data = (GLintptr) state->storeUnpack.rowLength;
|
||||
break;
|
||||
case GL_UNPACK_IMAGE_HEIGHT:
|
||||
*data = (GLintptr) state->storeUnpack.imageHeight;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_ROWS:
|
||||
*data = (GLintptr) state->storeUnpack.skipRows;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_PIXELS:
|
||||
*data = (GLintptr) state->storeUnpack.skipPixels;
|
||||
break;
|
||||
case GL_UNPACK_SKIP_IMAGES:
|
||||
*data = (GLintptr) state->storeUnpack.skipImages;
|
||||
break;
|
||||
case GL_UNPACK_ALIGNMENT:
|
||||
*data = (GLintptr) state->storeUnpack.alignment;
|
||||
break;
|
||||
case GL_UNPACK_SWAP_BYTES:
|
||||
*data = (GLintptr) state->storeUnpack.swapEndian;
|
||||
break;
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
*data = (GLintptr) state->storeUnpack.lsbFirst;
|
||||
break;
|
||||
case GL_CLIENT_ATTRIB_STACK_DEPTH:
|
||||
*data = (GLintptr) (gc->attributes.stackPointer - gc->attributes.stack);
|
||||
break;
|
||||
case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
|
||||
*data = (GLintptr) __GL_CLIENT_ATTRIB_STACK_DEPTH;
|
||||
break;
|
||||
case GL_CLIENT_ACTIVE_TEXTURE:
|
||||
*data = (GLintptr) (tex_unit + GL_TEXTURE0);
|
||||
break;
|
||||
|
||||
default:
|
||||
retval = GL_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__indirect_glGetBooleanv(GLenum val, GLboolean * b)
|
||||
{
|
||||
const GLenum origVal = val;
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXSingleReply reply;
|
||||
|
||||
val = RemapTransposeEnum(val);
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetBooleanv, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, val);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
|
||||
if (compsize == 0) {
|
||||
/*
|
||||
** Error occurred; don't modify user's buffer.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
GLintptr data;
|
||||
|
||||
/*
|
||||
** We still needed to send the request to the server in order to
|
||||
** find out whether it was legal to make a query (it's illegal,
|
||||
** for example, to call a query between glBegin() and glEnd()).
|
||||
*/
|
||||
|
||||
if (get_client_data(gc, val, &data)) {
|
||||
*b = (GLboolean) data;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
** Not a local value, so use what we got from the server.
|
||||
*/
|
||||
if (compsize == 1) {
|
||||
__GLX_SINGLE_GET_CHAR(b);
|
||||
}
|
||||
else {
|
||||
__GLX_SINGLE_GET_CHAR_ARRAY(b, compsize);
|
||||
if (val != origVal) {
|
||||
/* matrix transpose */
|
||||
TransposeMatrixb(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glGetDoublev(GLenum val, GLdouble * d)
|
||||
{
|
||||
const GLenum origVal = val;
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXSingleReply reply;
|
||||
|
||||
val = RemapTransposeEnum(val);
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetDoublev, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, val);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
|
||||
if (compsize == 0) {
|
||||
/*
|
||||
** Error occurred; don't modify user's buffer.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
GLintptr data;
|
||||
|
||||
/*
|
||||
** We still needed to send the request to the server in order to
|
||||
** find out whether it was legal to make a query (it's illegal,
|
||||
** for example, to call a query between glBegin() and glEnd()).
|
||||
*/
|
||||
|
||||
if (get_client_data(gc, val, &data)) {
|
||||
*d = (GLdouble) data;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
** Not a local value, so use what we got from the server.
|
||||
*/
|
||||
if (compsize == 1) {
|
||||
__GLX_SINGLE_GET_DOUBLE(d);
|
||||
}
|
||||
else {
|
||||
__GLX_SINGLE_GET_DOUBLE_ARRAY(d, compsize);
|
||||
if (val != origVal) {
|
||||
/* matrix transpose */
|
||||
TransposeMatrixd(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glGetFloatv(GLenum val, GLfloat * f)
|
||||
{
|
||||
const GLenum origVal = val;
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXSingleReply reply;
|
||||
|
||||
val = RemapTransposeEnum(val);
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetFloatv, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, val);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
|
||||
if (compsize == 0) {
|
||||
/*
|
||||
** Error occurred; don't modify user's buffer.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
GLintptr data;
|
||||
|
||||
/*
|
||||
** We still needed to send the request to the server in order to
|
||||
** find out whether it was legal to make a query (it's illegal,
|
||||
** for example, to call a query between glBegin() and glEnd()).
|
||||
*/
|
||||
|
||||
if (get_client_data(gc, val, &data)) {
|
||||
*f = (GLfloat) data;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
** Not a local value, so use what we got from the server.
|
||||
*/
|
||||
if (compsize == 1) {
|
||||
__GLX_SINGLE_GET_FLOAT(f);
|
||||
}
|
||||
else {
|
||||
__GLX_SINGLE_GET_FLOAT_ARRAY(f, compsize);
|
||||
if (val != origVal) {
|
||||
/* matrix transpose */
|
||||
TransposeMatrixf(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glGetIntegerv(GLenum val, GLint * i)
|
||||
{
|
||||
const GLenum origVal = val;
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXSingleReply reply;
|
||||
|
||||
val = RemapTransposeEnum(val);
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_GetIntegerv, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, val);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
|
||||
if (compsize == 0) {
|
||||
/*
|
||||
** Error occurred; don't modify user's buffer.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
GLintptr data;
|
||||
|
||||
/*
|
||||
** We still needed to send the request to the server in order to
|
||||
** find out whether it was legal to make a query (it's illegal,
|
||||
** for example, to call a query between glBegin() and glEnd()).
|
||||
*/
|
||||
|
||||
if (get_client_data(gc, val, &data)) {
|
||||
*i = (GLint) data;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
** Not a local value, so use what we got from the server.
|
||||
*/
|
||||
if (compsize == 1) {
|
||||
__GLX_SINGLE_GET_LONG(i);
|
||||
}
|
||||
else {
|
||||
__GLX_SINGLE_GET_LONG_ARRAY(i, compsize);
|
||||
if (val != origVal) {
|
||||
/* matrix transpose */
|
||||
TransposeMatrixi(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
/*
|
||||
** Send all pending commands to server.
|
||||
*/
|
||||
void
|
||||
__indirect_glFlush(void)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_Flush, 0);
|
||||
__GLX_SINGLE_END();
|
||||
|
||||
/* And finally flush the X protocol data */
|
||||
XFlush(dpy);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_FeedbackBuffer, 8);
|
||||
__GLX_SINGLE_PUT_LONG(0, size);
|
||||
__GLX_SINGLE_PUT_LONG(4, type);
|
||||
__GLX_SINGLE_END();
|
||||
|
||||
gc->feedbackBuf = buffer;
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glSelectBuffer(GLsizei numnames, GLuint * buffer)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_SelectBuffer, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, numnames);
|
||||
__GLX_SINGLE_END();
|
||||
|
||||
gc->selectBuf = buffer;
|
||||
}
|
||||
|
||||
GLint
|
||||
__indirect_glRenderMode(GLenum mode)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
GLint retval = 0;
|
||||
xGLXRenderModeReply reply;
|
||||
|
||||
if (!dpy)
|
||||
return -1;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_RenderMode, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, mode);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_RETVAL(retval, GLint);
|
||||
|
||||
if (reply.newMode != mode) {
|
||||
/*
|
||||
** Switch to new mode did not take effect, therefore an error
|
||||
** occurred. When an error happens the server won't send us any
|
||||
** other data.
|
||||
*/
|
||||
}
|
||||
else {
|
||||
/* Read the feedback or selection data */
|
||||
if (gc->renderMode == GL_FEEDBACK) {
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
__GLX_SINGLE_GET_FLOAT_ARRAY(gc->feedbackBuf, compsize);
|
||||
}
|
||||
else if (gc->renderMode == GL_SELECT) {
|
||||
__GLX_SINGLE_GET_SIZE(compsize);
|
||||
__GLX_SINGLE_GET_LONG_ARRAY(gc->selectBuf, compsize);
|
||||
}
|
||||
gc->renderMode = mode;
|
||||
}
|
||||
__GLX_SINGLE_END();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glFinish(void)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
xGLXSingleReply reply;
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_Finish, 0);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_END();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the major and minor version numbers from a version string.
|
||||
*/
|
||||
static void
|
||||
version_from_string(const char *ver, int *major_version, int *minor_version)
|
||||
{
|
||||
const char *end;
|
||||
long major;
|
||||
long minor;
|
||||
|
||||
major = strtol(ver, (char **) &end, 10);
|
||||
minor = strtol(end + 1, NULL, 10);
|
||||
*major_version = major;
|
||||
*minor_version = minor;
|
||||
}
|
||||
|
||||
|
||||
const GLubyte *
|
||||
__indirect_glGetString(GLenum name)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
Display *dpy = gc->currentDpy;
|
||||
GLubyte *s = NULL;
|
||||
|
||||
if (!dpy)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
** Return the cached copy if the string has already been fetched
|
||||
*/
|
||||
switch (name) {
|
||||
case GL_VENDOR:
|
||||
if (gc->vendor)
|
||||
return gc->vendor;
|
||||
break;
|
||||
case GL_RENDERER:
|
||||
if (gc->renderer)
|
||||
return gc->renderer;
|
||||
break;
|
||||
case GL_VERSION:
|
||||
if (gc->version)
|
||||
return gc->version;
|
||||
break;
|
||||
case GL_EXTENSIONS:
|
||||
if (gc->extensions)
|
||||
return gc->extensions;
|
||||
break;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Get requested string from server
|
||||
*/
|
||||
|
||||
(void) __glXFlushRenderBuffer(gc, gc->pc);
|
||||
s = (GLubyte *) __glXGetString(dpy, gc->currentContextTag, name);
|
||||
if (!s) {
|
||||
/* Throw data on the floor */
|
||||
__glXSetError(gc, GL_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
** Update local cache
|
||||
*/
|
||||
switch (name) {
|
||||
case GL_VENDOR:
|
||||
gc->vendor = s;
|
||||
break;
|
||||
|
||||
case GL_RENDERER:
|
||||
gc->renderer = s;
|
||||
break;
|
||||
|
||||
case GL_VERSION:{
|
||||
const int client_major = 1;
|
||||
const int client_minor = 4;
|
||||
|
||||
version_from_string((char *) s,
|
||||
&gc->server_major, &gc->server_minor);
|
||||
|
||||
if ((gc->server_major < client_major)
|
||||
|| ((gc->server_major == client_major)
|
||||
&& (gc->server_minor <= client_minor))) {
|
||||
gc->version = s;
|
||||
}
|
||||
else {
|
||||
/* Allow 7 bytes for the client-side GL version. This allows
|
||||
* for upto version 999.999. I'm not holding my breath for
|
||||
* that one! The extra 4 is for the ' ()\0' that will be
|
||||
* added.
|
||||
*/
|
||||
const size_t size = 7 + strlen((char *) s) + 4;
|
||||
|
||||
gc->version = malloc(size);
|
||||
if (gc->version == NULL) {
|
||||
/* If we couldn't allocate memory for the new string,
|
||||
* make a best-effort and just copy the client-side version
|
||||
* to the string and use that. It probably doesn't
|
||||
* matter what is done here. If there not memory available
|
||||
* for a short string, the system is probably going to die
|
||||
* soon anyway.
|
||||
*/
|
||||
snprintf((char *) s, strlen((char *) s) + 1, "%u.%u",
|
||||
client_major, client_minor);
|
||||
gc->version = s;
|
||||
}
|
||||
else {
|
||||
snprintf((char *) gc->version, size, "%u.%u (%s)",
|
||||
client_major, client_minor, s);
|
||||
free(s);
|
||||
s = gc->version;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_EXTENSIONS:{
|
||||
__glXCalculateUsableGLExtensions(gc, (char *) s);
|
||||
free(s);
|
||||
s = gc->extensions;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
__indirect_glIsEnabled(GLenum cap)
|
||||
{
|
||||
__GLX_SINGLE_DECLARE_VARIABLES();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
xGLXSingleReply reply;
|
||||
GLboolean retval = 0;
|
||||
GLintptr enable;
|
||||
|
||||
if (!dpy)
|
||||
return 0;
|
||||
|
||||
switch (cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
case GL_NORMAL_ARRAY:
|
||||
case GL_COLOR_ARRAY:
|
||||
case GL_INDEX_ARRAY:
|
||||
case GL_EDGE_FLAG_ARRAY:
|
||||
case GL_SECONDARY_COLOR_ARRAY:
|
||||
case GL_FOG_COORD_ARRAY:
|
||||
retval = __glXGetArrayEnable(state, cap, 0, &enable);
|
||||
assert(retval);
|
||||
return (GLboolean) enable;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
retval = __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY,
|
||||
__glXGetActiveTextureUnit(state), &enable);
|
||||
assert(retval);
|
||||
return (GLboolean) enable;
|
||||
break;
|
||||
}
|
||||
|
||||
__GLX_SINGLE_LOAD_VARIABLES();
|
||||
__GLX_SINGLE_BEGIN(X_GLsop_IsEnabled, 4);
|
||||
__GLX_SINGLE_PUT_LONG(0, cap);
|
||||
__GLX_SINGLE_READ_XREPLY();
|
||||
__GLX_SINGLE_GET_RETVAL(retval, GLboolean);
|
||||
__GLX_SINGLE_END();
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glGetPointerv(GLenum pname, void **params)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
Display *dpy = gc->currentDpy;
|
||||
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_VERTEX_ARRAY_POINTER:
|
||||
case GL_NORMAL_ARRAY_POINTER:
|
||||
case GL_COLOR_ARRAY_POINTER:
|
||||
case GL_INDEX_ARRAY_POINTER:
|
||||
case GL_EDGE_FLAG_ARRAY_POINTER:
|
||||
__glXGetArrayPointer(state, pname - GL_VERTEX_ARRAY_POINTER
|
||||
+ GL_VERTEX_ARRAY, 0, params);
|
||||
return;
|
||||
case GL_TEXTURE_COORD_ARRAY_POINTER:
|
||||
__glXGetArrayPointer(state, GL_TEXTURE_COORD_ARRAY,
|
||||
__glXGetActiveTextureUnit(state), params);
|
||||
return;
|
||||
case GL_SECONDARY_COLOR_ARRAY_POINTER:
|
||||
case GL_FOG_COORD_ARRAY_POINTER:
|
||||
__glXGetArrayPointer(state, pname - GL_FOG_COORD_ARRAY_POINTER
|
||||
+ GL_FOG_COORD_ARRAY, 0, params);
|
||||
return;
|
||||
case GL_FEEDBACK_BUFFER_POINTER:
|
||||
*params = (void *) gc->feedbackBuf;
|
||||
return;
|
||||
case GL_SELECTION_BUFFER_POINTER:
|
||||
*params = (void *) gc->selectBuf;
|
||||
return;
|
||||
default:
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This was previously auto-generated, but we need to special-case
|
||||
* how we handle writing into the 'residences' buffer when n%4!=0.
|
||||
*/
|
||||
#define X_GLsop_AreTexturesResident 143
|
||||
GLboolean
|
||||
__indirect_glAreTexturesResident(GLsizei n, const GLuint * textures,
|
||||
GLboolean * residences)
|
||||
{
|
||||
struct glx_context *const gc = __glXGetCurrentContext();
|
||||
Display *const dpy = gc->currentDpy;
|
||||
GLboolean retval = (GLboolean) 0;
|
||||
if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) {
|
||||
xcb_connection_t *c = XGetXCBConnection(dpy);
|
||||
xcb_glx_are_textures_resident_reply_t *reply;
|
||||
(void) __glXFlushRenderBuffer(gc, gc->pc);
|
||||
reply =
|
||||
xcb_glx_are_textures_resident_reply(c,
|
||||
xcb_glx_are_textures_resident
|
||||
(c, gc->currentContextTag, n,
|
||||
textures), NULL);
|
||||
(void) memcpy(residences, xcb_glx_are_textures_resident_data(reply),
|
||||
xcb_glx_are_textures_resident_data_length(reply) *
|
||||
sizeof(GLboolean));
|
||||
retval = reply->ret_val;
|
||||
free(reply);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
|
||||
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: SGI-B-2.0
|
||||
*/
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "indirect.h"
|
||||
#include "indirect_vertex_array.h"
|
||||
|
||||
#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* \name Vertex array pointer bridge functions
|
||||
*
|
||||
* When EXT_vertex_array was moved into the core GL spec, the \c count
|
||||
* parameter was lost. This libGL really only wants to implement the GL 1.1
|
||||
* version, but we need to support applications that were written to the old
|
||||
* interface. These bridge functions are part of the glue that makes this
|
||||
* happen.
|
||||
*/
|
||||
/*@{*/
|
||||
void
|
||||
__indirect_glColorPointerEXT(GLint size, GLenum type, GLsizei stride,
|
||||
GLsizei count, const GLvoid * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glColorPointer(size, type, stride, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glEdgeFlagPointerEXT(GLsizei stride,
|
||||
GLsizei count, const GLboolean * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glEdgeFlagPointer(stride, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glIndexPointerEXT(GLenum type, GLsizei stride,
|
||||
GLsizei count, const GLvoid * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glIndexPointer(type, stride, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glNormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
|
||||
const GLvoid * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glNormalPointer(type, stride, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glTexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
|
||||
GLsizei count, const GLvoid * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glTexCoordPointer(size, type, stride, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
__indirect_glVertexPointerEXT(GLint size, GLenum type, GLsizei stride,
|
||||
GLsizei count, const GLvoid * pointer)
|
||||
{
|
||||
(void) count;
|
||||
__indirect_glVertexPointer(size, type, stride, pointer);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
__indirect_glInterleavedArrays(GLenum format, GLsizei stride,
|
||||
const GLvoid * pointer)
|
||||
{
|
||||
struct glx_context *gc = __glXGetCurrentContext();
|
||||
__GLXattribute *state = (__GLXattribute *) (gc->client_state_private);
|
||||
|
||||
#define NONE {0, 0, 0}
|
||||
#define F(x) {GL_FLOAT, x, x * sizeof(GLfloat)}
|
||||
#define UB4 {GL_UNSIGNED_BYTE, 4, 4 * sizeof(GLubyte)}
|
||||
|
||||
/* Each row in this array describes the elements of a particular
|
||||
* interleaved array mode. Each column describes, in the order in which
|
||||
* they appear in the interleaved arrays, one of the four possible types
|
||||
* of vertex data that can appear in an interleaved array.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* The enum describing the GL type, as would be passed to the
|
||||
* appropriate gl*Pointer function.
|
||||
*/
|
||||
GLushort type;
|
||||
|
||||
/**
|
||||
* Number of elements in the subarray, as would be passed (as the
|
||||
* \c size parameter) to the appropriate gl*Pointer function.
|
||||
*/
|
||||
GLubyte count;
|
||||
|
||||
/**
|
||||
* True size of a single element in the subarray, as would be passed
|
||||
* (as the \c stride parameter) to the appropriate gl*Pointer
|
||||
* function.
|
||||
*/
|
||||
GLubyte size;
|
||||
}
|
||||
static const modes[14][4] = {
|
||||
/* texture color normal vertex */
|
||||
{NONE, NONE, NONE, F(2)}, /* GL_V2F */
|
||||
{NONE, NONE, NONE, F(3)}, /* GL_V3F */
|
||||
{NONE, UB4, NONE, F(2)}, /* GL_C4UB_V2F */
|
||||
{NONE, UB4, NONE, F(3)}, /* GL_C4UB_V3F */
|
||||
{NONE, F(3), NONE, F(3)}, /* GL_C3F_V3F */
|
||||
{NONE, NONE, F(3), F(3)}, /* GL_N3F_V3F */
|
||||
{NONE, F(4), F(3), F(3)}, /* GL_C4F_N3F_V3F */
|
||||
{F(2), NONE, NONE, F(3)}, /* GL_T2F_V3F */
|
||||
{F(4), NONE, NONE, F(4)}, /* GL_T4F_V4F */
|
||||
{F(2), UB4, NONE, F(3)}, /* GL_T2F_C4UB_V3F */
|
||||
{F(2), F(3), NONE, F(3)}, /* GL_T2F_C3F_V3F */
|
||||
{F(2), NONE, F(3), F(3)}, /* GL_T2F_N3F_V3F */
|
||||
{F(2), F(4), F(3), F(3)}, /* GL_T2F_C4F_N3F_V3F */
|
||||
{F(4), F(4), F(3), F(4)}, /* GL_T4F_C4F_N3F_V4F */
|
||||
};
|
||||
#undef NONE
|
||||
#undef F
|
||||
#undef UB4
|
||||
|
||||
GLint trueStride, size;
|
||||
int offsets[4];
|
||||
unsigned i;
|
||||
const int idx = format - GL_V2F;
|
||||
|
||||
|
||||
/* All valid formats are on the range [GL_V2F, GL_V2F+0x0D]. Since idx
|
||||
* is just the format biased by -GL_V2F, all valid idx values are on the
|
||||
* range [0, 0x0D].
|
||||
*/
|
||||
if ((idx < 0) || (idx > 0x0D)) {
|
||||
__glXSetError(gc, GL_INVALID_ENUM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stride < 0) {
|
||||
__glXSetError(gc, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* If the 'count' for a subarray is non-zero, then the offset of its
|
||||
* first element is at the currently accumulated 'size'.
|
||||
*/
|
||||
size = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
offsets[i] = (modes[idx][i].count != 0) ? size : -1;
|
||||
size += modes[idx][i].size;
|
||||
}
|
||||
|
||||
trueStride = (stride == 0) ? size : stride;
|
||||
|
||||
__glXArrayDisableAll(state);
|
||||
|
||||
if (offsets[0] >= 0) {
|
||||
__indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
__indirect_glTexCoordPointer(modes[idx][0].count, GL_FLOAT,
|
||||
trueStride, (const char *) pointer);
|
||||
}
|
||||
if (offsets[1] >= 0) {
|
||||
__indirect_glEnableClientState(GL_COLOR_ARRAY);
|
||||
__indirect_glColorPointer(modes[idx][1].count, modes[idx][1].type,
|
||||
trueStride,
|
||||
(const char *) pointer + offsets[1]);
|
||||
}
|
||||
if (offsets[2] >= 0) {
|
||||
__indirect_glEnableClientState(GL_NORMAL_ARRAY);
|
||||
__indirect_glNormalPointer(GL_FLOAT, trueStride,
|
||||
(const char *) pointer + offsets[2]);
|
||||
}
|
||||
__indirect_glEnableClientState(GL_VERTEX_ARRAY);
|
||||
__indirect_glVertexPointer(modes[idx][3].count, GL_FLOAT,
|
||||
trueStride,
|
||||
(const char *) pointer + offsets[3]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
# Copyright © 2017 Jon Turney
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# protocol defines for the Windows-DRI server extension
|
||||
|
||||
files_windowsdriproto = files(
|
||||
'windowsdriconst.h',
|
||||
'windowsdristr.h',
|
||||
)
|
||||
|
||||
install_headers(
|
||||
files_windowsdriproto,
|
||||
subdir: 'X11/extensions',
|
||||
)
|
||||
|
||||
pkg.generate(
|
||||
name : 'windowsdriproto',
|
||||
description : 'Windows-DRI extension headers',
|
||||
version : '1.0.0',
|
||||
)
|
||||
|
||||
# library for using the Windows-DRI server extension
|
||||
files_libwindowsdri = files(
|
||||
'xwindowsdri.c',
|
||||
'xwindowsdri.h',
|
||||
)
|
||||
|
||||
libwindowsdri = static_library(
|
||||
'driwindows',
|
||||
[files_libwindowsdri, files_windowsdriproto],
|
||||
dependencies: dep_xext,
|
||||
build_by_default: false,
|
||||
)
|
||||
|
||||
# library for native GL on windows
|
||||
files_libwindowsglx = files(
|
||||
'windowsgl.c',
|
||||
'windowsgl.h',
|
||||
'windowsgl_internal.h',
|
||||
'windows_drawable.c',
|
||||
'wgl.c',
|
||||
'wgl.h',
|
||||
)
|
||||
|
||||
libwindowsglx = static_library(
|
||||
'glxwindows',
|
||||
[files_libwindowsglx, files_windowsdriproto],
|
||||
include_directories: [inc_include, inc_src, inc_glapi],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
build_by_default: false,
|
||||
)
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Wrapper functions for calling WGL extension functions
|
||||
*/
|
||||
|
||||
#include "wgl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define RESOLVE_DECL(type) \
|
||||
static type type##proc = NULL;
|
||||
|
||||
#define PRERESOLVE(type, symbol) \
|
||||
type##proc = (type)wglGetProcAddress(symbol); \
|
||||
if (type##proc == NULL) \
|
||||
printf("Can't resolve \"%s\"\n", symbol);
|
||||
|
||||
#define CHECK_RESOLVED(type, retval) \
|
||||
if (type##proc == NULL) { \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define RESOLVED_PROC(type) type##proc
|
||||
|
||||
RESOLVE_DECL(PFNWGLGETEXTENSIONSSTRINGARBPROC);
|
||||
RESOLVE_DECL(PFNWGLCREATECONTEXTATTRIBSARBPROC);
|
||||
RESOLVE_DECL(PFNWGLMAKECONTEXTCURRENTARBPROC);
|
||||
RESOLVE_DECL(PFNWGLCREATEPBUFFERARBPROC);
|
||||
RESOLVE_DECL(PFNWGLGETPBUFFERDCARBPROC);
|
||||
RESOLVE_DECL(PFNWGLRELEASEPBUFFERDCARBPROC);
|
||||
RESOLVE_DECL(PFNWGLDESTROYPBUFFERARBPROC);
|
||||
|
||||
void wglResolveExtensionProcs(void)
|
||||
{
|
||||
PRERESOLVE(PFNWGLGETEXTENSIONSSTRINGARBPROC, "wglGetExtensionsStringARB");
|
||||
PRERESOLVE(PFNWGLCREATECONTEXTATTRIBSARBPROC, "wglCreateContextAttribsARB");
|
||||
PRERESOLVE(PFNWGLMAKECONTEXTCURRENTARBPROC, "wglMakeContextCurrentARB");
|
||||
PRERESOLVE(PFNWGLCREATEPBUFFERARBPROC, "wglCreatePbufferARB");
|
||||
PRERESOLVE(PFNWGLGETPBUFFERDCARBPROC, "wglGetPbufferDCARB");
|
||||
PRERESOLVE(PFNWGLRELEASEPBUFFERDCARBPROC, "wglReleasePbufferDCARB");
|
||||
PRERESOLVE(PFNWGLDESTROYPBUFFERARBPROC, "wglDestroyPbufferARB");
|
||||
}
|
||||
|
||||
const char *wglGetExtensionsStringARB(HDC hdc_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLGETEXTENSIONSSTRINGARBPROC, "");
|
||||
return RESOLVED_PROC(PFNWGLGETEXTENSIONSSTRINGARBPROC)(hdc_);
|
||||
}
|
||||
|
||||
HGLRC wglCreateContextAttribsARB(HDC hdc_, HGLRC hShareContext_,
|
||||
const int *attribList_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLCREATECONTEXTATTRIBSARBPROC, NULL);
|
||||
return RESOLVED_PROC(PFNWGLCREATECONTEXTATTRIBSARBPROC)(hdc_, hShareContext_, attribList_);
|
||||
}
|
||||
|
||||
BOOL wglMakeContextCurrentARB(HDC hDrawDC_, HDC hReadDC_, HGLRC hglrc_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLMAKECONTEXTCURRENTARBPROC, false);
|
||||
return RESOLVED_PROC(PFNWGLMAKECONTEXTCURRENTARBPROC)(hDrawDC_, hReadDC_, hglrc_);
|
||||
}
|
||||
|
||||
HPBUFFERARB wglCreatePbufferARB(HDC hDC_, int iPixelFormat_, int iWidth_,
|
||||
int iHeight_, const int *piAttribList_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLCREATEPBUFFERARBPROC, NULL);
|
||||
return RESOLVED_PROC(PFNWGLCREATEPBUFFERARBPROC)(hDC_, iPixelFormat_, iWidth_, iHeight_, piAttribList_);
|
||||
}
|
||||
|
||||
HDC wglGetPbufferDCARB(HPBUFFERARB hPbuffer_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLGETPBUFFERDCARBPROC, NULL);
|
||||
return RESOLVED_PROC(PFNWGLGETPBUFFERDCARBPROC)(hPbuffer_);
|
||||
}
|
||||
|
||||
int wglReleasePbufferDCARB(HPBUFFERARB hPbuffer_, HDC hDC_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLRELEASEPBUFFERDCARBPROC, 0)
|
||||
return RESOLVED_PROC(PFNWGLRELEASEPBUFFERDCARBPROC)(hPbuffer_, hDC_);
|
||||
}
|
||||
|
||||
BOOL wglDestroyPbufferARB(HPBUFFERARB hPbuffer_)
|
||||
{
|
||||
CHECK_RESOLVED(PFNWGLDESTROYPBUFFERARBPROC, false);
|
||||
return RESOLVED_PROC(PFNWGLDESTROYPBUFFERARBPROC)(hPbuffer_);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef wgl_h
|
||||
#define wgl_h
|
||||
|
||||
#include <X11/Xmd.h> // for BOOL
|
||||
#include <X11/Xwindows.h> // as this doesn't provide one
|
||||
#include <GL/gl.h>
|
||||
#include <GL/wglext.h>
|
||||
|
||||
void wglResolveExtensionProcs(void);
|
||||
|
||||
const char *wglGetExtensionsStringARB(HDC hdc_);
|
||||
HGLRC wglCreateContextAttribsARB(HDC hdc_, HGLRC hShareContext_,
|
||||
const int *attribList_);
|
||||
BOOL wglMakeContextCurrentARB(HDC hDrawDC_, HDC hReadDC_, HGLRC hglrc_);
|
||||
HPBUFFERARB wglCreatePbufferARB(HDC hDC_, int iPixelFormat_, int iWidth_,
|
||||
int iHeight_, const int *piAttribList_);
|
||||
HDC wglGetPbufferDCARB(HPBUFFERARB hPbuffer_);
|
||||
int wglReleasePbufferDCARB(HPBUFFERARB hPbuffer_, HDC hDC_);
|
||||
BOOL wglDestroyPbufferARB(HPBUFFERARB hPbuffer_);
|
||||
|
||||
#endif /* wgl_h */
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "windowsgl.h"
|
||||
#include "windowsgl_internal.h"
|
||||
#include "windowsdriconst.h"
|
||||
#include "wgl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Window drawable
|
||||
*/
|
||||
|
||||
static
|
||||
HDC window_getdc(windowsDrawable *d)
|
||||
{
|
||||
return GetDC(d->hWnd);
|
||||
}
|
||||
|
||||
static
|
||||
void window_releasedc(windowsDrawable *d, HDC dc)
|
||||
{
|
||||
ReleaseDC(d->hWnd, dc);
|
||||
}
|
||||
|
||||
static struct windowsdrawable_callbacks window_callbacks = {
|
||||
.type = WindowsDRIDrawableWindow,
|
||||
.getdc = window_getdc,
|
||||
.releasedc = window_releasedc
|
||||
};
|
||||
|
||||
/*
|
||||
* Pixmap drawable
|
||||
*/
|
||||
|
||||
static
|
||||
HDC pixmap_getdc(windowsDrawable *d)
|
||||
{
|
||||
return d->dibDC;
|
||||
}
|
||||
|
||||
static
|
||||
void pixmap_releasedc(windowsDrawable *d, HDC dc)
|
||||
{
|
||||
GdiFlush();
|
||||
}
|
||||
|
||||
static struct windowsdrawable_callbacks pixmap_callbacks = {
|
||||
.type = WindowsDRIDrawablePixmap,
|
||||
.getdc = pixmap_getdc,
|
||||
.releasedc = pixmap_releasedc
|
||||
};
|
||||
|
||||
/*
|
||||
* Pbuffer drawable
|
||||
*/
|
||||
|
||||
static
|
||||
HDC pbuffer_getdc(windowsDrawable *d)
|
||||
{
|
||||
return wglGetPbufferDCARB(d->hPbuffer);
|
||||
}
|
||||
|
||||
static
|
||||
void pbuffer_releasedc(windowsDrawable *d, HDC dc)
|
||||
{
|
||||
wglReleasePbufferDCARB(d->hPbuffer, dc);
|
||||
}
|
||||
|
||||
static struct windowsdrawable_callbacks pbuffer_callbacks = {
|
||||
.type = WindowsDRIDrawablePbuffer,
|
||||
.getdc = pbuffer_getdc,
|
||||
.releasedc = pbuffer_releasedc
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
windowsDrawable *
|
||||
windows_create_drawable(int type, void *handle)
|
||||
{
|
||||
windowsDrawable *d;
|
||||
|
||||
d = calloc(1, sizeof *d);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case WindowsDRIDrawableWindow:
|
||||
d->hWnd = handle;
|
||||
d->callbacks = &window_callbacks;
|
||||
break;
|
||||
|
||||
case WindowsDRIDrawablePixmap:
|
||||
{
|
||||
BITMAPINFOHEADER *pBmpHeader;
|
||||
void *pBits;
|
||||
|
||||
char name[MAX_PATH];
|
||||
|
||||
d->callbacks = &pixmap_callbacks;
|
||||
|
||||
// Access file mapping object by a name
|
||||
snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", (unsigned int)(uintptr_t)handle);
|
||||
d->hSection = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, name);
|
||||
if (!d->hSection)
|
||||
printf("OpenFileMapping failed %x\n", (int)GetLastError());
|
||||
|
||||
// Create a screen-compatible DC
|
||||
d->dibDC = CreateCompatibleDC(NULL);
|
||||
|
||||
// Map the shared memory section to access the BITMAPINFOHEADER
|
||||
pBmpHeader = (BITMAPINFOHEADER *)MapViewOfFile(d->hSection, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(BITMAPINFOHEADER));
|
||||
if (!pBmpHeader)
|
||||
printf("MapViewOfFile failed %x\n", (int)GetLastError());
|
||||
|
||||
// Create a DIB using the file mapping
|
||||
d->hDIB = CreateDIBSection(d->dibDC, (BITMAPINFO *) pBmpHeader,
|
||||
DIB_RGB_COLORS, &pBits, d->hSection,
|
||||
sizeof(BITMAPINFOHEADER));
|
||||
|
||||
// Done with the BITMAPINFOHEADER
|
||||
UnmapViewOfFile(pBmpHeader);
|
||||
|
||||
// Select the DIB into the DC
|
||||
d->hOldDIB = SelectObject(d->dibDC, d->hDIB);
|
||||
}
|
||||
break;
|
||||
|
||||
case WindowsDRIDrawablePbuffer:
|
||||
d->hPbuffer = handle;
|
||||
d->callbacks = &pbuffer_callbacks;
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
windows_destroy_drawable(windowsDrawable *drawable)
|
||||
{
|
||||
switch (drawable->callbacks->type)
|
||||
{
|
||||
case WindowsDRIDrawableWindow:
|
||||
break;
|
||||
|
||||
case WindowsDRIDrawablePixmap:
|
||||
{
|
||||
// Select the default DIB into the DC
|
||||
SelectObject(drawable->dibDC, drawable->hOldDIB);
|
||||
|
||||
// delete the screen-compatible DC
|
||||
DeleteDC(drawable->dibDC);
|
||||
|
||||
// Delete the DIB
|
||||
DeleteObject(drawable->hDIB);
|
||||
|
||||
// Close the file mapping object
|
||||
CloseHandle(drawable->hSection);
|
||||
}
|
||||
break;
|
||||
|
||||
case WindowsDRIDrawablePbuffer:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
free(drawable);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWSDRICONST_H
|
||||
#define WINDOWSDRICONST_H
|
||||
|
||||
/* Requests */
|
||||
#define X_WindowsDRIQueryVersion 0
|
||||
#define X_WindowsDRIQueryDirectRenderingCapable 1
|
||||
#define X_WindowsDRIQueryDrawable 9
|
||||
#define X_WindowsDRIFBConfigToPixelFormat 10
|
||||
|
||||
/* Events */
|
||||
#define WindowsDRINumberEvents 0
|
||||
|
||||
/* Errors */
|
||||
#define WindowsDRIClientNotLocal 0
|
||||
#define WindowsDRINumberErrors (WindowsDRIClientNotLocal + 1)
|
||||
|
||||
/* Kinds of Drawables */
|
||||
#define WindowsDRIDrawableWindow 0
|
||||
#define WindowsDRIDrawablePixmap 1
|
||||
#define WindowsDRIDrawablePbuffer 2
|
||||
|
||||
#endif /* WINDOWSDRICONST_H */
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WINDOWSDRISTR_H
|
||||
#define WINDOWSDRISTR_H
|
||||
|
||||
#include "windowsdriconst.h"
|
||||
|
||||
#define WINDOWSDRINAME "Windows-DRI"
|
||||
|
||||
#define WINDOWS_DRI_MAJOR_VERSION 1 /* current version numbers */
|
||||
#define WINDOWS_DRI_MINOR_VERSION 0
|
||||
#define WINDOWS_DRI_PATCH_VERSION 0
|
||||
|
||||
typedef struct _WindowsDRIQueryVersion
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRIQueryVersion */
|
||||
CARD16 length B16;
|
||||
} xWindowsDRIQueryVersionReq;
|
||||
#define sz_xWindowsDRIQueryVersionReq 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD16 majorVersion B16; /* major version of DRI protocol */
|
||||
CARD16 minorVersion B16; /* minor version of DRI protocol */
|
||||
CARD32 patchVersion B32; /* patch version of DRI protocol */
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xWindowsDRIQueryVersionReply;
|
||||
#define sz_xWindowsDRIQueryVersionReply 32
|
||||
|
||||
typedef struct _WindowsDRIQueryDirectRenderingCapable
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
} xWindowsDRIQueryDirectRenderingCapableReq;
|
||||
#define sz_xWindowsDRIQueryDirectRenderingCapableReq 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
BOOL isCapable;
|
||||
BOOL pad2;
|
||||
BOOL pad3;
|
||||
BOOL pad4;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad7 B32;
|
||||
CARD32 pad8 B32;
|
||||
CARD32 pad9 B32;
|
||||
} xWindowsDRIQueryDirectRenderingCapableReply;
|
||||
#define sz_xWindowsDRIQueryDirectRenderingCapableReply 32
|
||||
|
||||
typedef struct _WindowsDRINotify
|
||||
{
|
||||
BYTE type; /* always eventBase + event type */
|
||||
BYTE kind;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 time B32; /* time of change */
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xWindowsDRINotifyEvent;
|
||||
#define sz_xWindowsDRINotifyEvent 32
|
||||
|
||||
typedef struct _WindowsDRIQueryDrawable
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRIQueryDrawable */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 drawable B32;
|
||||
} xWindowsDRIQueryDrawableReq;
|
||||
#define sz_xWindowsDRIQueryDrawableReq 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 drawable_type B32;
|
||||
CARD32 handle B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xWindowsDRIQueryDrawableReply;
|
||||
#define sz_xWindowsDRIQueryDrawableReply 32
|
||||
|
||||
typedef struct _WindowsDRIFBConfigToPixelFormat
|
||||
{
|
||||
CARD8 reqType; /* always DRIReqCode */
|
||||
CARD8 driReqType; /* always X_DRIFBConfigToPixelFormat */
|
||||
CARD16 length B16;
|
||||
CARD32 screen B32;
|
||||
CARD32 fbConfigID B32;
|
||||
} xWindowsDRIFBConfigToPixelFormatReq;
|
||||
|
||||
#define sz_xWindowsDRIFBConfigToPixelFormatReq 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE type; /* X_Reply */
|
||||
BOOL pad1;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 pixelFormatIndex B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xWindowsDRIFBConfigToPixelFormatReply;
|
||||
#define sz_xWindowsDRIFBConfigToPixelFormatReply 32
|
||||
|
||||
#endif /* WINDOWSDRISTR_H */
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "windowsgl.h"
|
||||
#include "windowsgl_internal.h"
|
||||
|
||||
#include "glapi.h"
|
||||
#include "wgl.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
static struct _glapi_table *windows_api = NULL;
|
||||
|
||||
static void *
|
||||
windows_get_dl_handle(void)
|
||||
{
|
||||
static void *dl_handle = NULL;
|
||||
|
||||
if (!dl_handle)
|
||||
dl_handle = dlopen("cygnativeGLthunk.dll", RTLD_NOW);
|
||||
|
||||
return dl_handle;
|
||||
}
|
||||
|
||||
static void
|
||||
windows_glapi_create_table(void)
|
||||
{
|
||||
if (windows_api)
|
||||
return;
|
||||
|
||||
windows_api = _glapi_create_table_from_handle(windows_get_dl_handle(), "gl");
|
||||
assert(windows_api);
|
||||
}
|
||||
|
||||
static void windows_mesa_glapi_set_dispatch(void)
|
||||
{
|
||||
windows_glapi_create_table();
|
||||
_mesa_glapi_set_dispatch(windows_api);
|
||||
}
|
||||
|
||||
windowsContext *
|
||||
windows_create_context(int pxfi, windowsContext *shared)
|
||||
{
|
||||
windowsContext *gc;
|
||||
|
||||
gc = calloc(1, sizeof *gc);
|
||||
if (gc == NULL)
|
||||
return NULL;
|
||||
|
||||
// create a temporary, invisible window
|
||||
#define GL_TEMP_WINDOW_CLASS "glTempWndClass"
|
||||
{
|
||||
static wATOM glTempWndClass = 0;
|
||||
|
||||
if (glTempWndClass == 0) {
|
||||
WNDCLASSEX wc;
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = 0;
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = GL_TEMP_WINDOW_CLASS;
|
||||
wc.hIconSm = 0;
|
||||
RegisterClassEx(&wc);
|
||||
}
|
||||
}
|
||||
|
||||
HWND hwnd = CreateWindowExA(0,
|
||||
GL_TEMP_WINDOW_CLASS,
|
||||
"glWindow",
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
HDC hdc = GetDC(hwnd);
|
||||
|
||||
// We must set the windows pixel format before we can create a WGL context
|
||||
gc->pxfi = pxfi;
|
||||
SetPixelFormat(hdc, gc->pxfi, NULL);
|
||||
|
||||
gc->ctx = wglCreateContext(hdc);
|
||||
|
||||
if (shared && gc->ctx)
|
||||
wglShareLists(shared->ctx, gc->ctx);
|
||||
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
if (!gc->ctx)
|
||||
{
|
||||
free(gc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
windowsContext *
|
||||
windows_create_context_attribs(int pxfi, windowsContext *shared, const int *attribList)
|
||||
{
|
||||
windowsContext *gc;
|
||||
|
||||
gc = calloc(1, sizeof *gc);
|
||||
if (gc == NULL)
|
||||
return NULL;
|
||||
|
||||
// create a temporary, invisible window
|
||||
#define GL_TEMP_WINDOW_CLASS "glTempWndClass"
|
||||
{
|
||||
static wATOM glTempWndClass = 0;
|
||||
|
||||
if (glTempWndClass == 0) {
|
||||
WNDCLASSEX wc;
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = 0;
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = GL_TEMP_WINDOW_CLASS;
|
||||
wc.hIconSm = 0;
|
||||
RegisterClassEx(&wc);
|
||||
}
|
||||
}
|
||||
|
||||
HWND hwnd = CreateWindowExA(0,
|
||||
GL_TEMP_WINDOW_CLASS,
|
||||
"glWindow",
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
NULL, NULL, GetModuleHandle(NULL), NULL);
|
||||
HDC hdc = GetDC(hwnd);
|
||||
HGLRC shareContext = NULL;
|
||||
if (shared)
|
||||
shareContext = shared->ctx;
|
||||
|
||||
// We must set the windows pixel format before we can create a WGL context
|
||||
gc->pxfi = pxfi;
|
||||
SetPixelFormat(hdc, gc->pxfi, NULL);
|
||||
|
||||
gc->ctx = wglCreateContextAttribsARB(hdc, shareContext, attribList);
|
||||
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
if (!gc->ctx)
|
||||
{
|
||||
free(gc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
void
|
||||
windows_destroy_context(windowsContext *context)
|
||||
{
|
||||
wglDeleteContext(context->ctx);
|
||||
context->ctx = NULL;
|
||||
free(context);
|
||||
}
|
||||
|
||||
int windows_bind_context(windowsContext *context, windowsDrawable *draw, windowsDrawable *read)
|
||||
{
|
||||
HDC drawDc = draw->callbacks->getdc(draw);
|
||||
|
||||
if (!draw->pxfi)
|
||||
{
|
||||
SetPixelFormat(drawDc, context->pxfi, NULL);
|
||||
draw->pxfi = context->pxfi;
|
||||
}
|
||||
|
||||
if ((read != NULL) && (read != draw))
|
||||
{
|
||||
/*
|
||||
If there is a separate read drawable, create a separate read DC, and
|
||||
use the wglMakeContextCurrent extension to make the context current
|
||||
drawing to one DC and reading from the other
|
||||
|
||||
Should only occur when WGL_ARB_make_current_read extension is present
|
||||
*/
|
||||
HDC readDc = read->callbacks->getdc(read);
|
||||
|
||||
BOOL ret = wglMakeContextCurrentARB(drawDc, readDc, context->ctx);
|
||||
|
||||
read->callbacks->releasedc(read, readDc);
|
||||
|
||||
if (!ret) {
|
||||
printf("wglMakeContextCurrentARB error: %08x\n", (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, just use wglMakeCurrent */
|
||||
BOOL ret = wglMakeCurrent(drawDc, context->ctx);
|
||||
if (!ret) {
|
||||
printf("wglMakeCurrent error: %08x\n", (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
draw->callbacks->releasedc(draw, drawDc);
|
||||
|
||||
windows_mesa_glapi_set_dispatch();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void windows_unbind_context(windowsContext * context)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
windows_swap_buffers(windowsDrawable *draw)
|
||||
{
|
||||
HDC drawDc = GetDC(draw->hWnd);
|
||||
SwapBuffers(drawDc);
|
||||
ReleaseDC(draw->hWnd, drawDc);
|
||||
}
|
||||
|
||||
|
||||
typedef void (__stdcall * PFNGLADDSWAPHINTRECTWIN) (GLint x, GLint y,
|
||||
GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
static void
|
||||
glAddSwapHintRectWIN(GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
PFNGLADDSWAPHINTRECTWIN proc = (PFNGLADDSWAPHINTRECTWIN)wglGetProcAddress("glAddSwapHintRectWIN");
|
||||
if (proc)
|
||||
proc(x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
windows_copy_subbuffer(windowsDrawable *draw,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
glAddSwapHintRectWIN(x, y, width, height);
|
||||
windows_swap_buffers(draw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for calling a test function on an initial context
|
||||
*/
|
||||
static void
|
||||
windows_call_with_context(void (*proc)(HDC, void *), void *args)
|
||||
{
|
||||
// create window class
|
||||
#define WIN_GL_TEST_WINDOW_CLASS "GLTest"
|
||||
{
|
||||
static wATOM glTestWndClass = 0;
|
||||
|
||||
if (glTestWndClass == 0) {
|
||||
WNDCLASSEX wc;
|
||||
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = GetModuleHandle(NULL);
|
||||
wc.hIcon = 0;
|
||||
wc.hCursor = 0;
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS;
|
||||
wc.hIconSm = 0;
|
||||
glTestWndClass = RegisterClassEx(&wc);
|
||||
}
|
||||
}
|
||||
|
||||
// create an invisible window for a scratch DC
|
||||
HWND hwnd = CreateWindowExA(0,
|
||||
WIN_GL_TEST_WINDOW_CLASS,
|
||||
"GL Renderer Capabilities Test Window",
|
||||
0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL),
|
||||
NULL);
|
||||
if (hwnd) {
|
||||
HDC hdc = GetDC(hwnd);
|
||||
|
||||
// we must set a pixel format before we can create a context, just use the first one...
|
||||
SetPixelFormat(hdc, 1, NULL);
|
||||
HGLRC hglrc = wglCreateContext(hdc);
|
||||
wglMakeCurrent(hdc, hglrc);
|
||||
|
||||
// call the test function
|
||||
proc(hdc, args);
|
||||
|
||||
// clean up
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hglrc);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
windows_check_render_test(HDC hdc, void *args)
|
||||
{
|
||||
int *result = (int *)args;
|
||||
|
||||
/* Rather than play linkage games using stdcall to ensure we get
|
||||
glGetString from opengl32.dll here, use dlsym */
|
||||
void *dlhandle = windows_get_dl_handle();
|
||||
const char *(*proc)(int) = dlsym(dlhandle, "glGetString");
|
||||
const char *gl_renderer = (const char *)proc(GL_RENDERER);
|
||||
|
||||
if ((!gl_renderer) || (strcasecmp(gl_renderer, "GDI Generic") == 0))
|
||||
*result = false;
|
||||
else
|
||||
*result = true;
|
||||
}
|
||||
|
||||
int
|
||||
windows_check_renderer(void)
|
||||
{
|
||||
int result;
|
||||
windows_call_with_context(windows_check_render_test, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char *gl_extensions;
|
||||
char *wgl_extensions;
|
||||
} windows_extensions_result;
|
||||
|
||||
static void
|
||||
windows_extensions_test(HDC hdc, void *args)
|
||||
{
|
||||
windows_extensions_result *r = (windows_extensions_result *)args;
|
||||
|
||||
void *dlhandle = windows_get_dl_handle();
|
||||
const char *(*proc)(int) = dlsym(dlhandle, "glGetString");
|
||||
|
||||
r->gl_extensions = strdup(proc(GL_EXTENSIONS));
|
||||
|
||||
wglResolveExtensionProcs();
|
||||
r->wgl_extensions = strdup(wglGetExtensionsStringARB(hdc));
|
||||
}
|
||||
|
||||
void
|
||||
windows_extensions(char **gl_extensions, char **wgl_extensions)
|
||||
{
|
||||
windows_extensions_result result;
|
||||
|
||||
*gl_extensions = "";
|
||||
*wgl_extensions = "";
|
||||
|
||||
windows_call_with_context(windows_extensions_test, &result);
|
||||
|
||||
*gl_extensions = result.gl_extensions;
|
||||
*wgl_extensions = result.wgl_extensions;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef windowsgl_h
|
||||
#define windowsgh_h
|
||||
|
||||
struct _windowsContext;
|
||||
struct _windowsDrawable;
|
||||
|
||||
typedef struct _windowsContext windowsContext;
|
||||
typedef struct _windowsDrawable windowsDrawable;
|
||||
|
||||
windowsContext *windows_create_context(int pxfi, windowsContext *shared);
|
||||
windowsContext *windows_create_context_attribs(int pxfi, windowsContext *shared, const int *attribList);
|
||||
void windows_destroy_context(windowsContext *contex);
|
||||
int windows_bind_context(windowsContext *context, windowsDrawable *, windowsDrawable *);
|
||||
void windows_unbind_context(windowsContext *context);
|
||||
|
||||
windowsDrawable *windows_create_drawable(int type, void *handle);
|
||||
void windows_destroy_drawable(windowsDrawable *);
|
||||
void windows_swap_buffers(windowsDrawable *);
|
||||
void windows_copy_subbuffer(windowsDrawable *windowsDrawable, int x, int y, int width, int height);
|
||||
|
||||
int windows_check_renderer(void);
|
||||
void windows_extensions(char **gl_extensions, char **wgl_extensions);
|
||||
|
||||
#endif /* windowsgl_h */
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef windowsgl_internal_h
|
||||
#define windowsgl_internal_h
|
||||
|
||||
#include "windowsgl.h"
|
||||
|
||||
#include <X11/Xmd.h> // for BOOL
|
||||
#include <X11/Xwindows.h> // as this doesn't provide one
|
||||
#include <GL/gl.h>
|
||||
#include <GL/wglext.h>
|
||||
|
||||
struct _windowsContext
|
||||
{
|
||||
struct glx_config *config;
|
||||
windowsContext *shareContext;
|
||||
HGLRC ctx;
|
||||
int pxfi;
|
||||
};
|
||||
|
||||
struct windowsdrawable_callbacks
|
||||
{
|
||||
int type; // WINDOW, PIXMAP, PBUFFER
|
||||
HDC (*getdc) (windowsDrawable *d);
|
||||
void (*releasedc) (windowsDrawable *d, HDC dc);
|
||||
};
|
||||
|
||||
struct _windowsDrawable
|
||||
{
|
||||
int pxfi; // 0 if not yet set
|
||||
struct windowsdrawable_callbacks *callbacks;
|
||||
|
||||
// for type WINDOW
|
||||
HWND hWnd;
|
||||
|
||||
// for type PIXMAP
|
||||
HANDLE hSection;
|
||||
HDC dibDC;
|
||||
HBITMAP hDIB;
|
||||
HBITMAP hOldDIB;
|
||||
|
||||
// for type PBUFFER
|
||||
HPBUFFERARB hPbuffer;
|
||||
};
|
||||
|
||||
#endif /* windowsgl_internal_h */
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* THIS IS NOT AN X CONSORTIUM STANDARD */
|
||||
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/extensions/Xext.h>
|
||||
#include <X11/extensions/extutil.h>
|
||||
#include "windowsdristr.h"
|
||||
#include "xwindowsdri.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static XExtensionInfo _windowsdri_info_data;
|
||||
static XExtensionInfo *windowsdri_info = &_windowsdri_info_data;
|
||||
static char *windowsdri_extension_name = WINDOWSDRINAME;
|
||||
|
||||
#define WindowsDRICheckExtension(dpy,i,val) \
|
||||
XextCheckExtension (dpy, i, windowsdri_extension_name, val)
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* private utility routines *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
static int close_display(Display * dpy, XExtCodes * extCodes);
|
||||
|
||||
static /* const */ XExtensionHooks windowsdri_extension_hooks = {
|
||||
NULL, /* create_gc */
|
||||
NULL, /* copy_gc */
|
||||
NULL, /* flush_gc */
|
||||
NULL, /* free_gc */
|
||||
NULL, /* create_font */
|
||||
NULL, /* free_font */
|
||||
close_display, /* close_display */
|
||||
NULL, /* wire_to_event */
|
||||
NULL, /* event_to_wire */
|
||||
NULL, /* error */
|
||||
NULL, /* error_string */
|
||||
};
|
||||
|
||||
static
|
||||
XEXT_GENERATE_FIND_DISPLAY(find_display, windowsdri_info,
|
||||
windowsdri_extension_name,
|
||||
&windowsdri_extension_hooks,
|
||||
WindowsDRINumberEvents, NULL)
|
||||
|
||||
static
|
||||
XEXT_GENERATE_CLOSE_DISPLAY(close_display, windowsdri_info)
|
||||
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* public Windows-DRI Extension routines *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define TRACE(msg, ...) fprintf(stderr, "WindowsDRI" msg "\n", ##__VA_ARGS__);
|
||||
#else
|
||||
#define TRACE(msg, ...)
|
||||
#endif
|
||||
|
||||
Bool
|
||||
XWindowsDRIQueryExtension(dpy, event_basep, error_basep)
|
||||
Display *dpy;
|
||||
int *event_basep, *error_basep;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
|
||||
TRACE("QueryExtension:");
|
||||
if (XextHasExtension(info)) {
|
||||
*event_basep = info->codes->first_event;
|
||||
*error_basep = info->codes->first_error;
|
||||
TRACE("QueryExtension: return True");
|
||||
return True;
|
||||
}
|
||||
else {
|
||||
TRACE("QueryExtension: return False");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
XWindowsDRIQueryVersion(dpy, majorVersion, minorVersion, patchVersion)
|
||||
Display *dpy;
|
||||
int *majorVersion;
|
||||
int *minorVersion;
|
||||
int *patchVersion;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xWindowsDRIQueryVersionReply rep;
|
||||
xWindowsDRIQueryVersionReq *req;
|
||||
|
||||
TRACE("QueryVersion:");
|
||||
WindowsDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(WindowsDRIQueryVersion, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_WindowsDRIQueryVersion;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryVersion: return False");
|
||||
return False;
|
||||
}
|
||||
*majorVersion = rep.majorVersion;
|
||||
*minorVersion = rep.minorVersion;
|
||||
*patchVersion = rep.patchVersion;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryVersion: %d.%d.%d", *majorVersion, *minorVersion, *patchVersion);
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XWindowsDRIQueryDirectRenderingCapable(dpy, screen, isCapable)
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Bool *isCapable;
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xWindowsDRIQueryDirectRenderingCapableReply rep;
|
||||
xWindowsDRIQueryDirectRenderingCapableReq *req;
|
||||
|
||||
TRACE("QueryDirectRenderingCapable:");
|
||||
WindowsDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(WindowsDRIQueryDirectRenderingCapable, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_WindowsDRIQueryDirectRenderingCapable;
|
||||
req->screen = screen;
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDirectRenderingCapable: return False");
|
||||
return False;
|
||||
}
|
||||
*isCapable = rep.isCapable;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDirectRenderingCapable:return True");
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XWindowsDRIQueryDrawable(Display *dpy, int screen, Drawable drawable,
|
||||
unsigned int * type, void ** handle)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xWindowsDRIQueryDrawableReply rep;
|
||||
xWindowsDRIQueryDrawableReq *req;
|
||||
|
||||
TRACE("QueryDrawable: XID %lx", drawable);
|
||||
WindowsDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(WindowsDRIQueryDrawable, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_WindowsDRIQueryDrawable;
|
||||
req->screen = screen;
|
||||
req->drawable = drawable;
|
||||
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDrawable: return False");
|
||||
return False;
|
||||
}
|
||||
|
||||
*type = rep.drawable_type;
|
||||
|
||||
// Note that despite being a derived type of void *, HANDLEs are defined to
|
||||
// be a sign-extended 32 bit value (so they can be passed to 32-bit
|
||||
// processes safely)
|
||||
*handle = (void *)(intptr_t)rep.handle;
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("QueryDrawable: type %d, handle %p", *type, *handle);
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool
|
||||
XWindowsDRIFBConfigToPixelFormat(Display *dpy, int screen, int fbConfigID,
|
||||
int *pxfi)
|
||||
{
|
||||
XExtDisplayInfo *info = find_display(dpy);
|
||||
xWindowsDRIFBConfigToPixelFormatReply rep;
|
||||
xWindowsDRIFBConfigToPixelFormatReq *req;
|
||||
|
||||
TRACE("FBConfigToPixelFormat: fbConfigID 0x%x", fbConfigID);
|
||||
WindowsDRICheckExtension(dpy, info, False);
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(WindowsDRIFBConfigToPixelFormat, req);
|
||||
req->reqType = info->codes->major_opcode;
|
||||
req->driReqType = X_WindowsDRIFBConfigToPixelFormat;
|
||||
req->screen = screen;
|
||||
req->fbConfigID = fbConfigID;
|
||||
|
||||
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("FBConfigToPixelFormat: return False");
|
||||
return False;
|
||||
}
|
||||
|
||||
*pxfi = rep.pixelFormatIndex;
|
||||
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
TRACE("FBConfigToPixelFormat: pixelformatindex %d", *pxfi);
|
||||
return True;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright © 2014 Jon Turney
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef XWINDOWSDRI_H
|
||||
#define XWINDOWSDRI_H
|
||||
|
||||
#include <X11/Xfuncproto.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type; /* of event */
|
||||
unsigned long serial; /* # of last request processed by server */
|
||||
Bool send_event; /* true if this came from a SendEvent request */
|
||||
Display *display; /* Display the event was read from */
|
||||
Window window; /* window of event */
|
||||
Time time; /* server timestamp when event happened */
|
||||
int kind; /* subtype of event */
|
||||
int arg;
|
||||
} XWindowsDRINotifyEvent;
|
||||
|
||||
_XFUNCPROTOBEGIN
|
||||
Bool XWindowsDRIQueryExtension(Display * dpy, int *event_base,
|
||||
int *error_base);
|
||||
|
||||
Bool XWindowsDRIQueryVersion(Display * dpy, int *majorVersion,
|
||||
int *minorVersion, int *patchVersion);
|
||||
|
||||
Bool XWindowsDRIQueryDirectRenderingCapable(Display * dpy, int screen,
|
||||
Bool *isCapable);
|
||||
|
||||
Bool XWindowsDRIQueryDrawable(Display * dpy, int screen, Drawable drawable,
|
||||
unsigned int *type, void ** handle);
|
||||
|
||||
Bool XWindowsDRIFBConfigToPixelFormat(Display *dpy, int screen, int fbConfigID,
|
||||
int *pxfi);
|
||||
_XFUNCPROTOEND
|
||||
|
||||
#endif /* XWINDOWSDRI_H */
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 1999 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* xfonts.c -- glXUseXFont() for Mesa written by
|
||||
* Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
|
||||
*/
|
||||
|
||||
/*
|
||||
This was take from Mesa and modified to work in the real GLX structure.
|
||||
It provides a fully client side implementation of glXUseXFont and is
|
||||
called by that routine when direct rendering is enabled.
|
||||
*/
|
||||
|
||||
#ifdef GLX_DIRECT_RENDERING
|
||||
|
||||
#include "glxclient.h"
|
||||
#include "mesa/glapi/glapi/glapi.h"
|
||||
#include "dispatch.h"
|
||||
|
||||
/* Implementation. */
|
||||
|
||||
/* Fill a BITMAP with a character C from thew current font
|
||||
in the graphics context GC. WIDTH is the width in bytes
|
||||
and HEIGHT is the height in bits.
|
||||
|
||||
Note that the generated bitmaps must be used with
|
||||
|
||||
glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
Possible optimizations:
|
||||
|
||||
* use only one reusable pixmap with the maximum dimensions.
|
||||
* draw the entire font into a single pixmap (careful with
|
||||
proportional fonts!).
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Generate OpenGL-compatible bitmap.
|
||||
*/
|
||||
static void
|
||||
fill_bitmap(Display * dpy, int screen, GC gc,
|
||||
unsigned int width, unsigned int height,
|
||||
int x0, int y0, unsigned int c, GLubyte * bitmap)
|
||||
{
|
||||
XImage *image;
|
||||
unsigned int x, y;
|
||||
Pixmap pixmap;
|
||||
XChar2b char2b;
|
||||
|
||||
pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen), 8 * width, height, 1);
|
||||
XSetForeground(dpy, gc, 0);
|
||||
XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
|
||||
XSetForeground(dpy, gc, 1);
|
||||
|
||||
char2b.byte1 = (c >> 8) & 0xff;
|
||||
char2b.byte2 = (c & 0xff);
|
||||
|
||||
XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
|
||||
|
||||
image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
|
||||
if (image) {
|
||||
/* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < 8 * width; x++)
|
||||
if (XGetPixel(image, x, y))
|
||||
bitmap[width * (height - y - 1) + x / 8] |=
|
||||
(1 << (7 - (x % 8)));
|
||||
XDestroyImage(image);
|
||||
}
|
||||
|
||||
XFreePixmap(dpy, pixmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* determine if a given glyph is valid and return the
|
||||
* corresponding XCharStruct.
|
||||
*/
|
||||
static XCharStruct *
|
||||
isvalid(XFontStruct * fs, int which)
|
||||
{
|
||||
unsigned int rows, pages;
|
||||
int byte1 = 0, byte2 = 0;
|
||||
int i, valid = 1;
|
||||
|
||||
rows = fs->max_byte1 - fs->min_byte1 + 1;
|
||||
pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
|
||||
|
||||
if (rows == 1) {
|
||||
/* "linear" fonts */
|
||||
if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
|
||||
valid = 0;
|
||||
}
|
||||
else {
|
||||
/* "matrix" fonts */
|
||||
byte2 = which & 0xff;
|
||||
byte1 = which >> 8;
|
||||
if ((fs->min_char_or_byte2 > byte2) ||
|
||||
(fs->max_char_or_byte2 < byte2) ||
|
||||
(fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (fs->per_char) {
|
||||
if (rows == 1) {
|
||||
/* "linear" fonts */
|
||||
return (fs->per_char + (which - fs->min_char_or_byte2));
|
||||
}
|
||||
else {
|
||||
/* "matrix" fonts */
|
||||
i = ((byte1 - fs->min_byte1) * pages) +
|
||||
(byte2 - fs->min_char_or_byte2);
|
||||
return (fs->per_char + i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return (&fs->min_bounds);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
DRI_glXUseXFont(struct glx_context *CC, Font font, int first, int count, int listbase)
|
||||
{
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Pixmap pixmap;
|
||||
GC gc;
|
||||
XGCValues values;
|
||||
unsigned long valuemask;
|
||||
XFontStruct *fs;
|
||||
|
||||
GLint swapbytes, lsbfirst, rowlength;
|
||||
GLint skiprows, skippixels, alignment;
|
||||
|
||||
unsigned int max_width, max_height, max_bm_width, max_bm_height;
|
||||
GLubyte *bm;
|
||||
|
||||
int i;
|
||||
|
||||
dpy = CC->currentDpy;
|
||||
screen = CC->psc->scr;
|
||||
|
||||
fs = XQueryFont(dpy, font);
|
||||
if (!fs) {
|
||||
__glXSetError(CC, GL_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate a bitmap that can fit all characters. */
|
||||
max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
|
||||
max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
|
||||
max_bm_width = (max_width + 7) / 8;
|
||||
max_bm_height = max_height;
|
||||
|
||||
bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte));
|
||||
if (!bm) {
|
||||
XFreeFontInfo(NULL, fs, 1);
|
||||
__glXSetError(CC, GL_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* get the page info */
|
||||
pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
|
||||
firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
|
||||
lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
|
||||
rows = fs->max_byte1 - fs->min_byte1 + 1;
|
||||
unsigned int first_char, last_char, pages, rows;
|
||||
#endif
|
||||
|
||||
/* Save the current packing mode for bitmaps. */
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, &swapbytes));
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, &lsbfirst));
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, &rowlength));
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, &skiprows));
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, &skippixels));
|
||||
CALL_GetIntegerv(GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, &alignment));
|
||||
|
||||
/* Enforce a standard packing mode which is compatible with
|
||||
fill_bitmap() from above. This is actually the default mode,
|
||||
except for the (non)alignment. */
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, GL_FALSE));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, GL_FALSE));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, 0));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, 1));
|
||||
|
||||
pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen), 10, 10, 1);
|
||||
values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
|
||||
values.background = WhitePixel(dpy, DefaultScreen(dpy));
|
||||
values.font = fs->fid;
|
||||
valuemask = GCForeground | GCBackground | GCFont;
|
||||
gc = XCreateGC(dpy, pixmap, valuemask, &values);
|
||||
XFreePixmap(dpy, pixmap);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int width, height, bm_width, bm_height;
|
||||
GLfloat x0, y0, dx, dy;
|
||||
XCharStruct *ch;
|
||||
int x, y;
|
||||
unsigned int c = first + i;
|
||||
int list = listbase + i;
|
||||
int valid;
|
||||
|
||||
/* check on index validity and get the bounds */
|
||||
ch = isvalid(fs, c);
|
||||
if (!ch) {
|
||||
ch = &fs->max_bounds;
|
||||
valid = 0;
|
||||
}
|
||||
else {
|
||||
valid = 1;
|
||||
}
|
||||
|
||||
/* glBitmap()' parameters:
|
||||
straight from the glXUseXFont(3) manpage. */
|
||||
width = ch->rbearing - ch->lbearing;
|
||||
height = ch->ascent + ch->descent;
|
||||
x0 = -ch->lbearing;
|
||||
y0 = ch->descent - 1;
|
||||
dx = ch->width;
|
||||
dy = 0;
|
||||
|
||||
/* X11's starting point. */
|
||||
x = -ch->lbearing;
|
||||
y = ch->ascent;
|
||||
|
||||
/* Round the width to a multiple of eight. We will use this also
|
||||
for the pixmap for capturing the X11 font. This is slightly
|
||||
inefficient, but it makes the OpenGL part real easy. */
|
||||
bm_width = (width + 7) / 8;
|
||||
bm_height = height;
|
||||
|
||||
CALL_NewList(GET_DISPATCH(), (list, GL_COMPILE));
|
||||
if (valid && (bm_width > 0) && (bm_height > 0)) {
|
||||
|
||||
memset(bm, '\0', bm_width * bm_height);
|
||||
fill_bitmap(dpy, screen, gc, bm_width, bm_height, x, y, c, bm);
|
||||
|
||||
CALL_Bitmap(GET_DISPATCH(), (width, height, x0, y0, dx, dy, bm));
|
||||
}
|
||||
else {
|
||||
CALL_Bitmap(GET_DISPATCH(), (0, 0, 0.0, 0.0, dx, dy, NULL));
|
||||
}
|
||||
CALL_EndList(GET_DISPATCH(), ());
|
||||
}
|
||||
|
||||
free(bm);
|
||||
XFreeFontInfo(NULL, fs, 1);
|
||||
XFreeGC(dpy, gc);
|
||||
|
||||
/* Restore saved packing modes. */
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, swapbytes));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, lsbfirst));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, rowlength));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, skiprows));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, skippixels));
|
||||
CALL_PixelStorei(GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, alignment));
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user