Blame va/x11/dri2_util.c

Packit Service 9402ce
/*
Packit Service 9402ce
 * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
Packit Service 9402ce
 *
Packit Service 9402ce
 * Permission is hereby granted, free of charge, to any person obtaining a
Packit Service 9402ce
 * copy of this software and associated documentation files (the
Packit Service 9402ce
 * "Software"), to deal in the Software without restriction, including
Packit Service 9402ce
 * without limitation the rights to use, copy, modify, merge, publish,
Packit Service 9402ce
 * distribute, sub license, and/or sell copies of the Software, and to
Packit Service 9402ce
 * permit persons to whom the Software is furnished to do so, subject to
Packit Service 9402ce
 * the following conditions:
Packit Service 9402ce
 *
Packit Service 9402ce
 * The above copyright notice and this permission notice (including the
Packit Service 9402ce
 * next paragraph) shall be included in all copies or substantial portions
Packit Service 9402ce
 * of the Software.
Packit Service 9402ce
 *
Packit Service 9402ce
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Packit Service 9402ce
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service 9402ce
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
Packit Service 9402ce
 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
Packit Service 9402ce
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
Packit Service 9402ce
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Packit Service 9402ce
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service 9402ce
 */
Packit Service 9402ce
#include <stdlib.h>
Packit Service 9402ce
#include <fcntl.h>
Packit Service 9402ce
#include <unistd.h>
Packit Service 9402ce
#include <assert.h>
Packit Service 9402ce
Packit Service 9402ce
#include <xf86drm.h>
Packit Service 9402ce
Packit Service 9402ce
#include <X11/Xlibint.h>
Packit Service 9402ce
#include <X11/Xlib.h>
Packit Service 9402ce
#include "va.h"
Packit Service 9402ce
#include "va_backend.h"
Packit Service 9402ce
Packit Service 9402ce
#include "va_dri2.h"
Packit Service 9402ce
#include "va_dri2tokens.h"
Packit Service 9402ce
#include "va_dricommon.h"
Packit Service 9402ce
Packit Service 9402ce
#define __DRI_BUFFER_FRONT_LEFT         0
Packit Service 9402ce
#define __DRI_BUFFER_BACK_LEFT          1
Packit Service 9402ce
#define __DRI_BUFFER_FRONT_RIGHT        2
Packit Service 9402ce
#define __DRI_BUFFER_BACK_RIGHT         3
Packit Service 9402ce
#define __DRI_BUFFER_DEPTH              4
Packit Service 9402ce
#define __DRI_BUFFER_STENCIL            5
Packit Service 9402ce
#define __DRI_BUFFER_ACCUM              6
Packit Service 9402ce
#define __DRI_BUFFER_FAKE_FRONT_LEFT    7
Packit Service 9402ce
#define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
Packit Service 9402ce
Packit Service 9402ce
struct dri2_drawable 
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri_drawable base;
Packit Service 9402ce
    union dri_buffer buffers[5];
Packit Service 9402ce
    int width;
Packit Service 9402ce
    int height;
Packit Service 9402ce
    int has_backbuffer;
Packit Service 9402ce
    int back_index;
Packit Service 9402ce
    int front_index;
Packit Service 9402ce
};
Packit Service 9402ce
Packit Service 9402ce
static int gsDRI2SwapAvailable;
Packit Service 9402ce
Packit Service 9402ce
static struct dri_drawable * 
Packit Service 9402ce
dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri2_drawable *dri2_drawable;
Packit Service 9402ce
Packit Service 9402ce
    dri2_drawable = calloc(1, sizeof(*dri2_drawable));
Packit Service 9402ce
Packit Service 9402ce
    if (!dri2_drawable)
Packit Service 9402ce
        return NULL;
Packit Service 9402ce
Packit Service 9402ce
    dri2_drawable->base.x_drawable = x_drawable;
Packit Service 9402ce
    dri2_drawable->base.x = 0;
Packit Service 9402ce
    dri2_drawable->base.y = 0;
Packit Service 9402ce
    VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
Packit Service 9402ce
Packit Service 9402ce
    return &dri2_drawable->base;
Packit Service 9402ce
}
Packit Service 9402ce
Packit Service 9402ce
static void 
Packit Service 9402ce
dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
Packit Service 9402ce
{
Packit Service 9402ce
    VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
Packit Service 9402ce
    free(dri_drawable);
Packit Service 9402ce
}
Packit Service 9402ce
Packit Service 9402ce
static void 
Packit Service 9402ce
dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
Packit Service 9402ce
    XRectangle xrect;
Packit Service 9402ce
    XserverRegion region;
Packit Service 9402ce
Packit Service 9402ce
    if (dri2_drawable->has_backbuffer) {
Packit Service 9402ce
        if (gsDRI2SwapAvailable) {
Packit Service 9402ce
            CARD64 ret;
Packit Service 9402ce
            VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable,
Packit Service 9402ce
			       0, 1, 0,
Packit Service 9402ce
			       &ret;;
Packit Service 9402ce
        } else {
Packit Service 9402ce
            xrect.x = 0;
Packit Service 9402ce
            xrect.y = 0;
Packit Service 9402ce
            xrect.width = dri2_drawable->width;
Packit Service 9402ce
            xrect.height = dri2_drawable->height;
Packit Service 9402ce
Packit Service 9402ce
            region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
Packit Service 9402ce
            VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
Packit Service 9402ce
                              DRI2BufferFrontLeft, DRI2BufferBackLeft);
Packit Service 9402ce
            XFixesDestroyRegion(ctx->native_dpy, region);
Packit Service 9402ce
        }
