apple_glx_surface.c [plain text]
#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);
glViewport(0, 0, width, height);
glScissor(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) {
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);
}
if (!s->pending_destroy) {
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);
}
}
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;
}
return true;
}
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;
if (create_surface(dpy, screen, d)) {
d->unlock(d);
d->destroy(d);
return true;
}
*resultptr = d;
d->unlock(d);
return false;
}
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);
d->destroy(d);
d->unlock(d);
}
}