1409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan/*
2409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
3409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan *
4409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * Permission is hereby granted, free of charge, to any person obtaining a
5409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * copy of this software and associated documentation files (the
6409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * "Software"), to deal in the Software without restriction, including
7409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * without limitation the rights to use, copy, modify, merge, publish,
8409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * distribute, sub license, and/or sell copies of the Software, and to
9409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * permit persons to whom the Software is furnished to do so, subject to
10409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * the following conditions:
11409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan *
12409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * The above copyright notice and this permission notice (including the
13409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * next paragraph) shall be included in all copies or substantial portions
14409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * of the Software.
15409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan *
16409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan */
2486c93d9c46415cf7746351c502a3513f637e77e4root#include <stdlib.h>
2586c93d9c46415cf7746351c502a3513f637e77e4root#include <fcntl.h>
2686c93d9c46415cf7746351c502a3513f637e77e4root#include <unistd.h>
2786c93d9c46415cf7746351c502a3513f637e77e4root#include <assert.h>
2886c93d9c46415cf7746351c502a3513f637e77e4root
2986c93d9c46415cf7746351c502a3513f637e77e4root#include <xf86drm.h>
3086c93d9c46415cf7746351c502a3513f637e77e4root
3186c93d9c46415cf7746351c502a3513f637e77e4root#include <X11/Xlibint.h>
3286c93d9c46415cf7746351c502a3513f637e77e4root#include <X11/Xlib.h>
3386c93d9c46415cf7746351c502a3513f637e77e4root#include "va.h"
3486c93d9c46415cf7746351c502a3513f637e77e4root#include "va_backend.h"
3586c93d9c46415cf7746351c502a3513f637e77e4root
3686c93d9c46415cf7746351c502a3513f637e77e4root#include "va_dri2.h"
3786c93d9c46415cf7746351c502a3513f637e77e4root#include "va_dri2tokens.h"
3886c93d9c46415cf7746351c502a3513f637e77e4root#include "va_dricommon.h"
3986c93d9c46415cf7746351c502a3513f637e77e4root
4086c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_FRONT_LEFT         0
4186c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_BACK_LEFT          1
4286c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_FRONT_RIGHT        2
4386c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_BACK_RIGHT         3
4486c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_DEPTH              4
4586c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_STENCIL            5
4686c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_ACCUM              6
4786c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_FAKE_FRONT_LEFT    7
4886c93d9c46415cf7746351c502a3513f637e77e4root#define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
4986c93d9c46415cf7746351c502a3513f637e77e4root
5086c93d9c46415cf7746351c502a3513f637e77e4rootstruct dri2_drawable
5186c93d9c46415cf7746351c502a3513f637e77e4root{
5286c93d9c46415cf7746351c502a3513f637e77e4root    struct dri_drawable base;
5386c93d9c46415cf7746351c502a3513f637e77e4root    union dri_buffer buffers[5];
5486c93d9c46415cf7746351c502a3513f637e77e4root    int width;
5586c93d9c46415cf7746351c502a3513f637e77e4root    int height;
5686c93d9c46415cf7746351c502a3513f637e77e4root    int has_backbuffer;
5786c93d9c46415cf7746351c502a3513f637e77e4root    int back_index;
5886c93d9c46415cf7746351c502a3513f637e77e4root    int front_index;
5986c93d9c46415cf7746351c502a3513f637e77e4root};
6086c93d9c46415cf7746351c502a3513f637e77e4root
61b0fac498ca4863166252f1268fda83394db54153Fei Jiangstatic int gsDRI2SwapAvailable;
62b0fac498ca4863166252f1268fda83394db54153Fei Jiang
6386c93d9c46415cf7746351c502a3513f637e77e4rootstatic struct dri_drawable *
6486c93d9c46415cf7746351c502a3513f637e77e4rootdri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
6586c93d9c46415cf7746351c502a3513f637e77e4root{
6686c93d9c46415cf7746351c502a3513f637e77e4root    struct dri2_drawable *dri2_drawable;
6786c93d9c46415cf7746351c502a3513f637e77e4root
6886c93d9c46415cf7746351c502a3513f637e77e4root    dri2_drawable = calloc(1, sizeof(*dri2_drawable));
6986c93d9c46415cf7746351c502a3513f637e77e4root
7086c93d9c46415cf7746351c502a3513f637e77e4root    if (!dri2_drawable)
7186c93d9c46415cf7746351c502a3513f637e77e4root        return NULL;
7286c93d9c46415cf7746351c502a3513f637e77e4root
7386c93d9c46415cf7746351c502a3513f637e77e4root    dri2_drawable->base.x_drawable = x_drawable;
7486c93d9c46415cf7746351c502a3513f637e77e4root    dri2_drawable->base.x = 0;
7586c93d9c46415cf7746351c502a3513f637e77e4root    dri2_drawable->base.y = 0;
765b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
7786c93d9c46415cf7746351c502a3513f637e77e4root
7886c93d9c46415cf7746351c502a3513f637e77e4root    return &dri2_drawable->base;
7986c93d9c46415cf7746351c502a3513f637e77e4root}
8086c93d9c46415cf7746351c502a3513f637e77e4root
8186c93d9c46415cf7746351c502a3513f637e77e4rootstatic void
8286c93d9c46415cf7746351c502a3513f637e77e4rootdri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
8386c93d9c46415cf7746351c502a3513f637e77e4root{
845b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
8586c93d9c46415cf7746351c502a3513f637e77e4root    free(dri_drawable);
8686c93d9c46415cf7746351c502a3513f637e77e4root}
8786c93d9c46415cf7746351c502a3513f637e77e4root
8886c93d9c46415cf7746351c502a3513f637e77e4rootstatic void
8986c93d9c46415cf7746351c502a3513f637e77e4rootdri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
9086c93d9c46415cf7746351c502a3513f637e77e4root{
9186c93d9c46415cf7746351c502a3513f637e77e4root    struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
9286c93d9c46415cf7746351c502a3513f637e77e4root    XRectangle xrect;
9386c93d9c46415cf7746351c502a3513f637e77e4root    XserverRegion region;
9486c93d9c46415cf7746351c502a3513f637e77e4root
9586c93d9c46415cf7746351c502a3513f637e77e4root    if (dri2_drawable->has_backbuffer) {
96b0fac498ca4863166252f1268fda83394db54153Fei Jiang        if (gsDRI2SwapAvailable) {
97b0fac498ca4863166252f1268fda83394db54153Fei Jiang            CARD64 ret;
98b0fac498ca4863166252f1268fda83394db54153Fei Jiang            VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable, 0, 0,
99b0fac498ca4863166252f1268fda83394db54153Fei Jiang                               0, &ret);
100b0fac498ca4863166252f1268fda83394db54153Fei Jiang        } else {
101b0fac498ca4863166252f1268fda83394db54153Fei Jiang            xrect.x = 0;
102b0fac498ca4863166252f1268fda83394db54153Fei Jiang            xrect.y = 0;
103b0fac498ca4863166252f1268fda83394db54153Fei Jiang            xrect.width = dri2_drawable->width;
104b0fac498ca4863166252f1268fda83394db54153Fei Jiang            xrect.height = dri2_drawable->height;
105b0fac498ca4863166252f1268fda83394db54153Fei Jiang
106b0fac498ca4863166252f1268fda83394db54153Fei Jiang            region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
107b0fac498ca4863166252f1268fda83394db54153Fei Jiang            VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
108b0fac498ca4863166252f1268fda83394db54153Fei Jiang                              DRI2BufferFrontLeft, DRI2BufferBackLeft);
109b0fac498ca4863166252f1268fda83394db54153Fei Jiang            XFixesDestroyRegion(ctx->native_dpy, region);
110b0fac498ca4863166252f1268fda83394db54153Fei Jiang        }
11186c93d9c46415cf7746351c502a3513f637e77e4root    }
11286c93d9c46415cf7746351c502a3513f637e77e4root}
11386c93d9c46415cf7746351c502a3513f637e77e4root
11486c93d9c46415cf7746351c502a3513f637e77e4rootstatic union dri_buffer *
11586c93d9c46415cf7746351c502a3513f637e77e4rootdri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
11686c93d9c46415cf7746351c502a3513f637e77e4root{
11786c93d9c46415cf7746351c502a3513f637e77e4root    struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
11886c93d9c46415cf7746351c502a3513f637e77e4root    int i;
11986c93d9c46415cf7746351c502a3513f637e77e4root    int count;
12086c93d9c46415cf7746351c502a3513f637e77e4root    unsigned int attachments[5];
12186c93d9c46415cf7746351c502a3513f637e77e4root    VA_DRI2Buffer *buffers;
12286c93d9c46415cf7746351c502a3513f637e77e4root
12386c93d9c46415cf7746351c502a3513f637e77e4root    i = 0;
124901c77a7aa491f56b63af7b655b67439481e4177Fei Jiang    if (dri_drawable->is_window)
125901c77a7aa491f56b63af7b655b67439481e4177Fei Jiang        attachments[i++] = __DRI_BUFFER_BACK_LEFT;
126901c77a7aa491f56b63af7b655b67439481e4177Fei Jiang    else
127901c77a7aa491f56b63af7b655b67439481e4177Fei Jiang        attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
128901c77a7aa491f56b63af7b655b67439481e4177Fei Jiang
129b0fac498ca4863166252f1268fda83394db54153Fei Jiang    buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
13086c93d9c46415cf7746351c502a3513f637e77e4root			     &dri2_drawable->width, &dri2_drawable->height,
13186c93d9c46415cf7746351c502a3513f637e77e4root                             attachments, i, &count);
13286c93d9c46415cf7746351c502a3513f637e77e4root    assert(buffers);
13386c93d9c46415cf7746351c502a3513f637e77e4root    if (buffers == NULL)
13486c93d9c46415cf7746351c502a3513f637e77e4root        return NULL;
13586c93d9c46415cf7746351c502a3513f637e77e4root
13686c93d9c46415cf7746351c502a3513f637e77e4root    dri2_drawable->has_backbuffer = 0;
13786c93d9c46415cf7746351c502a3513f637e77e4root
13886c93d9c46415cf7746351c502a3513f637e77e4root    for (i = 0; i < count; i++) {
13986c93d9c46415cf7746351c502a3513f637e77e4root        dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
14086c93d9c46415cf7746351c502a3513f637e77e4root        dri2_drawable->buffers[i].dri2.name = buffers[i].name;
14186c93d9c46415cf7746351c502a3513f637e77e4root        dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
14286c93d9c46415cf7746351c502a3513f637e77e4root        dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
14386c93d9c46415cf7746351c502a3513f637e77e4root        dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
14486c93d9c46415cf7746351c502a3513f637e77e4root
14586c93d9c46415cf7746351c502a3513f637e77e4root        if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
14686c93d9c46415cf7746351c502a3513f637e77e4root            dri2_drawable->has_backbuffer = 1;
14786c93d9c46415cf7746351c502a3513f637e77e4root            dri2_drawable->back_index = i;
14886c93d9c46415cf7746351c502a3513f637e77e4root        }
14986c93d9c46415cf7746351c502a3513f637e77e4root
15086c93d9c46415cf7746351c502a3513f637e77e4root        if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
15186c93d9c46415cf7746351c502a3513f637e77e4root            dri2_drawable->front_index = i;
15286c93d9c46415cf7746351c502a3513f637e77e4root    }
15386c93d9c46415cf7746351c502a3513f637e77e4root
15486c93d9c46415cf7746351c502a3513f637e77e4root    dri_drawable->width = dri2_drawable->width;
15586c93d9c46415cf7746351c502a3513f637e77e4root    dri_drawable->height = dri2_drawable->height;
15686c93d9c46415cf7746351c502a3513f637e77e4root    Xfree(buffers);
15786c93d9c46415cf7746351c502a3513f637e77e4root
15886c93d9c46415cf7746351c502a3513f637e77e4root    if (dri2_drawable->has_backbuffer)
15986c93d9c46415cf7746351c502a3513f637e77e4root        return &dri2_drawable->buffers[dri2_drawable->back_index];
16086c93d9c46415cf7746351c502a3513f637e77e4root
16186c93d9c46415cf7746351c502a3513f637e77e4root    return &dri2_drawable->buffers[dri2_drawable->front_index];
16286c93d9c46415cf7746351c502a3513f637e77e4root}
16386c93d9c46415cf7746351c502a3513f637e77e4root
16410965d59ea630e8a6856845faffb8e0f39b159a3Kun Wangvoid
16586c93d9c46415cf7746351c502a3513f637e77e4rootdri2Close(VADriverContextP ctx)
16686c93d9c46415cf7746351c502a3513f637e77e4root{
167409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
16886c93d9c46415cf7746351c502a3513f637e77e4root
16986c93d9c46415cf7746351c502a3513f637e77e4root    free_drawable_hashtable(ctx);
170601e657275d5edf21b79d64a49d9d392628ae487Austin Yuan
171409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    if (dri_state->base.fd >= 0);
172409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan	close(dri_state->base.fd);
17386c93d9c46415cf7746351c502a3513f637e77e4root}
17486c93d9c46415cf7746351c502a3513f637e77e4root
17586c93d9c46415cf7746351c502a3513f637e77e4rootBool
17686c93d9c46415cf7746351c502a3513f637e77e4rootisDRI2Connected(VADriverContextP ctx, char **driver_name)
17786c93d9c46415cf7746351c502a3513f637e77e4root{
178409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
17986c93d9c46415cf7746351c502a3513f637e77e4root    int major, minor;
18086c93d9c46415cf7746351c502a3513f637e77e4root    int error_base;
18186c93d9c46415cf7746351c502a3513f637e77e4root    int event_base;
18286c93d9c46415cf7746351c502a3513f637e77e4root    char *device_name = NULL;
18386c93d9c46415cf7746351c502a3513f637e77e4root    drm_magic_t magic;
18486c93d9c46415cf7746351c502a3513f637e77e4root    *driver_name = NULL;
185409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    dri_state->base.fd = -1;
186409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    dri_state->base.auth_type = VA_NONE;
1875b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
18886c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
18986c93d9c46415cf7746351c502a3513f637e77e4root
1905b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
19186c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
19286c93d9c46415cf7746351c502a3513f637e77e4root
193409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan
1945b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
1956044ab9a375eb73b08f45d87966652f98f918668Austin Yuan                     driver_name, &device_name) || !device_name)
19686c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
19786c93d9c46415cf7746351c502a3513f637e77e4root
198409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    dri_state->base.fd = open(device_name, O_RDWR);
199409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    assert(dri_state->base.fd >= 0);
20086c93d9c46415cf7746351c502a3513f637e77e4root
201409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    if (dri_state->base.fd < 0)
20286c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
20386c93d9c46415cf7746351c502a3513f637e77e4root
204409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    if (drmGetMagic(dri_state->base.fd, &magic))
20586c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
20686c93d9c46415cf7746351c502a3513f637e77e4root
2075b3d55a0433b48477823f81821817a78ef53ac2eShuduo Sang    if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
20886c93d9c46415cf7746351c502a3513f637e77e4root                          magic))
20986c93d9c46415cf7746351c502a3513f637e77e4root        goto err_out;
21086c93d9c46415cf7746351c502a3513f637e77e4root
211409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    dri_state->base.auth_type = VA_DRI2;
21286c93d9c46415cf7746351c502a3513f637e77e4root    dri_state->createDrawable = dri2CreateDrawable;
21386c93d9c46415cf7746351c502a3513f637e77e4root    dri_state->destroyDrawable = dri2DestroyDrawable;
21486c93d9c46415cf7746351c502a3513f637e77e4root    dri_state->swapBuffer = dri2SwapBuffer;
21586c93d9c46415cf7746351c502a3513f637e77e4root    dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
21686c93d9c46415cf7746351c502a3513f637e77e4root    dri_state->close = dri2Close;
217b0fac498ca4863166252f1268fda83394db54153Fei Jiang    gsDRI2SwapAvailable = (minor >= 2);
21886c93d9c46415cf7746351c502a3513f637e77e4root
2196044ab9a375eb73b08f45d87966652f98f918668Austin Yuan    Xfree(device_name);
22036bee3ca78947ad82f87473b5d29b9a7177ebaedShuduo Sang
22186c93d9c46415cf7746351c502a3513f637e77e4root    return True;
22286c93d9c46415cf7746351c502a3513f637e77e4root
22386c93d9c46415cf7746351c502a3513f637e77e4rooterr_out:
22486c93d9c46415cf7746351c502a3513f637e77e4root    if (device_name)
22586c93d9c46415cf7746351c502a3513f637e77e4root        Xfree(device_name);
22686c93d9c46415cf7746351c502a3513f637e77e4root
22786c93d9c46415cf7746351c502a3513f637e77e4root    if (*driver_name)
22886c93d9c46415cf7746351c502a3513f637e77e4root        Xfree(*driver_name);
22986c93d9c46415cf7746351c502a3513f637e77e4root
230409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    if (dri_state->base.fd >= 0)
231409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan        close(dri_state->base.fd);
23286c93d9c46415cf7746351c502a3513f637e77e4root
23386c93d9c46415cf7746351c502a3513f637e77e4root    *driver_name = NULL;
234409de6acb4473c973ed2532e340831dc582e5e0eAustin Yuan    dri_state->base.fd = -1;
23586c93d9c46415cf7746351c502a3513f637e77e4root
23686c93d9c46415cf7746351c502a3513f637e77e4root    return False;
23786c93d9c46415cf7746351c502a3513f637e77e4root}
23886c93d9c46415cf7746351c502a3513f637e77e4root
239