Home | History | Annotate | Download | only in x11
      1 /*
      2  * Copyright (c) 2012 Intel Corporation. All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sub license, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
     20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 #include <stdlib.h>
     25 #include <fcntl.h>
     26 #include <unistd.h>
     27 #include <assert.h>
     28 
     29 #include <xf86drm.h>
     30 
     31 #include <X11/Xlibint.h>
     32 #include <X11/Xlib.h>
     33 #include "va.h"
     34 #include "va_backend.h"
     35 
     36 #include "va_dri2.h"
     37 #include "va_dri2tokens.h"
     38 #include "va_dricommon.h"
     39 
     40 #define __DRI_BUFFER_FRONT_LEFT         0
     41 #define __DRI_BUFFER_BACK_LEFT          1
     42 #define __DRI_BUFFER_FRONT_RIGHT        2
     43 #define __DRI_BUFFER_BACK_RIGHT         3
     44 #define __DRI_BUFFER_DEPTH              4
     45 #define __DRI_BUFFER_STENCIL            5
     46 #define __DRI_BUFFER_ACCUM              6
     47 #define __DRI_BUFFER_FAKE_FRONT_LEFT    7
     48 #define __DRI_BUFFER_FAKE_FRONT_RIGHT   8
     49 
     50 struct dri2_drawable
     51 {
     52     struct dri_drawable base;
     53     union dri_buffer buffers[5];
     54     int width;
     55     int height;
     56     int has_backbuffer;
     57     int back_index;
     58     int front_index;
     59 };
     60 
     61 static int gsDRI2SwapAvailable;
     62 
     63 static struct dri_drawable *
     64 dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
     65 {
     66     struct dri2_drawable *dri2_drawable;
     67 
     68     dri2_drawable = calloc(1, sizeof(*dri2_drawable));
     69 
     70     if (!dri2_drawable)
     71         return NULL;
     72 
     73     dri2_drawable->base.x_drawable = x_drawable;
     74     dri2_drawable->base.x = 0;
     75     dri2_drawable->base.y = 0;
     76     VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
     77 
     78     return &dri2_drawable->base;
     79 }
     80 
     81 static void
     82 dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
     83 {
     84     VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
     85     free(dri_drawable);
     86 }
     87 
     88 static void
     89 dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
     90 {
     91     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
     92     XRectangle xrect;
     93     XserverRegion region;
     94 
     95     if (dri2_drawable->has_backbuffer) {
     96         if (gsDRI2SwapAvailable) {
     97             CARD64 ret;
     98             VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable, 0, 0,
     99                                0, &ret);
    100         } else {
    101             xrect.x = 0;
    102             xrect.y = 0;
    103             xrect.width = dri2_drawable->width;
    104             xrect.height = dri2_drawable->height;
    105 
    106             region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
    107             VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
    108                               DRI2BufferFrontLeft, DRI2BufferBackLeft);
    109             XFixesDestroyRegion(ctx->native_dpy, region);
    110         }
    111     }
    112 }
    113 
    114 static union dri_buffer *
    115 dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
    116 {
    117     struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
    118     int i;
    119     int count;
    120     unsigned int attachments[5];
    121     VA_DRI2Buffer *buffers;
    122 
    123     i = 0;
    124     if (dri_drawable->is_window)
    125         attachments[i++] = __DRI_BUFFER_BACK_LEFT;
    126     else
    127         attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
    128 
    129     buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
    130 			     &dri2_drawable->width, &dri2_drawable->height,
    131                              attachments, i, &count);
    132     assert(buffers);
    133     if (buffers == NULL)
    134         return NULL;
    135 
    136     dri2_drawable->has_backbuffer = 0;
    137 
    138     for (i = 0; i < count; i++) {
    139         dri2_drawable->buffers[i].dri2.attachment = buffers[i].attachment;
    140         dri2_drawable->buffers[i].dri2.name = buffers[i].name;
    141         dri2_drawable->buffers[i].dri2.pitch = buffers[i].pitch;
    142         dri2_drawable->buffers[i].dri2.cpp = buffers[i].cpp;
    143         dri2_drawable->buffers[i].dri2.flags = buffers[i].flags;
    144 
    145         if (buffers[i].attachment == __DRI_BUFFER_BACK_LEFT) {
    146             dri2_drawable->has_backbuffer = 1;
    147             dri2_drawable->back_index = i;
    148         }
    149 
    150         if (buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
    151             dri2_drawable->front_index = i;
    152     }
    153 
    154     dri_drawable->width = dri2_drawable->width;
    155     dri_drawable->height = dri2_drawable->height;
    156     Xfree(buffers);
    157 
    158     if (dri2_drawable->has_backbuffer)
    159         return &dri2_drawable->buffers[dri2_drawable->back_index];
    160 
    161     return &dri2_drawable->buffers[dri2_drawable->front_index];
    162 }
    163 
    164 void
    165 dri2Close(VADriverContextP ctx)
    166 {
    167     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
    168 
    169     free_drawable_hashtable(ctx);
    170 
    171     if (dri_state->base.fd >= 0);
    172 	close(dri_state->base.fd);
    173 }
    174 
    175 Bool
    176 isDRI2Connected(VADriverContextP ctx, char **driver_name)
    177 {
    178     struct dri_state *dri_state = (struct dri_state *)ctx->drm_state;
    179     int major, minor;
    180     int error_base;
    181     int event_base;
    182     char *device_name = NULL;
    183     drm_magic_t magic;
    184     *driver_name = NULL;
    185     dri_state->base.fd = -1;
    186     dri_state->base.auth_type = VA_NONE;
    187     if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
    188         goto err_out;
    189 
    190     if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
    191         goto err_out;
    192 
    193 
    194     if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
    195                      driver_name, &device_name) || !device_name)
    196         goto err_out;
    197 
    198     dri_state->base.fd = open(device_name, O_RDWR);
    199     assert(dri_state->base.fd >= 0);
    200 
    201     if (dri_state->base.fd < 0)
    202         goto err_out;
    203 
    204     if (drmGetMagic(dri_state->base.fd, &magic))
    205         goto err_out;
    206 
    207     if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
    208                           magic))
    209         goto err_out;
    210 
    211     dri_state->base.auth_type = VA_DRI2;
    212     dri_state->createDrawable = dri2CreateDrawable;
    213     dri_state->destroyDrawable = dri2DestroyDrawable;
    214     dri_state->swapBuffer = dri2SwapBuffer;
    215     dri_state->getRenderingBuffer = dri2GetRenderingBuffer;
    216     dri_state->close = dri2Close;
    217     gsDRI2SwapAvailable = (minor >= 2);
    218 
    219     Xfree(device_name);
    220 
    221     return True;
    222 
    223 err_out:
    224     if (device_name)
    225         Xfree(device_name);
    226 
    227     if (*driver_name)
    228         Xfree(*driver_name);
    229 
    230     if (dri_state->base.fd >= 0)
    231         close(dri_state->base.fd);
    232 
    233     *driver_name = NULL;
    234     dri_state->base.fd = -1;
    235 
    236     return False;
    237 }
    238 
    239