This commit is contained in:
elwrcl committed 2026-06-06 13:25:15 +03:00
1 parent 04d4dc8b09
commit 818cab85dc
12511 files changed
+6156641

No files matched your search

+71
View File
@@ -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).
+26
View File
@@ -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.
+128
View File
@@ -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;
}
+87
View File
@@ -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
+79
View File
@@ -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));
}
+146
View File
@@ -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);
}
+51
View File
@@ -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
+618
View File
@@ -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;
}
+93
View File
@@ -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 */
+553
View File
@@ -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;
}
+227
View File
@@ -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
+119
View File
@@ -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);
}
+57
View File
@@ -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
+346
View File
@@ -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;
}
+229
View File
@@ -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);
}
+225
View File
@@ -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);
}
}
}
+198
View File
@@ -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();
}
}
+41
View File
@@ -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
+40
View File
@@ -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
+121
View File
@@ -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);
}
+125
View File
@@ -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));
}
}
+48
View File
@@ -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));
}
+450
View File
@@ -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;
}
+124
View File
@@ -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_ */
+266
View File
@@ -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_ */
+231
View File
@@ -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
+44
View File
@@ -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,
)
+197
View File
@@ -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
+108
View File
@@ -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
+200
View File
@@ -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);
}
+170
View File
@@ -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;
}
+198
View File
@@ -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;
}
+584
View File
@@ -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 */
+96
View File
@@ -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;
};
+1005
View File
File diff suppressed because it is too large. Load diff
+118
View File
@@ -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 */
+108
View File
@@ -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 */
+688
View File
@@ -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 */
+55
View File
@@ -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
+520
View File
@@ -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
View File
@@ -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
+97
View File
@@ -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__
+4
View File
@@ -0,0 +1,4 @@
__glx_Main
MesaGLInteropGLXExportObject
MesaGLInteropGLXFlushObjects
MesaGLInteropGLXQueryDeviceInfo
+84
View File
@@ -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);
}
+53
View File
@@ -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
+92
View File
@@ -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;
}
+803
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+301
View File
@@ -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;
}
+118
View File
@@ -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 */
+194
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+766
View File
@@ -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);
}
+296
View File
@@ -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 */
+82
View File
@@ -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;
}
+14
View File
@@ -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
+70
View File
@@ -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__
+473
View File
@@ -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
+20
View File
@@ -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_ */
+378
View File
@@ -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
+49
View File
@@ -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_ */
+343
View File
@@ -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);
}
}
+85
View File
@@ -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
+64
View File
@@ -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 */
+305
View File
@@ -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_ */
+293
View File
@@ -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();
}
+112
View File
@@ -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
+162
View File
@@ -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
+180
View File
@@ -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__ */
+129
View File
@@ -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
View File
@@ -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;
}
}
}
+330
View File
@@ -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, &param);
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, &param);
break;
default:
__glXSetError(gc, GL_INVALID_ENUM);
break;
}
}
+173
View File
@@ -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);
}
+362
View File
@@ -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
+89
View File
@@ -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);
}
+843
View File
@@ -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;
}
+192
View File
@@ -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
+51
View File
@@ -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,
)
+109
View File
@@ -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_);
}
+44
View File
@@ -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 */
+193
View File
@@ -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);
}
+45
View File
@@ -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 */
+152
View File
@@ -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 */
+391
View File
@@ -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;
}
+47
View File
@@ -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 */
+67
View File
@@ -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 */
+237
View File
@@ -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;
}
+59
View File
@@ -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
View File
@@ -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