Packit Service 9402ce
    }
Packit Service 9402ce
}
Packit Service 9402ce
Packit Service 9402ce
static union dri_buffer *
Packit Service 9402ce
dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
Packit Service 9402ce
    int i;
Packit Service 9402ce
    int count;
Packit Service 9402ce
    unsigned int attachments[5];
Packit Service 9402ce
    VA_DRI2Buffer *buffers;
Packit Service 9402ce
    
Packit Service 9402ce
    i = 0;
Packit Service 9402ce
    if (dri_drawable->is_window)
Packit Service 9402ce
        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
Packit Service 9402ce
    else
Packit Service 9402ce
        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
Packit Service 9402ce
Packit Service 9402ce
    buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
Packit Service 9402ce
			     &dri2_drawable->width, &dri2_drawable->height, 
Packit Service 9402ce
                             attachments, i, &count);
Packit Service 9402ce
    if (buffers == NULL)
Packit Service 9402ce
        return NULL;
Packit Service 9402ce
Packit Service 9402ce
    dri2_drawable->has_backbuffer = 0;
Packit Service 9402ce
Packit Service 9402ce
    for (i = 0; i < count; i++) {
Packit Service 9402ce
        dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
Packit Service 9402ce
        dri2_drawable->buffers[i].dri2.name = buffers[i].name;
Packit Service 9402ce
        dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
Packit Service 9402ce
        dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
Packit Service 9402ce
        dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
Packit Service 9402ce
        
Packit Service 9402ce
        if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
Packit Service 9402ce
            dri2_drawable->has_backbuffer = 1;
Packit Service 9402ce
            dri2_drawable->back_index = i;
Packit Service 9402ce
        }
Packit Service 9402ce
Packit Service 9402ce
        if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
Packit Service 9402ce
            dri2_drawable->front_index = i;
Packit Service 9402ce
    }
Packit Service 9402ce
    
Packit Service 9402ce
    dri_drawable->width = dri2_drawable->width;
Packit Service 9402ce
    dri_drawable->height = dri2_drawable->height;
Packit Service 9402ce
    Xfree(buffers);
Packit Service 9402ce
Packit Service 9402ce
    if (dri2_drawable->has_backbuffer)
Packit Service 9402ce
        return &dri2_drawable->buffers[dri2_drawable->back_index];
Packit Service 9402ce
Packit Service 9402ce
    return &dri2_drawable->buffers[dri2_drawable->front_index];
Packit Service 9402ce
}
Packit Service 9402ce
Packit Service 9402ce
static void
Packit Service 9402ce
dri2Close(VADriverContextP ctx)
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
Packit Service 9402ce
Packit Service 9402ce
    va_dri_free_drawable_hashtable(ctx);
Packit Service 9402ce
Packit Service 9402ce
    if (dri_state->base.fd >= 0)
Packit Service 9402ce
	close(dri_state->base.fd);
Packit Service 9402ce
}
Packit Service 9402ce
Packit Service 9402ce
Bool 
Packit Service 9402ce
va_isDRI2Connected(VADriverContextP ctx, char **driver_name)
Packit Service 9402ce
{
Packit Service 9402ce
    struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
Packit Service 9402ce
    int major, minor;
Packit Service 9402ce
    int error_base;
Packit Service 9402ce
    int event_base;
Packit Service 9402ce
    char *device_name = NULL;
Packit Service 9402ce
    drm_magic_t magic;        
Packit Service 9402ce
    *driver_name = NULL;
Packit Service 9402ce
    dri_state->base.fd = -1;
Packit Service 9402ce
    dri_state->base.auth_type = VA_NONE;
Packit Service 9402ce
    if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
    if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
Packit Service 9402ce
    if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
Packit Service 9402ce
                     driver_name, &device_name))
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
    dri_state->base.fd = open(device_name, O_RDWR);
Packit Service 9402ce
Packit Service 9402ce
    if (dri_state->base.fd < 0)
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
    if (drmGetMagic(dri_state->base.fd, &magic))
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
    if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
Packit Service 9402ce
                          magic))
Packit Service 9402ce
        goto err_out;
Packit Service 9402ce
Packit Service 9402ce
    dri_state->base.auth_type = VA_DRI2;
Packit Service 9402ce
    dri_state->createDrawable = dri2CreateDrawable;
Packit Service 9402ce
    dri_state->destroyDrawable = dri2DestroyDrawable;
Packit Service 9402ce
    dri_state->swapBuffer = dri2SwapBuffer;
Packit Service 9402ce
    dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
Packit Service 9402ce
    dri_state->close = dri2Close;
Packit Service 9402ce
    gsDRI2SwapAvailable = (minor >= 2);
Packit Service 9402ce
Packit Service 9402ce
    Xfree(device_name);
Packit Service 9402ce
Packit Service 9402ce
    return True;
Packit Service 9402ce
Packit Service 9402ce
err_out:
Packit Service 9402ce
    if (device_name)
Packit Service 9402ce
        Xfree(device_name);
Packit Service 9402ce
Packit Service 9402ce
    if (*driver_name)
Packit Service 9402ce
        Xfree(*driver_name);
Packit Service 9402ce
Packit Service 9402ce
    if (dri_state->base.fd >= 0)
Packit Service 9402ce
        close(dri_state->base.fd);
Packit Service 9402ce
Packit Service 9402ce
    *driver_name = NULL;
Packit Service 9402ce
    dri_state->base.fd = -1;
Packit Service 9402ce
    
Packit Service 9402ce
    return False;
Packit Service 9402ce
}
Packit Service 9402ce