MAGIC_MACRO(glXGetScreenDriver),
MAGIC_MACRO(glXGetDriverConfig),
MAGIC_MACRO(glXSwapIntervalSGI),
+MAGIC_MACRO(glXCreatePixmap),
+MAGIC_MACRO(glXDestroyPixmap),
MAGIC_MACRO(glGetString),
MAGIC_MACRO(glGenTextures_fake),
MAGIC_MACRO(glGenBuffersARB_fake),
MAGIC_MACRO(glGenLists_fake),
+MAGIC_MACRO(glEGLImageTargetTexture2DOES_fake),
MAGIC_MACRO(_glDrawElements_buffer),
MAGIC_MACRO(_glDrawRangeElements_buffer),
MAGIC_MACRO(_glMultiDrawElements_buffer),
/* OS-independent glXQueryExtensionsString */
extern const char *glo_glXQueryExtensionsString(void);
+/* Create a light-weight context just for creating surface */
+extern GloContext *__glo_context_create(int formatFlags);
+
/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
extern GloContext *glo_context_create(int formatFlags, GloContext *shareLists);
/* Destroy a previouslu created OpenGL context */
extern void glo_context_destroy(GloContext *context);
+/* Update the context in surface and free previous light-weight context */
+extern void glo_surface_update_context(GloSurface *surface, GloContext *context);
+
+/* Link the pixmap associated with surface as texture */
+extern void glo_surface_as_texture(GloSurface *surface);
+
/* Create a surface with given width and height, */
extern GloSurface *glo_surface_create(int width, int height, GloContext *context);
/* ------------------------------------------------------------------------ */
-/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
-GloContext *glo_context_create(int formatFlags, GloContext *shareLists) {
- if (!glo_inited)
- glo_init();
+/* Create a light-weight context just for creating surface */
+GloContext *__glo_context_create(int formatFlags) {
GLXFBConfig *fbConfigs;
int numReturned;
context->formatFlags = formatFlags;
context->fbConfig = fbConfigs[0];
+ return context;
+}
+
+/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
+GloContext *glo_context_create(int formatFlags, GloContext *shareLists) {
+
+ GloContext *context = __glo_context_create(formatFlags);
+
/* Create a GLX context for OpenGL rendering */
context->context = glXCreateNewContext(glo.dpy, context->fbConfig,
GLX_RGBA_TYPE,
/* ------------------------------------------------------------------------ */
+/* Update the context in surface and free previous light-weight context */
+void glo_surface_update_context(GloSurface *surface, GloContext *context)
+{
+ if ( surface->context )
+ qemu_free(surface->context);
+ surface->context = context;
+}
+
/* Create a surface with given width and height, formatflags are from the
* GLO_ constants */
GloSurface *glo_surface_create(int width, int height, GloContext *context) {
printf("GL VENDOR %s\n", glGetString(GL_VENDOR));
printf("GL RENDERER %s\n", glGetString(GL_RENDERER));
printf("GL VERSION %s\n", glGetString(GL_VERSION));
+ printf("GLSL VERSION %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
if (strstr (glGetString(GL_RENDERER), "Software")) {
printf ("Host does not have GL hardware acceleration!\n");
Pixmap pixmap;
XImage *image;
XShmSegmentInfo shminfo;
+ GLXPixmap glxPixmap;
};
extern void glo_surface_getcontents_readpixels(int formatFlags, int stride,
/* ------------------------------------------------------------------------ */
-/* Create an OpenGL context for a certain pixel format.
- formatflags are from the GLO_ constants */
-
-GloContext *glo_context_create(int formatFlags, GloContext *shareLists) {
- if (!glo_inited)
- glo_init();
+/* Create a light-weight context just for creating surface */
+GloContext *__glo_context_create(int formatFlags) {
GLXFBConfig *fbConfigs;
int numReturned;
context->formatFlags = formatFlags;
context->fbConfig = fbConfigs[0];
+ return context;
+}
+
+/* Create an OpenGL context for a certain pixel format.
+ formatflags are from the GLO_ constants */
+
+GloContext *glo_context_create(int formatFlags, GloContext *shareLists) {
+
+ GloContext *context = __glo_context_create(formatFlags);
+
/* Create a GLX context for OpenGL rendering */
context->context = glXCreateNewContext(glo.dpy, context->fbConfig,
GLX_RGBA_TYPE,
/* ------------------------------------------------------------------------ */
+/* Update the context in surface and free previous light-weight context */
+void glo_surface_update_context(GloSurface *surface, GloContext *context)
+{
+ if ( surface->context )
+ g_free(surface->context);
+ surface->context = context;
+}
+
/* Create a surface with given width and height, formatflags are from the
* GLO_ constants */
GloSurface *glo_surface_create(int width, int height, GloContext *context) {
return NULL;
}
+ /* Create a GLX pixmap to associate the frame buffer configuration with the
+ * created X window */
+ /*XXX: need attribute_list? */
+ surface->glxPixmap = glXCreatePixmap( glo.dpy, context->fbConfig, surface->pixmap, NULL );
+ if (!surface->glxPixmap) {
+ printf( "glXCreatePixmap failed\n" );
+ //exit( EXIT_FAILURE );
+ return NULL;
+ }
+
XSync(glo.dpy, 0);
/* set hints and properties */
*height = surface->height;
}
+/* Bind the surface as texture */
+void glo_surface_as_texture(GloSurface *surface)
+{
+ void (*ptr_func_glXBindTexImageEXT) (Display *dpy, GLXDrawable draw, int buffer, int *attrib_list);
+ ptr_func_glXBindTexImageEXT =
+ (void(*)(Display*, GLXDrawable, int, int*))glo_getprocaddress((const char*)"glXBindTexImageEXT");
+
+ /*XXX: When to call the glXReleaseTexImageEXT?*/
+ if (!ptr_func_glXBindTexImageEXT)
+ {
+ fprintf (stderr, "glXBindTexImageEXT not supported! Can't emulate glEGLImageTargetTexture2DOES!\n");
+ }
+
+ ptr_func_glXBindTexImageEXT(glo.dpy, surface->glxPixmap, GLX_FRONT_LEFT_EXT, NULL);
+}
+
/* Abstract glXQueryExtensionString() */
const char *glo_glXQueryExtensionsString(void) {
return glXQueryExtensionsString(glo.dpy, 0);
#define MAX_FBCONFIG 10
+#define MAX_PENDING_QSURFACE 8
+#define MAX_PENDING_DRAWABLE 8
+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define DIM(X) (sizeof(X) / sizeof(X[0]))
GLState **glstates;
GLState *current_state;
+ /* Pending drawables that will be used as texture */
+ ClientGLXDrawable pending_drawables[MAX_PENDING_DRAWABLE];
+
+ /* Created Pixmap surfaces, will link to context in MakeCurrent */
+ QGloSurface *pending_qsurfaces[MAX_PENDING_QSURFACE];
+
int nfbconfig;
const GLXFBConfig *fbconfigs[MAX_FBCONFIG];
int fbconfigs_max[MAX_FBCONFIG];
state->current_qsurface = qsurface;
}
+/* Find the qsurface with required drawable in active & pending qsurfaces */
+QGloSurface* find_qsurface_from_client_drawable(ProcessState *process, ClientGLXDrawable client_drawable)
+{
+ /* search for surfaces in current conetxt */
+ int i;
+ QGloSurface *qsurface = get_qsurface_from_client_drawable(process->current_state, client_drawable);
+
+ if (qsurface)
+ return qsurface;
+
+ /* search the pending surfaces */
+ for ( i = 0; i < MAX_PENDING_QSURFACE; i++ )
+ {
+ qsurface = process->pending_qsurfaces[i];
+ if ( qsurface && qsurface->client_drawable == client_drawable )
+ return qsurface;
+ }
+
+ return NULL;
+}
+
/* Make the appropriate qsurface current for a given client_drawable */
static int set_current_qsurface(GLState *state,
ClientGLXDrawable client_drawable)
return 0;
}
+/* */
+static int keep_drawable(ProcessState *process, ClientGLXDrawable drawable)
+{
+ int i;
+ for ( i = 0; i < MAX_PENDING_DRAWABLE; i++)
+ {
+ if ( process->pending_drawables[i] == 0 )
+ {
+ process->pending_drawables[i] = drawable;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int link_drawable(ProcessState *process, ClientGLXDrawable drawable)
+{
+ int i;
+ for ( i = 0; i < MAX_PENDING_DRAWABLE; i++ )
+ {
+ if ( process->pending_drawables[i] == drawable )
+ {
+ process->pending_drawables[i] = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Need to create pixmap surface when guest do so, as guest may use it before
+ * MakeCurrent. As no context available at this point, we do the follwoing:
+ * 1. Create one light-weight context just for surface creation.
+ * 2. Store this qsurface, and link it with right context when MakeCurrent
+ */
+static int keep_qsurface(ProcessState *process, QGloSurface *qsurface)
+{
+ int i;
+ for ( i = 0; i < MAX_PENDING_QSURFACE; i++)
+ {
+ if ( process->pending_qsurfaces[i] == NULL )
+ {
+ process->pending_qsurfaces[i] = qsurface;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawable client_drawable)
+{
+ int i;
+ QGloSurface *qsurface;
+ for ( i = 0; i < MAX_PENDING_QSURFACE; i++ )
+ {
+ qsurface = process->pending_qsurfaces[i];
+ if ( qsurface && qsurface->client_drawable == client_drawable )
+ {
+ process->pending_qsurfaces[i] = NULL;
+ qsurface->ref = 1;
+/* qsurface->surface->context = glstate->context;*/
+ glo_surface_update_context(qsurface->surface, glstate->context);
+ bind_qsurface(glstate, qsurface);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+
static int get_server_texture(ProcessState *process,
unsigned int client_texture)
{
if (!glstate) {
DEBUGF( " --invalid fake_ctxt (%d)!\n", fake_ctxt);
} else {
- if(!set_current_qsurface(glstate, client_drawable)) {
+ if(!set_current_qsurface(glstate, client_drawable) &&
+ !link_qsurface(process, glstate, client_drawable) ) {
// If there is no surface, create one.
QGloSurface *qsurface = calloc(1, sizeof(QGloSurface));
qsurface->surface = glo_surface_create(4, 4,
}
break;
}
+ case glXCreatePixmap_func:
+ {
+ int client_fbconfig = args[1];
+
+ ret.i = 0;
+ const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig);
+
+ if (fbconfig) {
+
+ /* Create a light-weight context just for creating surface */
+ GloContext *context = __glo_context_create(fbconfig->formatFlags);
+
+ /* glXPixmap same as input Pixmap */
+ ClientGLXDrawable client_drawable = to_drawable(args[2]);
+
+ QGloSurface *qsurface = calloc(1, sizeof(QGloSurface));
+ /*FIXME: need pass w,h from simulator-opengl */
+ qsurface->surface = glo_surface_create(512, 512, context);
+ qsurface->client_drawable = client_drawable;
+ /* qsurface->ref = 1;*/
+
+ /* Keep this surface, will link it with context in MakeCurrent */
+ if (!keep_qsurface(process, qsurface))
+ {
+ DEBUGF( "No space to store create pixmap surface. Need call MakeCurrent to free them.\n");
+ ret.i = 0;
+ break;
+ }
+
+ /* If this pixmap is linked as texture previously */
+ if (link_drawable(process, client_drawable))
+ glo_surface_as_texture(qsurface->surface);
+
+ ret.i = client_drawable;
+
+ }
+ break;
+ }
+ case glXDestroyPixmap_func:
+ {
+ break;
+ }
+ case glEGLImageTargetTexture2DOES_fake_func:
+ {
+ int target = args[0];
+ ClientGLXDrawable client_drawable = to_drawable(args[1]);
+ QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable);
+
+ if ( !qsurface )
+ {
+ if ( !keep_drawable(process, client_drawable) )
+ {
+ DEBUGF( "No space to store drawable for ImageTargetTexture. Need call CreatePixmapSurface to free them.\n");
+ break;
+ }
+ }
+ else
+ glo_surface_as_texture(qsurface->surface);
+
+ break;
+ }
+
/* Begin of texture stuff */
case glBindTexture_func:
case glBindTextureEXT_func:
static const int glXSwapIntervalSGI_signature[] =
{ TYPE_INT, 0, 1, TYPE_INT };
+static const int glXCreatePixmap_signature[] =
+ { TYPE_INT, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_ARRAY_INT };
+
+static const int glXDestroyPixmap_signature[] =
+ { TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT };
+
static const int glXBindTexImageATI_signature[] =
{ TYPE_NONE, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT };
static const int glXReleaseTexImageATI_signature[] =
static const int glXReleaseTexImageARB_signature[] =
{ TYPE_INT, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT };
+static const int glEGLImageTargetTexture2DOES_fake_signature[] =
+ { TYPE_NONE, 0, 2, TYPE_UNSIGNED_INT, TYPE_INT };
+
/* const GLubyte * glGetString( GLenum name ) */
static const int glGetString_signature[] =
{ TYPE_CONST_CHAR, 0, 1, TYPE_INT };